mirror of
https://github.com/arduino/Arduino.git
synced 2025-01-07 22:46:08 +01:00
181 lines
4.5 KiB
Plaintext
181 lines
4.5 KiB
Plaintext
/*
|
|
* This sketch attempts to initialize a SD card and analyze its structure.
|
|
*/
|
|
#include <SdFat.h>
|
|
#include <SdFatUtil.h>
|
|
|
|
// offset to partition table
|
|
#define PART_OFFSET (512-64-2)
|
|
|
|
Sd2Card card;
|
|
SdVolume vol;
|
|
|
|
//global for card erase sector size
|
|
uint32_t sectorSize;
|
|
|
|
void sdError(void) {
|
|
PgmPrintln("SD error");
|
|
PgmPrint("errorCode: ");
|
|
Serial.println(card.errorCode(), HEX);
|
|
PgmPrint("errorData: ");
|
|
Serial.println(card.errorData(), HEX);
|
|
return;
|
|
}
|
|
|
|
uint8_t cidDmp(void) {
|
|
cid_t cid;
|
|
if (!card.readCID(&cid)) {
|
|
PgmPrint("readCID failed");
|
|
sdError();
|
|
return false;
|
|
}
|
|
PgmPrint("\nManufacturer ID: ");
|
|
Serial.println(cid.mid, HEX);
|
|
PgmPrint("OEM ID: ");
|
|
Serial.print(cid.oid[0]);
|
|
Serial.println(cid.oid[1]);
|
|
PgmPrint("Product: ");
|
|
for (uint8_t i = 0; i < 5; i++) {
|
|
Serial.print(cid.pnm[i]);
|
|
}
|
|
PgmPrint("\nVersion: ");
|
|
Serial.print(cid.prv_n, DEC);
|
|
Serial.print('.');
|
|
Serial.println(cid.prv_m, DEC);
|
|
PgmPrint("Serial number: ");
|
|
Serial.println(cid.psn);
|
|
PgmPrint("Manufacturing date: ");
|
|
Serial.print(cid.mdt_month);
|
|
Serial.print('/');
|
|
Serial.println(2000 + cid.mdt_year_low + (cid.mdt_year_high <<4));
|
|
Serial.println();
|
|
return true;
|
|
}
|
|
|
|
uint8_t csdDmp(void) {
|
|
csd_t csd;
|
|
uint8_t eraseSingleBlock;
|
|
uint32_t cardSize = card.cardSize();
|
|
if (cardSize == 0 || !card.readCSD(&csd)) {
|
|
PgmPrintln("readCSD failed");
|
|
sdError();
|
|
return false;
|
|
}
|
|
if (csd.v1.csd_ver == 0) {
|
|
eraseSingleBlock = csd.v1.erase_blk_en;
|
|
sectorSize = (csd.v1.sector_size_high << 1) | csd.v1.sector_size_low;
|
|
}
|
|
else if (csd.v2.csd_ver == 1) {
|
|
eraseSingleBlock = csd.v2.erase_blk_en;
|
|
sectorSize = (csd.v2.sector_size_high << 1) | csd.v2.sector_size_low;
|
|
}
|
|
else {
|
|
PgmPrintln("csd version error");
|
|
return false;
|
|
}
|
|
sectorSize++;
|
|
PgmPrint("cardSize: ");
|
|
Serial.print(cardSize);
|
|
PgmPrintln(" (512 byte blocks)");
|
|
PgmPrint("flashEraseSize: ");
|
|
Serial.print(sectorSize, DEC);
|
|
PgmPrintln(" blocks");
|
|
PgmPrint("eraseSingleBlock: ");
|
|
if (eraseSingleBlock) {
|
|
PgmPrintln("true");
|
|
}
|
|
else {
|
|
PgmPrintln("false");
|
|
}
|
|
return true;
|
|
}
|
|
// print partition table
|
|
uint8_t partDmp(void) {
|
|
part_t pt;
|
|
PgmPrintln("\npart,boot,type,start,length");
|
|
for (uint8_t ip = 1; ip < 5; ip++) {
|
|
if (!card.readData(0, PART_OFFSET + 16*(ip-1), 16, (uint8_t *)&pt)) {
|
|
PgmPrint("read partition table failed");
|
|
sdError();
|
|
return false;
|
|
}
|
|
Serial.print(ip, DEC);
|
|
Serial.print(',');
|
|
Serial.print(pt.boot,HEX);
|
|
Serial.print(',');
|
|
Serial.print(pt.type, HEX);
|
|
Serial.print(',');
|
|
Serial.print(pt.firstSector);
|
|
Serial.print(',');
|
|
Serial.println(pt.totalSectors);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void volDmp(void) {
|
|
PgmPrint("\nVolume is FAT");
|
|
Serial.println(vol.fatType(), DEC);
|
|
PgmPrint("blocksPerCluster: ");
|
|
Serial.println(vol.blocksPerCluster(), DEC);
|
|
PgmPrint("clusterCount: ");
|
|
Serial.println(vol.clusterCount());
|
|
PgmPrint("fatStartBlock: ");
|
|
Serial.println(vol.fatStartBlock());
|
|
PgmPrint("fatCount: ");
|
|
Serial.println(vol.fatCount(), DEC);
|
|
PgmPrint("blocksPerFat: ");
|
|
Serial.println(vol.blocksPerFat());
|
|
PgmPrint("rootDirStart: ");
|
|
Serial.println(vol.rootDirStart());
|
|
PgmPrint("dataStartBlock: ");
|
|
Serial.println(vol.dataStartBlock());
|
|
if (vol.dataStartBlock()%sectorSize) {
|
|
PgmPrintln("Data area is not aligned on flash erase boundaries!");
|
|
}
|
|
}
|
|
|
|
void setup() {
|
|
Serial.begin(9600);
|
|
}
|
|
|
|
void loop() {
|
|
PgmPrintln("\ntype any character to start");
|
|
while (!Serial.available());
|
|
Serial.flush();
|
|
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.
|
|
uint8_t r = card.init(SPI_HALF_SPEED);
|
|
t = millis() - t;
|
|
if (!r) {
|
|
PgmPrintln("\ncard.init failed");
|
|
sdError();
|
|
return;
|
|
}
|
|
PgmPrint("\ninit time: ");
|
|
Serial.println(t);
|
|
PgmPrint("\nCard type: ");
|
|
switch(card.type()) {
|
|
case SD_CARD_TYPE_SD1:
|
|
PgmPrintln("SD1");
|
|
break;
|
|
case SD_CARD_TYPE_SD2:
|
|
PgmPrintln("SD2");
|
|
break;
|
|
case SD_CARD_TYPE_SDHC:
|
|
PgmPrintln("SDHC");
|
|
break;
|
|
default:
|
|
PgmPrintln("Unknown");
|
|
}
|
|
if(!cidDmp()) return;
|
|
if(!csdDmp()) return;
|
|
if(!partDmp()) return;
|
|
if (!vol.init(&card)) {
|
|
PgmPrintln("\nvol.init failed");
|
|
sdError();
|
|
return;
|
|
}
|
|
volDmp();
|
|
}
|