bug fix with sdspi select.

code style fixes.
This commit is contained in:
nvt-se 2009-05-26 13:00:07 +00:00
parent e9d279620f
commit 28619eabc0

View file

@ -47,9 +47,9 @@ Berlin, 2007
* @brief MMC-/SD-Card library * @brief MMC-/SD-Card library
* *
* @author Michael Baar <baar@inf.fu-berlin.de> * @author Michael Baar <baar@inf.fu-berlin.de>
* @version $Revision: 1.8 $ * @version $Revision: 1.9 $
* *
* $Id: sd.c,v 1.8 2009/05/26 12:15:46 nvt-se Exp $ * $Id: sd.c,v 1.9 2009/05/26 13:00:07 nvt-se Exp $
* *
* Initialisation and basic functions for read and write access * Initialisation and basic functions for read and write access
*/ */
@ -71,10 +71,10 @@ volatile sd_state_t sd_state;
void void
sd_init(void) sd_init(void)
{ {
// depending on the system global variables may not get initialised on startup /* depending on the system global variables may not get initialised on startup */
memset((void *)&sd_state, 0, sizeof (sd_state)); memset((void *)&sd_state, 0, sizeof (sd_state));
// initialize io ports /* initialize io ports */
sd_init_platform(); sd_init_platform();
} }
@ -96,24 +96,24 @@ sd_init_card(sd_cache_t * pCache)
return SD_INIT_SUCCESS; return SD_INIT_SUCCESS;
} }
// Wait for UART and switch to SPI mode /* Wait for UART and switch to SPI mode */
if(!uart_lock_wait(UART_MODE_SPI)) { if(!uart_lock_wait(UART_MODE_SPI)) {
return SD_INIT_FAILED; return SD_INIT_FAILED;
} }
// reset card /* reset card */
resetcnt = _sd_reset(&r3); resetcnt = _sd_reset(&r3);
if(resetcnt >= SD_RESET_RETRY_COUNT) { if(resetcnt >= SD_RESET_RETRY_COUNT) {
ret = SD_INIT_FAILED; ret = SD_INIT_FAILED;
goto sd_init_card_fail; goto sd_init_card_fail;
} }
// Test for hardware compatibility /* Test for hardware compatibility */
if((r3.ocr & SD_V_MASK) != SD_V_MASK) { if((r3.ocr & SD_V_MASK) != SD_V_MASK) {
ret = SD_INIT_NOTSUPP; ret = SD_INIT_NOTSUPP;
goto sd_init_card_fail; goto sd_init_card_fail;
} }
// Test for software compatibility /* Test for software compatibility */
if(!_sd_read_register(&csd, SD_CMD_SEND_CSD, sizeof (struct sd_csd))) { if(!_sd_read_register(&csd, SD_CMD_SEND_CSD, sizeof (struct sd_csd))) {
ret = SD_INIT_FAILED; ret = SD_INIT_FAILED;
goto sd_init_card_fail; goto sd_init_card_fail;
@ -138,7 +138,7 @@ sd_init_card_fail:
if(ret != SD_INIT_SUCCESS) { if(ret != SD_INIT_SUCCESS) {
return ret; return ret;
} }
// state /* state */
sd_state.MinBlockLen_bit = 9; sd_state.MinBlockLen_bit = 9;
sd_state.MaxBlockLen_bit = SD_CSD_READ_BL_LEN(csd); sd_state.MaxBlockLen_bit = SD_CSD_READ_BL_LEN(csd);
sd_state.Flags = SD_INITIALIZED; sd_state.Flags = SD_INITIALIZED;
@ -186,7 +186,7 @@ sd_close(void)
{ {
sd_flush(); sd_flush();
// reset state /* reset state */
memset((void *)&sd_state, 0, sizeof (sd_state)); memset((void *)&sd_state, 0, sizeof (sd_state));
} }
@ -197,12 +197,12 @@ sd_set_blocklength(const uint8_t blocklength_bit)
uint8_t ret; uint8_t ret;
uint8_t arg[4]; uint8_t arg[4];
// test if already set /* test if already set */
if(blocklength_bit == sd_state.BlockLen_bit) { if(blocklength_bit == sd_state.BlockLen_bit) {
return sd_state.BlockLen_bit; return sd_state.BlockLen_bit;
} }
// Wait for UART and switch to SPI mode /* Wait for UART and switch to SPI mode */
if(!uart_lock_wait(UART_MODE_SPI)) { if(!uart_lock_wait(UART_MODE_SPI)) {
return sd_state.BlockLen_bit; return sd_state.BlockLen_bit;
} }
@ -210,7 +210,7 @@ sd_set_blocklength(const uint8_t blocklength_bit)
((uint16_t *)arg)[1] = 0; ((uint16_t *)arg)[1] = 0;
((uint16_t *)arg)[0] = 1 << blocklength_bit; ((uint16_t *)arg)[0] = 1 << blocklength_bit;
// set blocklength command /* set blocklength command */
if(_sd_send_cmd(SD_CMD_SET_BLOCKLENGTH, SD_RESPONSE_SIZE_R1, arg, NULL)) { if(_sd_send_cmd(SD_CMD_SET_BLOCKLENGTH, SD_RESPONSE_SIZE_R1, arg, NULL)) {
sd_state.BlockLen_bit = blocklength_bit; sd_state.BlockLen_bit = blocklength_bit;
sd_state.BlockLen = ((uint16_t *)arg)[0]; sd_state.BlockLen = ((uint16_t *)arg)[0];
@ -219,17 +219,17 @@ sd_set_blocklength(const uint8_t blocklength_bit)
ret = SD_BLOCKLENGTH_INVALID; ret = SD_BLOCKLENGTH_INVALID;
} }
// unlock uart /* unlock uart */
uart_unlock(UART_MODE_SPI); uart_unlock(UART_MODE_SPI);
return ret; return ret;
} }
//@} /*@} */
/////////////////////////////////////////////////////////////////////////////// /*///////////////////////////////////////////////////////////////////////////// */
// Public functions, Reading /* Public functions, Reading */
/////////////////////////////////////////////////////////////////////////////// /*///////////////////////////////////////////////////////////////////////////// */
uint16_t uint16_t
sd_align_address(uint32_t * pAddress) sd_align_address(uint32_t * pAddress)
{ {
@ -257,7 +257,7 @@ sd_read_block(void (*const pBuffer), const uint32_t address)
sdspi_read(pBuffer, sd_state.BlockLen, TRUE); sdspi_read(pBuffer, sd_state.BlockLen, TRUE);
// receive CRC16 and finish /* receive CRC16 and finish */
_sd_read_stop(2); _sd_read_stop(2);
splx(s); splx(s);
@ -274,19 +274,19 @@ sd_read_byte(void *pBuffer, const uint32_t address)
return sd_read_block(pBuffer, address); return sd_read_block(pBuffer, address);
} else { } else {
uint32_t blAdr = address; uint32_t blAdr = address;
uint16_t offset; // bytes from aligned address to start of first byte to keep uint16_t offset; /* bytes from aligned address to start of first byte to keep */
// align /* align */
offset = sd_align_address(&blAdr); offset = sd_align_address(&blAdr);
// start /* start */
if(!_sd_read_start(SD_CMD_READ_SINGLE_BLOCK, address)) { if(!_sd_read_start(SD_CMD_READ_SINGLE_BLOCK, address)) {
return FALSE; return FALSE;
} }
// read /* read */
sdspi_read(pBuffer, offset + 1, FALSE); sdspi_read(pBuffer, offset + 1, FALSE);
// done /* done */
_sd_read_stop(sd_state.BlockLen - offset - 1); _sd_read_stop(sd_state.BlockLen - offset - 1);
} }
@ -298,84 +298,84 @@ sd_read_byte(void *pBuffer, const uint32_t address)
unsigned int unsigned int
sd_read(void *pBuffer, unsigned long address, unsigned int size) sd_read(void *pBuffer, unsigned long address, unsigned int size)
{ {
unsigned char *p; // pointer to current pos in receive buffer unsigned char *p; /* pointer to current pos in receive buffer */
unsigned int offset; // bytes from aligned address to start of first byte to keep unsigned int offset; /* bytes from aligned address to start of first byte to keep */
unsigned int read_count; // num bytes to read in one iteration unsigned int read_count; /* num bytes to read in one iteration */
bool dump_flag; // number of bytes to dump in last iteration bool dump_flag; /* number of bytes to dump in last iteration */
unsigned int num_bytes_read; // number of bytes read into receive buffer unsigned int num_bytes_read; /* number of bytes read into receive buffer */
unsigned char ret; unsigned char ret;
// /* */
// parameter processing /* parameter processing */
// /* */
if(size == 0) { if(size == 0) {
return 0; return 0;
} }
// align to block /* align to block */
offset = sd_align_address(&address); offset = sd_align_address(&address);
if((offset == 0) && (sd_state.BlockLen == size)) { if((offset == 0) && (sd_state.BlockLen == size)) {
// best case: perfectly block aligned, no chunking /* best case: perfectly block aligned, no chunking */
// -> do shortcut /* -> do shortcut */
return sd_read_block(pBuffer, address); return sd_read_block(pBuffer, address);
} }
// calculate first block /* calculate first block */
if(size > sd_state.BlockLen) { if(size > sd_state.BlockLen) {
read_count = sd_state.BlockLen; read_count = sd_state.BlockLen;
} else { } else {
read_count = size; read_count = size;
} }
// /* */
// Data transfer /* Data transfer */
// /* */
s = splhigh(s); s = splhigh(s);
// request data transfer /* request data transfer */
ret = _sd_read_start(SD_CMD_READ_SINGLE_BLOCK, address); ret = _sd_read_start(SD_CMD_READ_SINGLE_BLOCK, address);
if(!ret) { if(!ret) {
splx(s); splx(s);
return 0; return 0;
} }
// run to offset /* run to offset */
if(offset) { if(offset) {
sdspi_read(pBuffer, offset, FALSE); // dump till offset sdspi_read(pBuffer, offset, FALSE); /* dump till offset */
dump_flag = ((read_count + offset) < sd_state.BlockLen); dump_flag = ((read_count + offset) < sd_state.BlockLen);
if(!dump_flag) { if(!dump_flag) {
read_count = sd_state.BlockLen - offset; // max bytes to read from first block read_count = sd_state.BlockLen - offset; /* max bytes to read from first block */
} }
} else { } else {
dump_flag = (read_count < sd_state.BlockLen); dump_flag = (read_count < sd_state.BlockLen);
} }
// /* */
// block read loop /* block read loop */
// /* */
num_bytes_read = 0; num_bytes_read = 0;
p = pBuffer; p = pBuffer;
do { do {
// whole block will be processed /* whole block will be processed */
size -= read_count; // global counter size -= read_count; /* global counter */
// read to receive buffer /* read to receive buffer */
sdspi_read(p, read_count, TRUE); sdspi_read(p, read_count, TRUE);
p += read_count; // increment buffer pointer p += read_count; /* increment buffer pointer */
num_bytes_read += read_count; num_bytes_read += read_count;
// finish block /* finish block */
if(dump_flag) { if(dump_flag) {
// cancel remaining bytes (last iteration) /* cancel remaining bytes (last iteration) */
_sd_read_stop(sd_state.BlockLen - read_count - offset); _sd_read_stop(sd_state.BlockLen - read_count - offset);
break; break;
// unselect is included in send_cmd /* unselect is included in send_cmd */
} else { } else {
sdspi_idle(2); // receive CRC16 sdspi_idle(2); /* receive CRC16 */
if(size != 0) { if(size != 0) {
// address calculation for next block /* address calculation for next block */
offset = 0; offset = 0;
address += sd_state.BlockLen; address += sd_state.BlockLen;
if(size > sd_state.BlockLen) { if(size > sd_state.BlockLen) {
@ -393,7 +393,7 @@ sd_read(void *pBuffer, unsigned long address, unsigned int size)
return 0; return 0;
} }
} else { } else {
// finished /* finished */
_sd_read_stop(0); _sd_read_stop(0);
break; break;
} }
@ -405,11 +405,11 @@ sd_read(void *pBuffer, unsigned long address, unsigned int size)
return num_bytes_read; return num_bytes_read;
} }
#endif // SD_READ_ANY #endif /* SD_READ_ANY */
/////////////////////////////////////////////////////////////////////////////// /*///////////////////////////////////////////////////////////////////////////// */
// Public functions, Writing /* Public functions, Writing */
/////////////////////////////////////////////////////////////////////////////// /*///////////////////////////////////////////////////////////////////////////// */
#if SD_WRITE #if SD_WRITE
enum sd_write_ret enum sd_write_ret
_sd_write_finish(void) _sd_write_finish(void)
@ -427,10 +427,10 @@ _sd_write_finish(void)
s = splhigh(); s = splhigh();
// dummy crc /* dummy crc */
sdspi_idle(2); sdspi_idle(2);
// receive data response (ZZS___ 3 bits crc response) /* receive data response (ZZS___ 3 bits crc response) */
for(i = 0; i < SD_TIMEOUT_NCR; i++) { for(i = 0; i < SD_TIMEOUT_NCR; i++) {
ret = sdspi_rx(); ret = sdspi_rx();
if((ret > 0) && (ret < 0xFF)) { if((ret > 0) && (ret < 0xFF)) {
@ -442,23 +442,23 @@ _sd_write_finish(void)
} }
} }
// wait for data to be written /* wait for data to be written */
_sd_wait_standby(NULL); _sd_wait_standby(NULL);
splx(s); splx(s);
sdspi_unselect(); sdspi_unselect();
if(ret) { if(ret) {
// data transfer to sd card buffer was successful /* data transfer to sd card buffer was successful */
// query for result of actual write operation /* query for result of actual write operation */
ret = _sd_send_cmd(SD_CMD_SEND_STATUS, SD_RESPONSE_SIZE_R2, NULL, &r2); ret = _sd_send_cmd(SD_CMD_SEND_STATUS, SD_RESPONSE_SIZE_R2, NULL, &r2);
if(ret && (r2 == 0)) { if(ret && (r2 == 0)) {
result = SD_WRITE_SUCCESS; result = SD_WRITE_SUCCESS;
} }
} else { } else {
// data transfer to sd card buffer failed /* data transfer to sd card buffer failed */
} }
// unlock uart (locked from every write operation) /* unlock uart (locked from every write operation) */
uart_unlock(UART_MODE_SPI); uart_unlock(UART_MODE_SPI);
return result; return result;
@ -486,17 +486,18 @@ _sd_write_block(const uint32_t * pAddress, const void *pBuffer, int increment)
uint8_t r1, ret; uint8_t r1, ret;
int s; int s;
// block write-access on write protection /* block write-access on write protection */
if(sd_protected()) { if(sd_protected()) {
return SD_WRITE_PROTECTED_ERR; return SD_WRITE_PROTECTED_ERR;
} }
// acquire uart /* acquire uart */
if(!uart_lock_wait(UART_MODE_SPI)) { if(!uart_lock_wait(UART_MODE_SPI)) {
return SD_WRITE_INTERFACE_ERR; return SD_WRITE_INTERFACE_ERR;
} }
// start write /* start write */
s = splhigh();
SD_LED_WRITE_ON; SD_LED_WRITE_ON;
r1 = 0; r1 = 0;
ret = _sd_send_cmd(SD_CMD_WRITE_SINGLE_BLOCK, SD_RESPONSE_SIZE_R1, ret = _sd_send_cmd(SD_CMD_WRITE_SINGLE_BLOCK, SD_RESPONSE_SIZE_R1,
@ -504,12 +505,13 @@ _sd_write_block(const uint32_t * pAddress, const void *pBuffer, int increment)
if(!ret || r1) { if(!ret || r1) {
leds_on(LEDS_ALL); leds_on(LEDS_ALL);
_sd_reset(NULL); _sd_reset(NULL);
splx(s);
uart_unlock(UART_MODE_SPI); uart_unlock(UART_MODE_SPI);
SD_LED_WRITE_OFF; SD_LED_WRITE_OFF;
return SD_WRITE_COMMAND_ERR; return SD_WRITE_COMMAND_ERR;
} }
// write data
s = splhigh(); /* write data */
sdspi_select(); sdspi_select();
sdspi_tx(0xFF); sdspi_tx(0xFF);
sdspi_tx(SD_TOKEN_WRITE); sdspi_tx(SD_TOKEN_WRITE);
@ -517,7 +519,7 @@ _sd_write_block(const uint32_t * pAddress, const void *pBuffer, int increment)
SD_LED_WRITE_OFF; SD_LED_WRITE_OFF;
// finish write /* finish write */
#if SPI_DMA_WRITE #if SPI_DMA_WRITE
sdspi_dma_lock = TRUE; sdspi_dma_lock = TRUE;
splx(s); splx(s);
@ -535,19 +537,17 @@ sd_set_block(const uint32_t address, const char (*const pChar))
return _sd_write_block(&address, pChar, FALSE); return _sd_write_block(&address, pChar, FALSE);
} }
enum sd_write_ret enum sd_write_ret
sd_write_block(const uint32_t address, void const (*const pBuffer)) sd_write_block(const uint32_t address, void const (*const pBuffer))
{ {
return _sd_write_block(&address, pBuffer, TRUE); return _sd_write_block(&address, pBuffer, TRUE);
} }
#endif #endif
/////////////////////////////////////////////////////////////////////////////// /*///////////////////////////////////////////////////////////////////////////// */
// Supporting functions /* Supporting functions */
/////////////////////////////////////////////////////////////////////////////// /*///////////////////////////////////////////////////////////////////////////// */
/** /**
@ -559,7 +559,7 @@ inline bool _sd_get_op_cond(struct sd_response_r1 * pResponse)
{ {
bool ret; bool ret;
// SD style /* SD style */
ret = _sd_send_cmd(SD_CMD_APP_SECIFIC_CMD, SD_RESPONSE_SIZE_R1, NULL, ret = _sd_send_cmd(SD_CMD_APP_SECIFIC_CMD, SD_RESPONSE_SIZE_R1, NULL,
pResponse); pResponse);
@ -568,7 +568,7 @@ inline bool _sd_get_op_cond(struct sd_response_r1 * pResponse)
ret = _sd_send_cmd(SD_ACMD_SEND_OP_COND, SD_RESPONSE_SIZE_R1, &arg, ret = _sd_send_cmd(SD_ACMD_SEND_OP_COND, SD_RESPONSE_SIZE_R1, &arg,
pResponse); pResponse);
} else { } else {
// MMC style init /* MMC style init */
ret = _sd_send_cmd(SD_CMD_SEND_OP_COND, SD_RESPONSE_SIZE_R1, NULL, ret = _sd_send_cmd(SD_CMD_SEND_OP_COND, SD_RESPONSE_SIZE_R1, NULL,
pResponse); pResponse);
if(*((uint8_t *)pResponse) & SD_R1_ERROR_MASK) { if(*((uint8_t *)pResponse) & SD_R1_ERROR_MASK) {
@ -653,11 +653,12 @@ _sd_send_cmd(const uint8_t command,
int i; /* loop counter */ int i; /* loop counter */
int s; /* interrupt state */ int s; /* interrupt state */
sdspi_select();
#if SD_WRITE && SPI_DMA_WRITE #if SD_WRITE && SPI_DMA_WRITE
sd_write_flush(); sd_write_flush();
#endif #endif
sdspi_select();
cmd[0] |= command; cmd[0] |= command;
if(pArg != NULL) { if(pArg != NULL) {
cmd[1] = ((uint8_t *)pArg)[3]; cmd[1] = ((uint8_t *)pArg)[3];
@ -669,7 +670,7 @@ _sd_send_cmd(const uint8_t command,
s = splhigh(); s = splhigh();
sdspi_write(cmd, 6, 1); sdspi_write(cmd, 6, 1);
// wait for start bit /* wait for start bit */
i = SD_TIMEOUT_NCR; i = SD_TIMEOUT_NCR;
do { do {
data = sdspi_rx(); data = sdspi_rx();
@ -684,10 +685,10 @@ _sd_send_cmd(const uint8_t command,
_sd_send_cmd_response: _sd_send_cmd_response:
s = splhigh(); s = splhigh();
// start bit received, read response with size i /* start bit received, read response with size i */
i = response_size - 1; i = response_size - 1;
if(pResponse != NULL) { if(pResponse != NULL) {
// copy response to response buffer /* copy response to response buffer */
do { do {
((uint8_t *)pResponse)[i] = data; ((uint8_t *)pResponse)[i] = data;
if(i == 0) { if(i == 0) {
@ -698,11 +699,11 @@ _sd_send_cmd_response:
i--; i--;
} while(1); } while(1);
} else { } else {
// receive and ignore response /* receive and ignore response */
sdspi_read(&data, i, 0); sdspi_read(&data, i, 0);
} }
// done successfully /* done successfully */
sdspi_unselect(); sdspi_unselect();
splx(s); splx(s);
@ -710,7 +711,7 @@ _sd_send_cmd_response:
return TRUE; return TRUE;
sd_send_cmd_fail: sd_send_cmd_fail:
// failed /* failed */
sdspi_unselect(); sdspi_unselect();
return FALSE; return FALSE;
@ -744,7 +745,7 @@ _sd_read_start(uint8_t cmd, uint32_t address)
uint8_t ret; uint8_t ret;
uint16_t i; uint16_t i;
// aquire uart /* acquire uart */
if(!uart_lock_wait(UART_MODE_SPI)) { if(!uart_lock_wait(UART_MODE_SPI)) {
return FALSE; return FALSE;
} }
@ -754,26 +755,15 @@ _sd_read_start(uint8_t cmd, uint32_t address)
goto _sd_read_start_fail; goto _sd_read_start_fail;
} }
// Wait for start bit (0) /* Wait for start bit (0) */
sdspi_select(); sdspi_select();
i = sdspi_wait_token(0xFF, 0xFF, SD_TOKEN_READ, SD_TIMEOUT_READ); i = sdspi_wait_token(0xFF, 0xFF, SD_TOKEN_READ, SD_TIMEOUT_READ);
if(i < SD_TIMEOUT_READ) { if(i < SD_TIMEOUT_READ) {
// token received, data bytes follow /* token received, data bytes follow */
SD_LED_READ_ON; SD_LED_READ_ON;
/*
Following code handles error tokens. Since these are currently not used in the
application they can just be ignored. Anyway this is still useful when debugging.
else if( (data != 0) && (data & SD_DATA_ERROR_TOKEN_MASK) == data ) {
// data error token
sdspi_rx();
break;
} */
return TRUE; return TRUE;
} else {
// error or timeout
} }
_sd_read_start_fail: _sd_read_start_fail:
@ -789,7 +779,7 @@ _sd_read_start_fail:
void void
_sd_read_stop(uint16_t count) _sd_read_stop(uint16_t count)
{ {
// finish block + crc /* finish block + crc */
if(count) { if(count) {
uint8_t dump; uint8_t dump;
@ -799,11 +789,11 @@ _sd_read_stop(uint16_t count)
SD_LED_READ_OFF; SD_LED_READ_OFF;
// wait for switch to standby mode /* wait for switch to standby mode */
if(!_sd_wait_standby(NULL)) { if(!_sd_wait_standby(NULL)) {
_sd_reset(NULL); _sd_reset(NULL);
} }
// unlock uart (locked from _sd_read_start) /* unlock uart (locked from _sd_read_start) */
uart_unlock(UART_MODE_SPI); uart_unlock(UART_MODE_SPI);
} }