Hints about the MMC/SD card library by Roland Riegel

STM32
Wed Mar 29, 2017 8:06 pm
Hy guys.
Thank you very much for this wonderful forum!
I’m a new user here.
I have an Arduino project that I would like to put on the “Blue Pill” STM32.
My goal is use a “Blue Pill” instead of an Arduino in order to run this:
https://github.com/krisztian1997/3dsunbricker
Following this instructions

http://www.stm32duino.com/viewtopic.php … =blue+pill

I added the library and the sketch in my Arduino IDE environment.
with the current release 1.8.1 of the Arduino IDE while compiling I get these error messages:

C:\Users\Ferrario\Documents\Arduino\libraries\sdrawroland\sd_raw_roland.cpp:6:24: fatal error: avr/io.h: No such file or directory

#include <avr/io.h>

By putting a remark sign before the #include <avr/io.h> into sd_raw_roland.cpp then I get these error messages:

…\Arduino\libraries\sdrawroland/sd_raw_config_roland.h:114:6: error: #error “no sd/mmc pin mapping available!”

#error “no sd/mmc pin mapping available!”

By using Arduino IDE 1.6.9 I gt only the latest error messages:

…\Arduino\libraries\sdrawroland/sd_raw_config_roland.h:114:6: error: #error “no sd/mmc pin mapping available!”

#error “no sd/mmc pin mapping available!”

So I choose to use Arduino IDE 1.6.9 for my attempts.
The STM32 environment that I made is fine cause I can compile simple examples, but when I try to compile the 3dsunbricker project it fails.
Maybe the Roland Riegel’s library doesn’t work out of the box with the STM32 or more simply it’s necessary to specify in it the SPI’s pins for the STM32F103C8 board.
Indeed while compiling Arduino IDE 1.6.9 says:

…\Arduino\libraries\sdrawroland/sd_raw_config_roland.h:114:6: error: #error “no sd/mmc pin mapping available!”

#error “no sd/mmc pin mapping available!”

By searching I found that the right pins should be these:

STM32 SD/MMC
PA4 SD_SS
PA5 SD_SCK
PA6 SD_DO (=MISO)
PA7 SD_DI (=MOSI)

I’m pretty sure they are correct because I have retrieved them from here:

http://www.stm32duino.com/viewtopic.php?t=117#p950
http://reblag.dk/wordpress/wp-content/u … iagram.pdf

Anyway something is weird into the diagram due the fact that SPI wires on pins A4, A5, A5 and A7 are for SPI channel 1 exactly like those on pins A15, B3, B4 and B5.
I guess it’s a typo.

But into sd_raw_config_roland.h it’s used a different format for the customisation of SD/MMC port access, something like these:

/* defines for customisation of sd/mmc port access */
#if defined(__AVR_ATmega8__) || \
defined(__AVR_ATmega48__) || \

(lines from 69 onwards into sd_raw_config_roland.h)

I wonder how can I add the right ones for the “Blue Pill”?

Actually I suspect that the matter is more hard to master so in the end the right way could be pretty different.
I need to initialize either SD than MMC and the MMC/SD card library by Roland Riegel is the only I know that natively allows for both kind of card.
On Arduino I tried a modified standard SD library and a modified SdFat libray but sadly I couldn’t make them work with the “Blue Pill”.
However Roland Riegel’s MMC/SD card library is much better of them in this scenario.
Any hint?
Thanks in advance.

STM32


Rick Kimball
Wed Mar 29, 2017 11:27 pm
why bother? I mean why not just buy an arduino atmega clone and just use it.

zoomx
Thu Mar 30, 2017 9:10 am
You can use also an SD adapter for PC and write your backup NAND image using some utilities like Win32DiskImager. You still need to solder.

STM32
Thu Mar 30, 2017 6:55 pm
Hi Rick,
I already own an Arduino, it is a MEGA 2560.
Of course the library and the sketch are functioning but Mega 2560 is too cumbersome for my purposes.
I need something small, something like Nano.
While I was choosing I thought that the “Blue Pill” could be a sensible choice.
Anyway in the end I think that the MMC/SD card library by Roland Riegel could be useful because the SDFat was ported on STM32 but it doesn’t allow for MMC.
For the Mega I changed SD and SdFat in order to support MMC cards, for the STM32 environment I’m not in the position to succeed.
For me another important point is to understand if and how it is possible to use the same syntax

/* defines for customisation of sd/mmc port access */
#if defined(__AVR_ATmega8__) || \
defined(__AVR_ATmega48__) || \

for the STM32 though.
I would like to make a portable device for servicing and repair, that is my goal.

STM32


STM32
Thu Mar 30, 2017 6:56 pm
Hi Zoomx,
soldering isn’t totally a problem for me.
Honestly I don’t understand what do you mean.
Then the whole thing isn’t so simple as you described.
In order to do what you wrote it is need a computer like some laptops which have MMC/SD card reader directly connected to the PCI bus.
I know that lately Ubuntu can do things like that but it needs some piece of hardware that is too cumbersome for my purposes and it isn’t standalone.
The matter is totally different using the “Blue Pill” which is small and standalone.

STM32


victor_pv
Thu Mar 30, 2017 9:46 pm
STM32 wrote:Hi Rick,
I already own an Arduino, it is a MEGA 2560.
Of course the library and the sketch are functioning but Mega 2560 is too cumbersome for my purposes.
I need something small, something like Nano.
While I was choosing I thought that the “Blue Pill” could be a sensible choice.
Anyway in the end I think that the MMC/SD card library by Roland Riegel could be useful because the SDFat was ported on STM32 but it doesn’t allow for MMC.
For the Mega I changed SD and SdFat in order to support MMC cards, for the STM32 environment I’m not in the position to succeed.
For me another important point is to understand if and how it is possible to use the same syntax

/* defines for customisation of sd/mmc port access */
#if defined(__AVR_ATmega8__) || \
defined(__AVR_ATmega48__) || \

for the STM32 though.
I would like to make a portable device for servicing and repair, that is my goal.

STM32


Rick Kimball
Thu Mar 30, 2017 11:20 pm
STM32 wrote:Hi Rick,
I already own an Arduino, it is a MEGA 2560.
Of course the library and the sketch are functioning but Mega 2560 is too cumbersome for my purposes.
I need something small, something like Nano.

stevestrong
Fri Mar 31, 2017 7:32 am
Rick Kimball wrote:My point was the cost of a Nano is like $3. The time it would take to make the code function on the bluepill seems non-trivial. My question is why not just buy a $3 nano and be done with it? If your end goal is to get into using the bluepill, then fine. If your end goal is just to play games then it seems a waste of time porting everything.

zoomx
Fri Mar 31, 2017 9:02 am
STM32 wrote:Hi Zoomx,
soldering isn’t totally a problem for me.
Honestly I don’t understand what do you mean.
Then the whole thing isn’t so simple as you described.
In order to do what you wrote it is need a computer like some laptops which have MMC/SD card reader directly connected to the PCI bus.
I know that lately Ubuntu can do things like that but it needs some piece of hardware that is too cumbersome for my purposes and it isn’t standalone.
The matter is totally different using the “Blue Pill” which is small and standalone.

STM32


STM32
Fri Mar 31, 2017 7:31 pm
Thank you guys, you’re opening up my mind.

@victor_pv

I agree but natively SdFat doesn’t support MMC so I can’t use it.
What I wanted to know was if it was possible to implement on STM32 such a thing, not so much lead that library into STM32.
I mean manage MMC/MMC+/eMMC on the “Blue Pill” as same Arduino can do.
Now I understand it isn’t so easy.
The better chance would be change the SdFat Beta in order to unlock MMC.
I know that works on the Arduino side (I tested it myself on Uno and Mega), so I’ll put more effort on it.
My starting doubt was about the syntax I wrote and if there were such a thing even for STM32.
Since nobody wrote about it I understand it doesn’t exists into the STM32 side.

@Rick

Like already I wrote from my side isn’t a matter of costs but rather to be able to do that thing with different hardware than Arduino, better if new ones aren’t cumbersome.
I wanted to see if there were any known way to manage MMC with the “Blue Pill”.
I thought it would be useful to add that capability.
I know that Arduino can do the job and due STM32 doesn’t (untill now), I have a single way to go.

@stevestrong

+1
Me too now that I’ve got your answers.

@zoomx

I get it now.
Actually mine was just as example, I didn’t intend to replicate the project on the “Blue Pill”, but rather to have a way to natively manage the MMC cards on it.
I shown the sketch in order to make sense at the whole context of the Roland Riegel’s library which is in the position to manage both MMC or SD cards.
Anyway it seems to me that lately Ubuntu can do the job when running on hardware that allows direct connected to PCI bus for the reader.
Raspberry Pi too does it for sure.
In a such scenario it would be enough a simple adapter that allows to bring outside the necessary signals in order to connect them on the device where you want to work.

STM32


stevestrong
Fri Mar 31, 2017 8:02 pm
Let me put it this way:
the job could be done by any of those who commented within an hour (adapt the spi routines and setup)
But then you did not learn anything.
And you are a hardware guy…if you want to learn sw, and really learn to work with “blue pill”, then you should do it yourself, or at least try.
So, if you browse the already ported libraries, then you could see how to deal with #ifdefs, there are even examples how to replace avr ddr registers.
Just show us what did you try, and then we will tell you how to do it right.

zoomx
Fri Mar 31, 2017 8:19 pm
What are the difference in the Arduino library between reading a SD and reading a MMC?

martinayotte
Fri Mar 31, 2017 8:24 pm
STM32 wrote:
I agree but natively SdFat doesn’t support MMC so I can’t use it.

STM32
Fri Mar 31, 2017 9:31 pm
Hi Stevestrong,
I fully agree with you.
But wait a minute, actually I didn’t ask to anybody to do anything.
I only asked about the syntax that I wrote because it is weird at my eyes and by thinking it could be related with the possibility to reach my purpose.
You and other guys have pointed at me your and their opininions so I learn that it is better for me go one other way.
Indeed now I’m trying to change SD and SdFat in order to allows MMC, exactly like I have already did on Arduino long before I discovered the Roland Riegel’s library.
I talked about that sketch I have linked and the Roland Riegel’s library only hoping the thing was easier to run on STM32.
As I wrote I’m an hardware guy, so please excuse me for being so naive on the software side.
Thanks.

STM32


STM32
Fri Mar 31, 2017 9:32 pm
Hi Zoomx,
for the little that I know it should be something related with the initialization of the cards.
Indeed the changes I’m making in the libraries are about the initialization.
I know that it’s a crude way but it works, or at least it worked on Arduino.
Thanks.

STM32


STM32
Fri Mar 31, 2017 9:33 pm
Hi Martinayotte,
I agree about the SdFat library.
The fact is that the device on which I need to do servicing doesn’t allow for SD but only for MMC and MMC+.
Actually it’s enough for me to retrieve CSD, CID and few other register’s content in order to understand if all it is fine, not do some complicated things.
Due to the fact that for my goal I would have still had to adapt or the standard SD library or the SdFat, I wanted to inquire about the Roland Riegel’s library as it natively manages MMC and MMC+ and seemed to me more fit for the purpose.
Thanks.

STM32


victor_pv
Sat Apr 01, 2017 12:07 am
On your question about the #ifdef, the one for our core is
#if defined(__STM32F1__)

stevestrong
Sat Apr 01, 2017 2:22 pm
If I would need to port something, I would start with commenting out parts of the header files which are AVR related.
Then go through the CPP code and replace functionality.

For example:
– comment out line 6 of the cpp file
– add #include “SPI.h”
– replace lines 219-227 by: SPI.beginTransaction(SPISettings(250000, DATA_MODE0, MSB_FIRST));
– and so on.


STM32
Sun Apr 02, 2017 3:53 pm
Hi Victor_pv,
thank you very much for your hint.
I’m not gone, I only need time in order to find the solution.
I tried your suggestion, I have put the Sd Spi STM32F1.cpp inside the same folder of the modified version of the SdFat that I made but the thing doesn’t work:

File included from C:\Arduino\libraries\SdFat/SdFat.h:38:0,

from C:\Arduino\libraries\SdFat\examples\MMC\MMC.ino:4:

C:\Arduino\libraries\SdFat/SdFile.h:44:7: error: conflicting return type specified for ‘virtual int SdFile::write(const char*)’

int write(const char* str);

^

In file included from C:\Arduino\hardware\Arduino_STM32\STM32F1\cores\maple/HardwareSerial.h:38:0,

from C:\Arduino\hardware\Arduino_STM32\STM32F1\cores\maple/wirish.h:69,

from C:\Arduino\hardware\Arduino_STM32\STM32F1\cores\maple/Arduino.h:30,

from sketch\MMC.ino.cpp:1:

C:\Arduino\hardware\Arduino_STM32\STM32F1\cores\maple/Print.h:41:20: error: overriding ‘virtual size_t Print::write(const char*)’

virtual size_t write(const char *str);

^

exit status

My modified version of the SdFat is based on the main version 20131225.
In order to unlock MMC support for the SdFat the changes I made are into the SD2Card.cpp and SdInfo.h.
Basically into SD2Card.cpp I changed the original line 176 from

return 0;

to

return 1;

This disables the error checking while initialization allowing the code to continue despite everything.

Then immediately after the line 259

bool Sd2Card::begin(uint8_t chipSelectPin, uint8_t sckDivisor) {

I added the line 260 as:

bool useCmd1 = false;

This in order to define the command CMD1 that is used to initialize MMC cards.

Then I replaced the original lines from 309 to 315 with these:

while (cardAcmd(ACMD41, arg) != R1_READY_STATE) {
// check for timeout
if (((uint16_t)millis() – t0) > SD_INIT_TIMEOUT) {
error(SD_CARD_ERROR_ACMD41);
goto fail;
}
}

This in order to perform a valid initialization both for SD and MMC cards.

Finally into SdInfo.h I added the definition for CMD1 as line 37 and 38:

/** SEND_OP_COND */
uint8_t const CMD1 = 0x01;

This in order to be able to use the new command.
I made all those changes on the base of something I read somewhere on the net but that I forgot exactly where.
So I don’t remember who is the real author, anyway with Arduino it works although I needed to change the original sketches into the SdFat due to the fact that they were no longer functioning like they are just out of the box.
In attachment are the modified files and a sample sketch for those who might find it useful or other.
Pay attention that it is a very crude code and it only works on Arduino.
Meanwhile I’ll continue the test and I’ll post the solution if I’ll find it.
Thanks.

STM32


STM32
Sun Apr 02, 2017 3:55 pm
Hi Stevestrong,
thanks a lot for the useful hints.
As you and others have made me realize I’m still too newbie to work on the porting so I’ll try in the future.
Actually porting wasn’t in my intention, I had just needed something capable to handle the MMC cards.
Following your indications I’m now working on the SdFat that it could be much easier for me due the fact that in the past I have succeeded with it into Arduino side.
Thanks.

STM32


victor_pv
Sun Apr 02, 2017 5:37 pm
Can you post a link to the version of the sdfat library that you are using?

STM32
Wed Apr 05, 2017 8:37 pm
Hi

@Victor_pv,
as I wrote the SdFat library that I’m using is the version 20131225.
Nowadays I’m not able to retrieve it from the repository, and it is to big to be attached here.
I know it’s very old so I have downloaded the more recent SdFat version 20160719 that I’ll try to modify in order to allow for MMC although this release is pretty different as structure.
I have to take a look at it before I can do the needed changes to allow for the MMC cards, but first I wanted to try the libray with normal SD cards.
As soon as there is something new I’ll post.
Tanks

STM32

Little OT.
Here is started something weird.
I have compiled the example SdInfo sketch without problem, then I have put it on the Blue Pill, but the code doesn’t start as it should.
In fact every time I start the terminal it is empty, there isn’t the text:

SdFat version: 20160719

Assuming the SD is the only SPI device.
Edit DISABLE_CHIP_SELECT to disable another device.

Assuming the SD chip select pin is: 53
Edit SD_CHIP_SELECT to change the SD chip select pin.

type any character to start

not even starting the whole thing with the SD shield not connected.
Into the sketch I have set
SD_CHIP_SELECT = PA4;
and when the SD shield is linked I use

PA5 SD_SCK
PA6 SD_DO (=MISO)
PA7 SD_DI (=MOSI)

I have tried to move data on SPI2 but nothing change, terminal is always empty.
Seems to me that the “Blue Pill” is working because by using other examples, for instance Test_RTClock, then the terminal shows data correctly.
I’m using the Arduino IDE 1.8.1 terminal.


victor_pv
Thu Apr 06, 2017 2:40 am
STM32 wrote:Hi

@Victor_pv,
as I wrote the SdFat library that I’m using is the version 20131225.
Nowadays I’m not able to retrieve it from the repository, and it is to big to be attached here.
I know it’s very old so I have downloaded the more recent SdFat version 20160719 that I’ll try to modify in order to allow for MMC although this release is pretty different as structure.
I have to take a look at it before I can do the needed changes to allow for the MMC cards, but first I wanted to try the libray with normal SD cards.
As soon as there is something new I’ll post.
Tanks

STM32

Little OT.
Here is started something weird.
I have compiled the example SdInfo sketch without problem, then I have put it on the Blue Pill, but the code doesn’t start as it should.
In fact every time I start the terminal it is empty, there isn’t the text:

SdFat version: 20160719

Assuming the SD is the only SPI device.
Edit DISABLE_CHIP_SELECT to disable another device.

Assuming the SD chip select pin is: 53
Edit SD_CHIP_SELECT to change the SD chip select pin.

type any character to start

not even starting the whole thing with the SD shield not connected.
Into the sketch I have set
SD_CHIP_SELECT = PA4;
and when the SD shield is linked I use

PA5 SD_SCK
PA6 SD_DO (=MISO)
PA7 SD_DI (=MOSI)

I have tried to move data on SPI2 but nothing change, terminal is always empty.
Seems to me that the “Blue Pill” is working because by using other examples, for instance Test_RTClock, then the terminal shows data correctly.
I’m using the Arduino IDE 1.8.1 terminal.


STM32
Thu Apr 06, 2017 8:00 pm
Hi Victor_pv,
the SD shield that I’m using with “Blue Pill” consists only by the connector, there isn’t any other hardware, it is 3,3V only.
For Arduino I use a different one which has level converter because my Arduino is one of the 5V series.
The weird thing isn’t that I can access the cards but rather that “Blue Pill” fails to perform the SdInfo sketch, Arduino IDE’s terminal doesn’t show any text.
I have to check data bus with an oscilloscope.
Also by starting the whole thing without any SD shield connected, namely by using the “Blue Pill” alone, nothing appears on the terminal inside the Arduino IDE.
This is the fact.
Anyway I had a look into the library and I saw what I guess I need to change in order to unlock MMC’s support.
During the weekend I’ll try to make some changes and I’ll post the results.
Due the problem I wrote, my current goal is to achieve the right compilation of the sketches with the SdFat modified by me in order to allow also for MMCs.
After that I’ll succeeded I’ll dig the matter about code that doesn’t appears into the Arduino IDE terminal, which is weird since other sample sketches are working fine with “Blue Pill”.
Thanks.

STM32


ag123
Thu Apr 06, 2017 9:26 pm
hi stm32
1st i know hardly anything about the internals of sd cards vs mmc cards
hence i did some google and ran into this site, i’d think it may be a pretty helpful as a starting point for info
http://wiki.seabright.co.nz/wiki/SdCardProtocol.html

it seemed that mmc vs sd are pretty different in terms of the *protocol* (i.e. commands to access the cards internals) even if both use an spi bus.
i’m not sure about this really, the specs are verbose and it’d take 1 to review that perhaps for those ‘low level’ ports
i.e. it may not be that ‘easy’ to sort of patch sdfat into and mmc-fat perhaps, one may end up rewriting large fractions of it (hope not)
perhaps someone more familar with sd vs mmc is in a better position to comment about it

in addition, i do not know anything about the atmega platform (e.g. arduino uno ) as well, there could be subtle differences even with things like spi etc
do check pins etc to see that they after all hooked up correctly to spi etc
http://wiki.stm32duino.com/index.php?title=Blue_Pill

and with these ‘low level’ stuff, it could really help to patch up gdb / openocd etc for debugs, etc, i’m not too sure how too

2 more links
http://elm-chan.org/docs/mmc/mmc_e.html
^^^ this is a good site, there are apparently something common in both mmc and sd, reading this web
http://ralimtek.com/Stm32_SPI_SD/

oh yes, i think there are also various stm32 ‘platform specifics’
e.g. clocking the peripheral bus
http://electronics.stackexchange.com/qu … igital-pot
^^^i think these are catered in the libraries that’s hooked up via stm32_arduino, but i think the notation may be different in the sense of ‘enabling’ it
and things like there are 2 SPI buses on stm32f103cbt6, make sure you have clocked/enabled the right bus and is ‘talking’ to the correct bus
http://www.st.com/en/microcontrollers/stm32f103c8.html


stevestrong
Fri Apr 07, 2017 11:38 am
ag123 wrote:it seemed that mmc vs sd are pretty different in terms of the *protocol* (i.e. commands to access the cards internals) even if both use an spi bus.
i’m not sure about this really, the specs are verbose and it’d take 1 to review that perhaps for those ‘low level’ ports
i.e. it may not be that ‘easy’ to sort of patch sdfat into and mmc-fat perhaps, one may end up rewriting large fractions of it (hope not)
perhaps someone more familar with sd vs mmc is in a better position to comment about it

ag123
Fri Apr 07, 2017 7:27 pm
@stevestrong

i’ve ‘mixed feelings’ about this. i’m not totally against the idea of using a ‘common’ sd / mmc library, i.e. a single library caters to both
as the web from elm-chan pointed out, it’d seem sd and mmc do share common commands
http://elm-chan.org/docs/mmc/mmc_e.html
my guess is that sd-fat is possibly a derivative from elm-chan’s original library hence, it could possibly already have codes that is compatible with both sd and mmc cards

however, i’d think sd vs mmc do diverge when the features that have made their way into the new hardware (e.g. the recent uhs type of sd cards / sdio (non-spi) interface etc is considered)

as to why it may be necessary to separate libraries, an easiest way to think is that after all we only have 20k of ram in stm32f103cb or stm32f103c8 which makes up the maple mini and blue pill and many other stm32f103xx boards (i.e. c-r medium density dev, less those v and z series)
trying to exploit the features specific to sd or mmc would mean running out of ram before anything much can be done

hence i’d think having a *separate* ‘lowest common denominator’ imho may not be a bad thing, just that ‘lowest common denominator’ means throwing out codes (i.e. reducing features to a minimum set, but that could mean breaking compatibility be it sd or mmc) that possible needs to be different between sd vs mmc.

and in addition sd being a lot more common today vs mmc, i’d agree that having them separate is probably a better thing

just 2c


stevestrong
Fri Apr 07, 2017 10:15 pm
My idea was just to port a code which is already proven to run for that application on other target boards.
So am not talking about a general lib which should support both sd and mmc and who knows what else, or some exotic functionality.
I am still convinced that porting the lib to blue pill would be the qickest way to get the sw running, to do what is actually designed for.
But, of corse, when someone has a better overview what is actually running in the background, other approaches would be also feasible.

STM32
Thu Apr 20, 2017 8:03 pm
Hi guys,
I’m still looking for a solution in order to change SdFat library to allow for MMC cards.
Until now I was unable to do the job because recent release is pretty different from the old so the trick I used in the past doesn’t work anymore, honestly not even the same trick with the oldest release 20131225 is working with my “Blue Pill”.
Anyway by surfing the web I found something very similar to the hint I used in the past in order to changes from myself the standard Arduino’s SD library and the SdFat library release 20131225.
As your reference, here it’s:

https://tinyurl.com/kwnnbe4

In the bottom, among some thoughts into >32 thoughts on “Arduino SD Library support for MMC Cards”< is explained how do the trick on SdFat library for Arduino.
I’ll don’t give up but now my problem is on a different side that I already wrote here, my “Blue Pill” doesn’t work as is expected due the fact the terminal it’s empty, there isn’t the output of the sketch.
With a MSO I checked pins output and all it’s 100% fine but no text as output on the Arduino IDE 1.8.1 terminal.
I have tried also with a second “Blue Pill” with the same result.
Seems to me that the two “Blue Pill” I have used are working because by using other examples on them, for instance Test_RTClock, then the terminal shows data correctly.
Both of the “Blue Pill” they have a 1.5kohm pullup resistor on D+ (R10 on the board).
Can someone who has experimented with “Blue Pill” and SD cards confirm that output is working via USB to the terminal?
Eventually can someone provide an example code which can be use for testing or put a link to something like that?
Thanks.

STM32


stevestrong
Thu Apr 20, 2017 8:13 pm
Try a simple blinky sketch with simple serial output in loop, without including SD card header.
Check the 3.3V voltage level, the on-board regulator is week.
It must be your software, and we cannot help if you don´t post it.

STM32
Thu Apr 20, 2017 8:50 pm
Hi Stevestrong,
Thanks.

stevestrong wrote:
Try a simple blinky sketch with simple serial output in loop, without including SD card header.

I did it using Test_RTClock without problem.

stevestrong wrote:
Check the 3.3V voltage level, the on-board regulator is week.

I used an MSO oscilloscope and all seems to be fine.

stevestrong wrote:
It must be your software, and we cannot help if you don´t post it.

My software isn’t mine, simply it’s the SdInfo example provided with SdFat version 20160719.
Here it is:

/*
* This program attempts to initialize an SD card and analyze its structure.
*/
#include <SPI.h>
#include "SdFat.h"
/*
* SD chip select pin. Common values are:
*
* Arduino Ethernet shield, pin 4.
* SparkFun SD shield, pin 8.
* Adafruit SD shields and modules, pin 10.
* Default SD chip select is the SPI SS pin.
*/
const uint8_t SD_CHIP_SELECT = PA4;
/*
* Set DISABLE_CHIP_SELECT to disable a second SPI device.
* For example, with the Ethernet shield, set DISABLE_CHIP_SELECT
* to 10 to disable the Ethernet controller.
*/
const int8_t DISABLE_CHIP_SELECT = -1;
SdFat sd;

// serial output steam
ArduinoOutStream cout(Serial);

// global for card size
uint32_t cardSize;

// global for card erase size
uint32_t eraseSize;
//------------------------------------------------------------------------------
// store error strings in flash
#define sdErrorMsg(msg) sdErrorMsg_F(F(msg));
void sdErrorMsg_F(const __FlashStringHelper* str) {
cout << str << endl;
if (sd.card()->errorCode()) {
cout << F("SD errorCode: ");
cout << hex << int(sd.card()->errorCode()) << endl;
cout << F("SD errorData: ");
cout << int(sd.card()->errorData()) << dec << endl;
}
}
//------------------------------------------------------------------------------
uint8_t cidDmp() {
cid_t cid;
if (!sd.card()->readCID(&cid)) {
sdErrorMsg("readCID failed");
return false;
}
cout << F("\nManufacturer ID: ");
cout << hex << int(cid.mid) << dec << endl;
cout << F("OEM ID: ") << cid.oid[0] << cid.oid[1] << endl;
cout << F("Product: ");
for (uint8_t i = 0; i < 5; i++) {
cout << cid.pnm[i];
}
cout << F("\nVersion: ");
cout << int(cid.prv_n) << '.' << int(cid.prv_m) << endl;
cout << F("Serial number: ") << hex << cid.psn << dec << endl;
cout << F("Manufacturing date: ");
cout << int(cid.mdt_month) << '/';
cout << (2000 + cid.mdt_year_low + 10 * cid.mdt_year_high) << endl;
cout << endl;
return true;
}
//------------------------------------------------------------------------------
uint8_t csdDmp() {
csd_t csd;
uint8_t eraseSingleBlock;
if (!sd.card()->readCSD(&csd)) {
sdErrorMsg("readCSD failed");
return false;
}
if (csd.v1.csd_ver == 0) {
eraseSingleBlock = csd.v1.erase_blk_en;
eraseSize = (csd.v1.sector_size_high << 1) | csd.v1.sector_size_low;
} else if (csd.v2.csd_ver == 1) {
eraseSingleBlock = csd.v2.erase_blk_en;
eraseSize = (csd.v2.sector_size_high << 1) | csd.v2.sector_size_low;
} else {
cout << F("csd version error\n");
return false;
}
eraseSize++;
cout << F("cardSize: ") << 0.000512*cardSize;
cout << F(" MB (MB = 1,000,000 bytes)\n");

cout << F("flashEraseSize: ") << int(eraseSize) << F(" blocks\n");
cout << F("eraseSingleBlock: ");
if (eraseSingleBlock) {
cout << F("true\n");
} else {
cout << F("false\n");
}
return true;
}
//------------------------------------------------------------------------------
// print partition table
uint8_t partDmp() {
cache_t *p = sd.vol()->cacheClear();
if (!p) {
sdErrorMsg("cacheClear failed");
return false;
}
if (!sd.card()->readBlock(0, p->data)) {
sdErrorMsg("read MBR failed");
return false;
}
for (uint8_t ip = 1; ip < 5; ip++) {
part_t *pt = &p->mbr.part[ip - 1];
if ((pt->boot & 0X7F) != 0 || pt->firstSector > cardSize) {
cout << F("\nNo MBR. Assuming Super Floppy format.\n");
return true;
}
}
cout << F("\nSD Partition Table\n");
cout << F("part,boot,type,start,length\n");
for (uint8_t ip = 1; ip < 5; ip++) {
part_t *pt = &p->mbr.part[ip - 1];
cout << int(ip) << ',' << hex << int(pt->boot) << ',' << int(pt->type);
cout << dec << ',' << pt->firstSector <<',' << pt->totalSectors << endl;
}
return true;
}
//------------------------------------------------------------------------------
void volDmp() {
cout << F("\nVolume is FAT") << int(sd.vol()->fatType()) << endl;
cout << F("blocksPerCluster: ") << int(sd.vol()->blocksPerCluster()) << endl;
cout << F("clusterCount: ") << sd.vol()->clusterCount() << endl;
cout << F("freeClusters: ");
uint32_t volFree = sd.vol()->freeClusterCount();
cout << volFree << endl;
float fs = 0.000512*volFree*sd.vol()->blocksPerCluster();
cout << F("freeSpace: ") << fs << F(" MB (MB = 1,000,000 bytes)\n");
cout << F("fatStartBlock: ") << sd.vol()->fatStartBlock() << endl;
cout << F("fatCount: ") << int(sd.vol()->fatCount()) << endl;
cout << F("blocksPerFat: ") << sd.vol()->blocksPerFat() << endl;
cout << F("rootDirStart: ") << sd.vol()->rootDirStart() << endl;
cout << F("dataStartBlock: ") << sd.vol()->dataStartBlock() << endl;
if (sd.vol()->dataStartBlock() % eraseSize) {
cout << F("Data area is not aligned on flash erase boundaries!\n");
cout << F("Download and use formatter from www.sdcard.org!\n");
}
}
//------------------------------------------------------------------------------
void setup() {
Serial.begin(9600);

// Wait for USB Serial
while (!Serial) {
SysCall::yield();
}

// use uppercase in hex and use 0X base prefix
cout << uppercase << showbase << endl;

// F stores strings in flash to save RAM
cout << F("SdFat version: ") << SD_FAT_VERSION << endl;
if (DISABLE_CHIP_SELECT < 0) {
cout << F(
"\nAssuming the SD is the only SPI device.\n"
"Edit DISABLE_CHIP_SELECT to disable another device.\n");
} else {
cout << F("\nDisabling SPI device on pin ");
cout << int(DISABLE_CHIP_SELECT) << endl;
pinMode(DISABLE_CHIP_SELECT, OUTPUT);
digitalWrite(DISABLE_CHIP_SELECT, HIGH);
}
cout << F("\nAssuming the SD chip select pin is: ") <<int(SD_CHIP_SELECT);
cout << F("\nEdit SD_CHIP_SELECT to change the SD chip select pin.\n");
}
//------------------------------------------------------------------------------
void loop() {
// Read any existing Serial data.
do {
delay(10);
} while (Serial.available() && Serial.read() >= 0);

// F stores strings in flash to save RAM
cout << F("\ntype any character to start\n");
while (!Serial.available()) {
SysCall::yield();
}

uint32_t t = millis();
// initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
// breadboards. use SPI_FULL_SPEED for better performance.
if (!sd.cardBegin(SD_CHIP_SELECT, SPI_HALF_SPEED)) {
sdErrorMsg("\ncardBegin failed");
return;
}
t = millis() - t;

cardSize = sd.card()->cardSize();
if (cardSize == 0) {
sdErrorMsg("cardSize failed");
return;
}
cout << F("\ninit time: ") << t << " ms" << endl;
cout << F("\nCard type: ");
switch (sd.card()->type()) {
case SD_CARD_TYPE_SD1:
cout << F("SD1\n");
break;

case SD_CARD_TYPE_SD2:
cout << F("SD2\n");
break;

case SD_CARD_TYPE_SDHC:
if (cardSize < 70000000) {
cout << F("SDHC\n");
} else {
cout << F("SDXC\n");
}
break;

default:
cout << F("Unknown\n");
}
if (!cidDmp()) {
return;
}
if (!csdDmp()) {
return;
}
uint32_t ocr;
if (!sd.card()->readOCR(&ocr)) {
sdErrorMsg("\nreadOCR failed");
return;
}
cout << F("OCR: ") << hex << ocr << dec << endl;
if (!partDmp()) {
return;
}
if (!sd.fsBegin()) {
sdErrorMsg("\nFile System initialization failed.\n");
return;
}
volDmp();
}


victor_pv
Thu Apr 20, 2017 9:30 pm
STM32 wrote:Hi Stevestrong,
Thanks.

stevestrong wrote:
Try a simple blinky sketch with simple serial output in loop, without including SD card header.

I did it using Test_RTClock without problem.

stevestrong wrote:
Check the 3.3V voltage level, the on-board regulator is week.

I used an MSO oscilloscope and all seems to be fine.

stevestrong wrote:
It must be your software, and we cannot help if you don´t post it.

My software isn’t mine, simply it’s the SdInfo example provided with SdFat version 20160719.
Here it is:

/*
* This program attempts to initialize an SD card and analyze its structure.
*/
#include <SPI.h>
#include "SdFat.h"
/*
* SD chip select pin. Common values are:
*
* Arduino Ethernet shield, pin 4.
* SparkFun SD shield, pin 8.
* Adafruit SD shields and modules, pin 10.
* Default SD chip select is the SPI SS pin.
*/
const uint8_t SD_CHIP_SELECT = PA4;
/*
* Set DISABLE_CHIP_SELECT to disable a second SPI device.
* For example, with the Ethernet shield, set DISABLE_CHIP_SELECT
* to 10 to disable the Ethernet controller.
*/
const int8_t DISABLE_CHIP_SELECT = -1;
SdFat sd;

// serial output steam
ArduinoOutStream cout(Serial);

// global for card size
uint32_t cardSize;

// global for card erase size
uint32_t eraseSize;
//------------------------------------------------------------------------------
// store error strings in flash
#define sdErrorMsg(msg) sdErrorMsg_F(F(msg));
void sdErrorMsg_F(const __FlashStringHelper* str) {
cout << str << endl;
if (sd.card()->errorCode()) {
cout << F("SD errorCode: ");
cout << hex << int(sd.card()->errorCode()) << endl;
cout << F("SD errorData: ");
cout << int(sd.card()->errorData()) << dec << endl;
}
}
//------------------------------------------------------------------------------
uint8_t cidDmp() {
cid_t cid;
if (!sd.card()->readCID(&cid)) {
sdErrorMsg("readCID failed");
return false;
}
cout << F("\nManufacturer ID: ");
cout << hex << int(cid.mid) << dec << endl;
cout << F("OEM ID: ") << cid.oid[0] << cid.oid[1] << endl;
cout << F("Product: ");
for (uint8_t i = 0; i < 5; i++) {
cout << cid.pnm[i];
}
cout << F("\nVersion: ");
cout << int(cid.prv_n) << '.' << int(cid.prv_m) << endl;
cout << F("Serial number: ") << hex << cid.psn << dec << endl;
cout << F("Manufacturing date: ");
cout << int(cid.mdt_month) << '/';
cout << (2000 + cid.mdt_year_low + 10 * cid.mdt_year_high) << endl;
cout << endl;
return true;
}
//------------------------------------------------------------------------------
uint8_t csdDmp() {
csd_t csd;
uint8_t eraseSingleBlock;
if (!sd.card()->readCSD(&csd)) {
sdErrorMsg("readCSD failed");
return false;
}
if (csd.v1.csd_ver == 0) {
eraseSingleBlock = csd.v1.erase_blk_en;
eraseSize = (csd.v1.sector_size_high << 1) | csd.v1.sector_size_low;
} else if (csd.v2.csd_ver == 1) {
eraseSingleBlock = csd.v2.erase_blk_en;
eraseSize = (csd.v2.sector_size_high << 1) | csd.v2.sector_size_low;
} else {
cout << F("csd version error\n");
return false;
}
eraseSize++;
cout << F("cardSize: ") << 0.000512*cardSize;
cout << F(" MB (MB = 1,000,000 bytes)\n");

cout << F("flashEraseSize: ") << int(eraseSize) << F(" blocks\n");
cout << F("eraseSingleBlock: ");
if (eraseSingleBlock) {
cout << F("true\n");
} else {
cout << F("false\n");
}
return true;
}
//------------------------------------------------------------------------------
// print partition table
uint8_t partDmp() {
cache_t *p = sd.vol()->cacheClear();
if (!p) {
sdErrorMsg("cacheClear failed");
return false;
}
if (!sd.card()->readBlock(0, p->data)) {
sdErrorMsg("read MBR failed");
return false;
}
for (uint8_t ip = 1; ip < 5; ip++) {
part_t *pt = &p->mbr.part[ip - 1];
if ((pt->boot & 0X7F) != 0 || pt->firstSector > cardSize) {
cout << F("\nNo MBR. Assuming Super Floppy format.\n");
return true;
}
}
cout << F("\nSD Partition Table\n");
cout << F("part,boot,type,start,length\n");
for (uint8_t ip = 1; ip < 5; ip++) {
part_t *pt = &p->mbr.part[ip - 1];
cout << int(ip) << ',' << hex << int(pt->boot) << ',' << int(pt->type);
cout << dec << ',' << pt->firstSector <<',' << pt->totalSectors << endl;
}
return true;
}
//------------------------------------------------------------------------------
void volDmp() {
cout << F("\nVolume is FAT") << int(sd.vol()->fatType()) << endl;
cout << F("blocksPerCluster: ") << int(sd.vol()->blocksPerCluster()) << endl;
cout << F("clusterCount: ") << sd.vol()->clusterCount() << endl;
cout << F("freeClusters: ");
uint32_t volFree = sd.vol()->freeClusterCount();
cout << volFree << endl;
float fs = 0.000512*volFree*sd.vol()->blocksPerCluster();
cout << F("freeSpace: ") << fs << F(" MB (MB = 1,000,000 bytes)\n");
cout << F("fatStartBlock: ") << sd.vol()->fatStartBlock() << endl;
cout << F("fatCount: ") << int(sd.vol()->fatCount()) << endl;
cout << F("blocksPerFat: ") << sd.vol()->blocksPerFat() << endl;
cout << F("rootDirStart: ") << sd.vol()->rootDirStart() << endl;
cout << F("dataStartBlock: ") << sd.vol()->dataStartBlock() << endl;
if (sd.vol()->dataStartBlock() % eraseSize) {
cout << F("Data area is not aligned on flash erase boundaries!\n");
cout << F("Download and use formatter from www.sdcard.org!\n");
}
}
//------------------------------------------------------------------------------
void setup() {
Serial.begin(9600);

// Wait for USB Serial
while (!Serial) {
SysCall::yield();
}

// use uppercase in hex and use 0X base prefix
cout << uppercase << showbase << endl;

// F stores strings in flash to save RAM
cout << F("SdFat version: ") << SD_FAT_VERSION << endl;
if (DISABLE_CHIP_SELECT < 0) {
cout << F(
"\nAssuming the SD is the only SPI device.\n"
"Edit DISABLE_CHIP_SELECT to disable another device.\n");
} else {
cout << F("\nDisabling SPI device on pin ");
cout << int(DISABLE_CHIP_SELECT) << endl;
pinMode(DISABLE_CHIP_SELECT, OUTPUT);
digitalWrite(DISABLE_CHIP_SELECT, HIGH);
}
cout << F("\nAssuming the SD chip select pin is: ") <<int(SD_CHIP_SELECT);
cout << F("\nEdit SD_CHIP_SELECT to change the SD chip select pin.\n");
}
//------------------------------------------------------------------------------
void loop() {
// Read any existing Serial data.
do {
delay(10);
} while (Serial.available() && Serial.read() >= 0);

// F stores strings in flash to save RAM
cout << F("\ntype any character to start\n");
while (!Serial.available()) {
SysCall::yield();
}

uint32_t t = millis();
// initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
// breadboards. use SPI_FULL_SPEED for better performance.
if (!sd.cardBegin(SD_CHIP_SELECT, SPI_HALF_SPEED)) {
sdErrorMsg("\ncardBegin failed");
return;
}
t = millis() - t;

cardSize = sd.card()->cardSize();
if (cardSize == 0) {
sdErrorMsg("cardSize failed");
return;
}
cout << F("\ninit time: ") << t << " ms" << endl;
cout << F("\nCard type: ");
switch (sd.card()->type()) {
case SD_CARD_TYPE_SD1:
cout << F("SD1\n");
break;

case SD_CARD_TYPE_SD2:
cout << F("SD2\n");
break;

case SD_CARD_TYPE_SDHC:
if (cardSize < 70000000) {
cout << F("SDHC\n");
} else {
cout << F("SDXC\n");
}
break;

default:
cout << F("Unknown\n");
}
if (!cidDmp()) {
return;
}
if (!csdDmp()) {
return;
}
uint32_t ocr;
if (!sd.card()->readOCR(&ocr)) {
sdErrorMsg("\nreadOCR failed");
return;
}
cout << F("OCR: ") << hex << ocr << dec << endl;
if (!partDmp()) {
return;
}
if (!sd.fsBegin()) {
sdErrorMsg("\nFile System initialization failed.\n");
return;
}
volDmp();
}


stevestrong
Fri Apr 21, 2017 7:36 am
I would like to know which upload method do you use.
SD card with SdFat lib combined with USB serial is widely used by many users here in forum, including me. And it works.
But…
USB serial is only working if you use the “Smt32duino bootloader”, or you add the linker flag “-DSERIAL_USB” to the build process.

The other thing is that the USB serial is visible on Win10 machine only 5 seconds after the board has been reset, this is the time needed to re-enumerate the COM ports.
So it can be that the SW runs OK, but you don’t see anything because all the output data is already sent before you re-open the serial monitor after upload (and board reset).
OTOH, the line
while (!Serial);


STM32
Fri Apr 21, 2017 8:11 pm
Hi Stevestrong,
Thanks.

stevestrong wrote:
Try some other of the sdfat examples just to confirm, but the examples have been used extensively so they should be ok.
Some SD card do not work as good in the spi mode, you may want to try different cards and different speeds.
I did the initial port of the sdfat library for our core, and the sdcard I was using first gave me many headaches. It worked only some times, so I spent countless hours checking the code thinking something should be bad, then checking connections, then it would work a few times, but next would fail with no changes. Eventually I decided to try a faster better sdcard (sandisk extreme), and everything worked perfect every run, over and over.

What you have written is conceptually correct, but in my opinion in this case it isn’t SD card, nor SPI speed, nor connections, it can be only the code that is running on the “Blue Pill”.
Anyone can test by himself without any need to have card, SD card connector nor wires connected to the “Blue Pill”.
Simply load into “Blue Pill” the sketch I put in my previous post and start the terminal using the “Blue Pill” alone only connected to the computer via USB connector and no SD card nor reader connected.
In that case you should get this message on the terminal:

SdFat version: 20160719

Assuming the SD is the only SPI device.
Edit DISABLE_CHIP_SELECT to disable another device.

Assuming the SD chip select pin is: PA4
Edit SD_CHIP_SELECT to change the SD chip select pin.

type any character to start

Even by blindly hit the keyboard nothing happens, the terminal remains empty when instead this message should appear:

cardBegin failed
SD errorCode: 0X1
SD errorData: 0X0

type any character to start

With my two “Blue Pill” I can’t get the messages, not even by pushing the reset button on the board.
That is the point.
The sample sketch named “Test_RTClock” is fully working just as well many other.
With a MSO oscilloscope I saw that code is running fine also if nothing appears into the terminal.
Both the “Blue Pill” I own they have a 1.5kohm pullup resistor on D+ (R10 on the board).
Based on all that I guess it is something in the SdInfo code.

stevestrong wrote:
I would like to know which upload method do you use.

I use “Blue Pill” board as normal Arduino board by using the on board microUSB while keeping “Boot0” and “Boot1” pins always connected to GND.

stevestrong wrote:
SD card with SdFat lib combined with USB serial is widely used by many users here in forum, including me. And it works.
But…
USB serial is only working if you use the “Smt32duino bootloader”, or you add the linker flag “-DSERIAL_USB” to the build process.


Being an hardware guy I don’t fully understand what do you mean, anyway on my two “Blue Pill” I have the Roger Clark’s Smt32duino bootloader.

stevestrong wrote:
The other thing is that the USB serial is visible on Win10 machine only 5 seconds after the board has been reset, this is the time needed to re-enumerate the COM ports.
So it can be that the SW runs OK, but you don’t see anything because all the output data is already sent before you re-open the serial monitor after upload (and board reset).


Maybe, but with different sketches the output into the terminal does work perhaps because better timing.

stevestrong wrote:
while (!Serial);


stevestrong
Sat Apr 22, 2017 7:28 am
The “Test_RTClock” example does not use the USB serial so you cannot compare with other sketches which use it.
The “Test_RTClock” example uses the USB serial in the main loop, so even if the first samples (within 5 seconds) are not shown, the rest is going to be shown in the serial monitor.

STM32 wrote:Being an hardware guy I don’t fully understand what do you mean, anyway on my two “Blue Pill” I have the Roger Clark’s Smt32duino bootloader.


STM32
Sat Apr 29, 2017 4:21 pm
Hi Stevestrong,
sorry for the late answer.
Thanks, your hint does works!
First it’s nice to know that the “Test_RTClock” is different from other examples due it does use the USB serial in the main loop, thanks!
Then I have to point out that I misunderstood the “Smt32duino bootloader” thing.
I used it from the beginning and of course with “Smt32duino bootloader” as a upload method, so on my side the whole things were right already from the beginning.
Same as above, I already know how to check all warning messages by turning on verbose messages in
Arduino IDE: File -> Preferences: Show verbose output during: compilation – check the box.

I repeat that finally using “delay(6000)” as you wrote just before outputting any serial messages does the trick, many thanks!

/*
* This program attempts to initialize an SD card and analyze its structure.
*/
#include <SPI.h>
#include "SdFat.h"
/*
* SD chip select pin. Common values are:
*
* Arduino Ethernet shield, pin 4.
* SparkFun SD shield, pin 8.
* Adafruit SD shields and modules, pin 10.
* Default SD chip select is the SPI SS pin.
*/
const uint8_t SD_CHIP_SELECT = PA4;
/*
* Set DISABLE_CHIP_SELECT to disable a second SPI device.
* For example, with the Ethernet shield, set DISABLE_CHIP_SELECT
* to 10 to disable the Ethernet controller.
*/
const int8_t DISABLE_CHIP_SELECT = -1;
SdFat sd;

// serial output steam
ArduinoOutStream cout(Serial);

// global for card size
uint32_t cardSize;

// global for card erase size
uint32_t eraseSize;
//------------------------------------------------------------------------------
// store error strings in flash
#define sdErrorMsg(msg) sdErrorMsg_F(F(msg));
void sdErrorMsg_F(const __FlashStringHelper* str) {
cout << str << endl;
if (sd.card()->errorCode()) {
cout << F("SD errorCode: ");
cout << hex << int(sd.card()->errorCode()) << endl;
cout << F("SD errorData: ");
cout << int(sd.card()->errorData()) << dec << endl;
}
}
//------------------------------------------------------------------------------
uint8_t cidDmp() {
cid_t cid;
if (!sd.card()->readCID(&cid)) {
sdErrorMsg("readCID failed");
return false;
}
cout << F("\nManufacturer ID: ");
cout << hex << int(cid.mid) << dec << endl;
cout << F("OEM ID: ") << cid.oid[0] << cid.oid[1] << endl;
cout << F("Product: ");
for (uint8_t i = 0; i < 5; i++) {
cout << cid.pnm[i];
}
cout << F("\nVersion: ");
cout << int(cid.prv_n) << '.' << int(cid.prv_m) << endl;
cout << F("Serial number: ") << hex << cid.psn << dec << endl;
cout << F("Manufacturing date: ");
cout << int(cid.mdt_month) << '/';
cout << (2000 + cid.mdt_year_low + 10 * cid.mdt_year_high) << endl;
cout << endl;
return true;
}
//------------------------------------------------------------------------------
uint8_t csdDmp() {
csd_t csd;
uint8_t eraseSingleBlock;
if (!sd.card()->readCSD(&csd)) {
sdErrorMsg("readCSD failed");
return false;
}
if (csd.v1.csd_ver == 0) {
eraseSingleBlock = csd.v1.erase_blk_en;
eraseSize = (csd.v1.sector_size_high << 1) | csd.v1.sector_size_low;
} else if (csd.v2.csd_ver == 1) {
eraseSingleBlock = csd.v2.erase_blk_en;
eraseSize = (csd.v2.sector_size_high << 1) | csd.v2.sector_size_low;
} else {
cout << F("csd version error\n");
return false;
}
eraseSize++;
cout << F("cardSize: ") << 0.000512*cardSize;
cout << F(" MB (MB = 1,000,000 bytes)\n");

cout << F("flashEraseSize: ") << int(eraseSize) << F(" blocks\n");
cout << F("eraseSingleBlock: ");
if (eraseSingleBlock) {
cout << F("true\n");
} else {
cout << F("false\n");
}
return true;
}
//------------------------------------------------------------------------------
// print partition table
uint8_t partDmp() {
cache_t *p = sd.vol()->cacheClear();
if (!p) {
sdErrorMsg("cacheClear failed");
return false;
}
if (!sd.card()->readBlock(0, p->data)) {
sdErrorMsg("read MBR failed");
return false;
}
for (uint8_t ip = 1; ip < 5; ip++) {
part_t *pt = &p->mbr.part[ip - 1];
if ((pt->boot & 0X7F) != 0 || pt->firstSector > cardSize) {
cout << F("\nNo MBR. Assuming Super Floppy format.\n");
return true;
}
}
cout << F("\nSD Partition Table\n");
cout << F("part,boot,type,start,length\n");
for (uint8_t ip = 1; ip < 5; ip++) {
part_t *pt = &p->mbr.part[ip - 1];
cout << int(ip) << ',' << hex << int(pt->boot) << ',' << int(pt->type);
cout << dec << ',' << pt->firstSector <<',' << pt->totalSectors << endl;
}
return true;
}
//------------------------------------------------------------------------------
void volDmp() {
cout << F("\nVolume is FAT") << int(sd.vol()->fatType()) << endl;
cout << F("blocksPerCluster: ") << int(sd.vol()->blocksPerCluster()) << endl;
cout << F("clusterCount: ") << sd.vol()->clusterCount() << endl;
cout << F("freeClusters: ");
uint32_t volFree = sd.vol()->freeClusterCount();
cout << volFree << endl;
float fs = 0.000512*volFree*sd.vol()->blocksPerCluster();
cout << F("freeSpace: ") << fs << F(" MB (MB = 1,000,000 bytes)\n");
cout << F("fatStartBlock: ") << sd.vol()->fatStartBlock() << endl;
cout << F("fatCount: ") << int(sd.vol()->fatCount()) << endl;
cout << F("blocksPerFat: ") << sd.vol()->blocksPerFat() << endl;
cout << F("rootDirStart: ") << sd.vol()->rootDirStart() << endl;
cout << F("dataStartBlock: ") << sd.vol()->dataStartBlock() << endl;
if (sd.vol()->dataStartBlock() % eraseSize) {
cout << F("Data area is not aligned on flash erase boundaries!\n");
cout << F("Download and use formatter from www.sdcard.org!\n");
}
}
//------------------------------------------------------------------------------
void setup() {
Serial.begin(9600);

// Wait for USB Serial
while (!Serial) {
SysCall::yield();
}
delay(6000);
// use uppercase in hex and use 0X base prefix
cout << uppercase << showbase << endl;

// F stores strings in flash to save RAM
cout << F("SdFat version: ") << SD_FAT_VERSION << endl;
if (DISABLE_CHIP_SELECT < 0) {
cout << F(
"\nAssuming the SD is the only SPI device.\n"
"Edit DISABLE_CHIP_SELECT to disable another device.\n");
} else {
cout << F("\nDisabling SPI device on pin ");
cout << int(DISABLE_CHIP_SELECT) << endl;
pinMode(DISABLE_CHIP_SELECT, OUTPUT);
digitalWrite(DISABLE_CHIP_SELECT, HIGH);
}
cout << F("\nAssuming the SD chip select pin is: ") <<int(SD_CHIP_SELECT);
cout << F("\nEdit SD_CHIP_SELECT to change the SD chip select pin.\n");
}
//------------------------------------------------------------------------------
void loop() {
// Read any existing Serial data.
do {
delay(10);
} while (Serial.available() && Serial.read() >= 0);

// F stores strings in flash to save RAM
cout << F("\ntype any character to start\n");
while (!Serial.available()) {
SysCall::yield();
}

uint32_t t = millis();
// initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
// breadboards. use SPI_FULL_SPEED for better performance.
if (!sd.cardBegin(SD_CHIP_SELECT, SPI_HALF_SPEED)) {
sdErrorMsg("\ncardBegin failed");
return;
}
t = millis() - t;

cardSize = sd.card()->cardSize();
if (cardSize == 0) {
sdErrorMsg("cardSize failed");
return;
}
cout << F("\ninit time: ") << t << " ms" << endl;
cout << F("\nCard type: ");
switch (sd.card()->type()) {
case SD_CARD_TYPE_SD1:
cout << F("SD1\n");
break;

case SD_CARD_TYPE_SD2:
cout << F("SD2\n");
break;

case SD_CARD_TYPE_SDHC:
if (cardSize < 70000000) {
cout << F("SDHC\n");
} else {
cout << F("SDXC\n");
}
break;

default:
cout << F("Unknown\n");
}
if (!cidDmp()) {
return;
}
if (!csdDmp()) {
return;
}
uint32_t ocr;
if (!sd.card()->readOCR(&ocr)) {
sdErrorMsg("\nreadOCR failed");
return;
}
cout << F("OCR: ") << hex << ocr << dec << endl;
if (!partDmp()) {
return;
}
if (!sd.fsBegin()) {
sdErrorMsg("\nFile System initialization failed.\n");
return;
}
volDmp();
}


Leave a Reply

Your email address will not be published. Required fields are marked *