Advertisement
leonllr_Eduge

code for SD on C8051F38C

Apr 7th, 2025 (edited)
342
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 15.26 KB | Source Code | 0 0
  1. // SD.c
  2. #include "diskio.h"
  3.  
  4. #include "SPI.h"
  5. #include "SD.h"
  6. #include "Microseconds.h"
  7. #include <REG51F380.H> // registres C8051F38C
  8.  
  9. // data streaming
  10. #define FORWARD(d) {}
  11.  
  12. #define _USE_WRITE 1
  13.  
  14. // for vscode
  15. //typedef sbit sbit;
  16.  
  17. sbit SD_CS = P1^4;
  18.  
  19. static uint8_t CardType;            /* b0:MMC, b1:SDv1, b2:SDv2, b3:Block addressing */
  20.  
  21. // main source: http://www.rjhcoding.com/avrc-sd-interface-1.php
  22.  
  23. // https://electronics.stackexchange.com/questions/602105/hoVw-can-i-initialize-use-sd-cards-with-spi
  24. // http://elm-chan.org/docs/mmc/mmc_e.html
  25.    
  26. /*-----------------------------------------------------------------------*/
  27. /* Initialize Disk Drive                                                 */
  28. /*-----------------------------------------------------------------------*/
  29. DSTATUS disk_initialize(void);
  30.  
  31.  
  32. /*-----------------------------------------------------------------------*/
  33. /* Read partial sector                                                   */
  34. /*-----------------------------------------------------------------------*/
  35.  
  36. DRESULT disk_readp (
  37.     uint8_t *buff,      /* Pointer to the read buffer (NULL:Read bytes are forwarded to the stream) */
  38.     uint32_t sector,    /* Sector number (LBA) */
  39.     uint16_t offset,    /* Byte offset to read from (0..511) */
  40.     uint16_t count      /* Number of bytes to read (ofs + cnt mus be <= 512) */
  41. ) compact;
  42.  
  43.  
  44.  
  45. /*-----------------------------------------------------------------------*/
  46. /* Write partial sector                                                  */
  47. /*-----------------------------------------------------------------------*/
  48. DRESULT disk_writep (
  49.     const uint8_t *buff,    /* Pointer to the bytes to be written (NULL:Initiate/Finalize sector write) */
  50.     uint32_t sc         /* Number of bytes to send, Sector number (LBA) or zero */
  51. );
  52.  
  53. /*
  54. void SD_Powerup()
  55. {
  56.     uint8_t i;
  57.    // make sure card is deselected
  58.    SD_CS = SPI_CS_DISABLE;
  59.  
  60.    // give SD card time to power up
  61.    MicrosecondsWait1000();
  62.    MicrosecondsWait1000();
  63.  
  64.    // send 80 clock cycles to synchronize
  65.    for(i = 0; i < 10; i++)
  66.       SPIWrite8(0xFF);
  67.  
  68.    // deselect SD card
  69.    SD_CS = SPI_CS_DISABLE;
  70.    SPIWrite8(0xFF);
  71. }*/
  72.  
  73. uint8_t SPI_Transfer(uint8_t SPI_data)
  74. {
  75.    SPIWrite8(SPI_data);
  76.  
  77.    // added wait and delay to prevent write/read colision
  78.    while(!TXBMT) {};
  79.  
  80.     // very slight improvement only
  81.    MicrosecondsWait1();
  82.  
  83.    return SPIReadDirect();
  84. }
  85.  
  86. // for init
  87. uint8_t SPI_TransferSlow(uint8_t SPI_data)
  88. {
  89.    SPIWrite8(SPI_data);
  90.  
  91.    // added wait and delay to prevent write/read colision
  92.    while(!TXBMT) {};
  93.  
  94.    MicrosecondsWait1();
  95.     MicrosecondsWait1();
  96.     MicrosecondsWait1();
  97.     MicrosecondsWait1();
  98.  
  99.    return SPIReadDirect();
  100. }
  101.  
  102. uint8_t SD_SendCommand(uint8_t cmd, uint32_t arg)
  103. {
  104.    idata uint8_t crc = 0xFF;
  105.    data uint8_t n, res;
  106.  
  107.    // transmit command to sd card
  108.    SPIWrite8(cmd|0x40);
  109.  
  110.    // transmit argument
  111.    SPIWrite8((uint8_t)(arg >> 24));
  112.    SPIWrite8((uint8_t)(arg >> 16));
  113.    SPIWrite8((uint8_t)(arg >> 8));
  114.    SPIWrite8((uint8_t)(arg));
  115.  
  116.    // https://github.com/arduino-libraries/SD/blob/master/src/utility/Sd2Card.cpp#L132
  117.    if (cmd == CMD0) {
  118.       crc = 0X95;  // correct crc for CMD0 with arg 0
  119.    }
  120.    if (cmd == CMD8) {
  121.       crc = 0X87;  // correct crc for CMD8 w
  122.    }
  123.  
  124.    // transmit crc
  125.    SPIWrite8(crc);
  126.  
  127.  
  128.    /* Receive a command response */
  129.     n = 10;                             /* Wait for a valid response in timeout of 10 attempts */
  130.     do {
  131.         res = SPI_Transfer(0xFF);
  132.     } while ((res & 0x80) && --n);
  133.  
  134.     return res;         /* Return with the response value */
  135. }
  136.  
  137. // for init
  138. uint8_t SD_SendCommandSlow(uint8_t cmd, uint32_t arg)
  139. {
  140.    uint8_t crc = 0xFF;
  141.    uint8_t n, res;
  142.  
  143.    // transmit command to sd card
  144.    SPIWrite8(cmd|0x40);
  145.  
  146.    // transmit argument
  147.    SPIWrite8((uint8_t)(arg >> 24));
  148.    SPIWrite8((uint8_t)(arg >> 16));
  149.    SPIWrite8((uint8_t)(arg >> 8));
  150.    SPIWrite8((uint8_t)(arg));
  151.  
  152.    // https://github.com/arduino-libraries/SD/blob/master/src/utility/Sd2Card.cpp#L132
  153.    if (cmd == CMD0) {
  154.       crc = 0X95;  // correct crc for CMD0 with arg 0
  155.    }
  156.    if (cmd == CMD8) {
  157.       crc = 0X87;  // correct crc for CMD8 w
  158.    }
  159.  
  160.    // transmit crc
  161.    SPIWrite8(crc);
  162.  
  163.  
  164.    /* Receive a command response */
  165.     n = 10;                             /* Wait for a valid response in timeout of 10 attempts */
  166.     do {
  167.         res = SPI_TransferSlow(0xFF);
  168.     } while ((res & 0x80) && --n);
  169.  
  170.     return res;         /* Return with the response value */
  171. }
  172.  
  173.  
  174. /*--------------------------------------------------------------------------
  175.  
  176.    Public Functions
  177.  
  178. ---------------------------------------------------------------------------*/
  179.  
  180.  
  181. /*-----------------------------------------------------------------------*/
  182. /* Initialize Disk Drive                                                 */
  183. /*-----------------------------------------------------------------------*/
  184.  
  185. DSTATUS disk_initialize (void)
  186. {
  187.     xdata uint8_t n, cmd, ty, buf[4];
  188.     xdata uint16_t tmr;
  189.    xdata uint8_t i;
  190.    xdata uint8_t oldSpiFrequency;
  191.  
  192.    // hardware and pinout specific
  193.    //P0MDOUT   = 0x29;
  194.    //P0SKIP    = 0x07;
  195.    //XBR0      = 0x02;
  196.  
  197.  
  198.    // try keeping CKPOL at 0 for SD
  199.    SPI0CFG = 0x40;//| 0x10; // MSTEN | CKPOL
  200.    SPI0CN = 0x01; // SPIEN
  201.  
  202.    oldSpiFrequency = SPI0CKR;
  203.  
  204.    SPI0CKR = SPI0CKR_SPEED_INIT;
  205.    SPI0CFG &= ~(0x20 | 0x10); // have both CKPOL and CKPHA to 0
  206.  
  207.  
  208.     // assert chip select
  209.    SPIWrite8(0xFF);
  210.    SD_CS = SPI_CS_ENABLE;
  211.    SPIWrite8(0xFF);
  212.  
  213.     /* Dummy clocks */
  214.    for(i = 0; i < 10; i++) SPIWrite8(0xFF);
  215.  
  216.  
  217.    
  218.  
  219.     ty = 0;
  220.     if (SD_SendCommandSlow(CMD0, 0) == 1) {         /* Enter Idle state */
  221.         if (SD_SendCommandSlow(CMD8, 0x1AA) == 1) { /* SDv2 */
  222.             for (n = 0; n < 4; n++) buf[n] = SPI_TransferSlow(0xFF);    /* Get trailing return value of R7 resp */
  223.             if (buf[2] == 0x01 && buf[3] == 0xAA) {         /* The card can work at vdd range of 2.7-3.6V */
  224.                 for (tmr = 1000; tmr; tmr--) {              /* Wait for leaving idle state (ACMD41 with HCS bit) */
  225.                     if (SD_SendCommandSlow(ACMD41, 1UL << 30) == 0) break;
  226.                     MicrosecondsWait1000();
  227.                 }
  228.                 if (tmr && SD_SendCommandSlow(CMD58, 0) == 0) {     /* Check CCS bit in the OCR */
  229.                     for (n = 0; n < 4; n++) buf[n] = SPI_TransferSlow(0xFF);
  230.                     ty = (buf[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;  /* SDv2 (HC or SC) */
  231.                 }
  232.             }
  233.         } else {                            /* SDv1 or MMCv3 */
  234.             if (SD_SendCommandSlow(ACMD41, 0) <= 1)     {
  235.                 ty = CT_SD1; cmd = ACMD41;  /* SDv1 */
  236.             } else {
  237.                 ty = CT_MMC; cmd = CMD1;    /* MMCv3 */
  238.             }
  239.             for (tmr = 1000; tmr; tmr--) {          /* Wait for leaving idle state */
  240.                 if (SD_SendCommandSlow(cmd, 0) == 0) break;
  241.                 MicrosecondsWait1000();
  242.             }
  243.             if (!tmr || SD_SendCommandSlow(CMD16, 512) != 0)            /* Set R/W block length to 512 */
  244.                 ty = 0;
  245.         }
  246.     }
  247.     CardType = ty;
  248.  
  249.     // deassert chip select
  250.    SPIWrite8(0xFF);
  251.    SD_CS = SPI_CS_DISABLE;
  252.    SPIWrite8(0xFF);
  253.  
  254.    SPI0CKR = oldSpiFrequency;
  255.  
  256.     return ty ? 0 : STA_NOINIT;
  257. }
  258.  
  259.  
  260.  
  261. /*-----------------------------------------------------------------------*/
  262. /* Read partial sector                                                   */
  263. /*-----------------------------------------------------------------------*/
  264.  
  265. DRESULT disk_readp (
  266.     uint8_t *buff,      /* Pointer to the read buffer (NULL:Read bytes are forwarded to the stream) */
  267.     uint32_t sector,    /* Sector number (LBA) */
  268.     uint16_t offset,    /* Byte offset to read from (0..511) */
  269.     uint16_t count      /* Number of bytes to read (ofs + cnt mus be <= 512) */
  270. ) compact
  271. {
  272.     idata DRESULT res;
  273.     data uint8_t d;
  274.     idata uint16_t bc, tmr;
  275.    idata uint8_t oldSpiFrequency;
  276.  
  277.  
  278.    oldSpiFrequency = SPI0CKR;
  279.  
  280.    SPI0CKR = SPI0CKR_SPEED_NORMAL;
  281.  
  282.    // assert chip select
  283.    SPIWrite8(0xFF);
  284.    SD_CS = SPI_CS_ENABLE;
  285.    SPIWrite8(0xFF);
  286.  
  287.  
  288.  
  289.     if (!(CardType & CT_BLOCK)) sector *= 512;  /* Convert to byte address if needed */
  290.  
  291.     res = RES_ERROR;
  292.     if (SD_SendCommand(CMD17, sector) == 0) {       /* READ_SINGLE_BLOCK */
  293.  
  294.         tmr = 1000;
  295.         do {                            /* Wait for data packet in timeout of 100ms */
  296.             MicrosecondsWait100();
  297.             d = SPI_Transfer(0xFF);
  298.         } while (d == 0xFF && --tmr);
  299.  
  300.         if (d == 0xFE) {                /* A data packet arrived */
  301.             bc = 514 - offset - count;
  302.  
  303.             /* Skip leading bytes */
  304.             while(offset--) SPIWrite8(0xFF);
  305.  
  306.             /* Receive a part of the sector */
  307.             if (buff) { /* Store data to the memory */
  308.                 do
  309.                     *buff++ = SPI_Transfer(0xFF);
  310.                 while (--count);
  311.             } else {    /* Forward data to the outgoing stream */
  312.                 do {
  313.                     d = SPI_Transfer(0xFF);
  314.                     FORWARD(d);
  315.                 } while (--count);
  316.             }
  317.  
  318.             /* Skip trailing bytes and CRC */
  319.             while(bc--) SPIWrite8(0xFF);
  320.  
  321.             res = RES_OK;
  322.         }
  323.     }
  324.  
  325.     // deassert chip select
  326.    SPIWrite8(0xFF);
  327.    SD_CS = SPI_CS_DISABLE;
  328.    SPIWrite8(0xFF);
  329.  
  330.    SPI0CKR = oldSpiFrequency;
  331.  
  332.     return res;
  333. }
  334.  
  335.  
  336.  
  337. /*-----------------------------------------------------------------------*/
  338. /* Write partial sector                                                  */
  339. /*-----------------------------------------------------------------------*/
  340. #if _USE_WRITE
  341.  
  342. DRESULT disk_writep (
  343.     const uint8_t *buff,    /* Pointer to the bytes to be written (NULL:Initiate/Finalize sector write) */
  344.     uint32_t sc         /* Number of bytes to send, Sector number (LBA) or zero */
  345. )
  346. {
  347.     idata DRESULT res;
  348.     idata uint16_t bc, tmr;
  349.     static data uint16_t wc;
  350.    idata uint8_t oldSpiFrequency;
  351.  
  352.    oldSpiFrequency = SPI0CKR;
  353.  
  354.    SPI0CKR = SPI0CKR_SPEED_NORMAL;
  355.  
  356.    // assert chip select
  357.    SPIWrite8(0xFF);
  358.    SD_CS = SPI_CS_ENABLE;
  359.    SPIWrite8(0xFF);
  360.  
  361.  
  362.     res = RES_ERROR;
  363.  
  364.     if (buff) {     /* Send data bytes */
  365.         bc = (UINT)sc;
  366.         while (bc && wc) {      /* Send data bytes to the card */
  367.             SPIWrite8(*buff++);
  368.             wc--; bc--;
  369.         }
  370.         res = RES_OK;
  371.     } else {
  372.         if (sc) {   /* Initiate sector write transaction */
  373.             if (!(CardType & CT_BLOCK)) sc *= 512;  /* Convert to byte address if needed */
  374.             if (SD_SendCommand(CMD24, sc) == 0) {           /* WRITE_SINGLE_BLOCK */
  375.                 SPIWrite8(0xFF); SPIWrite8(0xFE);       /* Data block header */
  376.                 wc = 512;                           /* Set byte counter */
  377.                 res = RES_OK;
  378.             }
  379.         } else {    /* Finalize sector write transaction */
  380.             bc = wc + 2;
  381.             while (bc--) SPIWrite8(0);  /* Fill left bytes and CRC with zeros */
  382.             if ((SPI_Transfer(0xFF) & 0x1F) == 0x05) {  /* Receive data resp and wait for end of write process in timeout of 300ms */
  383.                 for (tmr = 10000; SPI_Transfer(0xFF) != 0xFF && tmr; tmr--) /* Wait for ready (max 1000ms) */
  384.                     MicrosecondsWait100();
  385.                 if (tmr) res = RES_OK;
  386.             }
  387.                 // deassert chip select
  388.             SPIWrite8(0xFF);
  389.             SD_CS = SPI_CS_DISABLE;
  390.             SPIWrite8(0xFF);
  391.  
  392.             SPI0CKR = oldSpiFrequency;
  393.         }
  394.     }
  395.  
  396.     return res;
  397. }
  398. #endif
  399.  
  400. // SD.h
  401. #ifndef __SD_H__
  402. #define __SD_H__
  403.  
  404. #include <REG51F380.H>
  405.  
  406. #include "types.h"
  407.  
  408.  
  409. // 100-400KHz during init
  410. #define SPI0CKR_SPEED_INIT (14*2*4)
  411. // max speed 20MHz+ is OK
  412. #define SPI0CKR_SPEED_NORMAL (0+3-1)
  413.  
  414.  
  415. #define CMD0_ARG    0x00000000
  416. #define CMD8_ARG    0x0000001AA
  417.  
  418. #define ACMD41_ARG  0x40000000
  419.  
  420. #define CMD0 0X00
  421. /** SEND_IF_COND - verify SD Memory Card interface operating condition.*/
  422. #define CMD8 0X08
  423. /** SEND_CSD - read the Card Specific Data (CSD register) */
  424. #define CMD9 0X09
  425. /** SEND_CID - read the card identification information (CID register) */
  426. #define CMD10 0X0A
  427. /** SEND_STATUS - read the card status register */
  428. #define CMD13 0X0D
  429. /** READ_BLOCK - read a single data block from the card */
  430. #define CMD17 0X11
  431. /** WRITE_BLOCK - write a single data block to the card */
  432. #define CMD24 0X18
  433. /** WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION */
  434. #define CMD25 0X19
  435. /** ERASE_WR_BLK_START - sets the address of the first block to be erased */
  436. #define CMD32 0X20
  437. /** ERASE_WR_BLK_END - sets the address of the last block of the continuous
  438.     range to be erased*/
  439. #define CMD33 0X21
  440. /** ERASE - erase all previously selected blocks */
  441. #define CMD38 0X26
  442. /** APP_CMD - escape for application specific command */
  443. #define CMD55 0X37
  444. /** READ_OCR - read the OCR register of a card */
  445. #define CMD58 0X3A
  446. /** SET_WR_BLK_ERASE_COUNT - Set the number of write blocks to be
  447.      pre-erased before writing */
  448. #define ACMD23 0X17
  449.  
  450. /** SD_SEND_OP_COMD - Sends host capacity support information and
  451.     activates the card's initialization process */
  452. #define ACMD41 0X29
  453.  
  454. #define PARAM_ERROR(X)      X & 0b01000000
  455. #define ADDR_ERROR(X)       X & 0b00100000
  456. #define ERASE_SEQ_ERROR(X)  X & 0b00010000
  457. #define CRC_ERROR(X)        X & 0b00001000
  458. #define ILLEGAL_CMD(X)      X & 0b00000100
  459. #define ERASE_RESET(X)      X & 0b00000010
  460. #define IN_IDLE(X)          X & 0b00000001
  461.  
  462. /*struct SD_Error_Struct {
  463.    unsigned IN_WHILE:1;
  464.    unsigned ERASE_RESET:1;
  465.    unsigned ILLEGAL_CMD:1;
  466.    unsigned CRC_ERROR:1;
  467.    unsigned ERASE_SEQ_ERROR:1;
  468.    unsigned ADDR_ERROR:1;
  469.    unsigned PARAM_ERROR:1;
  470.    unsigned padding:1;
  471. } SD_Error_t;*/
  472.  
  473.  
  474.  
  475.  
  476. #define CMD_VER(X)          ((X >> 4) & 0xF0)
  477. #define VOL_ACC(X)          (X & 0x1F)
  478.  
  479. #define VOLTAGE_ACC_27_33   0b00000001
  480. #define VOLTAGE_ACC_LOW     0b00000010
  481. #define VOLTAGE_ACC_RES1    0b00000100
  482. #define VOLTAGE_ACC_RES2    0b00001000
  483.  
  484.  
  485. #define SD_IN_IDLE_STATE    0x01
  486. #define SD_READY            0x00
  487. #define SD_R1_NO_ERROR(X)   X < 0x02
  488.  
  489. #define R3_BYTES            4
  490. #define R7_BYTES            4
  491.  
  492. #define CMD0_MAX_ATTEMPTS       255
  493. #define CMD55_MAX_ATTEMPTS      255
  494. #define SD_ERROR                1
  495. #define SD_SUCCESS              0
  496. #define SD_MAX_READ_ATTEMPTS    1563
  497. #define SD_MAX_WRITE_ATTEMPTS   3907
  498. #define SD_READ_START_TOKEN     0xFE
  499. #define SD_INIT_CYCLES          80
  500.  
  501. #define SD_START_TOKEN          0xFE
  502. #define SD_ERROR_TOKEN          0x00
  503.  
  504. #define SD_DATA_ACCEPTED        0x05
  505. #define SD_DATA_REJECTED_CRC    0x0B
  506. #define SD_DATA_REJECTED_WRITE  0x0D
  507.  
  508. #define SD_BLOCK_LEN            512
  509.  
  510. /*--------------------------------------------------------------------------
  511.  
  512.    Module Private Functions
  513.  
  514. ---------------------------------------------------------------------------*/
  515.  
  516.  
  517. /* Definitions for MMC/SDC command */
  518. //#define CMD0  (0x40+0)    /* GO_IDLE_STATE */
  519. #define CMD1    (0x40+1)    /* SEND_OP_COND (MMC) */
  520. //#define   ACMD41  (0xC0+41)   /* SEND_OP_COND (SDC) */
  521. //#define CMD8  (0x40+8)    /* SEND_IF_COND */
  522. #define CMD16   (0x40+16)   /* SET_BLOCKLEN */
  523. //#define CMD17 (0x40+17)   /* READ_SINGLE_BLOCK */
  524. //#define CMD24 (0x40+24)   /* WRITE_BLOCK */
  525. //#define CMD55 (0x40+55)   /* APP_CMD */
  526. //#define CMD58 (0x40+58)   /* READ_OCR */
  527.  
  528. /* Card type flags (CardType) */
  529. #define CT_MMC              0x01    /* MMC ver 3 */
  530. #define CT_SD1              0x02    /* SD ver 1 */
  531. #define CT_SD2              0x04    /* SD ver 2 */
  532. #define CT_SDC              (CT_SD1|CT_SD2) /* SD */
  533. #define CT_BLOCK            0x08    /* Block addressing */
  534.  
  535.  
  536.  
  537. //void SD_Powerup();
  538.  
  539. uint8_t SPI_Transfer(uint8_t SPI_data);
  540. uint8_t SPI_TransferSlow(uint8_t SPI_data);
  541.  
  542. uint8_t SD_SendCommand(uint8_t cmd, uint32_t arg);
  543. uint8_t SD_SendCommandSlow(uint8_t cmd, uint32_t arg);
  544.  
  545. /*
  546. // R1 seams to be a header for other commands
  547. uint8_t SD_readResponseR1();
  548.  
  549. uint8_t SD_GoIdle();
  550.  
  551. void SD_readResponseR7R3(uint8_t *res);
  552.  
  553. uint8_t SD_Init();
  554.  
  555. void SD_SendInterfaceCondition(uint8_t *res);
  556.  
  557. void SD_ReadOCR(uint8_t *res);
  558.  
  559. uint8_t SD_sendAppSpecificCMDStatus();
  560.  
  561. uint8_t SD_sendOperationConditions();
  562.  
  563. uint8_t SD_ReadSingleBlock(uint32_t addr, uint8_t *buf, uint8_t *token);
  564.  
  565. //uint8_t SD_WriteSingleBlock(uint32_t addr, uint8_t *buf, uint8_t *token);
  566. */
  567.  
  568.  
  569.  
  570.  
  571. #endif
Tags: sd F38C C51
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement