Feature/351 firmware factorytest wmenu add an exit command#383
Feature/351 firmware factorytest wmenu add an exit command#383
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 39329f1e0d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (g_globalExitRequested) { | ||
| g_globalExitRequested = false; | ||
| Serial.println(F("\n[GLOBAL EXIT] Aborting current operation.")); | ||
| printMenu(); | ||
| return; |
There was a problem hiding this comment.
Handle global exit inside long-running command flows
The new global-exit flag is only consumed at the top of loop(), so if exit is entered during runAllTests() (or any command path that does not return to loop() quickly), the operation keeps running additional tests before the abort is honored. In this commit readLineOrMenuAbort()/promptYesNo() set g_globalExitRequested, but runAllTests() never checks it, so the "exit current operation immediately" behavior is broken specifically during Run-All and can execute unintended hardware tests after the operator asked to stop.
Useful? React with 👍 / 👎.
| static volatile bool g_globalExitRequested = false; | ||
|
|
||
| // Case-insensitive check for exact string "exit" | ||
| static bool isExitCommand(const String &s) |
There was a problem hiding this comment.
This whole function can be simplified with the String::equalsIgnoreCase() method.
// Case-insensitive check for exact string "exit"
static bool isExitCommand(const String &s)
{
return s.equalsIgnoreCase("exit");
}There was a problem hiding this comment.
I realize now the char* exit should probably be defined in a const. Well, you get the idea. lol
There was a problem hiding this comment.
I should also be clear on why this works. The char*, the exit string, is implicitly converted into a String object because of the String::String(const char*) constructor. As a note, for those unaware like I was until just now, C++ will implicitly convert types if there is a matching constructor matching that type. In this case, there is a String constructor for type const char* so it gets used. The only time this does not happen implicitly is if the constructor is proceeded with the keyword explicit (which in my opinion should be the default).
Now, being a String this CAN incur memory/heap allocation. One concern is that system does not have available memory for heap allocation, but that won't be a concern in this test. The OTHER and very serious concerns in embedded systems is memory fragmentation due to the lack of MMU. Lucky for us, the ESP32 SoC has an MMU so memory fragmentation I believe shouldn't happen.
Anyways, this is all to say that your solution is not necessarily incorrect. Or even sub-optimal. In fact, some may argue it is the "technically correct" solution. However, especially since this is a test and not running the firmware for a long period of time where the aforementioned problems COULD be encountered, I don't see anything wrong with using a String to make your life easier.
Global Exit CommandI added a global Current Behavior
ClarificationAt the moment, For example, if a test is in the middle of a short wait (such as a few seconds of speaker playback or a Wi-Fi connection attempt), it will complete that short wait before returning to the menu. It does not interrupt delays mid-execution. Open QuestionBefore adding additional checks inside those loops, I’d like feedback: Do we want:
NamingI used If the team prefers the word |
|
Implemented @TheBakedPotato 's suggestion by simplifying the break detection using equalsIgnoreCase(). Per @ForrestErickson recommendation, renamed the user command from exit to break for terminology consistency. Additionally, updated long-running test loops (Inputs, Speaker, WiFi STA, RS-232) to check g_globalBreakRequested cooperatively. The system now aborts immediately at loop level with proper peripheral cleanup, rather than waiting for delays or blocking operations to complete. |
| @@ -1,4 +1,4 @@ | |||
| #define FIRMWARE_VERSION "v0.4.2.7" | |||
| #define FIRMWARE_VERSION "v0.4.3.3" | |||
There was a problem hiding this comment.
Purely asking for clarification, not looking for a change. But why is the FIRMWARE_VERSION in the form of w.x.y.z? Not saying this is incorrect in anyway at all, just seems "unconventional" and not sure what the different numbers mean.
There was a problem hiding this comment.
here according to me we are following 0.major.minor.patch type versioning, since we haven't launched any version thus it's 0 there while after that we are following the normal semantic versioning, Also i changed it from 2.x to 3.x as i am adding a new feature that we think is a minor change.
Hope this is correct and clears your doubt.
There was a problem hiding this comment.
Regarding, ' just seems "unconventional" ' It is because we did not know the phrase ' semantic versioning ' till recently when you got us up to speed. Good work on that!
|
|
||
| unsigned long start = millis(); | ||
| while (millis() - start < 10000UL) { | ||
| if (g_globalBreakRequested) return false; |
There was a problem hiding this comment.
This is more about style and convention, but it might be best to still put the return false; in braces. I know C/C++ allow NOT putting in braces but by using braces it makes it much more clear what the scope is of the if statement. I believe not using braces can sometimes lead to odd and unexpected bugs because a change is made and it's not clear that thr body to the if statement was modified.
So my suggestion is to do:
if (g_globalBreakRequested)
{
return false;
}|
It looks like the reset is likely caused by repeated For example, when the user types To reduce this risk, I’m removing the Longer term, I plan to migrate serial input parsing from dynamic |
Update on GLOBAL BREAK changesWhat I changed
This removes heap allocation from the main interactive/break path and makes break handling more deterministic. Left for future cleanup
These are not in tight loops but can be migrated to |
Oh boy. My bad! I think I misinterpreted the MMU the ESP32 has. It seems to only used for mapping external memory from the SPI flash or SRAM. I don't think it is in use for the embedded RAM hence the memory fragmentation issues. I am very sorry for suggesting to use the |







Links
What & Why
Validation / How to Verify
exit,EXIT,Exit,eXiTexit+ Enter:Artifacts (attach if relevant)
Checklist