I am using SPIM4 with easyDMA in list mode to read a set of registers from an SPI device, and everything seemed to work great until I attempted to use the double buffered TXD and RXD registers. Am I missing something, or is the double buffered functionality limited when easyDMA is used in list mode?
Code examples and results are listed below. The working example does not rely on the TXD and RXD registers being double buffered, but the broken example does.
Working Example
In the example below I do not rely on the SPIM registers to be double buffered, and the result is in line with what I would expect.
- Paint the receive buffer with 0xAA
- Log the painted receive buffer
- Prepare SPIM for 9 transactions of 7 bytes using list mode and a counter
- Enable external data ready trigger
- Clear (old) counter compare event
- Wait for new counter compare event
- Log filled receive buffer
| Test code | Result |
memset(result, 0xAA, RET_LEN * num_regs); LOG_HEXDUMP_INF(result, RET_LEN*num_regs, "Flushed rx buff"); // Wait for first transaction to start spim->TXD.PTR = (uint32_t)read_cmd_buff; spim->RXD.PTR = (uint32_t)result; nrfx_dppi_group_enable(drdy_event_group); NRF_TIMER0->EVENTS_COMPARE[0] = 0; while(!(NRF_TIMER0->EVENTS_COMPARE[0])); LOG_HEXDUMP_INF(result, RET_LEN*num_regs, "Filled rx buff"); |
Running burst test
Burst test finished
[00:01:13.967,193] <inf> ADE7953: Flushed rx buff
aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa |........ ........
aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa |........ ........
aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa |........ ........
aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa |........ .......
[00:01:13.967,498] <inf> ADE7953: Filled rx buff
ff ff fe 00 0c c6 6b ff ff ff ff f7 6f fd ff ff |......k. ....o...
fe 00 27 15 2f ff ff fe 00 28 7a 9f ff ff fe 00 |..'./... .(z.....
04 5e e9 ff ff ff ff fb a2 56 ff ff fe 00 06 2e |.^...... .V......
07 ff ff ff a5 78 a5 78 ff ff ff fd d0 fd d0 |.....x.x ....... |
Broken example
When I modify the code to prime for the next transaction after the first has started it seems like the last transaction is lost:
| Test code | Result |
// Paint receive buffer with 0xAA
memset(result, 0xAA, RET_LEN * num_regs);
LOG_HEXDUMP_INF(result, RET_LEN*num_regs, "Flushed rx buff");
// Prepare transaction
spim->TXD.PTR = (uint32_t)read_cmd_buff;
spim->RXD.PTR = (uint32_t)result;
spim->EVENTS_STARTED = 0;
nrfx_dppi_group_enable(drdy_event_group);
// Wait for transaction to start
while(!(spim->EVENTS_STARTED));
// Prime for next transaction
spim->TXD.PTR = (uint32_t)read_cmd_buff;
spim->TXD.MAXCNT = CMD_LEN;
spim->RXD.PTR = (uint32_t)result;
spim->RXD.MAXCNT = RET_LEN;
//nrfx_dppi_group_enable(drdy_event_group); // Not enabeling next ransfer
// Wait for transaction to complete
NRF_TIMER0->EVENTS_COMPARE[0] = 0;
while(!(NRF_TIMER0->EVENTS_COMPARE[0]));
// Log result
LOG_HEXDUMP_INF(result, RET_LEN*num_regs, "Filled rx buff"); |
Running burst test
Burst test finished
[00:06:05.437,072] <inf> ADE7953: Flushed rx buff
aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa |........ ........
aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa |........ ........
aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa |........ ........
aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa |........ .......
[00:06:05.437,255] <inf> ADE7953: Filled rx buff
ff ff ff ff fb fb d5 ff ff fe 00 11 0d 0b ff ff |........ ........
fe 00 27 15 7f ff ff fe 00 28 7a 28 ff ff fe 00 |..'..... .(z(....
04 5e b5 ff ff ff ff fb a2 bf ff ff fe 00 06 2e |.^...... ........
02 ff ff ff a5 7c a5 7c aa aa aa aa aa aa aa |.....|.| ....... |