These are the examples provided for [[/users/frank26080115/libraries/LPC1700CMSIS_Lib/]] Note, the entire "program" is not compilable!
Diff: SPI/SDCard/spi_sdcard.c
- Revision:
- 0:bf7b9fba3924
diff -r 000000000000 -r bf7b9fba3924 SPI/SDCard/spi_sdcard.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SPI/SDCard/spi_sdcard.c Sun Mar 20 05:38:56 2011 +0000 @@ -0,0 +1,606 @@ +/******************** (C) COPYRIGHT 2010 NXPSemiconductors ************ + * @file spi_sdcard.c + * @purpose This example describes how to use SPI at mode SPI master/8bit + * on LPC1768 to communicate with SC16IS750/760 Demo board + * in interrupt mode + * @version 1.0 + * @date 16. July. 2010 + * @author NXP MCU SW Application Team + *--------------------------------------------------------------------- + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * products. This software is supplied "AS IS" without any warranties. + * NXP Semiconductors assumes no responsibility or liability for the + * use of the software, conveys no license or title under any patent, + * copyright, or mask work right to the product. NXP Semiconductors + * reserves the right to make changes in the software without + * notification. NXP Semiconductors also make no representation or + * warranty that such application will be suitable for the specified + * use without further testing or modification. + **********************************************************************/ +#include "lpc17xx_spi.h" +#include "lpc17xx_libcfg.h" +#include "lpc17xx_pinsel.h" +#include "debug_frmwrk.h" +#include "lpc17xx_gpio.h" + +/* Example group ----------------------------------------------------------- */ +/** @defgroup SPI_SDCard SDCard + * @ingroup SPI_Examples + * @{ + */ + +/************************** PRIVATE DEFINTIONS *********************/ +// PORT number that /CS pin assigned on +#define CS_PORT_NUM 0 +// PIN number that /CS pin assigned on +#define CS_PIN_NUM 16 + +#define SD_DETECT_PORTNUM 4 +#define SD_DETECT_PINNUM 29 +typedef enum _sd_connect_status +{ + SD_CONNECTED, + SD_DISCONNECTED +}sd_connect_status; +typedef enum _sd_error +{ + SD_OK, + SD_NG, + SD_CMD_BAD_PARAMETER, + SD_ERROR_TOKEN, + SD_ERROR_TIMEOUT, + SD_ERROR_BUS_NOT_IDLE, + SD_ERROR_CMD0, + SD_ERROR_CMD55, + SD_ERROR_ACMD41, + SD_ERROR_CMD59, +}sd_error; + +//SD command code +#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 + +#define GETBIT(in, bit) ((in & (1<<bit)) >> bit) +#define SD_CMD_BLOCK_LENGTH 6 +#define SD_DATA_BLOCK_LENGTH 515 +#define SD_WAIT_R1_TIMEOUT 100000 +/************************** PRIVATE VARIABLES *************************/ +uint8_t menu1[] = +"********************************************************************************\n\r" +"Hello NXP Semiconductors \n\r" +"SPI communicate with SD card demo \n\r" +"\t - MCU: LPC17xx \n\r" +"\t - Core: ARM Cortex-M3 \n\r" +"\t - Communicate via: UART0 - 115200bps \n\r" +" Demo SPI module, read SD card's CID register and display via UART0\n\r" +"********************************************************************************\n\r"; +// SPI Configuration structure variable +SPI_CFG_Type SPI_ConfigStruct; +// SPI Data Setup structure variable +SPI_DATA_SETUP_Type xferConfig; + +uint8_t sd_cmd_buf[SD_CMD_BLOCK_LENGTH]; +uint8_t sd_data_buf[SD_DATA_BLOCK_LENGTH]; +/************************** PRIVATE FUNCTIONS *************************/ +void CS_Init(void); +void CS_Force(int32_t state); +void print_menu(void); +sd_connect_status SD_GetCardConnectStatus(void); +uint8_t crc_7(uint8_t old_crc, uint8_t data); +uint8_t crc_7final(uint8_t old_crc); +uint32_t SD_SendReceiveData_Polling(void* tx_buf, void* rx_buf, uint32_t length); +void SD_SendCommand(uint8_t cmd, uint8_t *arg); +sd_error SD_WaitR1(uint8_t *buffer, uint32_t length, uint32_t timeout); +sd_error SD_WaitDeviceIdle(uint32_t num_char); +sd_error SD_Init(uint8_t retries); +sd_error SD_GetCID(void); +/*----------------- INTERRUPT SERVICE ROUTINES --------------------------*/ + +/*-------------------------PRIVATE FUNCTIONS------------------------------*/ + +/*********************************************************************//** + * @brief Initialize CS pin as GPIO function to drive /CS pin + * due to definition of CS_PORT_NUM and CS_PORT_NUM + * @param None + * @return None + ***********************************************************************/ +void CS_Init(void) +{ + GPIO_SetDir(CS_PORT_NUM, (1<<CS_PIN_NUM), 1); + GPIO_SetValue(CS_PORT_NUM, (1<<CS_PIN_NUM)); +} +/*********************************************************************//** + * @brief Drive CS output pin to low/high level to select slave device + * via /CS pin state + * @param[in] state State of CS output pin that will be driven: + * - 0: Drive CS pin to low level + * - 1: Drive CS pin to high level + * @return None + ***********************************************************************/ +void CS_Force(int32_t state) +{ + if (state){ + GPIO_SetValue(CS_PORT_NUM, (1<<CS_PIN_NUM)); + }else{ + GPIO_ClearValue(CS_PORT_NUM, (1<<CS_PIN_NUM)); + } +} +/*********************************************************************//** + * @brief Print Welcome menu + * @param[in] none + * @return None + **********************************************************************/ +void print_menu(void) +{ + _DBG(menu1); +} +/*********************************************************************//** + * @brief check if SD card is inserted or not + * @param[in] none + * @return SD_CONNECTED or SD_DISCONNECTED + **********************************************************************/ +sd_connect_status SD_GetCardConnectStatus(void) +{ + sd_connect_status ret=SD_DISCONNECTED; + + if((GPIO_ReadValue(SD_DETECT_PORTNUM)&(1<<SD_DETECT_PINNUM))== 0) + ret = SD_CONNECTED; + + return ret; +} +/*********************************************************************//** + * @brief Calculate CRC-7 as required by SD specification + * @param[in] - old_crc: 0x00 to start new CRC + * or value from previous call to continue. + * - data: data byte to add to CRC computation + * @return CRC-7 checksum which MUST be augmented by crc_7augment() before used + **********************************************************************/ +uint8_t crc_7(uint8_t old_crc, uint8_t data) +{ + uint8_t new_crc,x; + + 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; /*CRC-7's polynomial is x^7 + x^3 + 1*/ + } + if(x==0) break; + } + return new_crc; +} +/*********************************************************************//** + * @brief Provides the zero-padding final step to CRC-7 + * @param[in] - old_crc: value from last crc_7()call + * @return Finalized CRC-7 checksum + **********************************************************************/ +uint8_t crc_7final(uint8_t old_crc) +{ + uint8_t new_crc,x; + + new_crc = old_crc; + for (x = 0; x < 7; x++) { + new_crc <<= 1; + if (GETBIT(new_crc, 7) == 1) { + new_crc ^= 0x89; /*CRC-7's polynomial is x^7 + x^3 + 1*/ + } + } + return new_crc; +} +/*********************************************************************//** + * @brief Send/receive data over SPI bus + * @param[in] - tx_buf: pointer to transmit buffer. + * NULL if send 0xFF. + * - rx_buf: pointer to receive buffer + * NULL if nothing to receive. + * - length: number of data to send or receive + * @return the actual data sent or received. + **********************************************************************/ +uint32_t SD_SendReceiveData_Polling(void* tx_buf, void* rx_buf, uint32_t length) +{ + //uint16_t i; + + CS_Force(0); + //for(i=0;i<1000;i++); + + xferConfig.tx_data = tx_buf; + xferConfig.rx_data = rx_buf; + xferConfig.length = length; + SPI_ReadWrite(LPC_SPI, &xferConfig, SPI_TRANSFER_POLLING); + + //for(i=0;i<1000;i++); + CS_Force(1); + return xferConfig.counter; +} +/*********************************************************************//** + * @brief Send command to SD card + * @param[in] - cmd: SD command code + * - arg: pointer to array of 4x8 bytes, argument of command + * @return n/a + **********************************************************************/ +void SD_SendCommand(uint8_t cmd, uint8_t *arg) +{ + uint8_t crc = 0x00; + + /* First byte has framing bits and command */ + sd_cmd_buf[0] = 0x40 | (cmd & 0x3f); + sd_cmd_buf[1] = arg[0]; + sd_cmd_buf[2] = arg[1]; + sd_cmd_buf[3] = arg[2]; + sd_cmd_buf[4] = arg[3]; + //calculate CRC + crc = crc_7(crc, sd_cmd_buf[0]);//start new crc-7 + crc = crc_7(crc, sd_cmd_buf[1]); + crc = crc_7(crc, sd_cmd_buf[2]); + crc = crc_7(crc, sd_cmd_buf[3]); + crc = crc_7(crc, sd_cmd_buf[4]); + crc = crc_7final(crc); + sd_cmd_buf[5] = (crc << 1) | 0x01;//stop bit + + SD_SendReceiveData_Polling(sd_cmd_buf,NULL,SD_CMD_BLOCK_LENGTH); +} +/*********************************************************************//** + * @brief Wait for SD card R1 response + * @param[in] - buffer: pointer to receive buffer + * - length: length of receive data, must equal 1+actual length of data + * length = 0 if receive R1 only + * - timeout: timeout for retry + * @return error code + **********************************************************************/ +sd_error SD_WaitR1(uint8_t *buffer, uint32_t length, uint32_t timeout) +{ + uint32_t j; + uint8_t dummy[2]; + uint8_t wait_idle; + + /* No null pointers allowed */ + if (buffer == NULL) return SD_CMD_BAD_PARAMETER; + + /* Wait for start bit on R1 */ + j=0;dummy[0]=0xFF; + while (GETBIT(dummy[0],7) == 1) + { + if (j>timeout)return SD_ERROR_TIMEOUT; + dummy[0]=0x00; + SD_SendReceiveData_Polling(NULL,dummy,1); + j++; + } + *buffer=dummy[0];//store R1 + if (length > 0)//read followed data + { + /* Wait for start token on data portion, if any */ + dummy[0] = 0xff;j = 0; + while (dummy[0] != 0xfe) + { + if (j > timeout)return SD_ERROR_TIMEOUT; + dummy[0]=0x00; + SD_SendReceiveData_Polling(NULL,dummy,1); + if ((dummy[0] != 0xff) && (dummy[0] != 0xfe)) // not idle or start token? + { + return SD_ERROR_TOKEN; + } + j++; + } + /* Read all bytes */ + SD_SendReceiveData_Polling(NULL,(buffer+1),(length - 1)); + } + /* Some more bit clocks to finish internal SD operations */ + dummy[0]=0x00;wait_idle=0; + while((dummy[0]!=0xff)&&(wait_idle<20)) + { + dummy[0]=0x00; + SD_SendReceiveData_Polling(NULL,dummy,1); + for(j=0;j<1000;j++); + wait_idle++; + } + if(wait_idle>=20) return SD_ERROR_BUS_NOT_IDLE; + return SD_OK; +} +/*********************************************************************//** + * @brief Wait for SD card idle + * @param[in] - num_char: number characters (8 bits clock) to wait + * @return device already in idle state or need more time + **********************************************************************/ +sd_error SD_WaitDeviceIdle(uint32_t num_char) +{ + uint8_t dummy[2]={0,0}; + uint32_t i=0; + + while ((i < num_char) && (dummy[0] != 0xff)) + { + dummy[0]=0x00; + SD_SendReceiveData_Polling(NULL,dummy,1); + if (dummy[0] == 0xff) + { + dummy[0]= 0x00; + SD_SendReceiveData_Polling(NULL,dummy,1); + if (dummy[0] == 0xff) + { + dummy[0]= 0x00; + SD_SendReceiveData_Polling(NULL,dummy,1); + } + } + i++; + } + if (dummy[0] != 0xff)return SD_ERROR_TIMEOUT; + + return SD_OK; +} +/*********************************************************************//** + * @brief Initialize SD card in SPI mode + * @param[in] - retries: number retry time + * @return initialization successful or terminated with specific error code + **********************************************************************/ +sd_error SD_Init(uint8_t retries) +{ + uint8_t rxdata,errors; + uint8_t SD_arg[4]={0,0,0,0}; + uint16_t i; + + // initialize SPI configuration structure to default + SPI_ConfigStructInit(&SPI_ConfigStruct); + // Initialize SPI peripheral with parameter given in structure above + SPI_Init(LPC_SPI, &SPI_ConfigStruct); + // Initialize /CS pin to GPIO function + CS_Init(); + // check for SD card insertion + _DBG("\n\rPlease plug-in SD card!"); + while(SD_GetCardConnectStatus()==SD_DISCONNECTED); + _DBG("...Connected!\n\r"); + // Wait for bus idle + if(SD_WaitDeviceIdle(160) != SD_OK) return SD_ERROR_BUS_NOT_IDLE; + _DBG("Initialize SD card in SPI mode..."); + + errors = 0; + /* Send the CMD0_GO_IDLE_STATE while CS is asserted */ + /* This signals the SD card to fall back to SPI mode */ + while(errors < retries) + { + SD_SendCommand(CMD0_GO_IDLE_STATE, SD_arg); + if(SD_WaitR1(&rxdata,0,1000)!= SD_OK) + { + errors++; + continue; + } + if(rxdata != R1_IDLE) + { + errors++; + continue; + } + else break; + } + if(errors >= retries)return SD_ERROR_CMD0; + + /* Check if the card is not MMC */ + /* Start its internal initialization process */ + while(1) + { + SD_SendCommand(CMD55_APP_CMD, SD_arg); + if(SD_WaitR1(&rxdata,0,1000)!= SD_OK) return SD_ERROR_CMD55; + + SD_SendCommand(ACMD41_SEND_OP_COND, SD_arg); + SD_WaitR1(&rxdata,0,1000); + if (rxdata & R1_IDLE) //in_idle_state = 1 + for (i = 0; i < 1000; i++); /* wait for a while */ + else break; //in_idle_state=0 --> ready + } + /* Enable CRC */ + SD_arg[3] = 0x01; + SD_SendCommand(CMD59_CRC_ON_OFF, SD_arg); + if(SD_WaitR1(&rxdata,0,1000)!= SD_OK) return SD_ERROR_CMD59; + if(rxdata != R1_NOERROR) return SD_ERROR_CMD59; + + return SD_OK; +} +/*********************************************************************//** + * @brief Get SD card's CID register + * @param[in] none + * @return OK or NG + * OK: the returned data from SD card is stored in sd_data_buf + **********************************************************************/ +sd_error SD_GetCID(void) +{ + uint8_t SD_arg[4]={0,0,0,0}; + + SD_SendCommand(CMD10_SEND_CID, SD_arg); + if(SD_WaitR1(sd_data_buf,18,1000)!= SD_OK) return SD_NG; + if(sd_data_buf[0]!= R1_NOERROR) return SD_NG; + return SD_OK; +} +/*-------------------------MAIN FUNCTION------------------------------*/ +/*********************************************************************//** + * @brief c_entry: Main SPI program body + * @param[in] None + * @return int + **********************************************************************/ +int c_entry(void) +{ + PINSEL_CFG_Type PinCfg; + sd_error sd_status; + uint8_t i; + uint8_t tem8; + uint32_t tem32; + /* + * Initialize SPI pin connect + * P0.15 - SCK; + * P0.16 - SSEL - used as GPIO + * P0.17 - MISO + * P0.18 - MOSI + */ + PinCfg.Funcnum = 3; + PinCfg.OpenDrain = 0; + PinCfg.Pinmode = 0; + PinCfg.Portnum = 0; + PinCfg.Pinnum = 15; + PINSEL_ConfigPin(&PinCfg); + PinCfg.Pinnum = 17; + PINSEL_ConfigPin(&PinCfg); + PinCfg.Pinnum = 18; + PINSEL_ConfigPin(&PinCfg); + PinCfg.Pinnum = 16; + PinCfg.Funcnum = 0; + PINSEL_ConfigPin(&PinCfg); + //Initialize SD card detection pin P4.29 + PinCfg.Portnum = 4; + PinCfg.Pinnum = 29; + PinCfg.Funcnum = 0;//GPIO function + PINSEL_ConfigPin(&PinCfg); + GPIO_SetDir(SD_DETECT_PORTNUM, (1<<SD_DETECT_PINNUM), 0);//input + + /* Initialize debug via UART0 + * 115200bps + * 8 data bit + * No parity + * 1 stop bit + * No flow control + */ + debug_frmwrk_init(); + + // print welcome screen + print_menu(); + + //initialize SD card + sd_status = SD_Init(10); + switch(sd_status) + { + case SD_ERROR_CMD0: + _DBG("Fail CMD0\n\r"); + break; + case SD_ERROR_CMD55: + _DBG("Fail CMD55\n\r"); + break; + case SD_ERROR_ACMD41: + _DBG("Fail ACMD41\n\r"); + break; + case SD_ERROR_CMD59: + _DBG("Fail CMD59\n\r"); + break; + case SD_ERROR_BUS_NOT_IDLE: + _DBG("Fail...Device is not in idle state.\n\r"); + break; + case SD_OK: + _DBG("Done!\n\r"); + break; + default: + _DBG("Fail\n\r"); + break; + } + if(sd_status == SD_OK) + { + //Clear receive buffer + for(i=1;i<18;i++)sd_data_buf[i]=0; + + _DBG("Reading SD card's CID register..."); + if(SD_GetCID()!= SD_OK) + { + _DBG("Fail\n\r"); + SPI_DeInit(LPC_SPI); + } + else + { + _DBG("Done!"); + _DBG("\n\rManufacture ID: ");_DBH(sd_data_buf[1]); + _DBG("\n\rApplication ID: ");_DBC(sd_data_buf[2]);_DBC(sd_data_buf[3]); + _DBG("\n\rProduct name: "); + for(i=4;i<9;i++) _DBC(sd_data_buf[i]); + _DBG("\n\rProduct revision: "); + tem8 = (sd_data_buf[9]&0xF0)>>4;_DBD(tem8); + _DBG("."); + tem8 = (sd_data_buf[9]&0x0F);_DBD(tem8); + _DBG("\n\rProduct serial number: "); + tem32= (sd_data_buf[13]<<24)|(sd_data_buf[12]<<16)| + (sd_data_buf[11]<<8)|(sd_data_buf[10]<<0); + _DBH32(tem32); + _DBG("\n\rManufacturing date: "); + tem8 = (sd_data_buf[15]&0x0F);_DBD(tem8); + _DBG("/"); + tem8 = ((sd_data_buf[14]&0x0F)<<4) | ((sd_data_buf[15]&0xF0)>>4); + _DBG("2");_DBD(tem8); + } + } + else + // DeInitialize SPI peripheral + SPI_DeInit(LPC_SPI); + /* Loop forever */ + while(1); + return 1; +} + +/* With ARM and GHS toolsets, the entry point is main() - this will + allow the linker to generate wrapper code to setup stacks, allocate + heap area, and initialize and copy code and data segments. For GNU + toolsets, the entry point is through __start() in the crt0_gnu.asm + file, and that startup code will setup stacks and data */ +int main(void) +{ + return c_entry(); +} + + +#ifdef DEBUG +/******************************************************************************* +* @brief Reports the name of the source file and the source line number +* where the CHECK_PARAM error has occurred. +* @param[in] file Pointer to the source file name +* @param[in] line assert_param error line source number +* @return None +*******************************************************************************/ +void check_failed(uint8_t *file, uint32_t line) +{ + /* User can add his own implementation to report the file name and line number, + ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + + /* Infinite loop */ + while(1); +} +#endif +/* + * @} + */