-
Notifications
You must be signed in to change notification settings - Fork 279
⚠️ rework DMA and GPTMR #1194
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
⚠️ rework DMA and GPTMR #1194
Conversation
stnolting
commented
Mar 2, 2025
⚠️ DMA: remove FIRQ-triggered auto-mode; re-arrange control register bist⚠️ GPTMR: remove mode configuration bit; timer now always operate in "continuous" mode (interval timer)
GPTMR is now always in "continuous" mode (interval timer)
make writing CRC data is 1 cycle faster
@stnolting Hmm any reason why the FIRQ trigger mode was removed? I was planning to use it :-) |
That was another completely over-engineered feature... 🙈 The DMA only has one channel, which also only has a single descriptor. Event-driven triggering therefore seems to make little sense. In addition, it does not require much overhead to start the (pre-programmed) DMA from an interrupt-driven service routine.
Can you give us a few details? Perhaps I was too hasty and there are actually real-word applications that would benefit greatly from this. 🤔 |
Indeed the 1 channel limitation is probably the biggest one. However, there still seem to be cases where one channel is already quite usedul.
I guess that's true for most applications. We have some test software where we used FreeRTOS and SPI to read SD Cards and I think the interrupt load was an issue, but I don't have any real numbers to back that claim. A large part of that issue might also be that the SPI SD card protocol is just stupid: You have to poll the busy flag bit-by-bit if I remember correctly, so you can't really do large bulk transfers well
I was thinking of implementing a simple SD card hardware controller. (it's in specification phase and might take some time until it's actually implemented, so don't expect too much). SD cards are usually transferring data in 512 byte sectors, but you can also do reads of consecutive sectors with a single command. As far as I can tell from the SD specifications, traditional controllers have a lot of memory and store a complete block in the controller. I'd like to provide a more lightweight implementation, where only a single 32 bit data register is required. Whenever 32 bit have been read, I'd make them available in a data register and issue an data ready interrupt. Then the controller is paused until the data register has been read. After the register was read, the controller continues transferring more data (as much as previously configured). The idea for DMA would now be to configure it like this:
This way the DMA would copy the whole SD card sector to memory without CPU interaction. Once the DMA finished interrupt triggers, the application can start processing the data and set up new SD card commands. I'm not sure where I've seen this before, but I think it was with ADCs in some microcontrollers: I think there you could configure the DMA to run on conversion done and copy the value to some memory location. Then you can take N samples without CPU interaction and after N samples you could for example average the results. A similar usage pattern would probably work for all bulk large data transfers, e.g. for SPI and UART as well (this would probably make the receive / send FIFOs somewhat obsolete). But I think on SPI and UART you usually don't have such large data transfers, so for that it's more of an artifical use case. |
Right. Most of the time I use the DMA interrupt to configure the next transfer from a software-managed list. This basically implements some kind of channelization. What's more, we now also have a dual-core option. I simply use the second core as a kind of DMA instead of the actual DMA hardware module.
Good point. The legacy SPI protocol is nice if you do not need much data at a high transfer speed. But I agree, an external dedicated SD-mode controller would be more efficient. I think there are some good ones here on GitHub, too.
You could increase the default bus timeout to some 1000 cycles and use the bus interface's ACK signal to halt the DMA/CPU until a new word of SD-card data is actually available. We are using this concept for accessing the CRC module: neorv32/rtl/core/neorv32_crc.vhd Line 82 in e9fe37f
neorv32/rtl/core/neorv32_crc.vhd Line 66 in e9fe37f
Sounds good! Maybe you can use double-buffering - transfer SD card data to one memory block while processing the previous SD data in another memory block. |