more protection against interrupts that might spoil SPI sequences.
made coding style more like that of contiki.
This commit is contained in:
parent
f39d2bd4c6
commit
e9d279620f
|
@ -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.7 $
|
* @version $Revision: 1.8 $
|
||||||
*
|
*
|
||||||
* $Id: sd.c,v 1.7 2009/05/25 13:19:04 nvt-se Exp $
|
* $Id: sd.c,v 1.8 2009/05/26 12:15:46 nvt-se Exp $
|
||||||
*
|
*
|
||||||
* Initialisation and basic functions for read and write access
|
* Initialisation and basic functions for read and write access
|
||||||
*/
|
*/
|
||||||
|
@ -88,40 +88,40 @@ sd_init_card(sd_cache_t * pCache)
|
||||||
int resetcnt;
|
int resetcnt;
|
||||||
struct sd_response_r3 r3;
|
struct sd_response_r3 r3;
|
||||||
|
|
||||||
if (!sd_detected()) {
|
if(!sd_detected()) {
|
||||||
return SD_INIT_NOCARD;
|
return SD_INIT_NOCARD;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sd_state.Flags & SD_INITIALIZED) {
|
if(sd_state.Flags & SD_INITIALIZED) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
ccc = SD_CSD_CCC(csd);
|
ccc = SD_CSD_CCC(csd);
|
||||||
|
|
||||||
if ((ccc & SD_DEFAULT_MINCCC) != SD_DEFAULT_MINCCC) {
|
if((ccc & SD_DEFAULT_MINCCC) != SD_DEFAULT_MINCCC) {
|
||||||
ret = SD_INIT_NOTSUPP;
|
ret = SD_INIT_NOTSUPP;
|
||||||
goto sd_init_card_fail;
|
goto sd_init_card_fail;
|
||||||
}
|
}
|
||||||
|
@ -135,19 +135,19 @@ sd_init_card_fail:
|
||||||
LOG_VERBOSE("(sd_init) result:%u, resetcnt:%i OCR:%.8lx, CCC:%.4x",
|
LOG_VERBOSE("(sd_init) result:%u, resetcnt:%i OCR:%.8lx, CCC:%.4x",
|
||||||
ret, resetcnt, r3.ocr, ccc);
|
ret, resetcnt, r3.ocr, ccc);
|
||||||
#endif
|
#endif
|
||||||
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;
|
||||||
if (SD_CSD_READ_PARTIAL(csd)) {
|
if(SD_CSD_READ_PARTIAL(csd)) {
|
||||||
sd_state.MinBlockLen_bit = 0;
|
sd_state.MinBlockLen_bit = 0;
|
||||||
sd_state.Flags |= SD_READ_PARTIAL;
|
sd_state.Flags |= SD_READ_PARTIAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SD_CSD_WRITE_PARTIAL(csd)) {
|
if(SD_CSD_WRITE_PARTIAL(csd)) {
|
||||||
sd_state.Flags |= SD_WRITE_PARTIAL;
|
sd_state.Flags |= SD_WRITE_PARTIAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ sd_init_card_fail:
|
||||||
sd_state.BlockLen = 1 << 9;
|
sd_state.BlockLen = 1 << 9;
|
||||||
|
|
||||||
#if SD_CACHE
|
#if SD_CACHE
|
||||||
if (pCache == NULL) {
|
if(pCache == NULL) {
|
||||||
return SD_INIT_NOTSUPP;
|
return SD_INIT_NOTSUPP;
|
||||||
}
|
}
|
||||||
sd_state.Cache = pCache;
|
sd_state.Cache = pCache;
|
||||||
|
@ -169,7 +169,7 @@ sd_init_card_fail:
|
||||||
void
|
void
|
||||||
sd_flush(void)
|
sd_flush(void)
|
||||||
{
|
{
|
||||||
if (uart_lock(UART_MODE_SPI)) {
|
if(uart_lock(UART_MODE_SPI)) {
|
||||||
#if SD_WRITE && SD_CACHE
|
#if SD_WRITE && SD_CACHE
|
||||||
_sd_cache_flush();
|
_sd_cache_flush();
|
||||||
#endif
|
#endif
|
||||||
|
@ -198,22 +198,22 @@ sd_set_blocklength(const uint8_t blocklength_bit)
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
((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];
|
||||||
ret = blocklength_bit;
|
ret = blocklength_bit;
|
||||||
} else {
|
} else {
|
||||||
ret = SD_BLOCKLENGTH_INVALID;
|
ret = SD_BLOCKLENGTH_INVALID;
|
||||||
|
@ -231,10 +231,10 @@ sd_set_blocklength(const uint8_t blocklength_bit)
|
||||||
// Public functions, Reading
|
// Public functions, Reading
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
uint16_t
|
uint16_t
|
||||||
sd_AlignAddress(uint32_t * pAddress)
|
sd_align_address(uint32_t * pAddress)
|
||||||
{
|
{
|
||||||
uint16_t blMask = sd_state.BlockLen - 1;
|
uint16_t blMask = sd_state.BlockLen - 1;
|
||||||
uint16_t *lw = (uint16_t *) pAddress;
|
uint16_t *lw = (uint16_t *)pAddress;
|
||||||
uint16_t offset = *lw & blMask;
|
uint16_t offset = *lw & blMask;
|
||||||
|
|
||||||
*lw &= ~blMask;
|
*lw &= ~blMask;
|
||||||
|
@ -246,7 +246,12 @@ sd_AlignAddress(uint32_t * pAddress)
|
||||||
uint16_t
|
uint16_t
|
||||||
sd_read_block(void (*const pBuffer), const uint32_t address)
|
sd_read_block(void (*const pBuffer), const uint32_t address)
|
||||||
{
|
{
|
||||||
if (!_sd_read_start(SD_CMD_READ_SINGLE_BLOCK, address)) {
|
int s;
|
||||||
|
|
||||||
|
s = splhigh();
|
||||||
|
|
||||||
|
if(!_sd_read_start(SD_CMD_READ_SINGLE_BLOCK, address)) {
|
||||||
|
splx(s);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,6 +260,8 @@ sd_read_block(void (*const pBuffer), const uint32_t address)
|
||||||
// receive CRC16 and finish
|
// receive CRC16 and finish
|
||||||
_sd_read_stop(2);
|
_sd_read_stop(2);
|
||||||
|
|
||||||
|
splx(s);
|
||||||
|
|
||||||
return sd_state.BlockLen;
|
return sd_state.BlockLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,21 +270,21 @@ sd_read_block(void (*const pBuffer), const uint32_t address)
|
||||||
bool
|
bool
|
||||||
sd_read_byte(void *pBuffer, const uint32_t address)
|
sd_read_byte(void *pBuffer, const uint32_t address)
|
||||||
{
|
{
|
||||||
if (sd_set_blocklength(0) == 0) {
|
if(sd_set_blocklength(0) == 0) {
|
||||||
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_AlignAddress(&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
|
||||||
Spi_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);
|
||||||
|
@ -301,20 +308,20 @@ sd_read(void *pBuffer, unsigned long address, unsigned int size)
|
||||||
//
|
//
|
||||||
// parameter processing
|
// parameter processing
|
||||||
//
|
//
|
||||||
if (size == 0) {
|
if(size == 0) {
|
||||||
return FALSE;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// align to block
|
// align to block
|
||||||
offset = sd_AlignAddress(&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;
|
||||||
|
@ -323,16 +330,20 @@ sd_read(void *pBuffer, unsigned long address, unsigned int size)
|
||||||
// Data transfer
|
// Data transfer
|
||||||
//
|
//
|
||||||
|
|
||||||
|
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) {
|
||||||
RETF(ret);
|
splx(s);
|
||||||
|
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 {
|
||||||
|
@ -356,18 +367,18 @@ sd_read(void *pBuffer, unsigned long address, unsigned int size)
|
||||||
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) {
|
||||||
read_count = sd_state.BlockLen;
|
read_count = sd_state.BlockLen;
|
||||||
dump_flag = FALSE;
|
dump_flag = FALSE;
|
||||||
} else {
|
} else {
|
||||||
|
@ -377,14 +388,19 @@ sd_read(void *pBuffer, unsigned long address, unsigned int size)
|
||||||
|
|
||||||
sdspi_unselect();
|
sdspi_unselect();
|
||||||
ret = _sd_read_start(SD_CMD_READ_SINGLE_BLOCK, address);
|
ret = _sd_read_start(SD_CMD_READ_SINGLE_BLOCK, address);
|
||||||
RETF(ret);
|
if(!ret) {
|
||||||
|
splx(s);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// finished
|
// finished
|
||||||
_sd_read_stop(0);
|
_sd_read_stop(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (1);
|
} while(1);
|
||||||
|
|
||||||
|
splx(s);
|
||||||
|
|
||||||
return num_bytes_read;
|
return num_bytes_read;
|
||||||
}
|
}
|
||||||
|
@ -409,16 +425,16 @@ _sd_write_finish(void)
|
||||||
sdspi_dma_lock = FALSE;
|
sdspi_dma_lock = FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
s = splhigh();
|
||||||
|
|
||||||
// dummy crc
|
// dummy crc
|
||||||
sdspi_idle(2);
|
sdspi_idle(2);
|
||||||
|
|
||||||
s = splhigh();
|
|
||||||
|
|
||||||
// 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)) {
|
||||||
while (ret & 0x80) {
|
while(ret & 0x80) {
|
||||||
ret <<= 1;
|
ret <<= 1;
|
||||||
}
|
}
|
||||||
ret = ((ret & 0x70) == 0x20);
|
ret = ((ret & 0x70) == 0x20);
|
||||||
|
@ -426,17 +442,16 @@ _sd_write_finish(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
splx(s);
|
|
||||||
|
|
||||||
// wait for data to be written
|
// wait for data to be written
|
||||||
_sd_wait_standby(NULL);
|
_sd_wait_standby(NULL);
|
||||||
|
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 {
|
||||||
|
@ -454,7 +469,7 @@ enum sd_write_ret
|
||||||
sd_write_flush(void)
|
sd_write_flush(void)
|
||||||
{
|
{
|
||||||
#if SPI_DMA_WRITE
|
#if SPI_DMA_WRITE
|
||||||
if (!sdspi_dma_lock) {
|
if(!sdspi_dma_lock) {
|
||||||
return SD_WRITE_DMA_ERR;
|
return SD_WRITE_DMA_ERR;
|
||||||
} else {
|
} else {
|
||||||
return _sd_write_finish();
|
return _sd_write_finish();
|
||||||
|
@ -472,12 +487,12 @@ _sd_write_block(const uint32_t * pAddress, const void *pBuffer, int increment)
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,7 +501,7 @@ _sd_write_block(const uint32_t * pAddress, const void *pBuffer, int increment)
|
||||||
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,
|
||||||
pAddress, &r1);
|
pAddress, &r1);
|
||||||
if (!ret || r1) {
|
if(!ret || r1) {
|
||||||
leds_on(LEDS_ALL);
|
leds_on(LEDS_ALL);
|
||||||
_sd_reset(NULL);
|
_sd_reset(NULL);
|
||||||
uart_unlock(UART_MODE_SPI);
|
uart_unlock(UART_MODE_SPI);
|
||||||
|
@ -494,21 +509,23 @@ _sd_write_block(const uint32_t * pAddress, const void *pBuffer, int increment)
|
||||||
return SD_WRITE_COMMAND_ERR;
|
return SD_WRITE_COMMAND_ERR;
|
||||||
}
|
}
|
||||||
// write data
|
// write data
|
||||||
sdspi_select();
|
|
||||||
s = splhigh();
|
s = splhigh();
|
||||||
|
sdspi_select();
|
||||||
sdspi_tx(0xFF);
|
sdspi_tx(0xFF);
|
||||||
sdspi_tx(SD_TOKEN_WRITE);
|
sdspi_tx(SD_TOKEN_WRITE);
|
||||||
sdspi_write(pBuffer, sd_state.BlockLen, increment);
|
sdspi_write(pBuffer, sd_state.BlockLen, increment);
|
||||||
splx(s);
|
|
||||||
|
|
||||||
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);
|
||||||
return SD_WRITE_SUCCESS;
|
return SD_WRITE_SUCCESS;
|
||||||
#else
|
#else
|
||||||
return _sd_write_finish();
|
ret = _sd_write_finish();
|
||||||
|
splx(s);
|
||||||
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -546,7 +563,7 @@ inline bool _sd_get_op_cond(struct sd_response_r1 * pResponse)
|
||||||
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);
|
||||||
|
|
||||||
if (ret) {
|
if(ret) {
|
||||||
uint32_t arg = SD_V_MASK;
|
uint32_t arg = SD_V_MASK;
|
||||||
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);
|
||||||
|
@ -554,7 +571,7 @@ inline bool _sd_get_op_cond(struct sd_response_r1 * pResponse)
|
||||||
// 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) {
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -574,7 +591,7 @@ _sd_wait_standby(struct sd_response_r3 * pOpCond)
|
||||||
struct sd_response_r3 opCond;
|
struct sd_response_r3 opCond;
|
||||||
struct sd_response_r3 *pR3 = pOpCond;
|
struct sd_response_r3 *pR3 = pOpCond;
|
||||||
|
|
||||||
if (pR3 == NULL) {
|
if(pR3 == NULL) {
|
||||||
pR3 = &opCond;
|
pR3 = &opCond;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,14 +599,14 @@ _sd_wait_standby(struct sd_response_r3 * pOpCond)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ret = _sd_get_op_cond((struct sd_response_r1 *)pR3);
|
ret = _sd_get_op_cond((struct sd_response_r1 *)pR3);
|
||||||
if (ret && (pR3->r1.in_idle_state == 0)) {
|
if(ret && (pR3->r1.in_idle_state == 0)) {
|
||||||
ret = _sd_send_cmd(SD_CMD_READ_OCR, SD_RESPONSE_SIZE_R3, NULL, pR3);
|
ret = _sd_send_cmd(SD_CMD_READ_OCR, SD_RESPONSE_SIZE_R3, NULL, pR3);
|
||||||
if (ret && !SD_OCR_BUSY(pR3->ocr)) {
|
if(ret && !SD_OCR_BUSY(pR3->ocr)) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i--;
|
i--;
|
||||||
} while (i);
|
} while(i);
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -605,13 +622,13 @@ _sd_reset(struct sd_response_r3 *pOpCond)
|
||||||
bool ret;
|
bool ret;
|
||||||
struct sd_response_r1 r1;
|
struct sd_response_r1 r1;
|
||||||
|
|
||||||
for (i = 0; i < SD_RESET_RETRY_COUNT; i++) {
|
for(i = 0; i < SD_RESET_RETRY_COUNT; i++) {
|
||||||
ret = _sd_send_cmd(SD_CMD_GO_IDLE_STATE, SD_RESPONSE_SIZE_R1, NULL, &r1);
|
ret = _sd_send_cmd(SD_CMD_GO_IDLE_STATE, SD_RESPONSE_SIZE_R1, NULL, &r1);
|
||||||
if (ret == 0 || r1.illegal_cmd) {
|
if(ret == 0 || r1.illegal_cmd) {
|
||||||
_sd_send_cmd(SD_CMD_STOP_TRANSMISSION, SD_RESPONSE_SIZE_R1, NULL, &r1);
|
_sd_send_cmd(SD_CMD_STOP_TRANSMISSION, SD_RESPONSE_SIZE_R1, NULL, &r1);
|
||||||
} else {
|
} else {
|
||||||
ret = _sd_wait_standby(pOpCond);
|
ret = _sd_wait_standby(pOpCond);
|
||||||
if (ret) {
|
if(ret) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -642,11 +659,11 @@ _sd_send_cmd(const uint8_t command,
|
||||||
|
|
||||||
sdspi_select();
|
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];
|
||||||
cmd[2] = ((uint8_t *) pArg)[2];
|
cmd[2] = ((uint8_t *)pArg)[2];
|
||||||
cmd[3] = ((uint8_t *) pArg)[1];
|
cmd[3] = ((uint8_t *)pArg)[1];
|
||||||
cmd[4] = ((uint8_t *) pArg)[0];
|
cmd[4] = ((uint8_t *)pArg)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
s = splhigh();
|
s = splhigh();
|
||||||
|
@ -656,10 +673,10 @@ _sd_send_cmd(const uint8_t command,
|
||||||
i = SD_TIMEOUT_NCR;
|
i = SD_TIMEOUT_NCR;
|
||||||
do {
|
do {
|
||||||
data = sdspi_rx();
|
data = sdspi_rx();
|
||||||
if ((data & 0x80) == 0) {
|
if((data & 0x80) == 0) {
|
||||||
goto _sd_send_cmd_response;
|
goto _sd_send_cmd_response;
|
||||||
}
|
}
|
||||||
} while (i--);
|
} while(i--);
|
||||||
|
|
||||||
splx(s);
|
splx(s);
|
||||||
|
|
||||||
|
@ -669,17 +686,17 @@ _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) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = sdspi_rx();
|
data = sdspi_rx();
|
||||||
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);
|
||||||
|
@ -706,7 +723,7 @@ sd_send_cmd_fail:
|
||||||
uint16_t
|
uint16_t
|
||||||
_sd_read_register(void *pBuffer, uint8_t cmd, uint16_t size)
|
_sd_read_register(void *pBuffer, uint8_t cmd, uint16_t size)
|
||||||
{
|
{
|
||||||
if (!_sd_read_start(cmd, 0)) {
|
if(!_sd_read_start(cmd, 0)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,12 +745,12 @@ _sd_read_start(uint8_t cmd, uint32_t address)
|
||||||
uint16_t i;
|
uint16_t i;
|
||||||
|
|
||||||
// aquire uart
|
// aquire uart
|
||||||
if (!uart_lock_wait(UART_MODE_SPI)) {
|
if(!uart_lock_wait(UART_MODE_SPI)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = _sd_send_cmd(cmd, SD_RESPONSE_SIZE_R1, &address, &r1);
|
ret = _sd_send_cmd(cmd, SD_RESPONSE_SIZE_R1, &address, &r1);
|
||||||
if (!ret || r1) {
|
if(!ret || r1) {
|
||||||
goto _sd_read_start_fail;
|
goto _sd_read_start_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -742,7 +759,7 @@ _sd_read_start(uint8_t cmd, uint32_t address)
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
@ -773,7 +790,7 @@ 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;
|
||||||
|
|
||||||
sdspi_read(&dump, count + 2, FALSE);
|
sdspi_read(&dump, count + 2, FALSE);
|
||||||
|
@ -783,7 +800,7 @@ _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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,9 +46,9 @@ Berlin, 2007
|
||||||
* @brief MMC-/SD-Card library, Public interface
|
* @brief MMC-/SD-Card library, Public interface
|
||||||
*
|
*
|
||||||
* @author Michael Baar <baar@inf.fu-berlin.de>
|
* @author Michael Baar <baar@inf.fu-berlin.de>
|
||||||
* @version $Revision: 1.5 $
|
* @version $Revision: 1.6 $
|
||||||
*
|
*
|
||||||
* $Id: sd.h,v 1.5 2008/11/10 14:32:49 nvt-se Exp $
|
* $Id: sd.h,v 1.6 2009/05/26 12:15:46 nvt-se Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -224,7 +224,7 @@ void sd_close(void);
|
||||||
* 2^n value, where n shall be between 0 and 11.
|
* 2^n value, where n shall be between 0 and 11.
|
||||||
* Be aware that a card may or may not support different blocksizes.
|
* Be aware that a card may or may not support different blocksizes.
|
||||||
*
|
*
|
||||||
* Since all read and write operations have to use blockaligned addresses
|
* Since all read and write operations have to use block-aligned addresses
|
||||||
* and need to process complete blocks always try to use the optimal blocksize
|
* and need to process complete blocks always try to use the optimal blocksize
|
||||||
* and let ::sd_read do the rest. If the blocklength is already set to the new
|
* and let ::sd_read do the rest. If the blocklength is already set to the new
|
||||||
* value nothing is done.
|
* value nothing is done.
|
||||||
|
@ -251,7 +251,7 @@ void sd_close(void);
|
||||||
* @param[in,out] pAddress address to align, will be modified to be block aligned
|
* @param[in,out] pAddress address to align, will be modified to be block aligned
|
||||||
* @return Offset from aligned address to original address
|
* @return Offset from aligned address to original address
|
||||||
*/
|
*/
|
||||||
uint16_t sd_AlignAddress(uint32_t * pAddress);
|
uint16_t sd_align_address(uint32_t * pAddress);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read one complete block from a block aligned address into buffer
|
* @brief Read one complete block from a block aligned address into buffer
|
||||||
|
|
|
@ -47,9 +47,9 @@ Berlin, 2007
|
||||||
* @brief MMC-/SD-Card library, cached read and write
|
* @brief MMC-/SD-Card library, cached read and write
|
||||||
*
|
*
|
||||||
* @author Michael Baar <baar@inf.fu-berlin.de>
|
* @author Michael Baar <baar@inf.fu-berlin.de>
|
||||||
* @version $Revision: 1.4 $
|
* @version $Revision: 1.5 $
|
||||||
*
|
*
|
||||||
* $Id: sd_cache.c,v 1.4 2008/03/31 14:32:00 nvt-se Exp $
|
* $Id: sd_cache.c,v 1.5 2009/05/26 12:15:46 nvt-se Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ _sd_cache_init(void)
|
||||||
|
|
||||||
sd_state.Cache->address = 1;
|
sd_state.Cache->address = 1;
|
||||||
sd_state.Cache->state = 0;
|
sd_state.Cache->state = 0;
|
||||||
// pre-read first block
|
/* pre-read first block */
|
||||||
sd_cache_read_block(&addr);
|
sd_cache_read_block(&addr);
|
||||||
SD_FREE_LOCK(sd_state.Cache);
|
SD_FREE_LOCK(sd_state.Cache);
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ _sd_cache_flush(void)
|
||||||
{
|
{
|
||||||
#if SD_WRITE
|
#if SD_WRITE
|
||||||
SD_GET_LOCK(sd_state.Cache);
|
SD_GET_LOCK(sd_state.Cache);
|
||||||
if (sd_state.Cache->state & SD_CACHE_DIRTY) {
|
if(sd_state.Cache->state & SD_CACHE_DIRTY) {
|
||||||
sd_set_blocklength(SD_WRITE_BLOCKLENGTH_BIT);
|
sd_set_blocklength(SD_WRITE_BLOCKLENGTH_BIT);
|
||||||
sd_write_block(sd_state.Cache->address, sd_state.Cache->buffer);
|
sd_write_block(sd_state.Cache->address, sd_state.Cache->buffer);
|
||||||
sd_state.Cache->state &= ~SD_CACHE_DIRTY;
|
sd_state.Cache->state &= ~SD_CACHE_DIRTY;
|
||||||
|
@ -89,17 +89,17 @@ _sd_cache_flush(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
sd_cache_t *
|
sd_cache_t *
|
||||||
sd_cache_read_block(const uint32_t * pblAdr)
|
sd_cache_read_block(const uint32_t *pblAdr)
|
||||||
{
|
{
|
||||||
SD_GET_LOCK(sd_state.Cache);
|
SD_GET_LOCK(sd_state.Cache);
|
||||||
if (sd_state.Cache->address != *pblAdr) {
|
if(sd_state.Cache->address != *pblAdr) {
|
||||||
sd_set_blocklength(SD_WRITE_BLOCKLENGTH_BIT);
|
sd_set_blocklength(SD_WRITE_BLOCKLENGTH_BIT);
|
||||||
if (sd_state.Cache->state & SD_CACHE_DIRTY) {
|
if(sd_state.Cache->state & SD_CACHE_DIRTY) {
|
||||||
sd_write_block(sd_state.Cache->address, sd_state.Cache->buffer);
|
sd_write_block(sd_state.Cache->address, sd_state.Cache->buffer);
|
||||||
sd_state.Cache->state &= ~SD_CACHE_DIRTY;
|
sd_state.Cache->state &= ~SD_CACHE_DIRTY;
|
||||||
}
|
}
|
||||||
sd_state.Cache->address = *pblAdr;
|
sd_state.Cache->address = *pblAdr;
|
||||||
if (!sd_read_block(sd_state.Cache->buffer, *pblAdr)) {
|
if(!sd_read_block(sd_state.Cache->buffer, *pblAdr)) {
|
||||||
SD_FREE_LOCK(sd_state.Cache);
|
SD_FREE_LOCK(sd_state.Cache);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -111,27 +111,27 @@ sd_cache_read_block(const uint32_t * pblAdr)
|
||||||
uint16_t
|
uint16_t
|
||||||
sd_read(void *pBuffer, uint32_t address, uint16_t size)
|
sd_read(void *pBuffer, uint32_t address, uint16_t size)
|
||||||
{
|
{
|
||||||
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 */
|
||||||
char *p; // pointer to current pos in receive buffer
|
char *p; /* pointer to current pos in receive buffer */
|
||||||
uint16_t bytes_left; // num bytes to read
|
uint16_t bytes_left; /* num bytes to read */
|
||||||
uint16_t read_count; // num bytes to read from current block
|
uint16_t read_count; /* num bytes to read from current block */
|
||||||
|
|
||||||
// parameter processing
|
/* parameter processing */
|
||||||
p = (char *)pBuffer;
|
p = (char *)pBuffer;
|
||||||
bytes_left = size;
|
bytes_left = size;
|
||||||
// align to block
|
/* align to block */
|
||||||
offset = sd_AlignAddress(&address);
|
offset = sd_align_address(&address);
|
||||||
|
|
||||||
// Data transfer
|
/* Data transfer */
|
||||||
do {
|
do {
|
||||||
// calculate block
|
/* calculate block */
|
||||||
if ((offset == 0) && (bytes_left >= sd_state.BlockLen)) {
|
if((offset == 0) && (bytes_left >= sd_state.BlockLen)) {
|
||||||
read_count = sd_state.BlockLen;
|
read_count = sd_state.BlockLen;
|
||||||
sd_read_block(p, address);
|
sd_read_block(p, address);
|
||||||
} else {
|
} else {
|
||||||
sd_cache_read_block(&address);
|
sd_cache_read_block(&address);
|
||||||
read_count = bytes_left + offset;
|
read_count = bytes_left + offset;
|
||||||
if (read_count > sd_state.BlockLen) {
|
if(read_count > sd_state.BlockLen) {
|
||||||
read_count = sd_state.BlockLen - offset;
|
read_count = sd_state.BlockLen - offset;
|
||||||
} else {
|
} else {
|
||||||
read_count = bytes_left;
|
read_count = bytes_left;
|
||||||
|
@ -142,43 +142,43 @@ sd_read(void *pBuffer, uint32_t address, uint16_t size)
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes_left -= read_count;
|
bytes_left -= read_count;
|
||||||
if (bytes_left == 0) {
|
if(bytes_left == 0) {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
p += read_count;
|
p += read_count;
|
||||||
address += sd_state.BlockLen;
|
address += sd_state.BlockLen;
|
||||||
} while (1);
|
} while(1);
|
||||||
}
|
}
|
||||||
#endif // SD_READ_ANY
|
#endif /* SD_READ_ANY */
|
||||||
|
|
||||||
#if SD_WRITE
|
#if SD_WRITE
|
||||||
uint16_t
|
uint16_t
|
||||||
sd_write(uint32_t address, void *pBuffer, uint16_t size)
|
sd_write(uint32_t address, void *pBuffer, uint16_t size)
|
||||||
{
|
{
|
||||||
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 */
|
||||||
char *p; // pointer to current pos in receive buffer
|
char *p; /* pointer to current pos in receive buffer */
|
||||||
uint16_t bytes_left; // num bytes to read
|
uint16_t bytes_left; /* num bytes to read */
|
||||||
uint16_t read_count; // num bytes to read from current block
|
uint16_t read_count; /* num bytes to read from current block */
|
||||||
|
|
||||||
// parameter processing
|
/* parameter processing */
|
||||||
p = (char *)pBuffer;
|
p = (char *)pBuffer;
|
||||||
bytes_left = size;
|
bytes_left = size;
|
||||||
// align to block
|
/* align to block */
|
||||||
offset = sd_AlignAddress(&address);
|
offset = sd_align_address(&address);
|
||||||
|
|
||||||
sd_set_blocklength(SD_WRITE_BLOCKLENGTH_BIT);
|
sd_set_blocklength(SD_WRITE_BLOCKLENGTH_BIT);
|
||||||
|
|
||||||
// Data transfer
|
/* Data transfer */
|
||||||
do {
|
do {
|
||||||
// calculate block
|
/* calculate block */
|
||||||
if ((offset == 0) && (bytes_left >= sd_state.BlockLen)) {
|
if((offset == 0) && (bytes_left >= sd_state.BlockLen)) {
|
||||||
read_count = sd_state.BlockLen;
|
read_count = sd_state.BlockLen;
|
||||||
sd_write_block(address, p);
|
sd_write_block(address, p);
|
||||||
} else {
|
} else {
|
||||||
sd_cache_read_block(&address);
|
sd_cache_read_block(&address);
|
||||||
read_count = bytes_left + offset;
|
read_count = bytes_left + offset;
|
||||||
if (read_count > sd_state.BlockLen) {
|
if(read_count > sd_state.BlockLen) {
|
||||||
read_count = sd_state.BlockLen - offset;
|
read_count = sd_state.BlockLen - offset;
|
||||||
} else {
|
} else {
|
||||||
read_count = bytes_left;
|
read_count = bytes_left;
|
||||||
|
@ -188,17 +188,17 @@ sd_write(uint32_t address, void *pBuffer, uint16_t size)
|
||||||
SD_FREE_LOCK(sd_state.Cache);
|
SD_FREE_LOCK(sd_state.Cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes_left == 0) {
|
if(bytes_left == 0) {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
p += read_count;
|
p += read_count;
|
||||||
bytes_left -= read_count;
|
bytes_left -= read_count;
|
||||||
address += sd_state.BlockLen;
|
address += sd_state.BlockLen;
|
||||||
} while (1);
|
} while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SD_WRITE
|
#endif /* SD_WRITE */
|
||||||
#endif // SD_CACHE
|
#endif /* SD_CACHE */
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
|
@ -47,9 +47,9 @@ Berlin, 2007
|
||||||
* @brief MMC-/SD-Card library, Block erase
|
* @brief MMC-/SD-Card library, Block erase
|
||||||
*
|
*
|
||||||
* @author Michael Baar <baar@inf.fu-berlin.de>
|
* @author Michael Baar <baar@inf.fu-berlin.de>
|
||||||
* @version $Revision: 1.4 $
|
* @version $Revision: 1.5 $
|
||||||
*
|
*
|
||||||
* $Id: sd_erase.c,v 1.4 2008/05/27 13:01:27 nvt-se Exp $
|
* $Id: sd_erase.c,v 1.5 2009/05/26 12:15:46 nvt-se Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -65,17 +65,17 @@ sd_erase_blocks(uint32_t address, uint16_t numBlocks)
|
||||||
uint8_t ret, r1;
|
uint8_t ret, r1;
|
||||||
uint32_t endAdr;
|
uint32_t endAdr;
|
||||||
|
|
||||||
if (sd_protected()) {
|
if(sd_protected()) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!uart_lock(UART_MODE_SPI)) {
|
if(!uart_lock(UART_MODE_SPI)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = _sd_send_cmd(SD_CMD_ERASE_WR_BLK_START_ADDR, SD_RESPONSE_SIZE_R1,
|
ret = _sd_send_cmd(SD_CMD_ERASE_WR_BLK_START_ADDR, SD_RESPONSE_SIZE_R1,
|
||||||
&address, &r1);
|
&address, &r1);
|
||||||
if (!ret | r1) {
|
if(!ret | r1) {
|
||||||
uart_unlock(UART_MODE_SPI);
|
uart_unlock(UART_MODE_SPI);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ sd_erase_blocks(uint32_t address, uint16_t numBlocks)
|
||||||
|
|
||||||
ret = _sd_send_cmd(SD_CMD_ERASE_WR_BLK_END_ADDR, SD_RESPONSE_SIZE_R1,
|
ret = _sd_send_cmd(SD_CMD_ERASE_WR_BLK_END_ADDR, SD_RESPONSE_SIZE_R1,
|
||||||
&endAdr, &r1);
|
&endAdr, &r1);
|
||||||
if (!ret | r1) {
|
if(!ret | r1) {
|
||||||
uart_unlock(UART_MODE_SPI);
|
uart_unlock(UART_MODE_SPI);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,9 +47,9 @@ Berlin, 2007
|
||||||
* @brief MMC-/SD-Card library, Additional Information
|
* @brief MMC-/SD-Card library, Additional Information
|
||||||
*
|
*
|
||||||
* @author Michael Baar <baar@inf.fu-berlin.de>
|
* @author Michael Baar <baar@inf.fu-berlin.de>
|
||||||
* @version $Revision: 1.3 $
|
* @version $Revision: 1.4 $
|
||||||
*
|
*
|
||||||
* $Id: sd_info.c,v 1.3 2008/03/28 23:03:05 nvt-se Exp $
|
* $Id: sd_info.c,v 1.4 2009/05/26 12:15:46 nvt-se Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,10 +70,10 @@ sd_get_size(void)
|
||||||
{
|
{
|
||||||
uint32_t size = 0;
|
uint32_t size = 0;
|
||||||
|
|
||||||
if (uart_lock(UART_MODE_SPI)) {
|
if(uart_lock(UART_MODE_SPI)) {
|
||||||
struct sd_csd csd;
|
struct sd_csd csd;
|
||||||
|
|
||||||
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))) {
|
||||||
size = SD_CSD_C_SIZE(csd) + 1;
|
size = SD_CSD_C_SIZE(csd) + 1;
|
||||||
size <<= SD_CSD_C_MULT(csd);
|
size <<= SD_CSD_C_MULT(csd);
|
||||||
size <<= 2;
|
size <<= 2;
|
||||||
|
|
|
@ -47,9 +47,9 @@ Berlin, 2007
|
||||||
* @brief Serial Peripheral Interface for SD library
|
* @brief Serial Peripheral Interface for SD library
|
||||||
*
|
*
|
||||||
* @author Michael Baar <baar@inf.fu-berlin.de>
|
* @author Michael Baar <baar@inf.fu-berlin.de>
|
||||||
* @version $Revision: 1.3 $
|
* @version $Revision: 1.4 $
|
||||||
*
|
*
|
||||||
* $Id: sdspi.c,v 1.3 2009/05/25 13:19:04 nvt-se Exp $
|
* $Id: sdspi.c,v 1.4 2009/05/26 12:15:46 nvt-se Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <msp430x16x.h>
|
#include <msp430x16x.h>
|
||||||
|
@ -72,7 +72,8 @@ sdspi_init(void)
|
||||||
sdspi_dma_lock = FALSE;
|
sdspi_dma_lock = FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The 16-bit value of UxBR0+UxBR1 is the division factor of the USART clock
|
/*
|
||||||
|
* The 16-bit value of UxBR0+UxBR1 is the division factor of the USART clock
|
||||||
* source, BRCLK. The maximum baud rate that can be generated in master
|
* source, BRCLK. The maximum baud rate that can be generated in master
|
||||||
* mode is BRCLK/2. The maximum baud rate that can be generated in slave
|
* mode is BRCLK/2. The maximum baud rate that can be generated in slave
|
||||||
* mode is BRCLK. The modulator in the USART baud rate generator is not used
|
* mode is BRCLK. The modulator in the USART baud rate generator is not used
|
||||||
|
@ -102,9 +103,10 @@ sdspi_tx(register const uint8_t c)
|
||||||
void
|
void
|
||||||
sdspi_dma_wait(void)
|
sdspi_dma_wait(void)
|
||||||
{
|
{
|
||||||
while (DMA0CTL & DMAEN) {
|
/* Wait until a previous transfer is complete */
|
||||||
|
while(DMA0CTL & DMAEN) {
|
||||||
_NOP();
|
_NOP();
|
||||||
} // Wait until a previous transfer is complete
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -118,44 +120,44 @@ sdspi_read(void *pDestination, const uint16_t size, const bool incDest)
|
||||||
#if SPI_DMA_READ
|
#if SPI_DMA_READ
|
||||||
sdspi_dma_wait();
|
sdspi_dma_wait();
|
||||||
|
|
||||||
UART_RESET_RXTX(); // clear interrupts
|
UART_RESET_RXTX(); /* clear interrupts */
|
||||||
|
|
||||||
// Configure the DMA transfer
|
/* Configure the DMA transfer */
|
||||||
DMA0SA = (uint16_t) & UART_RX; // source DMA address
|
DMA0SA = (uint16_t) & UART_RX; /* source DMA address */
|
||||||
DMA0DA = (uint16_t) pDestination; // destination DMA address
|
DMA0DA = (uint16_t) pDestination; /* destination DMA address */
|
||||||
DMA0SZ = size; // number of bytes to be transferred
|
DMA0SZ = size; /* number of bytes to be transferred */
|
||||||
DMA1SA = (uint16_t) & UART_TX; // source DMA address (constant 0xff)
|
DMA1SA = (uint16_t) & UART_TX; /* source DMA address (constant 0xff) */
|
||||||
DMA1DA = DMA1SA; // destination DMA address
|
DMA1DA = DMA1SA; /* destination DMA address */
|
||||||
DMA1SZ = size - 1; // number of bytes to be transferred
|
DMA1SZ = size - 1; /* number of bytes to be transferred */
|
||||||
DMACTL0 = DMA0TSEL_9 | DMA1TSEL_9; // trigger is UART1 receive for both DMA0 and DMA1
|
DMACTL0 = DMA0TSEL_9 | DMA1TSEL_9; /* trigger is UART1 receive for both DMA0 and DMA1 */
|
||||||
DMA0CTL = DMADT_0 | // Single transfer mode
|
DMA0CTL = DMADT_0 | /* Single transfer mode */
|
||||||
DMASBDB | // Byte mode
|
DMASBDB | /* Byte mode */
|
||||||
DMADSTINCR0 | DMADSTINCR1 | // Increment destination
|
DMADSTINCR0 | DMADSTINCR1 | /* Increment destination */
|
||||||
DMAEN; // Enable DMA
|
DMAEN; /* Enable DMA */
|
||||||
if (!incDest) {
|
if(!incDest) {
|
||||||
DMA0CTL &= ~(DMADSTINCR0 | DMADSTINCR1);
|
DMA0CTL &= ~(DMADSTINCR0 | DMADSTINCR1);
|
||||||
}
|
}
|
||||||
|
|
||||||
DMA1CTL = DMADT_0 | // Single transfer mode
|
DMA1CTL = DMADT_0 | /* Single transfer mode */
|
||||||
DMASBDB | // Byte mode
|
DMASBDB | /* Byte mode */
|
||||||
DMAEN; // Enable DMA
|
DMAEN; /* Enable DMA */
|
||||||
|
|
||||||
UART_TX = SPI_IDLE_SYMBOL; // Initiate transfer by sending the first byte
|
UART_TX = SPI_IDLE_SYMBOL; /* Initiate transfer by sending the first byte */
|
||||||
sdspi_dma_wait();
|
sdspi_dma_wait();
|
||||||
|
|
||||||
#else
|
#else
|
||||||
register uint8_t *p = (uint8_t *) pDestination;
|
register uint8_t *p = (uint8_t *)pDestination;
|
||||||
register uint16_t i = size;
|
register uint16_t i = size;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
UART_TX = SPI_IDLE_SYMBOL;
|
UART_TX = SPI_IDLE_SYMBOL;
|
||||||
UART_WAIT_RX();
|
UART_WAIT_RX();
|
||||||
*p = UART_RX;
|
*p = UART_RX;
|
||||||
if (incDest) {
|
if(incDest) {
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
i--;
|
i--;
|
||||||
} while (i);
|
} while(i);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
splx(s);
|
splx(s);
|
||||||
|
@ -171,25 +173,25 @@ sdspi_write(const void *pSource, const uint16_t size, const int increment)
|
||||||
#if SPI_DMA_WRITE
|
#if SPI_DMA_WRITE
|
||||||
sdspi_dma_wait();
|
sdspi_dma_wait();
|
||||||
|
|
||||||
UART_RESET_RXTX(); // clear interrupts
|
UART_RESET_RXTX(); /* clear interrupts */
|
||||||
|
|
||||||
// Configure the DMA transfer
|
/* Configure the DMA transfer */
|
||||||
DMA0SA = ((uint16_t) pSource) + 1; // source DMA address
|
DMA0SA = ((uint16_t) pSource) + 1; /* source DMA address */
|
||||||
DMA0DA = (uint16_t) & UART_TX; // destination DMA address
|
DMA0DA = (uint16_t) & UART_TX; /* destination DMA address */
|
||||||
DMA0SZ = size - 1; // number of bytes to be transferred
|
DMA0SZ = size - 1; /* number of bytes to be transferred */
|
||||||
DMACTL0 = DMA0TSEL_9; // trigger is UART1 receive
|
DMACTL0 = DMA0TSEL_9; /* trigger is UART1 receive */
|
||||||
DMA0CTL = DMADT_0 | // Single transfer mode
|
DMA0CTL = DMADT_0 | /* Single transfer mode */
|
||||||
DMASBDB | // Byte mode
|
DMASBDB | /* Byte mode */
|
||||||
DMASRCINCR_3 | // Increment source
|
DMASRCINCR_3 | /* Increment source */
|
||||||
DMAEN; // Enable DMA
|
DMAEN; /* Enable DMA */
|
||||||
if (increment == 0) {
|
if(increment == 0) {
|
||||||
DMA0CTL &= ~DMASRCINCR_3;
|
DMA0CTL &= ~DMASRCINCR_3;
|
||||||
}
|
}
|
||||||
|
|
||||||
sdspi_dma_lock = TRUE;
|
sdspi_dma_lock = TRUE;
|
||||||
SPI_TX = ((uint8_t *) pSource)[0];
|
SPI_TX = ((uint8_t *)pSource)[0];
|
||||||
#else
|
#else
|
||||||
register uint8_t *p = (uint8_t *) pSource;
|
register uint8_t *p = (uint8_t *)pSource;
|
||||||
register uint16_t i = size;
|
register uint16_t i = size;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -198,7 +200,7 @@ sdspi_write(const void *pSource, const uint16_t size, const int increment)
|
||||||
UART_RX;
|
UART_RX;
|
||||||
p += increment;
|
p += increment;
|
||||||
i--;
|
i--;
|
||||||
} while (i);
|
} while(i);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
splx(s);
|
splx(s);
|
||||||
|
@ -215,7 +217,7 @@ sdspi_idle(register const uint16_t clocks)
|
||||||
UART_WAIT_RX();
|
UART_WAIT_RX();
|
||||||
UART_RX;
|
UART_RX;
|
||||||
i--;
|
i--;
|
||||||
} while (i);
|
} while(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -231,6 +233,6 @@ sdspi_wait_token(const uint8_t feed, const uint8_t mask,
|
||||||
UART_WAIT_RX();
|
UART_WAIT_RX();
|
||||||
rx = UART_RX;
|
rx = UART_RX;
|
||||||
i++;
|
i++;
|
||||||
} while (((rx & mask) != token) && (i < timeout));
|
} while(((rx & mask) != token) && (i < timeout));
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue