99
1010#include < cmath>
1111
12-
13-
1412namespace xbot ::driver::gps {
1513
1614GpsDriver::GpsDriver () {
@@ -19,54 +17,49 @@ GpsDriver::GpsDriver() {
1917bool GpsDriver::StartDriver (UARTDriver *uart, uint32_t baudrate) {
2018 chDbgAssert (stopped_, " don't start the driver twice" );
2119 chDbgAssert (uart != nullptr , " need to provide a driver" );
22- if (!stopped_) {
20+ if (!stopped_) {
2321 return false ;
2422 }
2523 this ->uart_ = uart;
2624 uart_config_.speed = baudrate;
2725 uart_config_.context = this ;
2826 bool uartStarted = uartStart (uart, &uart_config_) == MSG_OK;
29- if (!uartStarted) {
27+ if (!uartStarted) {
3028 return false ;
3129 }
3230
33-
34- uart_config_.rxchar_cb = [](UARTDriver* uartp, uint16_t c) {
35- (void )uartp;
36- (void )c;
37- static int missing_bytes=0 ;
38- missing_bytes++;
39- };
40-
41- uart_config_.rxend_cb = [](UARTDriver* uartp) {
31+ uart_config_.rxend_cb = [](UARTDriver *uartp) {
4232 (void )uartp;
4333 static int i = 0 ;
4434 i++;
45- GpsDriver* instance = reinterpret_cast <const UARTConfigEx*>(uartp->config )->context ;
46- if (!instance->processing_done_ ) {
35+ GpsDriver * instance = reinterpret_cast <const UARTConfigEx *>(uartp->config )->context ;
36+ if (!instance->processing_done_ ) {
4737 // This is bad, processing is too slow to keep up with updates!
4838 // We just read into the same buffer again
49- uint8_t * next_recv_buffer = (instance->processing_buffer_ == instance->recv_buffer1_ ) ? instance->recv_buffer2_ : instance->recv_buffer1_ ;
39+ uint8_t *next_recv_buffer =
40+ (instance->processing_buffer_ == instance->recv_buffer1_ ) ? instance->recv_buffer2_ : instance->recv_buffer1_ ;
5041 uartStartReceiveI (uartp, RECV_BUFFER_SIZE, next_recv_buffer);
5142 } else {
5243 // Swap buffers and read into the next one
5344 // Get the pointer to the receiving buffer (it's not the processing buffer)
54- uint8_t * next_recv_buffer = instance->processing_buffer_ ;
45+ uint8_t * next_recv_buffer = instance->processing_buffer_ ;
5546 uartStartReceiveI (uartp, RECV_BUFFER_SIZE, next_recv_buffer);
56- instance->processing_buffer_ = (instance->processing_buffer_ == instance->recv_buffer1_ ) ? instance->recv_buffer2_ : instance->recv_buffer1_ ;
47+ instance->processing_buffer_ =
48+ (instance->processing_buffer_ == instance->recv_buffer1_ ) ? instance->recv_buffer2_ : instance->recv_buffer1_ ;
5749 instance->processing_buffer_len_ = RECV_BUFFER_SIZE;
5850 instance->processing_done_ = false ;
5951 // Signal the processing thread
60- if (instance->processing_thread_ ) {
52+ if (instance->processing_thread_ ) {
6153 chEvtSignalI (instance->processing_thread_ , 1 );
6254 }
6355 }
6456 };
6557
66-
67-
6858 stopped_ = false ;
6959 processing_thread_ = chThdCreateStatic (&thd_wa_, sizeof (thd_wa_), NORMALPRIO, threadHelper, this );
60+ #ifdef USE_SEGGER_SYSTEMVIEW
61+ processing_thread_->name = " GpsDriver" ;
62+ #endif
7063
7164 uartStartReceive (uart, RECV_BUFFER_SIZE, recv_buffer1_);
7265 return true ;
@@ -75,8 +68,7 @@ bool GpsDriver::StartDriver(UARTDriver *uart, uint32_t baudrate) {
7568void GpsDriver::SetStateCallback (const GpsDriver::StateCallback &function) {
7669 state_callback_ = function;
7770}
78- void GpsDriver::SetDatum (double datum_lat, double datum_long,
79- double datum_height) {
71+ void GpsDriver::SetDatum (double datum_lat, double datum_long, double datum_height) {
8072 datum_lat_ = datum_lat;
8173 datum_long_ = datum_long;
8274 datum_u_ = datum_height;
@@ -89,10 +81,39 @@ bool GpsDriver::send_raw(const void *data, size_t size) {
8981}
9082
9183void GpsDriver::threadFunc () {
92- while (!stopped_) {
93- // Wait for data to arrive, process and mark as done
94- chEvtWaitAny (ALL_EVENTS);
95- ProcessBytes (processing_buffer_, processing_buffer_len_);
84+ while (!stopped_) {
85+ // Wait for data to arrive
86+ bool timeout = chEvtWaitAnyTimeout (ALL_EVENTS, TIME_MS2I (RECV_TIMEOUT_MILLIS)) == 0 ;
87+ if (timeout) {
88+ // If timeout, we take the buffer and restart the reception
89+ // Else, the ISR has already prepared the buffer for us
90+ // Lock the core to prevent the RX interrupt from firing
91+ chSysLock ();
92+ // Check, that processing_done_ is still true
93+ // (in case ISR happened between the timeout and now, this will be set to false by ISR)
94+ if (processing_done_) {
95+ // Stop reception and get the partial received length
96+ size_t not_received_len = uartStopReceiveI (uart_);
97+ if (not_received_len != UART_ERR_NOT_ACTIVE) {
98+ // Uart was still receiving, so the buffer length is not complete
99+ processing_buffer_len_ = RECV_BUFFER_SIZE - not_received_len;
100+ } else {
101+ // Uart was not active.
102+ // This should not happen, but could during debug when pausing the chip
103+ // we ignore this buffer, but carry on as usual
104+ processing_buffer_len_ = 0 ;
105+ }
106+ uint8_t *next_recv_buffer = processing_buffer_;
107+ uartStartReceiveI (uart_, RECV_BUFFER_SIZE, next_recv_buffer);
108+ processing_buffer_ = (processing_buffer_ == recv_buffer1_) ? recv_buffer2_ : recv_buffer1_;
109+ processing_done_ = false ;
110+ }
111+ // allow ISR again
112+ chSysUnlock ();
113+ }
114+ if (processing_buffer_len_ > 0 ) {
115+ ProcessBytes (processing_buffer_, processing_buffer_len_);
116+ }
96117 processing_done_ = true ;
97118 }
98119}
@@ -105,4 +126,4 @@ void GpsDriver::threadHelper(void *instance) {
105126void GpsDriver::SendRTCM (const uint8_t *data, size_t size) {
106127 send_raw (data, size);
107128}
108- } // namespace xbot::driver::gps
129+ } // namespace xbot::driver::gps
0 commit comments