SD card example throwing "Argument exception" on the first line for netduino3

After upgrading my VS libraries to 0.12, upgrading the core, syncing master to 0.12 and rebuilding th netduino3 and loading the DFU, the sd card example won’t work. The first line

var sd = SdCardController.GetDefault();

Crashes with an Argument exception. I thought maybe it was due to the netduino3 using SPI 3 for the SD card, but I changed the code to this

var provider = SdCardProvider.FromId(STM32F4.SpiBus.Spi3);
var sdControllers = SdCardController.GetControllers(provider);
var sd = sdControllers[0];
var drive = FileSystem.Mount(sd);

And the first line of this also crashes with Argument Null exception.

Any ideas as to what is wrong? Thanks in advance.

Well I got farther, by adding the following into the Device.h file:

#define INCLUDE_SD
#define STM32F4_SD_DATA0_PINS { { PIN(C, 8), AF(12) } }
#define STM32F4_SD_DATA1_PINS { { PIN(C, 9), AF(12) } }
#define STM32F4_SD_DATA2_PINS { { PIN(C, 10), AF(12) } }
#define STM32F4_SD_DATA3_PINS { { PIN(C, 11), AF(12) } }
#define STM32F4_SD_CLK_PINS { { PIN(C, 12), AF(12) } }
#define STM32F4_SD_CMD_PINS { { PIN(D, 2), AF(12) } }

Now the second line:

var drive = FileSystem.Mount(sd);

Throws an InvalidOperationException. I noticed that the netduino3 has a P-channel MOSFET controlling the power rail for the pullups to the SD card. I’ve added this code though at the beginning, and still it’s not working.

GpioPin sdOn = GpioController.GetDefault().OpenPin(STM32F4.GpioPin.PB1);
sdOn.SetDriveMode(GpioPinDriveMode.Output);
sdOn.Write(GpioPinValue.Low);

Now I’m out of ideas again. Is there anything else that is needed in device.h? Also, my SD card is FAT32, is that supported? Is there an SD card limit? I’m definitely going to need support for FAT32/16gb cards for the long-term but could work around it now.

This is not documented yet but file system and graphics require previous resources and so they are not part of the core. They are available on or larger commercial SoMs. For makers with smaller devices, we are providing file system wrappers to you can optimally add file system provider. This provider can be the popular tiny file system for example. This is perfect for smaller flash memory devices. You can also implement fat32.

By the way, the SD low level drivers are included. You can simply write and read raw sectors as a quick way to access data.

I’m not sure what you mean by previous resources. What else is required besides the CPU? The STM32F series have SDIO support built in so I’d assume it to just work with the SD card wired to these pins.

How do I get to the Low-Level controller? I see the interface ISdCardLowLevelController implemented, but do not the concrete class for it. Is this something I’d need to implement myself in c++ to expose it?

If all else fails I could just write an SPI-based driver for the card, but that would probably be a bit slower than using the built-in SDIO.

Meant to say precious resources. The idea is that file system eats a lot of resources that would be wasted if the user does not need it.

About SPI divers, we have implanted that as well. We just need to document it.

Do you need fat32 or you simply need a way to store and read data?

It has to be FAT32 as I need to support loading the sd card in the computer to change files. In fact I really want to be able to use the OTG_FS port to be able to directly plug-in the device to the computer and have it act as a mass storage device.

I could definitely build FAT32 on top of SPI; in fact it looks like the netduino3 is actually only wired for SPI on the SD card. But would I be able to build a driver on top of the ISDCardLowLevelController? I’m still trying to figure out where the concrete implementation of that lives, if it even is created yet. Basically, if there was a low-level SDIO provider that I could use like SPI so I could get the 4-bit SDIO speed I could create my own library off SDIO.

STM32 mcu can work in many different way on mem card, e.g. MMC (old and new std), SD, 1 or 4 bit, and polling or Int.
For what I see in native code, the base managed library can do (STM32):

    sdCardProvider.Acquire = &STM32F4_SdCard_Acquire;
    sdCardProvider.Release = &STM32F4_SdCard_Release;
    sdCardProvider.GetControllerCount = &STM32F4_SdCard_GetControllerCount;

    sdCardProvider.WriteSectors = &STM32F4_SdCard_WriteSector;
    sdCardProvider.ReadSectors = &STM32F4_SdCard_ReadSector;
    sdCardProvider.EraseSectors = &STM32F4_SdCard_EraseSector;
    sdCardProvider.IsSectorErased = &STM32F4_SdCard_IsSectorErased;
    sdCardProvider.GetSectorMap = &STM32F4_SdCard_GetSectorMap;

I don’t know if managed library has a file system manager implemented. If you need a filesystem then you need to buy UCM modules, or do it yourself for other boards, for what I understand.
:disappointed_relieved:

1 Like

I’m fine with building a filesystem out of the raw low-level drives. My issue is right now I cannot even find the concrete WriteSectors, ReadSectors, EraseSectors, and GetSectorMap methods. In the namespaces

GHIElectronics.TinyCLR.Devices.SdCard
GHIElectronics.TinyCLR.Devices.SdCard.Provider

I only see the class

SdCardController
SdCardProvider

Neither of these implement the ISdCardLowLevelController, which is the one that has the methods you mention above. So my question is, how do I call those C++ methods from the C# code? Do I need to manually make a binding or is it exposed somewhere else that I cannot find.

Tomorrow I’ll take a look at the native code and I will try to compile my Discovery F746 porting… I will check.
I think we need John or Gus help here…

@John_Brochue is saying the low level is there but it is purposely hidden since you do not typically want users to directly read and write sectors. Accessing them will be documented for sure.

I was afraid of this answer … :smirk:

var controller = SdCardController.GetDefault();
var lowLevel = (ISdCardLowLevelController)controller.Provider;

Not every controller will implement that interface, it’s provider-dependent. The one we provide does. You didn’t see it used because it’s an internal class.

1 Like

Thanks! This should at least get me going to see how feasible building a FAT lookup would be on top of the low-level reader.