Shop OBEX P1 Docs P2 Docs Learn Events
P2 uSD Card Driver — FAT32 Filesystem (spin2/pasm2) - Page 2 — Parallax Forums

P2 uSD Card Driver — FAT32 Filesystem (spin2/pasm2)

2

Comments

  • evanhevanh Posts: 17,122
    edited 2026-03-04 23:43

    It's an older 2013 Adata 16GB. My first uSD card. But just marking cards as incompatible is hardly a good solution. Need to resolve to a solution that makes them work. That goes for your Silicon Power card too. I presume it works with Flexspin's built-in FAT32 filesystem just fine?

    Also, we're hardly experts on implementing the spec. I found many times, that experience taught me, I wasn't reading the spec correctly in the first place. EDIT: Or just didn't read it at all.

  • Stephen MoracoStephen Moraco Posts: 442
    edited 2026-03-04 23:55

    @evanh said:
    It's an older 2013 Adata 16GB. My first uSD card. But just marking cards as incompatible is hardly a good solution.

    My intent is to get every card I find working. I didn't want to delay releasing this driver to everyone while I worked on one errant card. ;-)

  • RaymanRayman Posts: 16,113

    @evanh does it work with any other p2 usd driver? 2013 is pretty old…

  • evanhevanh Posts: 17,122
    edited 2026-03-05 07:50

    @Rayman said:
    @evanh does it work with any other p2 usd driver? 2013 is pretty old…

    Yes, it's one of my regular set of test cards.

    Here it is with the plug-in 4-bit driver and Flexspin's built-in FAT32 filesystem:

       clkfreq = 200000000   clkmode = 0x10009fb
      Compiled with FlexC v7.6.4
    SD card driver (4-bit SD mode) v1.13
     sdsd_open: using pins: 21 20 16 23 22
     Card detected ... power cycle of SD card
      power-down threshold = 37   pin state = 1
      power-down slope = 21099 us   pin state = 0
     SD clock-divider set to sysclock/500 (400 kHz)
     Card idle OK
     OCR register c0ff8000  - SDHC/SDXC Card
     Data Transfer Mode entered - Published RCA 59b40000
     CID register backed up
     4-bit data interface engaged
      Speed Class = C10  UHS Grade = U1
      Video Class = V0  App Class = A0
      Cache = 0  Queue = 0
      TRIM = 0  FULE = 0
      Card User Capacity = 15067 MB (14.71 GB)
     High-Speed access mode engaged
     SD clock-divider set to sysclock/4 (50.0 MHz)
      rxlag=10 selected  Lowest=6 Highest=13
     CID decode:  ManID=1d   OEMID=AD  Name=SD   
      Ver=0.2   Serial=b16204c2   Date=2013-3
    SD Card Init Successful
     cluster size = 8192 bytes
    
     Buffer = 2 kB,  Written 512 kB at 4711 kB/s,  Verified,  Read 512 kB at 14631 kB/s
     Buffer = 2 kB,  Written 512 kB at 7815 kB/s,  Verified,  Read 512 kB at 14606 kB/s
     Buffer = 2 kB,  Written 512 kB at 7834 kB/s,  Verified,  Read 512 kB at 14615 kB/s
    
     Buffer = 8 kB,  Written 2048 kB at 7298 kB/s,  Verified,  Read 2048 kB at 19449 kB/s
     Buffer = 8 kB,  Written 2048 kB at 5986 kB/s,  Verified,  Read 2048 kB at 19448 kB/s
     Buffer = 8 kB,  Written 2048 kB at 7582 kB/s,  Verified,  Read 2048 kB at 19448 kB/s
    
     Buffer = 32 kB,  Written 4096 kB at 10385 kB/s,  Verified,  Read 4096 kB at 19987 kB/s
     Buffer = 32 kB,  Written 4096 kB at 11326 kB/s,  Verified,  Read 4096 kB at 19987 kB/s
     Buffer = 32 kB,  Written 4096 kB at 10785 kB/s,  Verified,  Read 4096 kB at 19986 kB/s
    
    exit
    

    And same again using Flexspin's built-in SD driver too:

       clkfreq = 200000000   clkmode = 0x10009fb
      Compiled with FlexC v7.6.4
    disk_initialize: PINS=21 19 20 16
    remapped PINS=21 19 20 16 18
    smartpin modes:  21=00064048  20=01000078  18=6300003a
    idle OK
    SDHC 25 MHz selected
    ty = 12
    SPI clock ratio = sysclock/8
     cluster size = 8192 bytes
    
     Buffer = 2 kB,  Written 512 kB at 640 kB/s,  Verified,  Read 512 kB at 1753 kB/s
     Buffer = 2 kB,  Written 512 kB at 627 kB/s,  Verified,  Read 512 kB at 1753 kB/s
     Buffer = 2 kB,  Written 512 kB at 643 kB/s,  Verified,  Read 512 kB at 1754 kB/s
    
     Buffer = 8 kB,  Written 2048 kB at 1542 kB/s,  Verified,  Read 2048 kB at 2563 kB/s
     Buffer = 8 kB,  Written 2048 kB at 1581 kB/s,  Verified,  Read 2048 kB at 2564 kB/s
     Buffer = 8 kB,  Written 2048 kB at 1592 kB/s,  Verified,  Read 2048 kB at 2563 kB/s
    
     Buffer = 32 kB,  Written 4096 kB at 1618 kB/s,  Verified,  Read 4096 kB at 2567 kB/s
     Buffer = 32 kB,  Written 4096 kB at 1606 kB/s,  Verified,  Read 4096 kB at 2567 kB/s
     Buffer = 32 kB,  Written 4096 kB at 1602 kB/s,  Verified,  Read 4096 kB at 2566 kB/s
    clear pins 21 19 20 16 18
    
    exit
    
  • evanhevanh Posts: 17,122

    @"Stephen Moraco" said:
    @evanh, ok, how can I help?

    Two things, first off (1) can you please identify the failing card? There is a utility (UTILS/) that reads the controller's registers and generates a two-line card identifier (UTILS/SD_card_characterize.spin2), if you will. And then (2) also in utilities, run the audit tool (UTILS/SD_FAT32_audit.spin2). This is non-destructive and surveys the entire silesystem structure on the card, reporting all errors.

    Audit gets nowhere until I force an okay check:

    Cog0  INIT $0000_0000 $0000_0000 load
    Cog0  INIT $0000_0404 $0000_0000 load
    Cog0  ==============================================
    Cog0    FAT32 Audit (via isp_fsck_utility)
    Cog0  ==============================================
    Cog0   
    Cog1  INIT $0000_0404 $0000_E08C load
    Cog2  INIT $0000_0404 $0000_E8F4 load
    Cog0  === FAT32 Filesystem Audit (read-only) ===
    Cog0  Card: 15067 MB
    Cog0   
    Cog0    ERROR: Invalid MBR signature
    Cog0  ERROR: Cannot read filesystem geometry
    Cog0   
    Cog0  END_SESSION
    

    checkCardStatus() forced okay:

    Cog0  INIT $0000_0000 $0000_0000 load
    Cog0  INIT $0000_0404 $0000_0000 load
    Cog0  ==============================================
    Cog0    FAT32 Audit (via isp_fsck_utility)
    Cog0  ==============================================
    Cog0   
    Cog1  INIT $0000_0404 $0000_E088 load
    Cog2  INIT $0000_0404 $0000_E8F0 load
    Cog0  === FAT32 Filesystem Audit (read-only) ===
    Cog0  Card: 15067 MB
    Cog0   
    Cog0    Geometry:
    Cog0      Partition start:  2048
    Cog0      Sectors/cluster:  16
    Cog0      Sectors/FAT:      15056
    Cog0      Total clusters:   1926564
    Cog0      Root cluster:     2
    Cog0      Data start:       32192
    Cog0   
    Cog0  Checking MBR (sector 0)...
    Cog0    [PASS] MBR boot signature ($AA55)
    Cog0    [PASS] Partition 1 boot flag ($00/$80)
    Cog0    [FAIL] Partition type ($0C = FAT32 LBA)
    Cog0    [PASS] Partition start > 0
    Cog0      Partition start: sector 2048
    Cog0    [PASS] Partition size > 0
    Cog0      Partition size: 30855168 sectors
    Cog0   
    Cog0  Checking VBR (boot sector)...
    Cog0    [PASS] VBR jump ($EB or $E9)
    Cog0    [PASS] VBR boot signature ($AA55)
    Cog0    [PASS] Bytes/sector = 512
    Cog0    [PASS] Sectors/cluster power of 2
    Cog0      Sectors/cluster: 16
    Cog0    [PASS] Reserved sectors = 32
    Cog0    [PASS] Number of FATs = 2
    Cog0    [PASS] Root entry count = 0 (FAT32)
    Cog0    [PASS] Total sectors 16-bit = 0
    Cog0    [PASS] Media type = $F8
    Cog0    [PASS] FAT size 16-bit = 0
    Cog0    [PASS] Hidden sectors = partition start
    Cog0    [PASS] Total sectors 32-bit > 0
    Cog0      Total sectors: 30855168
    Cog0    [PASS] Sectors per FAT > 0
    Cog0      Sectors/FAT: 15056
    Cog0    [PASS] Root cluster = 2
    Cog0    [PASS] FSInfo at sector 1
    Cog0    [PASS] Backup boot at sector 6
    Cog0    [PASS] Extended boot sig = $29
    Cog0    [PASS] FS type = FAT32
    Cog0   
    Cog0  Checking Backup VBR...
    Cog0    [PASS] Backup VBR matches primary
    Cog0   
    Cog0  Checking FSInfo sector...
    Cog0    [PASS] Lead signature ($41615252)
    Cog0    [PASS] Struct signature ($61417272)
    Cog0    [PASS] Trail signature ($AA550000)
    Cog0    [PASS] Free cluster count set
    Cog0      Free clusters: 1924898
    Cog0    [PASS] Next free hint valid
    Cog0    [FAIL] Backup FSInfo matches primary
    Cog0   
    Cog0  Checking FAT table...
    Cog0    [PASS] FAT[0] = $0FFFFFF8 (media)
    Cog0    [PASS] FAT[1] = $0FFFFFFF (EOC)
    Cog0    [PASS] FAT[2] root cluster allocated
    Cog0    [PASS] FAT1 first sector == FAT2
    Cog0   
    Cog0  Checking Root Directory...
    Cog0    [PASS] Volume label entry (attr=$08)
    Cog0    [PASS] Valid volume label chars
    Cog0    [PASS] Second entry valid or end
    Cog0   
    Cog0  Checking mount/unmount cycle...
    Cog0    [PASS] mount() succeeds
    Cog0    Calculating free space...
    Cog0    [PASS] Free space > 0
    Cog0      Free: 30808000 sectors
    Cog0   
    Cog0   
    Cog0  === AUDIT COMPLETE ===
    Cog0  Tests: 39  Pass: 37
    Cog0  Fail: 2
    Cog0  FILESYSTEM INTEGRITY: ISSUES DETECTED
    Cog0   
    Cog0  Failed checks:
    Cog0    - Partition type ($0C = FAT32 LBA)
    Cog0    - Backup FSInfo matches primary
    Cog0   
    Cog0  END_SESSION
    
  • evanhevanh Posts: 17,122

    Characterize with forced okay:

    Cog0  INIT $0000_0000 $0000_0000 load
    Cog0  INIT $0000_0404 $0000_0000 load
    Cog0  ##############################################
    Cog0  #  SD Card Characterization Report V3       #
    Cog0  #  All register fields - comprehensive      #
    Cog0  ##############################################
    Cog0   
    Cog0  Initializing SD card (no-mount mode)...
    Cog1  INIT $0000_0404 $0000_C108 load
    Cog0  Card initialized successfully.
    Cog0   
    Cog0  --- Reading Card Registers ---
    Cog0    CID: OK (16 bytes)
    Cog0    CSD: OK (16 bytes)
    Cog0    SCR: OK (8 bytes)
    Cog0    OCR: OK (4 bytes)
    Cog0    SD Status: OK (64 bytes)
    Cog0   
    Cog0   
    Cog0  ======== CID REGISTER (Card Identification) ========
    Cog0  [USED] = Field used by V3 driver
    Cog0  [INFO] = Informational only
    Cog0   
    Cog0  [USED] MID (Manufacturer ID):     $$1D (AData)
    Cog0  [INFO] OID (OEM/Application ID): $$41 $$44 (ASCII)
    Cog0  [INFO] PNM (Product Name):        [SD   ]
    Cog0  [INFO] PRV (Product Revision):    0.2
    Cog0  [INFO] PSN (Serial Number):       $$B162_04C2
    Cog0  [INFO] MDT (Manufacturing Date): 2_013-03
    Cog0  [INFO] CRC7:                      $$7E
    Cog0   
    Cog0  ======== CSD REGISTER (Card Specific Data) ========
    Cog0   
    Cog0  [USED] CSD_STRUCTURE:        1 (CSD Version 2.0)
    Cog0         Card Type:            SDHC/SDXC (High/Extended Capacity)
    Cog0   
    Cog0  --- Timing Parameters ---
    Cog0  [USED] TRAN_SPEED:           $$32 (25 MHz max)
    Cog0  [USED] TAAC:                 $$0E (read access time-1)
    Cog0  [USED] NSAC:                 0 (read access time-2, CLK cycles)
    Cog0  [USED] R2W_FACTOR:           2 (write time = read time x 4)
    Cog0         Read Timeout:         100 ms (calculated)
    Cog0         Write Timeout:        250 ms (calculated)
    Cog0   
    Cog0  --- Capacity ---
    Cog0  [USED] C_SIZE:               30_133 (15_067 MB)
    Cog0         Capacity:             ~14 GB
    Cog0         Total Sectors:        30_857_216
    Cog0   
    Cog0  --- Command Classes (CCC) ---
    Cog0  [INFO] CCC:                  $$5B5
    Cog0         Class 0 (basic):      Yes
    Cog0         Class 2 (block read): Yes
    Cog0         Class 4 (block write):Yes
    Cog0         Class 5 (erase):      Yes
    Cog0         Class 6 (write prot): No
    Cog0         Class 7 (lock card):  Yes
    Cog0         Class 8 (app spec):   Yes
    Cog0         Class 10 (switch):    Yes
    Cog0   
    Cog0  --- Block Parameters ---
    Cog0  [INFO] READ_BL_LEN:          9 (512 bytes)
    Cog0  [INFO] WRITE_BL_LEN:         9 (512 bytes)
    Cog0  [INFO] READ_BL_PARTIAL:      0
    Cog0  [INFO] WRITE_BL_PARTIAL:     0
    Cog0  [INFO] READ_BLK_MISALIGN:    0
    Cog0  [INFO] WRITE_BLK_MISALIGN:   0
    Cog0   
    Cog0  --- Erase Parameters ---
    Cog0  [INFO] ERASE_BLK_EN:         1 (512-byte erase)
    Cog0  [INFO] SECTOR_SIZE:          127 (erase sector = 65_536 bytes)
    Cog0   
    Cog0  --- Write Protection ---
    Cog0  [INFO] WP_GRP_SIZE:          0
    Cog0  [INFO] WP_GRP_ENABLE:        0
    Cog0  [INFO] PERM_WRITE_PROTECT:   0
    Cog0  [INFO] TMP_WRITE_PROTECT:    0
    Cog0   
    Cog0  --- Other Fields ---
    Cog0  [INFO] DSR_IMP:              0 (Driver Stage Register not implemented)
    Cog0  [INFO] FILE_FORMAT_GRP:      0
    Cog0  [INFO] FILE_FORMAT:          0
    Cog0  [INFO] COPY:                 0
    Cog0  [INFO] CRC7:                 $$76
    Cog0   
    Cog0  ======== OCR REGISTER (Operating Conditions) ========
    Cog0   
    Cog0         OCR Value:            $$C0FF_8000
    Cog0   
    Cog0  [INFO] Bit 31 (Power Up):    1 (Ready)
    Cog0  [USED] Bit 30 (CCS):         1 (SDHC/SDXC) ** CRITICAL: Determines addressing mode **
    Cog0  [INFO] Bit 29 (UHS-II):      0 (Not UHS-II)
    Cog0  [INFO] Bit 24 (S18A):        0 (3.3V only)
    Cog0   
    Cog0  --- Voltage Window ---
    Cog0  [INFO] 3.5-3.6V:             Supported
    Cog0  [INFO] 3.4-3.5V:             Supported
    Cog0  [INFO] 3.3-3.4V:             Supported
    Cog0  [INFO] 3.2-3.3V:             Supported
    Cog0  [INFO] 3.1-3.2V:             Supported
    Cog0  [INFO] 3.0-3.1V:             Supported
    Cog0  [INFO] 2.9-3.0V:             Supported
    Cog0  [INFO] 2.8-2.9V:             Supported
    Cog0  [INFO] 2.7-2.8V:             Supported
    Cog0   
    Cog0  ======== SCR REGISTER (SD Configuration) ========
    Cog0   
    Cog0  [INFO] SCR_STRUCTURE:        0 (SCR Version 1.0)
    Cog0  [USED] SD_SPEC:              2
    Cog0         SD Version:           3.0x
    Cog0  [INFO] SD_SPEC3:             1 (SD 3.0 support: Yes)
    Cog0  [INFO] SD_SPEC4:             0 (SD 4.0 support: No)
    Cog0  [INFO] SD_SPECX:             0 (SD 5.x/6.x/7.x indicator)
    Cog0   
    Cog0  --- Bus Width Support ---
    Cog0  [INFO] SD_BUS_WIDTHS:        $$05
    Cog0         1-bit bus:            Supported (SPI mode uses this)
    Cog0         4-bit bus:            Supported
    Cog0   
    Cog0  --- Security ---
    Cog0  [INFO] SD_SECURITY:          3
    Cog0         Security:             SDHC Card (security v2.00)
    Cog0  [INFO] EX_SECURITY:          0
    Cog0   
    Cog0  --- Command Support ---
    Cog0  [INFO] CMD_SUPPORT:          $$00
    Cog0   
    Cog0  [INFO] DATA_STAT_AFTER_ERASE:0
    Cog0   
    Cog0  ======== RAW REGISTER DATA ========
    Cog0   
    Cog0  CID: $1D $41 $44 $53 $44 $20 $20 $20 $02 $B1 $62 $04 $C2 $00 $D3 $FD
    Cog0  CSD: $40 $0E $00 $32 $5B $59 $00 $00 $75 $B5 $7F $80 $0A $40 $00 $ED
    Cog0  OCR: $$C0FF_8000
    Cog0  SCR: $02 $35 $80 $03 $00 $00 $00 $00
    Cog0   
    Cog0  ======== FILESYSTEM INFORMATION ========
    Cog0   
    Cog0  MBR Partition Type:          $$0B
    Cog0                               FAT32 (CHS)
    Cog0  VBR at sector:               2_048
    Cog0   
    Cog0  --- FAT32 Filesystem ---
    Cog0  OEM Name:                    [mkfs.fat]
    Cog0  Volume Label:                [ADATA16    ]
    Cog0  Volume Serial:               $$F711_D3AB
    Cog0  FS Type:                     [FAT32   ]
    Cog0  Bytes/Sector:                512
    Cog0  Sectors/Cluster:             16 (8 KB clusters)
    Cog0  Reserved Sectors:            32
    Cog0  Number of FATs:              2
    Cog0  Sectors per FAT:             15_056
    Cog0  Root Cluster:                2
    Cog0  Total Sectors:               30_855_168
    Cog0  Data Region Start:           Sector 30_144
    Cog0  Total Clusters:              1_926_564
    Cog0   
    Cog0  ##############################################
    Cog0    UNIQUE CARD ID: AData_SD_0.2_B16204C2_201303
    Cog0  ##############################################
    Cog0   
    Cog0  ##############################################
    Cog0    CARD DESIGNATOR
    Cog0  ##############################################
    Cog0  AData SD    SDHC 14GB [FAT32] SD 3.x rev0.2 SN:$B162_04C2 2_013/03
    Cog0  Class 10, U1, V0, SPI 25 MHz  [mkfs.fat]
    Cog0  ##############################################
    Cog0   
    Cog0  ======== V3 DRIVER USAGE SUMMARY ========
    Cog0   
    Cog0  Fields marked [USED] are actively used by the driver:
    Cog0   
    Cog0  CID Register:
    Cog0    - MID: Determines PNY cards (20MHz limit) vs others (25MHz)
    Cog0   
    Cog0  CSD Register:
    Cog0    - CSD_STRUCTURE: Determines SDSC vs SDHC/SDXC formulas
    Cog0    - TRAN_SPEED: Calculates maximum SPI clock frequency
    Cog0    - TAAC/NSAC/R2W_FACTOR: Calculates timeouts (SDSC only)
    Cog0    - C_SIZE + multipliers: Calculates card capacity
    Cog0   
    Cog0  SCR Register:
    Cog0    - SD_SPEC: Determines CMD6 (High Speed) support
    Cog0   
    Cog0  OCR Register:
    Cog0    - CCS bit: CRITICAL - determines addressing mode
    Cog0      CCS=0: SDSC byte addressing (sector << 9)
    Cog0      CCS=1: SDHC/SDXC block addressing (sector)
    Cog0   
    Cog0  ##############################################
    Cog0  END_CHARACTERIZATION
    Cog0  ##############################################
    
  • Stephen MoracoStephen Moraco Posts: 442
    edited 2026-03-05 23:21

    @evanh hmm... your detail is helping me understand. It's starting to look like some controllers in the past reported CMD13 poorly. We can test for this case and detune our use of CMD13. Then your card will work. Also, changing two of the audit findings from error to warning. Does all this sound like what you expect?

    And thank you for all the details on what's happening. It left no question as to what's being seen and how the driver is reacting. As we learn about these edge case cards, I'm leaving detailed analysis documents in the repo for each case we find.

  • RaymanRayman Posts: 16,113

    @"Stephen Moraco" some usd drivers have option to not use a cog but use inline assembly instead. Could that be a future feature here?

  • evanhevanh Posts: 17,122
    edited 2026-03-06 00:33

    Until proven otherwise, I consider these cases as being buggy driver software not following the spec. I struck it a lot during the SD mode development. I'd mistime or reorder something that didn't upset most cards but there'd be one or two that threw a spaz because I did it wrong.

  • Stephen MoracoStephen Moraco Posts: 442
    edited 2026-03-06 00:43

    @evanh said:
    Until proven otherwise, I consider these cases as being buggy driver software not following the spec. I struck it a lot during the SD mode development. I'd mistime or reorder something that didn't upset most cards but there'd be one or two that threw a spaz because of my error.

    The challenge for me is that the data stream needs to be analyzed for cmd13 returns, as it's either bad content or mistimed (bit shifted), but how do we prove it? You have the card; I can't recreate this. Thoughts? Also, why are only the cmd13 responses affected if it's stream alignment? Your testing has proven that the data path for sector content is fine (CRC-protected reads/writes and is working). There are my other commands using the same SPI code, but only cmd13 is having sync problems? We've got more to learn here.

    I'm releasing a modified driver shortly. Can you test it against this card, please? v1.2.1. With the release, you'll have the full cmd13 analysis in the repo for review.

  • evanhevanh Posts: 17,122

    Yup, you deal with the cards you've got. I'll see what I can do at this end. I have the gear, I just have to get motivated.

    Actually, this is where splitting the SD driver from the FS handler would be helpful. Create a clear divide between what is filesystem management and what is device management.

    The sequences in Flexspin's original sdmm.c driver is rather small. Admittedly, it also doesn't provide any card details but the support for generic command/response is all there and can be used to make large reports or pass back the card data, via an ioctl() say.

    Also be able to easily swap in alternative drivers to compare. I did a lot more comparing once Eric had made a runtime plug-in interface for Flexspin's drivers.

  • @evanh said:
    Yup, you deal with the cards you've got. I'll see what I can do at this end. I have the gear, I just have to get motivated.

    OK, I published the point release v1.2.1. See also my findings from your logs: CMD13 Analysis and the implementation decision TD-009

    I'm completing the adjustments to my unfinished card now, too. Upcoming release.

  • evanhevanh Posts: 17,122

    Interesting reading about CMD13 not always supported by cards. So maybe not a driver bug then. I wonder if that might sometimes apply to SD mode too. CMD13 is not something I used for that driver either.

  • evanhevanh Posts: 17,122
    edited 2026-03-06 12:49

    Um, Stephen, where did you read about buggy CMD13 in cards? That better not have been AI hallucinations? I've just added it to the sdmm.c SPI mode driver from Flexspin and it's now happily producing valid CMD13 zero responses at end of every group of blocks read from all my SD cards.

    send_cmd() has an intriguing check in it though. It seems to skip over any reply bytes that have bit7 set. Not something I'd paid any attention to until now:

        ...
        /* Receive command response */
        if (cmd == CMD12) rcvr_mmc(buf+6, 1);   /* Skip a stuff byte when stop reading */
        n = 10;                             /* Wait for a valid response in timeout of 10 attempts */
        do
            rcvr_mmc(buf+6, 1);
        while ((buf[6] & 0x80) && --n);
    
        return buf[6];          /* Return with the response value */
    
  • Slop-driven development

  • evanhevanh Posts: 17,122

    Looking at the spec for SPI mode, there is indeed leeway for extra bytes between a command and its response:

    Ncr can be anything from 1 to 8 bytes.

  • evanhevanh Posts: 17,122

    So it makes sense to discard any bytes with a leading bit7 set high.

  • Stephen MoracoStephen Moraco Posts: 442
    edited 2026-03-06 21:19

    @evanh, yes, there are posts on the interwebs across various embedded forums and even microchip forums indicating cmd13 problems. We all know the quality of the information depends on the reporting user's experience level, but the reports are out there. I'm still reviewing the details you provided. Thank you.

    While chasing the SP Elite problems to their root cause (my other card), I learned that our driver was not logging traffic, which was very telling. The newer Elite card was sending the next sector start while we were commanding it to stop sectors, causing full-duplex traffic. This prevented the driver from having definitive proof of the correct behavior and caused stuff to be in our RX pipeline. The spec is very clear about how to reset and continue in this case. Which we now do, and this newly working card is now one of our top performers.

    Given this new diagnostic thinking, I'm building a temporary early release, v1.2.9 (I'm about to release v1.3.0 after adding deeper regression testing). I'm adding full-duplex logging to the cmd13 handling to see if there is any further indication in the traffic pattern. I'll add a test/diagnostic source file to this distribution that you should be able to compile and run, then send me the logs. Since this is an older card, it is more of a long shot and may or may not provide new info to guide us, but it's worth looking at everything we can.

    FYI- This is now documented for this driver. The finding for this Elite card: multi-sector reads are supported in two ways: feed forward: send cmd23, number of sectors, then cmd18 reads the sectors, or terminate when complete: without using cmd23, use cmd18 to read the sectors, then send cmd12 to end the transfer. The Elite Card and the Lexar 64GB card both show cmd23 as supported in the register values, but in actual use, both devices, in SPI mode, fail the command as not supported, so the driver falls back to read and then terminates after the desired sector count is received.

    So it seems we have different behavior in SPI mode vs. SD mode. And we get to learn the boundaries experientially...

  • Stephen MoracoStephen Moraco Posts: 442
    edited 2026-03-06 21:38

    @evanh v1.2.9 is now available as a pre-release.

    So we need to run this against your older card.

    If you were using my tools, from the top folder of unpacked .zip, you would compile and run with
    - pnut-ts -d -I src/ diagnostic-tests/SD_diag_cmd13_capture.spin2
    - pnut-term-ts -r diagnostic-tests/SD_diag_cmd13_capture.bin

    This would auto capture the log in ./logs/

  • evanhevanh Posts: 17,122
    edited 2026-03-06 23:53

    @"Stephen Moraco" said:
    @evanh, yes, there are posts on the interwebs across various embedded forums and even microchip forums indicating cmd13 problems. We all know the quality of the information depends on the reporting user's experience level, but the reports are out there. I'm still reviewing the details you provided. Thank you.

    Well, it's pretty clear now that anyone who has ever had a single issue with CMD13 is also using shitty drivers that can't even handle a pretty basic requirement of expecting multiple filler turn-around bytes. It shouldn't take anyone reading the spec all that long to work it out.

    As for SD mode, it requires multiple filler turn-around bits, rather than bytes. Every clocked bit, starting from the third bit, has to be tested. And there's no particular limit on how many. But everyone uses a licenced hardware controller there instead, so you'll not be reading complaints about that.

  • evanhevanh Posts: 17,122
    edited 2026-03-07 00:08

    @"Stephen Moraco" said:
    FYI- This is now documented for this driver. The finding for this Elite card: multi-sector reads are supported in two ways: feed forward: send cmd23, number of sectors, then cmd18 reads the sectors, or terminate when complete: without using cmd23, use cmd18 to read the sectors, then send cmd12 to end the transfer. The Elite Card and the Lexar 64GB card both show cmd23 as supported in the register values, but in actual use, both devices, in SPI mode, fail the command as not supported, so the driver falls back to read and then terminates after the desired sector count is received.

    CMD23 is a similar situation to CMD13 for me - And I'm suspecting a similar outcome here. My experience with CMD23 is a single test in the early days. CMD12 is simpler to manage so CMD23 comes across as redundant and ends up not being used by performant drivers. It's comparable to the old C strings vs Pascal strings.

    At any rate, I expect we'll find out all the cards can handle both solutions and it's the driver with the bugs. Possibly the very same bug that threw CMD13.

  • Stephen MoracoStephen Moraco Posts: 442
    edited 2026-03-07 06:21

    @evanh, new v1.3.0 coming soon with revised CMD13 handling based on your findings above. It passes our new richer regression test suite. Please verify it's fully working for your older card now... thank you so much for being persistent.

  • NEWS

    I just released v1.3.0

    Here's what's new/fixed:

    v1.3.0

    R1 response parsing fix, CMD12 tolerance, CMD23 probing, 427 regression tests across 20 suites.

    Bug Fixes

    • R1 response parsing: skip bytes with bit 7 set per SD spec Section 7.3.2.1 (fixes CMD13 false errors on cards with bus artifacts)
    • CMD12 tolerance: multi-block reads recover via CS deassert on cards with aggressive read-ahead pipelines

    New Features

    • cardWarnings(): Bitmask API for init-time capability discoveries
    • CMD23 probing: automatic SET_BLOCK_COUNT detection and use when supported in SPI mode

    Improvements

    • recoverToIdle(): CS deassert recovery per SD spec Section 7.2.2
    • readSectors(): CMD23 path with auto-stop verification and fallback to CMD12

    Visit the P2 microSD FAT32 Filesystem repository for full documentation, including a driver tutorial, theory of operations, and card catalog.

    The release package can be downloaded from the Releases page. Download the sd-card-driver-{version}.zip
    file.

    If you find issues, please file them at the Issues page.

    What's next? Quickly address any reported issues. I've exhausted my card set after spending $$ to get a few more in my test pool. Hmm... what about SD Mode (6-wire spi) for this driver? Do we have users that would want that performance for the embedded application?

    Enjoy!

    Stephen

  • evanhevanh Posts: 17,122
    edited 2026-03-07 11:07

    [doh] It looks like you're right. The card is violating Ncs minimum of zero. The Flexspin sdmm.c driver has obviously been developed through trial and error so it has one blank byte preceding every command. This makes that card happy - And presumably many others too.

    I'll admit I'm surprised. And apologies for going a little aggressive. I can't say I've had too much of the driver not being the problem. Maybe you're also right about SPI mode being poor cousin too. ie: Manufacturers don't test it much.

    Here's a snapshot of sdmm.c issuing CMD13 - But it's the same for all commands.
    Top-mid screen - CS (Blue trace) is lowered to initiate a command. A blank spacer byte is issued with MOSI (Green trace) set high. Then the six byte command is issued. Then a blank response byte. Then the two byte R2 response (MISO, Pink trace) of all zeros. Orange trace is SD clock.

  • bob_g4bbybob_g4bby Posts: 571
    edited 2026-03-07 10:40

    Congratulations on this driver - it opens up the available memory space for programmers enormously. Judging by this thread, it's no wonder that Taqoz forth was a little fussy over which SD cards it would work with. The documentation and examples look to be excellent - getting up to speed with it will be quick.

  • evanhevanh Posts: 17,122

    It took me ages to get the scope all wired up today to record the above snapshot. A probe was still at work and I also crafted an external trigger cable as a fifth probe. Then I had trouble coaxing Stephen's code to remap the pin order to my hand wired SD slot - Which I didn't really need to do but I wanted to use that slot for all tests.

  • evanhevanh Posts: 17,122
    edited 2026-03-07 12:17

    Actually, what sdmm.c is really doing there is testing for card ready/busy. Which takes a minimum of one byte to confirm. It will in fact continue waiting for a ready state, clocking in more card busies for up to 500 ms.

    It does this check at beginning of every command except CMD12.

    PS: All very sensible and likely a common trait of well written drivers. Which maybe some card manufacturers have inadvertently keyed to.

  • evanhevanh Posts: 17,122

    Ha, and looking through your code, Stephen, it looks like for most if not all other command sequences you've already put a padding sp_transfer_8($FF) immediately following the pinl(cs). So that's why only CMD13 was a problem.

    You might want to make a generic send_command() function instead of building each sequence separately like that.

  • @evanh, what is the current state with v1.3.0 vs. your older card? Is the logic working?

    BTW- Good eye, and I had already noticed the code duplication when I saw so many identical fixes for the byte ignoring change. Reducing that now and rerunning the regression suite. Likely a v1.3.1 shortly. (it's much easier to make code reduction changes like this when we have a full regression suite in place!)

  • roglohrogloh Posts: 6,268
    edited 2026-03-08 04:44

    @"Stephen Moraco" said:
    Hmm... what about SD Mode (6-wire spi) for this driver? Do we have users that would want that performance for the embedded application?

    Yes, a higher performance SD card option for your driver would certainly be desirable. With sufficient buffering in RAM, it potentially opens the P2 & SD cards to further applications such as -

    • high speed logging - eg. logic analyser, high speed ADCs streaming to disk.
    • high speed video transfers to/from disk for capture/playback, even direct capture at VGA resolutions/refresh rates becomes feasible
    • running native P2 hubexec code or other bytecode directly off some cached removable storage?
    • faster transfers can increase performance when disk sharing amongst multiple COGs by reducing overall latency for other COGs to access the same disk
Sign In or Register to comment.