Browse Source

HAL_ChibiOS: fixed flow control auto-detect without DMA

this fixes automatic flow control detection when we are not using DMA
for TX
mission-4.1.18
Andrew Tridgell 7 years ago
parent
commit
83f38d536e
  1. 48
      libraries/AP_HAL_ChibiOS/UARTDriver.cpp
  2. 1
      libraries/AP_HAL_ChibiOS/UARTDriver.h

48
libraries/AP_HAL_ChibiOS/UARTDriver.cpp

@ -652,6 +652,7 @@ void UARTDriver::write_pending_bytes_DMA(uint32_t n) @@ -652,6 +652,7 @@ void UARTDriver::write_pending_bytes_DMA(uint32_t n)
}
/* TX DMA channel preparation.*/
_total_written += tx_len;
_writebuf.advance(tx_len);
tx_len = _writebuf.peekbytes(tx_bounce_buf, MIN(n, TX_BOUNCE_BUFSIZE));
if (tx_len == 0) {
@ -712,6 +713,7 @@ void UARTDriver::write_pending_bytes_NODMA(uint32_t n) @@ -712,6 +713,7 @@ void UARTDriver::write_pending_bytes_NODMA(uint32_t n)
}
if (ret > 0) {
_last_write_completed_us = AP_HAL::micros();
_total_written += ret;
}
_writebuf.advance(ret);
@ -751,9 +753,27 @@ void UARTDriver::write_pending_bytes(void) @@ -751,9 +753,27 @@ void UARTDriver::write_pending_bytes(void)
if (_first_write_started_us == 0) {
_first_write_started_us = AP_HAL::micros();
}
if (_last_write_completed_us != 0) {
_flow_control = FLOW_CONTROL_ENABLE;
} else if (AP_HAL::micros() - _first_write_started_us > 500*1000UL) {
if (sdef.dma_tx) {
// when we are using DMA we have a reliable indication that a write
// has completed from the DMA completion interrupt
if (_last_write_completed_us != 0) {
_flow_control = FLOW_CONTROL_ENABLE;
return;
}
} else {
// without DMA we need to look at the number of bytes written into the queue versus the
// remaining queue space
uint32_t space = qSpaceI(&((SerialDriver*)sdef.serial)->oqueue);
uint32_t used = SERIAL_BUFFERS_SIZE - space;
// threshold is 8 for the GCS_Common code to unstick SiK radios, which
// sends 6 bytes with flow control disabled
const uint8_t threshold = 8;
if (_total_written > used && _total_written - used > threshold) {
_flow_control = FLOW_CONTROL_ENABLE;
return;
}
}
if (AP_HAL::micros() - _first_write_started_us > 500*1000UL) {
// it doesn't look like hw flow control is working
hal.console->printf("disabling flow control on serial %u\n", sdef.get_index());
set_flow_control(FLOW_CONTROL_DISABLE);
@ -868,8 +888,9 @@ void UARTDriver::set_flow_control(enum flow_control flowcontrol) @@ -868,8 +888,9 @@ void UARTDriver::set_flow_control(enum flow_control flowcontrol)
if (sdef.rts_line == 0 || sdef.is_usb) {
// no hw flow control available
return;
}
}
#if HAL_USE_SERIAL == TRUE
SerialDriver *sd = (SerialDriver*)(sdef.serial);
_flow_control = flowcontrol;
if (!_initialised) {
// not ready yet, we just set variable for when we call begin
@ -883,7 +904,13 @@ void UARTDriver::set_flow_control(enum flow_control flowcontrol) @@ -883,7 +904,13 @@ void UARTDriver::set_flow_control(enum flow_control flowcontrol)
palClearLine(sdef.rts_line);
_rts_is_active = true;
// disable hardware CTS support
((SerialDriver*)(sdef.serial))->usart->CR3 &= ~(USART_CR3_CTSE | USART_CR3_RTSE);
chSysLock();
if ((sd->usart->CR3 & (USART_CR3_CTSE | USART_CR3_RTSE)) != 0) {
sd->usart->CR1 &= ~USART_CR1_UE;
sd->usart->CR3 &= ~(USART_CR3_CTSE | USART_CR3_RTSE);
sd->usart->CR1 |= USART_CR1_UE;
}
chSysUnlock();
break;
case FLOW_CONTROL_AUTO:
@ -899,8 +926,15 @@ void UARTDriver::set_flow_control(enum flow_control flowcontrol) @@ -899,8 +926,15 @@ void UARTDriver::set_flow_control(enum flow_control flowcontrol)
palClearLine(sdef.rts_line);
_rts_is_active = true;
// enable hardware CTS support, disable RTS support as we do that in software
((SerialDriver*)(sdef.serial))->usart->CR3 |= USART_CR3_CTSE;
((SerialDriver*)(sdef.serial))->usart->CR3 &= ~USART_CR3_RTSE;
chSysLock();
if ((sd->usart->CR3 & (USART_CR3_CTSE | USART_CR3_RTSE)) != USART_CR3_CTSE) {
// CTSE and RTSE can only be written when uart is disabled
sd->usart->CR1 &= ~USART_CR1_UE;
sd->usart->CR3 |= USART_CR3_CTSE;
sd->usart->CR3 &= ~USART_CR3_RTSE;
sd->usart->CR1 |= USART_CR1_UE;
}
chSysUnlock();
break;
}
#endif // HAL_USE_SERIAL

1
libraries/AP_HAL_ChibiOS/UARTDriver.h

@ -154,6 +154,7 @@ private: @@ -154,6 +154,7 @@ private:
bool _rts_is_active;
uint32_t _last_write_completed_us;
uint32_t _first_write_started_us;
uint32_t _total_written;
// set to true for unbuffered writes (low latency writes)
bool unbuffered_writes;

Loading…
Cancel
Save