sparkfun / Arduino_Apollo3

Arduino core to support the Apollo3 microcontroller from Ambiq Micro
83 stars 37 forks source link

Is SD card functionality supported? #9

Closed idea--list closed 5 years ago

idea--list commented 5 years ago

I am considering this platform for my next project. Just wonder if SD card functionality is already supported or will that be in the close future?

oclyke commented 5 years ago

Hi @idea--list,

SD functionality is definitely possible, however it is not yet implemented. There will be a few possibilities to do so:

  1. Use a HW interface -- Apollo3 has a 'secure card' interface built-in however I am not familiar with what that is. Does it relate to 'secure digital?' If so we may develop SW support
  2. If there is no HW support for SD then we can easily implement the SPI version of SD interface using the IOMaster functionality
  3. Finally at the highest level of abstraction we may also use SD SW support that relies on the Arduino "SPI.h" interface. This option may be possible to get working in the shortest amount of time because the fundamentals of "SPI.h" are already imemented.

Thanks for asking!

nseidle commented 5 years ago

What a wonderful handle idea--list!

SD is supported via SPI and the Arduino standard SD libs (Bill Greiman's last time I checked). But please keep the ideas coming. Doing an encrypted flash example is a fascinating idea that I'd like to see.

oclyke commented 5 years ago

@idea--list Here's some more information: https://forum.sparkfun.com/viewtopic.php?f=164&t=50250

Most important to note is that there is currently a bug in the SPI library. We will fix it soon but have other priorities first. In the meantime you can manually fix "SPI.transfer(byte)" by adding a return statement "return 0;" to the end of the function. Somehow this was not caught by the compiler.

idea--list commented 5 years ago

My project is currently based on the MAX32630FTHR board that also has an SD-card slot. I am logging data at about 500Hz sampling rate that yields up to 100MB data per day. Turns out that board has an SPI implementation that impacts the transfer rate quite much (~70 KB/sec), thus data transfer takes hours if i connect that board to my PC (USBMSD).

However if i remove the card from the board and put it directly in the pc, i can copy the same amount of data in just some seconds... This is a huge bottleneck in real IoT as we either have ease of use (card does not need to be removed from the IoT device) or great transfer speed but that needs a different HW design as the sd card needs to be removed to copy the data

So i wish you will end up with an SD (and not SPI) implementation ;-)

@oclyke Did some research the datasheet of the Apollo3 MCU mentions "Secure Card IO" on page 405, so the chip supports SD-mode that is much faster then via SPI. Also found the specification of the SDIO-mode that can be downloaded here: https://www.sdcard.org/downloads/pls/pdf/index.php?p=PartE1_SDIO_Simplified_Specification_Ver3.00.jpg&f=PartE1_SDIO_Simplified_Specification_Ver3.00.pdf&e=EN_SSE1

oclyke commented 5 years ago

@idea--list,

An SD mode would be really cool but I don't think that the Apollo3 has SD support. I was originally hopeful about the 'Secure Card' features but I do not think it is related to SD. (See ISO 7816 info below). I just finished some pressing bootloader development and so I will shortly get to testing the SD library. I'll keep you updated about it.

https://en.wikipedia.org/wiki/ISO/IEC_7816

secure

idea--list commented 5 years ago

@oclyke Thanks for the info. Well even SPI is better than nothing. However Ambiq explicitly mentions "Secure Card IO" in their datasheet. That is how most manufacturers make clear that their product supports the original SD-mode with its benefits over just a plain SPI. I hope also Ambiq knows this difference and they are not using exactly those words just by mistake. image

Turns out that for SPI implementation you need 1 pin less on the card slot than for 1-pin SD-mode (and there is also a 4-pin version of SD-mode that is the fastest). This means you just can not take any sd card slot until you are not absolutely sure what does the MCU support. Otherwise you might choose just a card slot that only supports SPI and later realize that the MCU would have support for SD-mode as well. But by then you already have a ready made HW design and some thousand units... :-) Maybe best idea would be to contact Ambiq from your behalf to clear if SD-mode is an option with this MCU or only SDI-mode is supported.

Meantime i also found opensource code for the SD-mode implementation, let me know if that would help you in any way.

Luckily enough these boards are still in the Spark X phase and if i understood right, you plan release RedBoard series board(s) after the certification. Meaning you can still easily alter HW design if it unlocks much higher speeds.

oclyke commented 5 years ago

@idea--list totally! We are definitely open to improvements. I am genuinely confused about the "Secure Card IO" stuff in the Apollo3 datasheet. I will try to get a more clear idea from Ambiq.

The good news is that whatever Secure Card is the Artemis module should be able to use that peripheral. The only Apollo3 pads not broken out on Artemis are 30 and 46. (Pad 47 has special requirements on start up b/c it is a strapping pin, but it can be used) Pad 46 has SCCRST as a functionality, but that functionality is also exposed on pads 26 and 16. The others (SCCIO and SCCCLK are available on several pads as well.

I would definitely be interested in the open source SD interface. Is that a bit-banging implementation? If so we could probably make it pretty fast with the Apollo3 fast GPIO features. Please share the link!

idea--list commented 5 years ago

@oclyke Here a discussion on Github: https://github.com/ARMmbed/mbed-os/issues/6384 And the code: https://github.com/JojoS62/mbed-os/tree/add-component-sdio-blockdevice/components/storage/blockdevice/COMPONENT_SDIO

The code is well commented, made for mbed-os which is a C++ based platform. Hope it gives some inspiration how to implement it your way. I mean in case the Apollo MCU has native SDIO support.

oclyke commented 5 years ago

@idea--list

We just released v1.0.6 (available through Arduino board manager) which allows the Arduino SD examples to work out of the box. Please give it a try and let us know if there are any more issues!

Thanks for taking the time to help us improve the Apollo3 core.

justiceamoh commented 4 years ago

Hi @oclyke, I'm having issues trying to interface with microSD using the Artemis Nano. I am using the Sparkfun microSD breakout board.

I've read in this issue and on the Sparkfun forum post that SD support is now built-in but the Arduino SD examples don't work for me. With a logic analyzer, I see communications on the SCK, MOSI and occasionally on the MISO pins. But the Arduino examples all fail to initialize the SD. It won't get pass the lines:

  while(!SD.begin(9)) {
    Serial.println("initialization failed!");
    delay(100);
  }

For hookup, I have:

microSD Artemis Nano
SCK SCK (Pin 11)
DI MOSI (Pin 12)
DO MISO (Pin 13)
CS Pin 9
VCC 3V3
GND GND

I am inferring from forum posts that CS/SS is not necessary with the Apollo3, right? Is there something I'm missing?

nseidle commented 4 years ago

Works for me: RedBoard ATP + microSD + SparkFun X 1GB card. I used the built-in SD CardInfo sketch.

The CS is needed to make SD work with SPI.

image

I'll see if I can replicate on a Nano...

nseidle commented 4 years ago

Works fine for me on Nano with CS on pin 9. I was originally worried that pin 9 was also used as TX1. Serial1 is configured at power up and TX/RX are set as UART. But when card.init(SPI_HALF_SPEED, chipSelect) is called I believe it re-inits the TX pin as GPIO 9.

You should be good. Let me know if you're still having issues. Consider opening a new issue so we can keep the threads clean.

justiceamoh commented 4 years ago

Thanks @nseidle ! I got it working with another SD holder from an old board -- and you're right, CS is required. I probably damaged the microSD breakout board. Thanks for your help and the rapid response!

nseidle commented 4 years ago

NP! Sorry to hear the breakout board was an issue. Feel free to pin our tech support group and get a replacement if needed.

Gyoorey commented 4 years ago

Is there SD Card support for the Apollo3 MCU? I'm trying to connect the FatFs library with the AmbiqSDK. Is there a good way to do this? Thanks.

nseidle commented 4 years ago

We've had great success using SdFat and SdFat-Beta from Bill Greiman with the Apollo3. I've only implemented it on the Arduino side tho, not through bare metal SDK.

Gyoorey commented 4 years ago

Yeah, I've seen it and tested it, works great. But I need to use the SDK. Do you guys have any idea how can I start implementing this? I need SD card support, SPI is OK too. I've seen HAL methods like am_hal_scard... . Could you figure out whether they are related to SD cards? Thanks.

justiceamoh commented 4 years ago

@Gyoorey, I actually looked into the am_hal_scard and it turns out it is a Smartcard interface (ISO7618) and NOT an SD card interface. The Ambiq folks clarified this here.

Your best shot will be to pull out the SPI interface from Sparkfun's Arduino core, which should then work with the SdFat library from Bill Greiman. It's on my list of things to do but won't get to it until a few weeks.

oclyke commented 4 years ago

@justiceamoh Thanks a bunch for that link... sadly it is not working for me. A clear explanation of this is just what I was searching for. Looking at the source code for the am_hal_scard stuff was not ringing any bells at all for SD cards (which I was fairly comfortable with once upon a time). I was pretty sure I had found concrete evidence once upon a time that this was related to something like ID badges, access cards, and the likes.

@Gyoorey Justice's advice is exactly what I would have said. All our Arduino support is just built on top of the SPI support in the SDK. You could (should) use Bill's library to handle the logic of dealing with SD cards. That way you only need to implement a handful of simple functions (e.g. "send X bytes over SPI" etc...)

justiceamoh commented 4 years ago

@oclyke oh my bad, I didn't realize it was just tied to my account. I asked about it via an info request and got a response. See image below:

ap3_scard

And you're right, Smartcard is for ID badges and access cards.

Gyoorey commented 4 years ago

@justiceamoh Thanks. My problem with the SdFat library is that it depends on the Arduino functions. The other thing is that FatFs needs C99 while SdFat is written in C++. I'd like to use only C in my project. We're building this and I don't feel confident about using a third-party C++ library here. We have a positive experience with the FatFs library, but with the STM MCUs... I'll try to implement the glue functions for FatFs and will let you know if I can make progress.

Gyoorey commented 4 years ago

I've finished the first version of the SD card SPI driver that works in the AmbiqSDK. Note: it is working in the newest SDK (2.4.2) as well, while SDFat won't work directly as the current SDK is missing several functions that have been removed from the older SDK version available in Arduino. It should work on any SFE Artemis boards as it relies on the .bsp files. I only have an ATP board, so testing was limited. Full speed block write speed is above 2MB/s. Just place this example in boards_sfe/common/examples. SD_card.zip

justiceamoh commented 4 years ago

That sounds great @Gyoorey! I actually started adapting SDFat beta library but hit some roadblocks. Thanks for sharing your implementation. I will check it out yours and let you know it goes. I pretty much have all the Sparkfun Artemis boards plus my own custom Artemis board so I can test on them all.

justiceamoh commented 4 years ago

@Gyoorey, so I have been trying to spin up your FatFs example on a custom Artemis board but running into issues. I get an error when I try to mount the filesystem. From this line: fr= f_mount(&fs,"",1); I can tell from the debugger that fr is returning FR_DISK_ERR.

The only difference I can perceive from your setup is that I'm using a different pin for CS, pin 39. And I adjust for that in the function _initialize_pins from SD_SPI.c where I directly configure the pin:

uint32_t _initialize_pins(uint8_t iom_instance) {
    am_bsp_iom_pins_enable(iom_instance, AM_HAL_IOM_SPI_MODE);
    am_hal_gpio_pinconfig(39,g_AM_HAL_GPIO_OUTPUT);
    cs_pin = 39;
    return 0;
}

I've tried more elaborate configurations of the pin also (similar to what you have) but no luck. In Arduino/SdFat setup, I am able to use pin 39 as CS successfully so I know the pin is capable. I've been digging into it but was wondering if you had any idea what could be the issue?

Gyoorey commented 4 years ago

@justiceamoh Unfortunately you cannot use pin 39 as a chip select line. It is a more restricted pin and can only serve as the clock line for IO Module 4. My implementation does not control the CS line manually but relies on the built-in IO Module capabilities, which include CS pin handling. Probably, the Arduino implementation is different and uses CS pin as a regular output pin. Meanwhile, I've found in long-term experiments that writing is not consistent enough so I'm still working on this. I will think about adding the flexible CS pin handling.

justiceamoh commented 4 years ago

Thanks for getting back @Gyoorey! Ah I see. And thanks for pointing out that the implementation relies on IOM to handle CS pin -- I thought you were manually driving CS. I know that pin 39 has no NCE functionality and can't be configured as an IOM CS. It is strange though that it is able to SD_init() successfully with CS as 39. I will look into manually handling CS in FatFs.

And thanks for mentioning the writing inconsistencies. I will keep an eye out for that. Thanks.

Gyoorey commented 4 years ago

Yeah, I was very inconsistent about the CS handling. I got some parts of the SD driver from somewhere else and manual CS sets/resets remained in the code. It is easy to add CS set and CS reset at the beginning/end of each SD_... functions. I'll do that. Meanwhile, today I've realized that the writing problem comes from the problem that when tranfer receive happening, the MOSI line goes down to low. The practice is to send 0xFF to the card and read the response. But this cannot be done simultaniously as full_duplex transfer has been removed from the latest SDK. Sometimes, when I check if card is busy, it responds with an IllegalCommand response, because of the full zero bytes on MOSI. This is a serious problem and the card's response is not consistent.

oclyke commented 4 years ago

@Gyoorey is your development work targeted for Arduino or for the pure AmbiqSuite SDK? I ask because you said:

The practice is to send 0xFF to the card and read the response. But this cannot be done simultaniously as full_duplex transfer has been removed from the latest SDK

This is true - however I have manually patched that capability back in. It is possible to perform (blocking) full duplex SPI transfers using both the Arduino environment as well as this patched branch of our SDK mirror.

Gyoorey commented 4 years ago

@oclyke Thanks, Ambiq suggested me to do that. However, I couldn't get/find information about the reason of removal. Did you just copy-pasted the code from the older SDK or investigated it more deeply so it is somewhat safe to use?

justiceamoh commented 4 years ago

I was actually going to mention your patch, @oclyke! I discovered it when I was working on a port of the Arduino SPI library. Thanks for that! I'm also curious as to why Ambiq removed that.

@Gyoorey, thanks for explaining the CS handling issues. I've been digging into the FatFs library myself -- your implementation is super lightweight so made it very easy for me to tweak. I'll keep at it.

Btw, @oclyke, let us know if we're polluting this thread. Can certainly open another issue to track work on the FatFs.

Gyoorey commented 4 years ago

I've patched the mentioned functionality back to the 2.4.2. SDK. In my case, using the normal blocking transfers and the full_duplexfunction one after the other causes "timeout" problems (it is returned from the transfer functions). Not immediately, but after some successful transfers. Do you guys have ideas about this error? There must a difference that makes these functions incompatible. I changed the driver to use only the full_duplextransfer and at first glance, it works great. I need to test it further, but with a logic analyzer, I can see that the previous problem is solved.

justiceamoh commented 4 years ago

@Gyoorey, I've not run into that error. Perhaps @oclyke can speak to it.

On another note, I just tried to run your FatFs example on an Artemis ATP, using pin 11/A11 as CS. It should be the same setup as yours, with no edits to the sources. Yet, I still had the error with mounting. Here's the Uart output:

SPI init...
SPI Ready!
SD Card SPI mode init...
SD Card Ready!
Mounting the filesystem...

Error mounting file system
mounting: 1

I wonder what the discrepancy is. I am using AmbiqSDK 2.4.2. Do you have any ideas on things I can investigate? Or can you share your most recent FatFs implementation?

Gyoorey commented 4 years ago

Do you have an SDHC card? You can try formating it with FAT32, giving it a name "" (nothing). That's what I have. You can also try to uncomment the mkfs part of the main. It should format the card. If these do not help, maybe that card is more sensitive to the faulty status checks I mentioned earlier. Let me test the new, full duplex version for couple of days and I will share it if works.

oclyke commented 4 years ago

Huh - I have not experienced that particular issue myself. Sounds frustrating. As for what I did when patching that code I did copy/paste the functionality from the previous SDK releases, I did perform some minimal testing (mostly basic Arduino test cases like sending and receiving the same data by jumping MOSI/MISO - nothing that would have uncovered your bug), and I did speak with Ambiq about it a little bit. What they said was that they removed it because they cannot support it in a non-blocking manner. They said that only one direction could be DMA controlled at a time so the other way needed to be interrupt or polling driven. Why exactly that prompted them to remove the functionality is beyond me... I'd prefer to have blocking fullduplex xfers than none at all.

justiceamoh commented 4 years ago

@Gyoorey, yeah I have an SDHC card and I named it "" also. Still no luck. Uncomment the mkfs results in a successful formatting, but mounting still fails. Sure, I'll look forward to testing the duplex version.

Gyoorey commented 4 years ago

@justiceamoh I've been testing it today and seems OK. Please update the SD_driver folder. _Note: The driver needs 1KB RAM for dummy arrays that are utilized during full_duplex xfers._ And one just for you... I've added the manual CS pin handling, so you can experiment with any pin you choose. To do so, you should call spi_cs_pin_set(pin_number); after spi_initialize...() to overwrite the default settings. For example: spi_cs_pin_set(39); SD_driver.zip

justiceamoh commented 4 years ago

Awesome! Thanks @Gyoorey. Let me spin it up right away. I'll let you know how it goes.

justiceamoh commented 4 years ago

@Gyoorey, the revised library works! I've tried different CS pins and they all work as expected. Works on the Redboard ATP and also on my own custom board. Also, I noticed the improved behavior where SD_Init fails if the wiring is off. Facilitates debugging. Thanks so much for working on this and for sharing.

oclyke commented 4 years ago

I second that - thanks a ton for sharing @Gyoorey!

Gyoorey commented 4 years ago

Happy to hear that it works. I'll make this development public on Github so future versions will be available there. Refactoring is needed and maybe a card detect line would be nice to have. Currently I'm planning to run long-term experiments to see if any problem comes up. Thank you guys for the cooperation.

justiceamoh commented 4 years ago

That is a great idea! Kindly share the repo here when you have it up. I may be able to contribute and help with testing. Thanks.

idea--list commented 3 years ago

Hi there, On my Artemis Thing Plus i just could not succeed with Mbed OS V6.3 SD related APIs. But i know one can also mix Ambiq SDK code within Mbed by commenting out this line: am_bsp_low_power_init(); So i was tempted to try Gyoorey's implementation for the SDK within Mbed to overcome the issue with Mbed's native SD implementation.

First tried it within an Ambiq SDK project. It runs as expected. So @Gyoorey Köszönöm szépen a megosztást! :-) However if i inject the code into an empty Mbed OS V6.3 project i get error messages like:

[Fatal Error] Kernel.h@27,10: 'chrono' file not found
[ERROR] In file included from .\lib\SD_driver\SD_SPI.c:8:

This fades my hopes to quickly find a way that would allow SD functionality on the Artemis boards in Mbed. Do you have any idea how to overcome the above mentioned error?

idea--list commented 3 years ago

So to sum it up:

Arduino would be a wrong choice for me and my project :flushed:

ahsan-kaukab commented 3 years ago

Thanks @Gyoorey for sharing the SDcard fat drivers. It help me a lot and saved my time

ahsan-kaukab commented 3 years ago

Thanks @Gyoorey for sharing the SDcard fat drivers. It help me a lot and saved my time. your drivers are working fine but i am facing issue as follow: When I read data from SD card and store that data in Flash memory ( flash writing is working as required) , SD card do not unmounted ( got stuck in the mount function ). Also when i reset the system the SD card is unable to mount again.

Gyoorey commented 3 years ago

@idea--list Thanks for your suggestions. I don't think that what you mentioned is a bug in the SD driver. It is somewhat the user's task to handle the SD card power supply and communication lines correctly before usage. E.g. I have an SD card power supply reset line. But, if that helps, you can always run the following lines before SPI and SD card init: am_hal_gpio_pinconfig(MISO_PIN, g_AM_HAL_GPIO_OUTPUT_12); am_hal_gpio_pinconfig(MOSI_PIN, g_AM_HAL_GPIO_OUTPUT_12); am_hal_gpio_state_write(MISO_PIN, AM_HAL_GPIO_OUTPUT_SET); am_hal_gpio_state_write(MOSI_PIN, AM_HAL_GPIO_OUTPUT_SET); am_util_delay_ms(10); am_hal_gpio_state_write(MISO_PIN, AM_HAL_GPIO_OUTPUT_CLEAR); am_hal_gpio_state_write(MOSI_PIN, AM_HAL_GPIO_OUTPUT_CLEAR); am_util_delay_ms(10); am_hal_gpio_state_write(MISO_PIN, AM_HAL_GPIO_OUTPUT_SET); am_hal_gpio_state_write(MOSI_PIN, AM_HAL_GPIO_OUTPUT_SET); am_util_delay_ms(10); am_hal_gpio_pinconfig(MISO_PIN, g_AM_HAL_GPIO_DISABLE); am_hal_gpio_pinconfig(MOSI_PIN g_AM_HAL_GPIO_DISABLE);

@ahsankaukab3 this might help you as well.

ahsan-kaukab commented 3 years ago

Thanks for responding @Gyoorey but unfortunately the problem is still there. FATFS reading and Flash writing is working fine on individual level but when i read data from SD card and write it in flash memory it work at first time but after i reset the system SD card can not even mount. ( Applying power cycle did not even solved the issue ) I guess the issue is with the cache memory ?