-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Fixes for poor HardwareSerial performance/crashes exacerbated by SDK1.5 #1320
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
… FIFO. Not sure why, but this reduces the occurrence rate of an occasional ~3.25 or ~7μs intercharacter delay, which was interfering with use of the UART to generate precise timing pulses (such as driving WS2812 LEDs).
…RAM. This is required per the non-OS SDK doc, which states: "Using non-OS SDK, please do not call any function defined with ICACHE_FLASH_ATTR in the interrupt handler." This avoids an "Illegal instruction" exception with epc1 pointing at a valid instruction (in flash) for one of the moved methods.
…RX if we can't allocate a buffer for them. Prior to this change, the interrupt could fire during initialisation, necessitating a deep check that the HardwareSerial structure had valid _tx_buffer or _rx_buffer each time an interrupt occurred. By keeping uart_t's and HardwareSerial's (txEnabled, _tx_buffer) and (rxEnabled, _rx_buffer) in sync, we can remove this extra check, as well as fixing a null pointer dereference if e.g. _tx_buffer allocation failed and write() was subsequently called.
Prior to this change, if interrupts were disabled during a call to HardwareSerial::write() when the circular buffer was full, or HardwareSerial::flush() when the circular buffer was non-empty, we would loop forever and trip a watchdog timeout.
Tracking _written was required on AVR devices to work around a hardware limitation when implementing flush(). The ESP8266 doesn't have the same issue, so we can remove the tracking and make write() more lightweight. The cost is a minor increase in work done in flush() when write() was not previously called, but this should be much rarer than individual character writes.
Can you please outline which parts of the code that you changed you think are actually related and causing the problems you describe. Going over the files, most edits seem to be more of your preferred coding style than actually changing anything in the logic. |
Sure. But let me first start by saying two things:
With regard to the individual commits, none of the changes independently "solve" the issues seen with the NeoPixelBus usage. I've tried to put the reason for each one into the individual commit message, but here's some more info on the set as a whole:
The remainder of the commits are to cut down the code size and number of instructions in the critical path:
|
Wow what a lengthy response :) To be clear about the "coding style" I meant mostly the Macros you defined as the compiler will replace them in the code and produce the same exact code but with while(0) around it, but skipping those through the changes is not easy :) extern "C" void system_set_os_print(uint8 onoff);
extern "C" void ets_install_putc1(void* routine);
static void _u0_putc(char c){
while(((U0S >> USTXC) & 0x7F) == 0x7F);
U0F = c;
}
void initSerial(){
Serial.begin(115200);
ets_install_putc1((void *) &_u0_putc);
system_set_os_print(1);
} This code enabled os_printf to work through it. Do some debugging and see if it will make a difference :) |
The http://kernelnewbies.org/FAQ/DoWhile0 seems to be a reasonable explanation of why this is the "right" thing to do in macros. I've also seen another thread here recent where disabling some debugging macros caused bad code by not using this style for empty macro blocks. It's probably not not strictly necessary here, given most of these are single statement expressions, but still protects against a class of errors that could come up. For example, if one were to erroneously write Do you have better guidance on that which is used by this project? I'm wondering if I missed a style guide somewhere. |
There is no style guide :) the same as those defines did not change the logic. The situations you explain are not something that the code was about to get into. Those changes just make it difficult to see what you actually changed. |
Fixes for poor HardwareSerial performance/crashes exacerbated by SDK1.5
After SDK 1.5, libraries like NeoPixelBus which use the UART to generate timing signals stopped working correctly (logic analyser shows large intercharacter delays) as well as experiencing crashes in the IRQ handler. This series of commits should up many of these issues.