Reading individual SD card sectors ising ESP32

I am trying to find code (hopefully Arduino IDE based) to R/W individual sectors on an SD card. There are numerous examples to R/W whole MSDOS files. I want to read sectors one at a time
Can somebody point me to an example.

PS. If this is not the best posting location, please advise.
John M

I just looked at the 2 most popular libraries, and they do not offer access to sectors.

The SdFat library has an example called LowLatencyLogger which writes data to consecutive sectors of an SD card so as to bypass all the file system activity. The coding is above my pay grade, but you might want to take a look. Basically, he creates files in advance, all with consecutive sectors, but with the data portions erased. Then for data logging he just writes directly to the card. He doesn't mess with the FAT table or the directory.

It's the AVR version of that library that has that example, but assuming it has been ported to the ESP32, it should also be available there. Note that the procedure for direct sector access varies with the type of card being used - SD, SDHC, SDXC.

I once wrote an SD card bootloader for MSP430 that would read new firmware from the card and flash it to the processor - only for SD and SDHC. The low-level read and write commands are not that complicated, but dealing with the different kinds of cards can be. But it's in MSP430 assembler, so probably not all that useful to you. But those low-level commands are somewhere in any SD card library. I think SdFat may be your best bet.

Thanks Sherman, unfortunately that's not much help. I want to run CPM3 from SD cards, so I need individual sector R/W's.
Somewhat similar I think to what you are suggesting is just read in a very large MSDOS file and with a internal pointer to a large CPM "disk" and move the pointer along to artificial sectors etc. It's a lot of overhead.

I cannot believe there is not some way to get a raw sector R/W out of some SD card library. It really has to be an ESP32 Arduino compatible library.

Anybody else that can help?

John

The MFRC522 library will do this check out the examples for this. It assumes that the sectors are unprotected, and have the default access keys of 0xFF for the sectors.

If the sectors are protected then without knowing the protection keys you have a much harder job cracking these protected sectors. You have to resort to a brute force approach.

As you want to use a 3V3 powered processor the hardware interfacing should be simple.

Thanks so much Grumpy. First positive hope I got!
I'm a little out of my depth here. (I do old 86 type cpu's. See (https://www.s100computers.com)). Anyway a few basic questions:-

I'm using 'standard' SD cards not an RIF reader. Will the code still work.
Since yours is a reader can I use the library to write sectors as well.
I want to use an ESP32-S3 module to do the sector read/writes. How do I decide and define the pins to interface the SD card. I have plenty of ESP32 S3 pins. I just want to know how to use the equivalent Arduino pins you used (10-13).
Can I just incorporate your "library.json" in my Arduino IDE (set for an ESP32 S3 Dev model).

John

Sorry but no.

SD cards have their own file file system in them for wear levelling sector allocation. There is no way round it.

Sorry for miss understanding what you had.

Mike I don't think accessing the SD card sectors is an issue. I read somewhere the same one can be written to a sector 100000 times before it fails.

I have written direct sector R/W's using a Z80 see here

with no problem.

I want to do the same thing with an ESP32 using the Arduino IDE.

I do. There is a 32 bit microprocessor inside each SD card that allocates blocks to files, marks bad blocks, implements wear leveling, transfers data, etc. As mentioned above.

You need to learn to talk to it using the SD card protocol, specific to the task.

According to the docs, for ESP32-S3, you can either use the SD library via SPI (slower) or SD_MMC with dedicated pins (faster). They both have sector access

  size_t numSectors();
  size_t sectorSize();
  uint64_t totalBytes();
  uint64_t usedBytes();
  bool readRAW(uint8_t *buffer, uint32_t sector);
  bool writeRAW(uint8_t *buffer, uint32_t sector);

If you're doing your own filesystem, not sure what kind of examples you expect. Was there a suitable MBR partition type to play nice with anything else on the drive? In any case, SD.begin() and be careful when writing.

I was able to read the MBR off a microSD in an M5Paper with the SD library.

  uint8_t buffer[SD.sectorSize()];
  if (SD.readRAW(buffer, 0)) {
    log_buf_i(buffer, sizeof(buffer));  // build with Core Debug Level: Info
  }

Absolutely fantastic kenb4, thanks. Will try it out
John M

Hi kenb4.
I cannot seem to get the following code to read an SD card sector as you suggested.

uint8_t buffer[SD.sectorSize()];
     SD.readRAW(buffer, 0);

int16_t z, char_count=0;  
 uint8_t value;
for (z=0; z<=512;  z++){
    value = buffer[z];
    if(char_count++ >= 32){
      Serial.print("\n");
      char_count = 0;
      }
    Serial.print(value,HEX);
  }

I just get all 0's no matter what the sector # is. There is no problem accessing the card with SD functions, gets the correct card type and can read/write to whole files etc.

Any suggestions from you or anybody else.
John

For starters, readRAW returns bool -- did it return true or false?

Try compiling with Core Debug Level set to Verbose

Ken I sent you a private message here yesterday did you get it?
John M

Ken I tried the following code:-

#define SD_MOSI 13
#define SD_MISO 12
#define SD_SCK 14
#define SD_CS_A 11
#define SD_CS_B 10

#include "FS.h"
#include "SD.h"
#include "SPI.h"
#include <SPI.h>

void setup() {
 Serial.begin(115200);
 delay(1000);
 Serial.println("In Setup");
 
  //SD.begin(4, *M5.EPD.GetSPI(), 20000000);
  SD.begin();
  uint32_t sector = 123;
  uint8_t buffer[SD.sectorSize()];

    if (!SD.readRAW(buffer, sector)) {
         Serial.println("Read failed");
      }
    Serial.println("Sector Read"); 
}

void loop() {
}

Got a runtime error:-
"Guru Meditation Error: Core 1 panic'ed (loadProbition). Exception was unhandled." Then a register dump.

If insted I use your "SD.begin(4, *M5.EPD.GetSPI(), 20000000);"
I get a compile error 'M5' was not declared in this scope.

Any suggestions?

You are using the wrong symbols to enclose your code.
You are using ''' which is the lower case of the double quote key "

Where as you need to use three back ticks, which on my keyboard is the un-shifted tilder key ~

Please amend your last post.

How do you amendn a post?

image

I didn't realize you also started that later thread on the same topic recently. As I said there -- maybe not clearly enough -- you need to determine the board-specific parameters for SD.begin

You haven't said exactly which board you are using. As I mentioned above here -- two months ago -- I'm using an M5Paper. The M5 variable is specific to that manufacturer, and declared by #include <M5EPD.h> for that board.

The micro-SD slot is built-in, and there's a handy diagram on the back


showing the CS (Chip Select) pin is 4. The CS is the first parameter for SD.begin; and that's the 4 that works on the M5Paper. I don't know where you got these two

but if you don't have more concrete wiring info, you could try one and then the other to see if either works (omit the other two arguments so they are the default)

SD.begin(SD_CS_A)  // or SD_CS_B

This may be a lost cause Ken.
SD_CS_A selects 11 for "Drive A:"I actually have two SD cards attached to the ESP32:-

SD_CS_A selects 11 for "Drive A:"
SD_CS_B selects 10 for "Drive B:"
Pins 13= SD_MOSI for both, 13 = SD_MISO & 14 =SD_CLK

Here is my most recent simple code:-

#define SD_MOSI 13
#define SD_MISO 12
#define SD_SCK 14
#define SD_CS_A 11
#define SD_CS_B 10

#include "FS.h"
#include "SD.h"
#include "SPI.h"
#include <SPI.h>

void setup() {
 Serial.begin(115200);
 delay(1000);
 Serial.println("In Setup");
 
  //SD.begin(4, *M5.EPD.GetSPI(), 20000000);
  SD.begin(SD_CS_A);
  uint32_t sector = 123;
  uint8_t buffer[SD.sectorSize()];

    if (!SD.readRAW(buffer, sector)) {
         Serial.println("Read failed");
      }
    Serial.println("Sector Read"); 
}

void loop() {
}

I get the following runtime errors:-

'In Setup
Guru Mediation Error:  Core1 paniced (load Prohibited). Exception was unhandled.
Then a registry dump.'

Any further suggestions?