?? main.c
字號:
//===========================================================================//=//= 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
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -