Problem with DW1000 Device Driver API interrupt handling

I discovered a problem with dwt_isr() in deca_device.c that people should be aware of.

The scenario is a program that is about to transmit a frame and doesn’t want an interrupt until the response arrives so it uses dwt_setinterrupt() to only enable receive frame interrupts and then calls dwt_starttx() with the DWT_RESPONSE_EXPECTED flag. When a receive interrupt arrives execution passes to dwt_isr(). dwt_isr() reads the SYS_STATUS register to see what interrupts have occurred but it doesn’t apply the SYS_MASK register so as well as invoking the application’s cbRxOk handler it also calls the cbTxDone handler. To make matters worse it calls them in that order so it looks like the receive happened before the transmit when it was actually the other way round.

The specific problem I had was that in the setup as described above my cbRxOk handler was setting up the transmit of the final frame in the 4 frame TWR exchange and I wanted a transmit interrupt to know when the final frame had gone. So the cbRxOk handler set the variables to indicate that the next transmit interrupt would be for the frame about to be sent. But immediately on return from the cbRxOk handler dwt_isr() made that rogue cbTxDone handler call and my code thought the frame had already been sent.

1 Like

Thumbs up for a good description.

Hi cbowley86,

Couple of notes/comments on your post:

Generally when one wants to process particular events from DW, you will set the interrupt mask register and also a callback to be called when such event arises. And then execute that DW function (TX, RX) and wait to process the event.

What you could do is not define TX callback if you are not interested in looking at TX events, and then when you get RX event, and the ISR calls RX callback, you can check the status register, and process also any other events (e.g. TX) if you wish to do so, or clear any other events too. The TX events will be cleared in the dwt_isr anyway, and no calllback called if there is none defined.

In your example, you do a TX, then RX and then TX again. The 1st TX generates an event, which you do not see as you do not have a mask set. Then when RX happens, the dwt_isr also sees the previous TX event. But your application is confused because it assumes this is the next TX event (from the Final). You need to change your RX callback to clear any previous TX events, if you are not interested in them and then get ready for processing TX event from the Final. (Do you set the mask for this?)

Anyway, you have full access to the code, so you can also modify the dwt_isr to a special version which suits your application. The dwt_isr, as provided, is a general example which will suit most applications.