Skip to content

Add BW16 SD Card Example using the SPI Bus #275

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/CI_compile_examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ jobs:
- source-url: https://github.com/ambiot/ambd_arduino/raw/dev/Arduino_zip_libraries/AmebaMotors.zip
- source-url: https://github.com/ambiot/ambd_arduino/raw/dev/Arduino_zip_libraries/AmebaEink.zip
- name: "SparkFun ADXL313 Arduino Library"
- name: "SdFat - Adafruit Fork"
verbose: false
enable-deltas-report: false
if: ${{ github.ref == 'refs/heads/dev' || github.event.pull_request.base.ref == 'dev'}}
Expand All @@ -141,6 +142,7 @@ jobs:
- source-url: https://github.com/ambiot/ambd_arduino/raw/master/Arduino_zip_libraries/AmebaMotors.zip
- source-url: https://github.com/ambiot/ambd_arduino/raw/master/Arduino_zip_libraries/AmebaEink.zip
- name: "SparkFun ADXL313 Arduino Library"
- name: "SdFat - Adafruit Fork"
verbose: false
enable-deltas-report: false
if: ${{ github.ref == 'refs/heads/master' || github.event.pull_request.base.ref == 'master' }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
/*
BW16 SPI Bus SD Card example:
This program attempts to initialize an SD card and analyze its structure.

It needs the Adafruit fork of the SdFat Library: https://github.com/adafruit/SdFat/

This example code is in the public domain.

This modified example credits to https://github.com/designer2k2
*/

#ifdef BOARD_AITHINKER_BW16

#include "SdFat.h"
#include "sdios.h"

#define SD_CONFIG SdSpiConfig(SS, DEDICATED_SPI, SD_SCK_MHZ(16))

//------------------------------------------------------------------------------
SdFs sd;
cid_t cid;
csd_t csd;
scr_t scr;
uint8_t cmd6Data[64];
uint32_t eraseSize;
uint32_t ocr;
static ArduinoOutStream cout(Serial);
//------------------------------------------------------------------------------
void cidDmp() {
cout << F("\nManufacturer ID: ");
cout << uppercase << showbase << 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("\nRevision: ") << cid.prvN() << '.' << cid.prvM() << endl;
cout << F("Serial number: ") << hex << cid.psn() << dec << endl;
cout << F("Manufacturing date: ");
cout << cid.mdtMonth() << '/' << cid.mdtYear() << endl;
cout << endl;
}
//------------------------------------------------------------------------------
void clearSerialInput() {
uint32_t m = micros();
do {
if (Serial.read() >= 0) {
m = micros();
}
} while (micros() - m < 10000);
}
//------------------------------------------------------------------------------
void csdDmp() {
eraseSize = csd.eraseSize();
cout << F("cardSize: ") << 0.000512 * csd.capacity();
cout << F(" MB (MB = 1,000,000 bytes)\n");

cout << F("flashEraseSize: ") << int(eraseSize) << F(" blocks\n");
cout << F("eraseSingleBlock: ");
if (csd.eraseSingleBlock()) {
cout << F("true\n");
} else {
cout << F("false\n");
}
cout << F("dataAfterErase: ");
if (scr.dataAfterErase()) {
cout << F("ones\n");
} else {
cout << F("zeros\n");
}
}
//------------------------------------------------------------------------------
void errorPrint() {
if (sd.sdErrorCode()) {
cout << F("SD errorCode: ") << hex << showbase;
printSdErrorSymbol(&Serial, sd.sdErrorCode());
cout << F(" = ") << int(sd.sdErrorCode()) << endl;
cout << F("SD errorData = ") << int(sd.sdErrorData()) << dec << endl;
}
}
//------------------------------------------------------------------------------
bool mbrDmp() {
MbrSector_t mbr;
bool valid = true;
if (!sd.card()->readSector(0, (uint8_t *)&mbr)) {
cout << F("\nread MBR failed.\n");
errorPrint();
return false;
}
cout << F("\nSD Partition Table\n");
cout << F("part,boot,bgnCHS[3],type,endCHS[3],start,length\n");
for (uint8_t ip = 1; ip < 5; ip++) {
MbrPart_t *pt = &mbr.part[ip - 1];
if ((pt->boot != 0 && pt->boot != 0X80) || getLe32(pt->relativeSectors) > csd.capacity()) {
valid = false;
}
cout << int(ip) << ',' << uppercase << showbase << hex;
cout << int(pt->boot) << ',';
for (int i = 0; i < 3; i++) {
cout << int(pt->beginCHS[i]) << ',';
}
cout << int(pt->type) << ',';
for (int i = 0; i < 3; i++) {
cout << int(pt->endCHS[i]) << ',';
}
cout << dec << getLe32(pt->relativeSectors) << ',';
cout << getLe32(pt->totalSectors) << endl;
}
if (!valid) {
cout << F("\nMBR not valid, assuming Super Floppy format.\n");
}
return true;
}
//------------------------------------------------------------------------------
void dmpVol() {
cout << F("\nScanning FAT, please wait.\n");
int32_t freeClusterCount = sd.freeClusterCount();
if (sd.fatType() <= 32) {
cout << F("\nVolume is FAT") << int(sd.fatType()) << endl;
} else {
cout << F("\nVolume is exFAT\n");
}
cout << F("sectorsPerCluster: ") << sd.sectorsPerCluster() << endl;
cout << F("fatStartSector: ") << sd.fatStartSector() << endl;
cout << F("dataStartSector: ") << sd.dataStartSector() << endl;
cout << F("clusterCount: ") << sd.clusterCount() << endl;
cout << F("freeClusterCount: ");
if (freeClusterCount >= 0) {
cout << freeClusterCount << endl;
} else {
cout << F("failed\n");
errorPrint();
}
}
//------------------------------------------------------------------------------
void printCardType() {

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 (csd.capacity() < 70000000) {
cout << F("SDHC\n");
} else {
cout << F("SDXC\n");
}
break;

default:
cout << F("Unknown\n");
}
}
//-----------------------------------------------------------------------------
void setup() {
Serial.begin(9600);
// Wait for USB Serial
while (!Serial) {
yield();
}
cout << F("SdFat version: ") << SD_FAT_VERSION_STR << endl;
}
//------------------------------------------------------------------------------
void loop() {
// Read any existing Serial data.
clearSerialInput();

// F stores strings in flash to save RAM
cout << F("\ntype any character to start\n");
while (!Serial.available()) {
yield();
}
uint32_t t = millis();
if (!sd.cardBegin(SD_CONFIG)) {
cout << F(
"\nSD initialization failed.\n"
"Do not reformat the card!\n"
"Is the card correctly inserted?\n"
"Is there a wiring/soldering problem?\n");
if (isSpi(SD_CONFIG)) {
cout << F(
"Does another SPI device need to be disabled?\n");
}
errorPrint();
return;
}
t = millis() - t;
cout << F("init time: ") << dec << t << " ms" << endl;

if (!sd.card()->readCID(&cid) || !sd.card()->readCSD(&csd) || !sd.card()->readOCR(&ocr) || !sd.card()->readSCR(&scr)) {
cout << F("readInfo failed\n");
errorPrint();
return;
}
printCardType();
cout << F("sdSpecVer: ") << 0.01 * scr.sdSpecVer() << endl;
cout << F("HighSpeedMode: ");
if (scr.sdSpecVer() && sd.card()->cardCMD6(0X00FFFFFF, cmd6Data) && (2 & cmd6Data[13])) {
cout << F("true\n");
} else {
cout << F("false\n");
}
cidDmp();
csdDmp();
cout << F("\nOCR: ") << uppercase << showbase;
cout << hex << ocr << dec << endl;
if (!mbrDmp()) {
return;
}
if (!sd.volumeBegin()) {
cout << F("\nvolumeBegin failed. Is the card formatted?\n");
errorPrint();
return;
}
dmpVol();
}

#else

void setup() {}

void loop() {}

#endif
6 changes: 6 additions & 0 deletions Arduino_package/hardware/variants/rtl8720dn_bw16/variant.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,12 @@ extern void wait_for_debug(void);
#define SPI_SCLK AMB_D10 // AMB_D10
#define SPI_SS AMB_D9 // AMB_D9

/* Arduino style SPI pin mapping */
static const uint8_t SS = SPI_SS;
static const uint8_t MOSI = SPI_MOSI;
static const uint8_t MISO = SPI_MISO;
static const uint8_t SCK = SPI_SCLK;

/* TwoWire/I2C pin mapping */
#define I2C_SDA AMB_D8 // AMB_D8
#define I2C_SCL AMB_D7 // AMB_D7
Expand Down