@@ -202,6 +202,8 @@ static volatile bool dma_write_complete;
202202#define EDMA_BASE (SOC_EDMA30CC_0_REGS)
203203#define DMA_EVENT_QUEUE (0)
204204
205+ static volatile bool rx_interrupts_enabled ;
206+
205207// The highest speed not greater than 3 Mbaud that can be exactly represented
206208// with the AM1808's UART clock divider and a relatively high oversampling rate.
207209// The formula is (CLOCK / (OVERSAMPLING_RATE * DIVISOR)) = BAUDRATE. Here are
@@ -219,23 +221,81 @@ void pbdrv_bluetooth_btstack_ev3_handle_tx_complete(void) {
219221 pbdrv_bluetooth_btstack_run_loop_trigger ();
220222}
221223
222- static void uart_rx_interrupt_handler (void ) {
223- IntSystemStatusClear (UART_RX_INTR );
224+ static inline void uart_rx_interrupt_set_enabled (bool enabled ) {
225+ if (enabled ) {
226+ UARTIntEnable (UART_PORT , UART_INT_RXDATA_CTI | UART_INT_LINE_STAT );
227+ } else {
228+ UARTIntDisable (UART_PORT , UART_INT_RXDATA_CTI | UART_INT_LINE_STAT );
229+ }
230+ rx_interrupts_enabled = enabled ;
231+ }
232+
233+ static inline bool uart_rx_interrupt_is_enabled (void ) {
234+ return rx_interrupts_enabled ;
235+ }
236+
237+ static void uart_rx_drain_fifo_into_ring_buffer (void ) {
224238 int c ;
225- while ((c = UARTCharGetNonBlocking (UART_PORT )) >= 0 ) {
239+ int avail = lwrb_get_free (& uart_rx_pending_ring_buffer );
240+ while (avail > 0 && (c = UARTCharGetNonBlocking (UART_PORT )) >= 0 ) {
226241 lwrb_write (& uart_rx_pending_ring_buffer , (uint8_t * )& c , 1 );
242+ avail -- ;
243+ }
244+ }
245+
246+ static void uart_rx_interrupt_handler (void ) {
247+ IntSystemStatusClear (UART_RX_INTR );
248+ uart_rx_drain_fifo_into_ring_buffer ();
249+ if (lwrb_get_free (& uart_rx_pending_ring_buffer ) == 0 ) {
250+ // RX buffer full, disable further RX interrupts until btstack consumes
251+ // some of the data.
252+ uart_rx_interrupt_set_enabled (false);
253+ pbdrv_bluetooth_btstack_run_loop_trigger ();
254+ return ;
227255 }
228256 if (read_buf && (size_t )read_buf_len <= lwrb_get_full (& uart_rx_pending_ring_buffer )) {
229257 pbdrv_bluetooth_btstack_run_loop_trigger ();
230258 }
231259}
232260
233261static void pbdrv_bluetooth_btstack_classic_drive_read () {
234- if (!read_buf || read_buf_len <= 0 || lwrb_get_full (& uart_rx_pending_ring_buffer ) < (size_t )read_buf_len ) {
262+ if (!read_buf || read_buf_len <= 0 ) {
263+ return ;
264+ }
265+
266+ int nread = lwrb_read (& uart_rx_pending_ring_buffer , read_buf , read_buf_len );
267+ read_buf += nread ;
268+ read_buf_len -= nread ;
269+
270+ // If UART RX interrupts are disabled (because we previously filled up
271+ // our ring buffer), see if we can re-enable them. We must first drain the
272+ // FIFO because the interrupt will not trigger if the FIFO is already full
273+ // above the trigger level.
274+ if (!uart_rx_interrupt_is_enabled ()) {
275+ // Drain as much of the FIFO as we can directly into the read buffer.
276+ int c ;
277+ while (read_buf_len > 0 && (c = UARTCharGetNonBlocking (UART_PORT )) >= 0 ) {
278+ * read_buf ++ = (uint8_t )c ;
279+ read_buf_len -- ;
280+ }
281+
282+ // Drain the rest into the ring buffer.
283+ uart_rx_drain_fifo_into_ring_buffer ();
284+
285+ // If there's any space available in the ring buffer, re-enable RX
286+ // interrupts. Note that if there's not space available, that
287+ // necessarily means that the current message has been completely read
288+ // and we will arrive back here when the next btstack message request
289+ // comes in.
290+ if (lwrb_get_free (& uart_rx_pending_ring_buffer ) > 0 ) {
291+ uart_rx_interrupt_set_enabled (true);
292+ }
293+ }
294+
295+ if (read_buf_len > 0 ) {
235296 return ;
236297 }
237298
238- lwrb_read (& uart_rx_pending_ring_buffer , read_buf , read_buf_len );
239299 read_buf = NULL ;
240300 read_buf_len = 0 ;
241301 if (block_received ) {
@@ -320,7 +380,7 @@ static int pbdrv_bluetooth_btstack_ev3_open(void) {
320380 IntRegister (UART_RX_INTR , uart_rx_interrupt_handler );
321381 IntChannelSet (UART_RX_INTR , 2 );
322382 IntSystemEnable (UART_RX_INTR );
323- UARTIntEnable ( UART_PORT , UART_INT_RXDATA_CTI | UART_INT_LINE_STAT );
383+ uart_rx_interrupt_set_enabled (true );
324384
325385 btstack_run_loop_set_data_source_handler (& pbdrv_bluetooth_btstack_classic_poll_data_source , pbdrv_bluetooth_btstack_classic_poll );
326386 btstack_run_loop_enable_data_source_callbacks (& pbdrv_bluetooth_btstack_classic_poll_data_source , DATA_SOURCE_CALLBACK_POLL );
@@ -334,7 +394,7 @@ static int pbdrv_bluetooth_btstack_ev3_close(void) {
334394
335395 UARTDMADisable (UART_PORT , (UART_RX_INTR_TRIG_LEVEL | UART_FIFO_MODE ));
336396 EDMA3FreeChannel (EDMA_BASE , EDMA3_CHANNEL_TYPE_DMA , DMA_CHA_TX , EDMA3_TRIG_MODE_EVENT , DMA_CHA_TX , DMA_EVENT_QUEUE );
337- UARTIntDisable ( UART_PORT , UART_INT_RXDATA_CTI | UART_INT_LINE_STAT );
397+ uart_rx_interrupt_set_enabled (false );
338398 UARTDisable (UART_PORT );
339399
340400 lwrb_free (& uart_rx_pending_ring_buffer );
0 commit comments