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

📄 main.c

📁 maxim的对sd卡的串行spi模式进行读写操作控制的程序源码
💻 C
📖 第 1 页 / 共 3 页
字号:
//===========================================================================//=//=  Copyright (C) 2006 MAXIM/Dallas Semiconductor Corporation. //=  All rights Reserved. Printed in U.S.A.//=//=  Permission is hereby granted, free of charge, to any person obtaining a//=  copy of this software and associated documentation files (the //=  "Software"), to deal in the Software without restriction, including//=  without limitation the rights to use, copy, modify, merge, publish,//=  distribute, sublicense, and/or sell copies of the Software, and to//=  permit persons to whom the Software is furnished to do so, subject to//=  the following conditions://=  //=  The above copyright notice and this permission notice shall be included//=  in all copies or substantial portions of the Software source code.//=  //=  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS//=  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF//=  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.//=  IN NO EVENT SHALL MAXIM/DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, //=  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR //=  OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR //=  THE USE OR OTHER DEALINGS IN THE SOFTWARE.//=//=  Except as contained in this notice, the name of MAXIM/Dallas //=  Semiconductor shall not be used except as stated in the MAXIM/Dallas //=  Semiconductor Branding Policy.//=//=     Description: MAXQ2000 Secure Digital (SD) Card Interface via SPI//=                 //=        Filename: main.c//=//=        Compiler: Rowley CrossWorks C compiler//=//=        Hardware: MAXQ2000 Evaluation Kit (Rev B)//=//===========================================================================#include <MAXQ2000.h>#include <stdio.h>#include <stdio_c.h>#include <stdint.h>#include <string.h>#include <stdarg.h>/* ---- Handy utility macros ---- *//* GETBIT(in,bit) returns bit 0-7 of in to caller */#define GETBIT(in, bit) ((in & (1<<bit)) >> bit)/* CLEARARGS(x) clears the 32-bit SD command argument */#define CLEAR_ARGS(x) x[0] = 0; x[1] = 0; x[2] = 0; x[3] = 0;/* Common command set */#define CMD0_GO_IDLE_STATE          0x00#define CMD1_SEND_OPCOND            0x01#define CMD9_SEND_CSD               0x09#define CMD10_SEND_CID              0x0a#define CMD12_STOP_TRANSMISSION     0x0b#define CMD13_SEND_STATUS           0x0c#define CMD16_SET_BLOCKLEN          0x10#define CMD17_READ_SINGLE_BLOCK     0x11#define CMD18_READ_MULTIPLE_BLOCK   0x12#define CMD24_WRITE_BLOCK           0x18#define CMD25_WRITE_MULTIPLE_BLOCK  0x19#define CMD27_PROGRAM_CSD           0x1b#define CMD28_SET_WRITE_PROT        0x1c#define CMD29_CLR_WRITE_PROT        0x1d#define CMD30_SEND_WRITE_PROT       0x1e#define CMD32_ERASE_WR_BLK_START_ADDR 0x20#define CMD33_ERASE_WR_BLK_END_ADDR   0x21#define CMD38_ERASE                 0x26#define CMD55_APP_CMD               0x37#define CMD56_GEN_CMD               0x38#define CMD58_READ_OCR              0x3a#define CMD59_CRC_ON_OFF            0x3b/* Application-specific commands (always prefixed with CMD55_APP_CMD) */#define ACMD13_SD_STATUS            0x0d#define ACMD22_SEND_NUM_WR_BLOCKS   0x16#define ACMD23_SET_WR_BLK_ERASE_COUNT 0x17#define ACMD41_SEND_OP_COND         0x29#define ACMD42_SET_CLR_CARD_DETECT  0x2a#define ACMD51_SEND_SCR             0x33/* R1 format responses (ORed together as a bit-field) */#define R1_NOERROR   0x00#define R1_IDLE      0x01#define R1_ERASE     0x02#define R1_ILLEGAL   0x04#define R1_CRC_ERR   0x08#define R1_ERASE_SEQ 0x10#define R1_ADDR_ERR  0x20#define R1_PARAM_ERR 0x40/* R2 format responses - second byte only, first is identical to R1 */#define R2_LOCKED    0x01#define R2_WP_FAILED 0x02#define R2_ERROR     0x04#define R2_CTRL_ERR  0x08#define R2_ECC_FAIL  0x10#define R2_WP_VIOL   0x20#define R2_ERASE_PARAM 0x40#define R2_RANGE_ERR 0x80/* CRC-related constants */#define SD_CRC7         0#define SD_CRC16        1#define CRC_OK          0#define CRC_FAIL       -1/* Transfer-related return codes */#define TR_OK           0#define TR_INVALID_ARG -1#define TR_TIMEOUT     -2#define TR_ERROR_TOKEN -3#define TR_NOT_IDLE    -4#define TR_FAILURE     -5/* Misc defines */#define BLOCK_BUFFER_LEN  515#define INPUT_BUFFER_LEN   10/* The following two timeouts should be computed from CSD parameters *//*  in a fully SD-compliant implementation */#define WAIT_R1_TIMEOUT    50#define WAIT_WRITE_TIMEOUT 32768/* Common globals *//* rxbuf is the block buffer used for all operations *//* 515 == 1 R1 response byte + 512 byte block + 2 bytes CRC16 */uint8_t rxbuf[BLOCK_BUFFER_LEN]; /* arg is the 32-bit SD command argument broken into 4 bytes */uint8_t arg[4] = {0x00, 0x00, 0x00, 0x00};/* Most SD cards use a blocksize of 512 bytes and is found in the CSD */uint16_t blocksize = 512; /* Buffer used by the cprintf() macro for strings stored in code space */unsigned char cbuf[80];/* Prototype definition for the assembly routine in copybuf.asm */int asm_copybuffer(unsigned char *dstaddr, const __code char *srcaddr, int len);/* Calls the printf() function after copying code-space string to RAM buffer * * Comments: * *   As the MAXQ2000 has limited RAM, copying all of the static string data *    into RAM reduces the space for the Rowley soft stack. We, therefore,  *    copy only the string needed at the current instant into a single buffer *    and pass this buffer to vprintf() along with the variable argument list. *  * Input arguments: *   *   format - code-space formatting string *   [<arg1> .. <argn>] - additional parameters to printf(str, ...) * * Returns: * *   result code from vprintf * */int cprintf(const __code char *format, ...){  va_list ap;  /* Initialize the varaiable argument list pointer */  va_start(ap, format);  /* Copy the code space string to RAM */  asm_copybuffer(cbuf, format, 80);  /* Call vprintf with our RAM format string plus the varaible argument list */  return vprintf((char *)cbuf, ap);}/* Hook function for Rowley printf() routines to send serial character  * * Input arguments:       * *   x - character to send to console held in lower byte * * Returns: * *   <none> * */int __putchar(int x){  SBUF0 = x;  while (!(SCON0 & 0x02));  SCON0 &= ~0x02;}/* Waits for, and reads, a character over the serial port * * Input arguments:       * *   <none> * * Returns: * *   character received over serial port * */uint8_t readuart(void){  while(!(SCON0 & 1)); /* Wait for RI to go high */  SCON0 &= ~0x01; /* Clear it */  return (uint8_t)SBUF0; /* Pass back the receive buffer */}/* Waits for, and reads, a character over the serial port * * Input arguments:       * *   in - character to transmit out of SPI MOSI pin * * Returns: * *   character received via SPI MISO pin * */uint8_t xferSPI(uint8_t in){  uint8_t out;  /* Caveat lector! This may hang on SPICN.6 and SPICN.7 forever */  while(SPICN & 0x80);           /* Wait for BUSY to be low */  SPICN &= ~0x40;                /* Clear transfer complete */  SPIB = in;                     /* Start the transfer */  while(!(SPICN & 0x40));        /* Wait for Transfer Complete */  out = SPIB;                    /* Copy off what was sent in */  SPICN &= ~0x40;                /* Clear transfer complete */#ifdef SPI_DEBUG  /* This may help during early debugging of the SPI bus */  /* Format is "->(transmitted byte) <-(received byte)" */  cprintf(C"->0x%02x <-0x%02x\r\n", in, out);#endif  return out;}/* Compares R1 expected response with received response * * Input arguments:       * *   r1       - received response *   expected - expected response * * Returns: * *   0 if equal, -1 otherwise * */int check_r1(uint8_t r1, uint8_t expected){  if (r1 != expected) {    cprintf(C"WARNING: R1 status 0x%02x, expecting 0x%02x\r\n", 	   rxbuf[0], expected);    return -1;  }  return 0;}/* Sends idle bytes to card, and waits for 5 consecutive idles from card  * * Input arguments:       * *   timeout - number of characters to wait before giving up * * Returns: * *   TR_OK if equal, TR_TIMEOUT otherwise * */int flush_spi(int timeout){  uint8_t recv;  int i = 0;  /* We unroll the loop to save on variable space. */  while ((i < timeout) && (recv != 0xff)) {    recv = xferSPI(0xff);    if (recv == 0xff) { /* Got 1 so far */      recv = xferSPI(0xff);      if (recv == 0xff) { /* Got 2 so far */	recv = xferSPI(0xff);	if (recv == 0xff) { /* Got 3 so far */	  recv = xferSPI(0xff);	  if (recv == 0xff) { /* Got 4 so far */	    recv = xferSPI(0xff);	  }	}      }    }    i++;  }  if (recv != 0xff) {     /* Only way to reach this is if we timed-out and didn't get 0xff */    return TR_TIMEOUT;  }  return TR_OK;}/* Wait for the start of transmission from the SD card  * * Input arguments:       * *   b      - pointer to buffer of AT LEAST length+1 size *   length - 0 to read only R1, otherwise > 0 to read data response * * Returns: * *   TR_TIMEOUT for timeout, TR_INVALID_ARG for null pointer *   TR_ERROR_TOKEN for length > 0 and error token received *   TR_NOT_IDLE if idle bus was not detected after transfer complete * *   (side effects: b[0] is R1 byte, b[1..length] is data if length > 0) *   (              b[1] is error token if return is TR_ERROR_TOKEN) * *//* Length is # of data bytes to follow R1 response. Status will be in b[0] */int waitForR1(uint8_t *b, uint32_t length){  uint8_t recv = 0xff;  int i = 0;  /* No null pointers allowed */  if (b == NULL) {    return TR_INVALID_ARG;  }  /* Wait for start bit on R1 */  while (GETBIT(recv,7) == 1) {    if (i > WAIT_R1_TIMEOUT) {      return TR_TIMEOUT;    }    recv = xferSPI(0xff);    i++;  }  *b = recv; /* Copy in status */  if (length > 0) {    /* Wait for start token on data portion, if any */    recv = 0xff; i = 0;    while (recv != 0xfe) {      if (i > 50) {	return TR_TIMEOUT;      }      recv = xferSPI(0xff);      if ((recv != 0xff) && (recv != 0xfe)) {	/* Not idle bus and not start token, something else. Bus issue?! */	/* Copy other token into buffer for program to examine */	*(b+1) = recv;	return TR_ERROR_TOKEN;      }      i++;    }        /* Read all bytes */    for (i = 1; i <= length; i++) {      *(b+i) = xferSPI(0xff);    }  }  /* Eight more bit clocks to finish internal SD operations */  recv = xferSPI(0xff);   if (recv != 0xff) {    /* Bus is not idle .. should not happen for single block transfers */    return TR_NOT_IDLE;  }  return 0;}/* CRC-7 as described in the Secure Digital spec  * * Input arguments:       * *   old_crc - 0x00 to start new CRC, or value from previous call to continue *   data    - data byte to add to CRC computation * * Returns: * *   CRC-7 checksum which MUST be augmented by crc_7augment() before use * */uint8_t crc_7(uint8_t old_crc, uint8_t data){  unsigned char new_crc;  int x;  /* CRC-7's polynomial is x^7 + x^3 + 1 */  /* How this works:   *   *  - Feed the bits into the loop MSB first   *  - Shift contents of register left by one, top bit of    *     register becomes x^7 term   *  - If top bit is set, XOR in the poly

⌨️ 快捷键说明

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