le: disable DMA interrupt to workaround timer interrupt issues

Under certain circumstances, it is possible for a timer interrupt to
fire while a DMA interrupt is being handled. Regardless of interrupt
priority and subpriority between the DMA and timer interrupt, the timer
interrupt will never be serviced.

The LE sniffing code uses the timer interrupt to poll the CC2400's
FS_LOCK status. If this bug is triggered, the FS_LOCK polling will not
occur and the timer interrupt will not be rescheduled, causing capture
to freeze.

Curiously this only occurs after all DMA channels have been disabled,
and the DMACIntStat register will indicate 0 on all channels. The
interrupt fires 8 microseconds after the previous byte is received, when
the next byte would be available from the radio had the DMA channel not
be disabled. Perhaps it's an issue draining the FIFO?

Regardless, if a timer interrupt fires during a DMA interrupt handler,
it should be serviced either pre-emptively (if higher priority) or after
the DMA interrupt handler finishes (same or lower priority). This may be
a hardware issue with the chip.

Closes #326, although this fix is a kludge
This commit is contained in:
Mike Ryan
2019-11-07 21:33:55 -08:00
parent 53f44b58c0
commit fea9d0fc2d
+5
View File
@@ -352,6 +352,9 @@ void le_DMA_IRQHandler(void) {
uint8_t tmp = (uint8_t)DIO_SSP_DR;
}
// XXX disable DMA interrupt as a workaround
ICER0 = ICER0_ICE_DMA;
// TODO error transition on queue_insert
queue_insert(&packet_queue, current_rxbuf);
@@ -670,6 +673,7 @@ void TIMER1_IRQHandler(void) {
// restart DMA and SSP
le_dma_init();
dio_ssp_start();
ISER0 = ISER0_ISE_DMA;
le_cc2400_strobe_rx();
T1MCR &= ~TMCR_MR2I;
@@ -693,6 +697,7 @@ void TIMER1_IRQHandler(void) {
// restart DMA and SSP
le_dma_init();
dio_ssp_start();
ISER0 = ISER0_ISE_DMA;
le_cc2400_strobe_rx();
} else {