Unverified Commit 3a2a7f8c authored by Earle F. Philhower, III's avatar Earle F. Philhower, III Committed by GitHub

Fix hang on Serial overflow, PIOSerial stop bit handling (#401)

When the Serial software FIFOs overeflowed, the IRQ handler would not
read any more data from the hardware FIFOs.  This would cause the
IRQ handler to be continually called as soon as it exited since the
HW FIFOS were not empty.

Now always read every available HW FIFO entry and throw out any that
don't fit in the SW FIFO.

Also fix a too long by half stop bit timing in the PIOSerial receiver.
parent 52a22e51
...@@ -91,7 +91,7 @@ void __not_in_flash_func(SerialPIO::_handleIRQ)() { ...@@ -91,7 +91,7 @@ void __not_in_flash_func(SerialPIO::_handleIRQ)() {
if (_rx == NOPIN) { if (_rx == NOPIN) {
return; return;
} }
while ((!pio_sm_is_rx_fifo_empty(_rxPIO, _rxSM)) && ((_writer + 1) % sizeof(_queue) != _reader)) { while (!pio_sm_is_rx_fifo_empty(_rxPIO, _rxSM)) {
uint32_t decode = _rxPIO->rxf[_rxSM]; uint32_t decode = _rxPIO->rxf[_rxSM];
decode >>= 32 - _rxBits; decode >>= 32 - _rxBits;
uint32_t val = 0; uint32_t val = 0;
...@@ -114,9 +114,13 @@ void __not_in_flash_func(SerialPIO::_handleIRQ)() { ...@@ -114,9 +114,13 @@ void __not_in_flash_func(SerialPIO::_handleIRQ)() {
} }
} }
_queue[_writer] = val & ((1 << _bits) - 1); if ((_writer + 1) % sizeof(_queue) != _reader) {
asm volatile("" ::: "memory"); // Ensure the queue is written before the written count advances _queue[_writer] = val & ((1 << _bits) - 1);
_writer = (_writer + 1) % sizeof(_queue); asm volatile("" ::: "memory"); // Ensure the queue is written before the written count advances
_writer = (_writer + 1) % sizeof(_queue);
} else {
// TODO: Overflow
}
} }
} }
...@@ -195,7 +199,7 @@ void SerialPIO::begin(unsigned long baud, uint16_t config) { ...@@ -195,7 +199,7 @@ void SerialPIO::begin(unsigned long baud, uint16_t config) {
_writer = 0; _writer = 0;
_reader = 0; _reader = 0;
_rxBits = 2 * (_bits + _stop + (_parity != UART_PARITY_NONE ? 1 : 0) + 1); _rxBits = 2 * (_bits + _stop + (_parity != UART_PARITY_NONE ? 1 : 0) + 1) - 1;
_rxPgm = _getRxProgram(_rxBits); _rxPgm = _getRxProgram(_rxBits);
int off; int off;
if (!_rxPgm->prepare(&_rxPIO, &_rxSM, &off)) { if (!_rxPgm->prepare(&_rxPIO, &_rxSM, &off)) {
...@@ -213,6 +217,9 @@ void SerialPIO::begin(unsigned long baud, uint16_t config) { ...@@ -213,6 +217,9 @@ void SerialPIO::begin(unsigned long baud, uint16_t config) {
pio_sm_put_blocking(_rxPIO, _rxSM, clock_get_hz(clk_sys) / (_baud * 2) - 2); pio_sm_put_blocking(_rxPIO, _rxSM, clock_get_hz(clk_sys) / (_baud * 2) - 2);
pio_sm_exec(_rxPIO, _rxSM, pio_encode_pull(false, false)); pio_sm_exec(_rxPIO, _rxSM, pio_encode_pull(false, false));
// Join the TX FIFO to the RX one now that we don't need it
_rxPIO->sm[_rxSM].shiftctrl |= 0x80000000;
// Enable interrupts on rxfifo // Enable interrupts on rxfifo
switch (_rxSM) { switch (_rxSM) {
case 0: pio_set_irq0_source_enabled(_rxPIO, pis_sm0_rx_fifo_not_empty, true); break; case 0: pio_set_irq0_source_enabled(_rxPIO, pis_sm0_rx_fifo_not_empty, true); break;
......
...@@ -248,10 +248,15 @@ void arduino::serialEvent2Run(void) { ...@@ -248,10 +248,15 @@ void arduino::serialEvent2Run(void) {
// IRQ handler, called when FIFO > 1/4 full or when it had held unread data for >32 bit times // IRQ handler, called when FIFO > 1/4 full or when it had held unread data for >32 bit times
void __not_in_flash_func(SerialUART::_handleIRQ)() { void __not_in_flash_func(SerialUART::_handleIRQ)() {
uart_get_hw(_uart)->icr |= UART_UARTICR_RTIC_BITS | UART_UARTICR_RXIC_BITS; uart_get_hw(_uart)->icr |= UART_UARTICR_RTIC_BITS | UART_UARTICR_RXIC_BITS;
while ((uart_is_readable(_uart)) && ((_writer + 1) % sizeof(_queue) != _reader)) { while (uart_is_readable(_uart)) {
_queue[_writer] = uart_getc(_uart); auto val = uart_getc(_uart);
asm volatile("" ::: "memory"); // Ensure the queue is written before the written count advances if ((_writer + 1) % sizeof(_queue) != _reader) {
_writer = (_writer + 1) % sizeof(_queue); _queue[_writer] = val;
asm volatile("" ::: "memory"); // Ensure the queue is written before the written count advances
_writer = (_writer + 1) % sizeof(_queue);
} else {
// TODO: Overflow
}
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment