I've been able to get the SDFat library working, but not with DMA. Can anyone who has been able to get DMA working with the SDFat library post an example? That would be really helpful!
Has any user created a SD memory shield/library from the Arduino to the Maple?
(149 posts) (39 voices)-
Posted 3 years ago #
-
I don't think that's been done yet. :\
I browsed through these forums and only heard people talking about it.
Posted 3 years ago # -
Sorry for the late posting of the code. I just created a repository in GitHub for the SDFat+DMA Library. I still have not done writing with DMA but it shouldn't be really hard following the same model that I did for the reading. It would be great if someone could do that... I am pretty swamped at this point (otherwise, I guess I will do it eventually).
Also, if you are new to DMA or uncertain as to how to get it working in the Maple I put together a little tutorial that shows the basics for SPI communication. You'll find it here: http://polplaiconesa.com/tutorials/SPI+DMA.html
Finally the repository:
https://github.com/polpla/Maple-SDFat-DMAPosted 3 years ago # -
Thanks for uploading/posting this - I know I'll find it useful! I think the immediate thing I've seen is what feurig reported previously: that the code makes use of magic numbers, but I think this is a carry-over from the original SDFat library more than anything you've done;-)
Other things I noticed so far are that SdCard.h is an empty file: https://github.com/polpla/Maple-SDFat-DMA/blob/master/SdCard.h
My one real question is whether the use of 'SerialUSB.println()' is a good idea for error cases without it being included via an #if since SerialUSB may not always be present, or may be being used for something application-specific, which the error messages may break.*
Also, stylistically there are a few
if (!truncate(0)) return false;
which IMO should be:
if (!truncate(0)) { // Magic number (zero) used to...<insert reason here> return false; }
And similar things.
Edit:
* I know this too is a carry-over from the original code - I'm just wondering if it is worth thinking about now...Posted 3 years ago # -
Sounds great! Do you want to start making the changes? Just commit when you are done :)
Posted 3 years ago # -
Does your improved SDFat version still use single block writes as the original version, which is awful slow ? DMA will not improve the write speed that much, as writing is a lot slower than reading.
Posted 3 years ago # -
@polpla I'll look at making non-functional changes such as the 'if()' formatting. I won't do anything with the error messages unless it's agreed that assuming 'SerialUSB.println()' won't cause application problems is a bad idea!
The question about block writes is a good one. Once I'm back on my PC I'll take a look...
Posted 3 years ago # -
So can we point the library page to the new code or fix the old code or both?
Posted 3 years ago # -
I added DMA to SD writeData() and did some simple SD readBlock() and writeBlock() performance tests with and without DMA at various SPI clock speeds. The table below shows those results. For comparison, the table reports raw unconnected maple SPI speeds with and without DMA. Also included are SPI and SD tests for 16MHz arduino (328p). I was using the Arduino SD/RTC shield with SANS 2GB SD card.
unconnected SPI performance (transfer 1000 bytes) maple spi maple spi/dma SPI clock read/write read/write 1.125MHz .85mbs 1.125mbs 2.25MHz 1.35mbs 2.25mbs 4.5MHz 1.8mbs 4.5mbs 9MHz 2.2mbs 8.9mbs 18MHz 2.2mbs 17.8mbs SD/SPI block (512 bytes) read/write Arduino SD/RTC shield maple spi maple spi/dma SPI clock read write read write 1.125MHz 0.75mbs 0.64mbs 1mbs 0.84mbs 2.25MHz 1.1mbs 0.91mbs 1.86mbs 1.36mbs 4.5MHz 1.4mbs 1.2mbs 3.19mbs 2.0mbs 9MHz 1.6mbs 1.25mbs 5.1mbs 2.6mbs 18MHz 1.6mbs 1.3mbs 7.1mbs 3.06mbs arduino avr328/16MHz SPI SD (with OPTIMIZE_HARDWARE_SPI) SPI clock read/write read write 2MHz 1.57mbs 1.4mbs 1.2mbs 4MHz 2.6 mbs 2.3mbs 1.7mbs 8MHz 3.8mbs 3.4mbs 2.1mbs
I added polpla's DMA code to the mapleSDfat library. For some reason, I couldn't get polpla's library to do SD write's even without DMA (I'm still trying to figure out why). I thought I could use just one DMA channel to do the SD block write's, but I always got write errors, so I used both rx/tx DMA channels, sending the replies to a one-byte sink. (My tests suggest you could use a one-byte ack[] vector in popla's library and remove DMA_MINC_MODE for the ack channel. I don't think you need DMA_CIRC_MODE flag either)
Here is snippet of the DMA code I used to write SD blocks in Sd2Card.cpp
uint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) { spiSend(token); #ifdef DO_DMA_WRITE dma_setup_transfer(DMA1, DMA_CH2, &SPI1->regs->DR, DMA_SIZE_8BITS, mysink, DMA_SIZE_8BITS, ( DMA_TRNS_CMPLT | DMA_TRNS_ERR)); dma_attach_interrupt(DMA1, DMA_CH2, DMAEvent); dma_setup_transfer(DMA1, DMA_CH3, &SPI1->regs->DR, DMA_SIZE_8BITS, (uint8_t *)src, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_FROM_MEM)); dma_set_priority(DMA1, DMA_CH2, DMA_PRIORITY_VERY_HIGH); dma_set_priority(DMA1, DMA_CH3, DMA_PRIORITY_VERY_HIGH); dma_set_num_transfers(DMA1, DMA_CH2, 512); dma_set_num_transfers(DMA1, DMA_CH3, 512); dmaActive = true; dma_enable(DMA1, DMA_CH3); dma_enable(DMA1, DMA_CH2); while(dmaActive) delayMicroseconds(1); dma_disable(DMA1, DMA_CH3); dma_disable(DMA1, DMA_CH2); #else for (uint16_t i = 0; i < 512; i++) { spiSend(src[i]); } #endif spiSend(0xff); // dummy crc ...
Posted 3 years ago # -
Oh my, this is exciting! Thanks, manitou. I'm gonna check it out soon and will post back!
Posted 3 years ago # -
see a more recent post and updated DMA write code at
http://forums.leaflabs.com/topic.php?id=1075&page=2Posted 3 years ago # -
What's the current status of the mapleSDfat library? The current code from google code will not work right out of the box.
A bunch of the changes mentioned in this thread are NOT implemented in that code.
I also tried Pol Pla's SDfat-DMA code from github but I don't have any example code to test with - trying with examples from regular mapleSDfat give me all sorts of compile errors that I don't understand.
I'm a noob with maple and C, so please excuse my ignorance.
-steve
Posted 3 years ago # -
Ok - starting over with the mapleSDfat library, I made the various changes mentioned in this thread and I think it's kinda working now.
I was able to run FileSys.pde and get some info back in serial monitor. But... any of the Ardunio Examples don't compile. "error: 'PSTR' was not declared in this scope"
I'm guessing those Arduino Examples are not ported over to Maple?
Posted 3 years ago # -
# undef PSTR
# define PSTR(x) xPosted 3 years ago #
Reply »
You must log in to post.