⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 maxim的对sd卡的串行spi模式进行读写操作控制的程序源码
💻 C
📖 第 1 页 / 共 3 页
字号:
   *     * Important note:   *  - Must be augmented with 7 zeros!   *   */    new_crc = old_crc;  for (x = 7; x >= 0; x--) {    new_crc <<= 1;    new_crc |= GETBIT(data,x);    if (GETBIT(new_crc, 7) == 1) {      new_crc ^= 0x89; /* XOR with poly -- this clears the top bit, too!*/    }  }  return new_crc;}/* Provides the zero-padding final step to CRC-7 * * Input arguments:       * *   old_crc - value from last call to crc_7() * * Returns: * *   Finalized CRC-7 checksum  * */uint8_t crc_7augment(uint8_t old_crc){  unsigned char new_crc;  int x;    new_crc = old_crc;  for (x = 0; x < 7; x++) {    new_crc <<= 1;    if (GETBIT(new_crc, 7) == 1) {      new_crc ^= 0x89; /* XOR with poly -- this clears the top bit, too!*/    }  }    return new_crc;}/* CRC-16 (CCITT) as described in the Secure Digital spec * * Input arguments:       * *   old_crc - 0x0000 to start new CRC, or value from previous call to continue *   data    - data byte to add to CRC computation * * Returns: * *   CRC-16 checksum which MUST be augmented by crc_16augment() before use * */uint16_t crc_16(uint16_t old_crc, uint8_t data){  uint16_t new_crc;  uint8_t flipit;  int x;  /* CRC-16's polynomial is x^16 + x^12 + x^5 + 1 */  new_crc = old_crc;  for (x = 7; x >= 0; x--) {    flipit = GETBIT(new_crc, 15); /* Carry-out from shift */    new_crc <<= 1;    new_crc |= GETBIT(data,x);    if (flipit == 1) {      /* Unlike CRC-7, we leave out the x^16 term because */      /* the carry bit has left our register */      new_crc ^= 0x1021;     }  }  return new_crc;}/* Provides the zero-padding final step to CRC-16 * * Input arguments:       * *   old_crc - value from last call to crc_16() * * Returns: * *   Finalized CRC-16 checksum  * */uint16_t crc_16augment(uint16_t old_crc){  uint16_t new_crc;  uint8_t flipit;  int x;    new_crc = old_crc;  for (x = 0; x < 16; x++) {    flipit = GETBIT(new_crc, 15);    new_crc <<= 1;    if (flipit == 1) {      new_crc ^= 0x1021;     }  }    return new_crc;}/* Verifies CRC-7 or CRC-16 against expected value * * Input arguments:       * *   type       - SD_CRC7 or SD_CRC16 *   b          - pointer to character data *   len        - length of data to check (must not be 0,  *                  which returns CRC_FAIL) *   expect     - expected CRC-7 (only LSB is significant) or CRC-16 value. * * Returns: * *   CRC_OK (0) - Data passes integrity check by selected CRC algorithm *   CRC_FAIL (-1) - Data fails integrity check or wrong */int verifyCRC(int type, uint8_t *b, uint32_t len, uint16_t expect){  uint16_t crc = 0x0000;  int i;  /* Sanity check arguments */  if ((b == NULL) || (len < 1) ||       (type != SD_CRC7) && (type != SD_CRC16)) {    return CRC_FAIL;  }  for (i = 0; i < len; i++) {    if (type == SD_CRC16) {      crc = crc_16(crc, *(b+i));    } else {      crc = crc_7((uint8_t)(crc & 0x00ff), *(b+i));    }  }  if (type == SD_CRC16) {    crc = crc_16augment(crc);  } else {    crc = crc_7augment(crc);  }  if (type == SD_CRC16) {    if (crc == expect) {      return CRC_OK;    }  } else {    if ((crc & 0x00ff) == (expect & 0x00ff)) {      return CRC_OK;    }  }  /* Always error out with failure by default. */  return CRC_FAIL;}/* Decode Card Identification register into human-readable format * * Input arguments: * *   b          - pointer to data buffer holding CID * * Returns: * *   <none> * */void decodeCID(uint8_t *b){  cprintf(C"  Manufacturer ID: 0x%02x\r\n", b[0]);  cprintf(C"  OEM/Application ID: %c%c\r\n", b[1], b[2]);  cprintf(C"  Product Name: %c%c%c%c%c\r\n", b[3], b[4], b[5], b[6], b[7]);  cprintf(C"  Product Revision: %u.%u\r\n", b[8], b[9]);  cprintf(C"  Serial Number: 0x%04x%04x\r\n", 	 (b[10] << 8)+b[11], (b[12] <<8) + b[13]);  cprintf(C"  Date Code: 0x%04x\r\n", ((b[13] & 0x0f) << 8) + b[14]);  return;}/* Transmit command to card. Calculates the proper CRC and handles framing  * * Input arguments: * *   cmd          - one of the SD card commands *   arg          - four bytes which hold the SD command argument * * Returns: * *   <none> * */void xmitcmd(uint8_t cmd, uint8_t *arg){  uint8_t crcb = 0x00;   uint8_t out;  /* First byte has framing bits and command */  out = 0x40 | (cmd & 0x3f);  crcb = crc_7(crcb, out);  xferSPI(out);  /* Next five bytes hold arguments, if any */  crcb = crc_7(crcb, arg[0]);  xferSPI(arg[0]);  crcb = crc_7(crcb, arg[1]);  xferSPI(arg[1]);  crcb = crc_7(crcb, arg[2]);  xferSPI(arg[2]);  crcb = crc_7(crcb, arg[3]);  xferSPI(arg[3]);  /* Finally, crc byte is transmitted,    * shifted left by one and the stop bit added    */  crcb = crc_7augment(crcb);  out = (crcb << 1) | 0x01;  xferSPI(out);}/* Initialize SD card in SPI mode * * Input arguments: * *   retries - number of retries to attempt before erroring out * * Returns: * *   <none> * */int init_sd_card(int retries){  uint8_t rxdata;  int status, errors, i;  status = -1; /* Currently in error */  errors = 0; /* Retry counter */  CLEAR_ARGS(arg);  /* Just in case the card is in some unknown state */  /* Flush out all data and attempt to get back to an idle bus */  flush_spi(516);  /* Sent the CMD0_GO_IDLE_STATE while CS is asserted */  /* This signals the SD card to fall back to SPI mode */  while ((status == -1) && (errors < retries)) {    cprintf(C"-> Send CMD0_GO_IDLE_STATE\r\n");    xmitcmd(CMD0_GO_IDLE_STATE, arg);    if ((i = waitForR1(&rxdata, 0)) < 0) {      if (i == TR_TIMEOUT) {	cprintf(C"ERROR: Timeout\r\n");      }      if (i == TR_NOT_IDLE) {	cprintf(C"ERROR: Bus not idle\r\n");      }      errors++;      continue;    }    if (rxdata != R1_IDLE) {      cprintf(C"ERROR: R1 != R1_IDLE\r\n");      errors++;      continue;    }    status = 0; /* We're talking to the card */    cprintf(C"-> Got Idle Card State\r\n");  }  if (status < 0) {    /* Failure to talk to card */    return TR_FAILURE;  }  /* Now that card is in SPI mode with IDLE bit set, we need */  /*  to send the command to start its initialization process */  /*  and wait for R1_IDLE to disappear before issuing other commands */  status = 1;  errors = 0;  while(status && (errors < retries)) {    cprintf(C"-> Send CMD55_APP_CMD\r\n");    xmitcmd(CMD55_APP_CMD, arg);    if (waitForR1(&rxdata, 0) < 0) {      /* If this is a MultiMediaCard (not SD), it won't respond here */      cprintf(C"ERROR: Timeout! Perhaps this is a MMC card?\r\n");      return TR_TIMEOUT;    }    check_r1(rxdata, R1_IDLE);    cprintf(C"-> Send ACMD41_SEND_OP_COND\r\n");    xmitcmd(ACMD41_SEND_OP_COND, arg);    if (waitForR1(&rxdata, 0) < 0) {      cprintf(C"ERROR: Timeout on ACMD41_SEND_OP_COND\r\n");      return TR_TIMEOUT;    }    status = rxdata & R1_IDLE;    if (status) {      /* Pause here for a bit to let the card start up */      for (i = 0; i < 10000; i++); /* busy loop */    }  }  if (status) {    /* Card never signaled ready */    return TR_FAILURE;  }      /* Enable CRC to protect against bus-induced data errors */    cprintf(C"-> Send CMD59_CRC_ON_OFF\r\n");  arg[3] = 0x01; /* LSB set to 1 enables CRC verification */  xmitcmd(CMD59_CRC_ON_OFF, arg);  CLEAR_ARGS(arg);  if (waitForR1(&rxdata, 0) < 0) {    cprintf(C"ERROR: Timeout on CMD59_CRC_ON_OFF\r\n");    return TR_TIMEOUT;  }  check_r1(rxdata, R1_NOERROR);  return TR_OK;}/* Retrieve the Card-specific Data register and decode * * Input arguments: * *   <none> * * Returns: * *   TR_OK if successful, TR_FAILURE otherwise * */int get_sd_csd(void){  uint8_t multiplier;  uint32_t cardsize;  CLEAR_ARGS(arg);  cprintf(C"-> Requesting CSD (Card Specific Data)\r\n");  xmitcmd(CMD9_SEND_CSD, arg);  if (waitForR1(rxbuf, 18) < 0) {    cprintf(C"ERROR: Timeout on CMD9_SEND_CSD\r\n");    return -1;  }  check_r1(rxbuf[0], R1_NOERROR);  if (verifyCRC(SD_CRC16, &rxbuf[1], 16, (rxbuf[17]<<8) + rxbuf[18])       != CRC_OK) {    cprintf(C"ERROR: Data block did not pass CRC16 check\r\n");    return TR_FAILURE;  }  if (verifyCRC(SD_CRC7, &rxbuf[1], 15, (rxbuf[16] >> 1)) != CRC_OK) {    cprintf(C"ERROR: CSD failed internal CRC7 check\r\n");    return TR_FAILURE;  }  /* Decode Card Specific Data */  /* A couple of items are of interest to us here:    *    *  - block size of card (typically 512, but may differ) from READ_BL_LEN   *  - total size of card from C_SIZE, C_SIZE_MULT, and READ_BL_LEN   *   */  /* Blocksize is easy to decode */  blocksize = 0x01 << (rxbuf[6] & 0x0f);  /* Cardsize is split over several bytes */  cardsize = ((rxbuf[7] & 0x03) << 10) | (rxbuf[8] << 2) | (rxbuf[9] & 0xc0);  /* Multiplier is also split over several bytes */  multiplier = ((rxbuf[10] & 0x03) << 1) | (rxbuf[11] >> 7);  /* Compute final card size */  cardsize <<= (multiplier + 2); /* Multiplier is 2^(m+2) */  switch (blocksize) {    case 512:      cardsize >>= 11;      break;    case 1024:      break;    case 2048:      cardsize <<= 9;      break;    default:      cprintf(C"Unsupported blocksize!\r\n");      return TR_FAILURE;      break;  }  cprintf(C"Card size: %uMB\r\n", cardsize);  return TR_OK;}/* Retrieve the Card Identification register and decode *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -