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

📄 main.c

📁 maxim的对sd卡的串行spi模式进行读写操作控制的程序源码
💻 C
📖 第 1 页 / 共 3 页
字号:
 * Input arguments: * *   <none> * * Returns: * *   TR_OK if successful, TR_FAILURE otherwise * */int get_sd_cid(void){  CLEAR_ARGS(arg);  cprintf(C"-> Requesting CID (Card Identification)\r\n");  xmitcmd(CMD10_SEND_CID, arg);  if (waitForR1(rxbuf, 18) < 0) {    cprintf(C"ERROR: Timeout on CMD10_SEND_CID\r\n");    return TR_FAILURE;  }  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: CID failed internal CRC7 check\r\n");    return TR_FAILURE;  }  /* Dump human-readable Card Identification data */  decodeCID(&rxbuf[1]);  return 0;}/* Dump a buffer in hexadecimal and printable ASCII format to the console * * Input arguments: * *   b - byte buffer to dump *   len - number of bytes to dump * * Returns: * *   <none> * */void hexdump(uint8_t *b, uint16_t len){  int x, c;  int line;  cprintf(C"ADDR|  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F | ASCII\r\n");  cprintf(C"------------------------------------------------------------------------\r\n");  for (line = 0; line < ((len % 16) ? (len / 16) + 1 : (len / 16)); line++) {    cprintf(C"%04X| ", line * 16);    for (x = 0; x < 16; x++) {      if (x + (line * 16) < len) {	c = b[x+line*16];	cprintf(C"%02x ", c);      } else {	cprintf(C"   ");      }    }    cprintf(C"| ");    for (x = 0; x < 16; x++) {      if (x + (line * 16) < len) {	c = b[x+line*16];	if ((c > 0x1f) && (c < 0x7f)) {	  cprintf(C"%c", c);	} else {	  cprintf(C".");	}      } else {	cprintf(C" ");      }    }    cprintf(C"\r\n");  }  cprintf(C"------------------------------------------------------------------------\r\n");}/* Read a block from the SD card into the block buffer * * Input arguments: * *   blocknr - block address to read  * * Returns: * *   TR_OK if successful, TR_FAILURE otherwise * */int readblock(uint32_t blocknr){  int result;  /* Read a block from the card */  cprintf(C"-> Reading block %u from card\r\n", blocknr);  /* The SD card read command requires a byte address aligned on */  /*  block boundaries. Compute this address from the block address */  blocknr *= blocksize;  /* This byte address is stored MSB-first in the argument buffer */  arg[0] = (blocknr & 0xff000000L) >> 24;  arg[1] = (blocknr & 0x00ff0000L) >> 16;  arg[2] = (blocknr & 0x0000ff00L) >> 8;  arg[3] = blocknr & 0x000000ffL;  /* Transmit the read command plus the byte address argument */  xmitcmd(CMD17_READ_SINGLE_BLOCK, arg);    /* We read 514 bytes as this is the blocksize (512) plus two CRC-16 bytes */  if ((result = waitForR1(rxbuf, 514)) < 0) {    switch (result) {      case TR_INVALID_ARG:	cprintf(C"Invalid argument\r\n");	break;      case TR_TIMEOUT:	cprintf(C"Data timeout\r\n");	break;      case TR_ERROR_TOKEN:	cprintf(C"Error token: 0x%02x\r\n", rxbuf[1]);	break;      case TR_NOT_IDLE:	cprintf(C"Bus not idle at end of transaction\r\n");	break;    }    return TR_FAILURE;  }  if (check_r1(rxbuf[0], R1_NOERROR) < 0) {    cprintf(C"Read failure\r\n");    return TR_FAILURE;  }  if (verifyCRC(SD_CRC16, &rxbuf[1], 512, (rxbuf[513]<<8) + rxbuf[514])       != CRC_OK) {    cprintf(C"ERROR: Data block did not pass CRC16 check\r\n");    return TR_FAILURE;  }  /* Dump the data for the user to examine */  hexdump(rxbuf+1, 512);  return TR_OK;}/* Write the block buffer into the SD card at the specified address * * Input arguments: * *   blocknr - block address to write * * Returns: * *   TR_OK if successful, TR_FAILURE otherwise * */int writeblock(uint32_t blocknr){  uint8_t rxdata;  uint16_t i, crc = 0x0000;  int result;  /* Write the block buffer back to card */  cprintf(C"-> Write block %u to card\r\n", blocknr);  /* Prepare the block buffer by adding the data start token */  rxbuf[0] = 0xfe;   /* Run a CRC-16 over the 512 bytes of data and append this to the end */  for (i = 1; i < 513; i++) {    crc = crc_16(crc, rxbuf[i]);  }  crc = crc_16augment(crc);  rxbuf[513] = crc >> 8;  rxbuf[514] = crc & 0x00ff;  /* The SD card read command requires a byte address aligned on */  /*  block boundaries. Compute this address from the block address */  blocknr *= blocksize;  /* This byte address is stored MSB-first in the argument buffer */  arg[0] = (blocknr & 0xff000000L) >> 24;  arg[1] = (blocknr & 0x00ff0000L) >> 16;  arg[2] = (blocknr & 0x0000ff00L) >> 8;  arg[3] = blocknr & 0x000000ffL;  /* Transmit the write command plus the byte address argument */  xmitcmd(CMD24_WRITE_BLOCK, arg);  /* The card will respond with a R1 format response indicating the */  /*  validity of the command and argument before a write can begin */  if ((result = waitForR1(&rxdata, 0)) < 0) {    switch (result) {      case TR_INVALID_ARG:	cprintf(C"Invalid argument\r\n");	break;      case TR_TIMEOUT:	cprintf(C"Data timeout\r\n");	break;      case TR_NOT_IDLE:	cprintf(C"Bus not idle at end of transaction\r\n");	break;    }    return TR_FAILURE;  }  if (check_r1(rxdata, R1_NOERROR) < 0) {    return TR_FAILURE;  }  /* Send the block of data to the SD card */  for (i = 0; i < BLOCK_BUFFER_LEN; i++) {    rxdata = xferSPI(rxbuf[i]);    if (rxdata != 0xff) {      /* The bus should be idle whilst we are transmitting */      /* If this is not the case, flag it */      cprintf(C"During write, strange readback 0x%x\r\n", rxdata);    }  }  /* Wait for the data response token */  i = 0;  rxdata = xferSPI(0xff);  /* The format of the data response token is: xxx0ddd1 */  /*  where x is don't-care, and ddd is the three-bit response code */  while ((rxdata & 0x10) || ((rxdata & 0x01) == 0)) {    i++;    if (i > WAIT_WRITE_TIMEOUT) {      /* After an arbitrarily large wait, give up and signal error */      /* A fully-compliant SD host would use the timeout calculated */      /*  from the CSD register to time out the write transaction */      cprintf(C"Timeout\r\n");      return TR_TIMEOUT; /* Write timeout */    }  }  /* Interpret the response */  switch ((rxdata & 0x0e) >> 1) {    case 0x02:      cprintf(C"Data accepted!\r\n");      break;    case 0x05:      cprintf(C"Rejected (CRC)\r\n");      break;    case 0x06:      cprintf(C"Rejected (Write)\r\n");      break;    default:      cprintf(C"Illegal response!", rxdata);      break;  }  /* The SD card will now send a stream of idle tokens (0x00) on its DO */  /*  line to indicate that it is busy writing the requested data to */  /*  the non-volatile storage. We must wait until the bus returns to */  /*  idle (0xff) before issuing any other commands */  i = 0;  rxdata = xferSPI(0xff);  while (rxdata != 0xff) {    /* Busy token sent back. Keep looping until timeout */    i++;    if (i > WAIT_WRITE_TIMEOUT) {      return TR_TIMEOUT;     }    rxdata = xferSPI(0xff);  }  return TR_OK;}int main(void){  uint8_t done, i, numarg, inbuf[INPUT_BUFFER_LEN];  uint16_t blocknr;  /* Set up the serial port for 115200 bps, no parity, 8 bits, 1 stop bit */  SCON0 = SCON0_REN | SCON0_SM1;  SMD0 = SMD0_SMOD0;     PR0 = 0x3afb;            /* 115200 bps for 16MHz HF xtal */  /* Set up the SPI port */  SPICF = 0x00;       /* Rising clock latches data, 8-bit */  SPICK = 0x28;       /* div 42 sysclock == 380kHz */  SPICN |= 0x03;      /* Enable SPI master */  PD5 |= 0x10;        /* /SS used as an output */  PO5 |= 0x10;        /* /SS = 1 */  cprintf(C"\r\nMAXQ2000 SD Card via SPI Demo Application\r\n");  done = 0;  while (!done) {    /* Output a prompt */    cprintf(C"> ");        /* Get input */    i = 0;    while ((i < INPUT_BUFFER_LEN-1) && ((inbuf[i] = readuart())!= 0x0d)) {      cprintf(C"%c", inbuf[i]);      i++;    }    cprintf(C"\r\n");    inbuf[i] = 0x00; /* Null terminate at all costs */    /* Attempt to convert to command */    if ((numarg = sscanf(inbuf, "%c %hu", &i, &blocknr)) < 1) {      cprintf(C"No command.");    } else {      switch (i) {	case 'd':	  /* Dump the block buffer in a human-readable format */	  hexdump(rxbuf, 1);	  hexdump(rxbuf+1, 512);	  hexdump(rxbuf+512, 2);	  break;	case 'c':	  PO5 &= ~0x10; /* Select chip */	  /* Retrieve Card Identification register */	  get_sd_cid();	  PO5 |= 0x10; /* Deselect chip */	  break;	case 's':	  PO5 &= ~0x10; /* Select chip */	  /* Retrieve Card Specific Data register */	  get_sd_csd();	  PO5 |= 0x10; /* Deselect chip */	  break;	case 'i':	  PO5 &= ~0x10; /* Select chip */	  /* Start the SD card in SPI mode */	  if (init_sd_card(10) == TR_OK) {	    cprintf(C"SD card intialized OK.\r\n");	  } else {	    cprintf(C"Error initializing SD card.\r\n");	  }	  PO5 |= 0x10; /* Deselect chip */	  break;	case 'r':	  /* Read a block into buffer and display */	  PO5 &= ~0x10; /* Select chip */	  if (numarg == 2) {	    if (readblock(blocknr) == TR_OK) {	      cprintf(C"Read successful.\r\n");	    } else {	      cprintf(C"Read failed.\r\n");	    }	  } else {	    cprintf(C"Read requires block number <arg1>\r\n");	  }	  PO5 |= 0x10; /* Deselect chip */	  break;	case 'w':	  /* Write a block from buffer */	  PO5 &= ~0x10; /* Select chip */	  if (numarg == 2) {	    if (writeblock(blocknr) == TR_OK) {	      cprintf(C"Write successful.\r\n");	    } else {	      cprintf(C"Write failed.\r\n");	    }	  } else {	    cprintf(C"Write requires block number\r\n");	  }	  PO5 |= 0x10; /* Deselect chip */	  break;	case 'e':	  /* Edit block buffer */	  /* for now, simply zero buffer and put "MAXQ2000 SD SPI" in buffer */	  cprintf(C"Block buffer cleared and set to default\r\n");	  memset(rxbuf+1, 0x00, 512);	  strcpy(rxbuf+1, "MAXQ2000 SD SPI");	  break;	case 'f':	  /* Flush the SPI bus */	  PO5 &= ~0x10; /* Select chip */	  if (flush_spi(1000) == TR_TIMEOUT) {	    cprintf(C"Error: Unable to flush SPI bus. Idle not detected.\r\n");	  }	  PO5 |= 0x10; /* Deselect chip */	  break;	default:	  cprintf(C"Program Usage:\r\n");	  cprintf(C" i           - Initialize card. MUST BE DONE FIRST AFTER ANY MEDIA CHANGE.\r\n");	  cprintf(C" c           - Retrieve Card Identification register\r\n");	  cprintf(C" s           - Retrieve Card Specific Data register\r\n");	  cprintf(C" d           - Dump the block buffer in hexadecimal and ASCII format\r\n");	  cprintf(C" r <address> - Reads card block <address> into the block buffer\r\n");	  cprintf(C" w <address> - Writes the block buffer to card at block <address>\r\n");	  cprintf(C" e           - Set block buffer to \"MAXQ2000 SD SPI\"\r\n");	  cprintf(C" f           - Flush all SPI bus bytes until 5 idle bytes are detected\r\n");	  break;      }    }  }  while (1); /* jump $ */}

⌨️ 快捷键说明

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