Removed unstable SD driver (to be replaced.)

This commit is contained in:
nvt-se 2009-09-17 13:24:49 +00:00
parent e974b896dc
commit 84b0ec7798
14 changed files with 2 additions and 2401 deletions

View file

@ -1,16 +1,15 @@
SENSORS = sensors.c irq.c sht11.c
SD = sd.c sd_cache.c sd_erase.c sd_info.c sd_msb430.c sdspi.c
MSB = dma.c infomem.c node-id.c \
msb430-uart1.c rs232.c \
cc1020.c cc1020-uip.c adc.c init-net-rime.c \
msb430-slip-arch.c cfs-coffee.c
CONTIKI_TARGET_DIRS = . dev dev/sd apps net loader
CONTIKI_TARGET_DIRS = . dev apps loader
ifndef CONTIKI_TARGET_MAIN
CONTIKI_TARGET_MAIN = contiki-msb430-main.c
endif
CONTIKI_TARGET_SOURCEFILES += $(SENSORS) $(SD) $(MSB) $(CONTIKI_TARGET_MAIN)
CONTIKI_TARGET_SOURCEFILES += $(SENSORS) $(MSB) $(CONTIKI_TARGET_MAIN)
MCU=msp430x1612
include $(CONTIKI)/cpu/msp430/Makefile.msp430

View file

@ -4,8 +4,6 @@
#define HAVE_STDINT_H
#include "msp430def.h"
#define WITH_SDC 0
#define ENERGEST_CONF_ON 1
#define IRQ_PORT1 0x01
@ -17,8 +15,6 @@
#define INFOMEM_BLOCK_SIZE 128
#define INFOMEM_NODE_ID 0x0000 /* - 0x0004 */
#define CFS_SD_CONF_OFFSET 0x0000
#define CC_CONF_REGISTER_ARGS 1
#define CC_CONF_FUNCTION_POINTER_ARGS 1
#define CC_CONF_INLINE inline
@ -83,21 +79,4 @@ typedef int bool;
#define LEDS_CONF_GREEN 0x00
#define LEDS_CONF_YELLOW 0x00
#define SD_LED_READ_ON (LEDS_PxOUT &=~LEDS_CONF_RED)
#define SD_LED_READ_OFF (LEDS_PxOUT |= LEDS_CONF_RED)
#define SD_LED_WRITE_ON SD_LED_READ_ON
#define SD_LED_WRITE_OFF SD_LED_READ_OFF
#define SD_READ_BYTE 0
#define SD_READ_ANY 1
#define SD_INFO 0
#define SD_WRITE 1
#define SD_WRITE_ANY 1
#define SD_FIND_FILE 0
#define SD_ERASE 0
#define SD_CACHE 1
#define SPI_WRITE SD_WRITE
#define SPI_DMA_READ 0
#define SPI_DMA_WRITE 0
#endif /* !CONTIKI_CONF_H */

View file

@ -68,11 +68,6 @@ msb_ports_init(void)
int
main(void)
{
#ifdef WITH_SDC
sd_cache_t sd_cache;
int r;
#endif
msp430_cpu_init();
watchdog_stop();
@ -118,17 +113,6 @@ main(void)
leds_off(LEDS_ALL);
#if WITH_SDC
sdspi_init();
sd_init();
r = sd_init_card(&sd_cache);
if (r == SD_INIT_SUCCESS) {
printf("Found SD card (%lu bytes)\n", sd_get_size());
} else {
printf("SD card initialization failed: %d\n", r);
}
#endif
printf(CONTIKI_VERSION_STRING " started. Node id %u, using %s.\n",
node_id, rime_mac->name);

View file

@ -47,16 +47,8 @@
#include "dev/rs232.h"
#include "dev/serial-line.h"
#include "dev/slip.h"
#ifdef WITH_SDC
#include "dev/sd/sd.h"
#include "dev/sd/sdspi.h"
#endif
#include "lib/sensors.h"
#include "net/rime.h"
#include "node-id.h"
#endif /* !CONTIKI_MSB430_H */

View file

@ -1,799 +0,0 @@
/*
Copyright 2007, Freie Universitaet Berlin. All rights reserved.
These sources were developed at the Freie Universität Berlin, Computer
Systems and Telematics group.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Freie Universitaet Berlin (FUB) nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
This software is provided by FUB and the contributors on an "as is"
basis, without any representations or warranties of any kind, express
or implied including, but not limited to, representations or
warranties of non-infringement, merchantability or fitness for a
particular purpose. In no event shall FUB or contributors be liable
for any direct, indirect, incidental, special, exemplary, or
consequential damages (including, but not limited to, procurement of
substitute goods or services; loss of use, data, or profits; or
business interruption) however caused and on any theory of liability,
whether in contract, strict liability, or tort (including negligence
or otherwise) arising in any way out of the use of this software, even
if advised of the possibility of such damage.
This implementation was developed by the CST group at the FUB.
For documentation and questions please use the web site
http://scatterweb.mi.fu-berlin.de and the mailinglist
scatterweb@lists.spline.inf.fu-berlin.de (subscription via the Website).
Berlin, 2007
*/
/**
* @file ScatterWeb.Sd.c
* @ingroup libsd
* @brief MMC-/SD-Card library
*
* @author Michael Baar <baar@inf.fu-berlin.de>
* @version $Revision: 1.9 $
*
* $Id: sd.c,v 1.9 2009/05/26 13:00:07 nvt-se Exp $
*
* Initialisation and basic functions for read and write access
*/
#include "sd_internals.h"
#include "sd.h"
#include "sdspi.h"
#include "dev/leds.h"
volatile sd_state_t sd_state;
/******************************************************************************
* @name Initialization and configuration
* @{
*/
void
sd_init(void)
{
/* depending on the system global variables may not get initialised on startup */
memset((void *)&sd_state, 0, sizeof (sd_state));
/* initialize io ports */
sd_init_platform();
}
enum sd_init_ret
sd_init_card(sd_cache_t * pCache)
{
enum sd_init_ret ret = SD_INIT_SUCCESS;
struct sd_csd csd;
uint16_t ccc = 0;
int resetcnt;
struct sd_response_r3 r3;
if(!sd_detected()) {
return SD_INIT_NOCARD;
}
if(sd_state.Flags & SD_INITIALIZED) {
return SD_INIT_SUCCESS;
}
/* Wait for UART and switch to SPI mode */
if(!uart_lock_wait(UART_MODE_SPI)) {
return SD_INIT_FAILED;
}
/* reset card */
resetcnt = _sd_reset(&r3);
if(resetcnt >= SD_RESET_RETRY_COUNT) {
ret = SD_INIT_FAILED;
goto sd_init_card_fail;
}
/* Test for hardware compatibility */
if((r3.ocr & SD_V_MASK) != SD_V_MASK) {
ret = SD_INIT_NOTSUPP;
goto sd_init_card_fail;
}
/* Test for software compatibility */
if(!_sd_read_register(&csd, SD_CMD_SEND_CSD, sizeof (struct sd_csd))) {
ret = SD_INIT_FAILED;
goto sd_init_card_fail;
}
ccc = SD_CSD_CCC(csd);
if((ccc & SD_DEFAULT_MINCCC) != SD_DEFAULT_MINCCC) {
ret = SD_INIT_NOTSUPP;
goto sd_init_card_fail;
}
sd_init_card_fail:
sdspi_unselect();
uart_unlock(UART_MODE_SPI);
#ifdef LOG_VERBOSE
LOG_VERBOSE("(sd_init) result:%u, resetcnt:%i OCR:%.8lx, CCC:%.4x",
ret, resetcnt, r3.ocr, ccc);
#endif
if(ret != SD_INIT_SUCCESS) {
return ret;
}
/* state */
sd_state.MinBlockLen_bit = 9;
sd_state.MaxBlockLen_bit = SD_CSD_READ_BL_LEN(csd);
sd_state.Flags = SD_INITIALIZED;
if(SD_CSD_READ_PARTIAL(csd)) {
sd_state.MinBlockLen_bit = 0;
sd_state.Flags |= SD_READ_PARTIAL;
}
if(SD_CSD_WRITE_PARTIAL(csd)) {
sd_state.Flags |= SD_WRITE_PARTIAL;
}
sd_state.BlockLen_bit = 9;
sd_state.BlockLen = 1 << 9;
#if SD_CACHE
if(pCache == NULL) {
return SD_INIT_NOTSUPP;
}
sd_state.Cache = pCache;
_sd_cache_init();
#endif
return ret;
}
void
sd_flush(void)
{
if(uart_lock(UART_MODE_SPI)) {
#if SD_WRITE && SD_CACHE
_sd_cache_flush();
#endif
#if SD_WRITE && SPI_DMA_WRITE
sd_write_flush();
#endif
uart_unlock(UART_MODE_SPI);
}
}
void
sd_close(void)
{
sd_flush();
/* reset state */
memset((void *)&sd_state, 0, sizeof (sd_state));
}
uint8_t
sd_set_blocklength(const uint8_t blocklength_bit)
{
uint8_t ret;
uint8_t arg[4];
/* test if already set */
if(blocklength_bit == sd_state.BlockLen_bit) {
return sd_state.BlockLen_bit;
}
/* Wait for UART and switch to SPI mode */
if(!uart_lock_wait(UART_MODE_SPI)) {
return sd_state.BlockLen_bit;
}
((uint16_t *)arg)[1] = 0;
((uint16_t *)arg)[0] = 1 << blocklength_bit;
/* set blocklength command */
if(_sd_send_cmd(SD_CMD_SET_BLOCKLENGTH, SD_RESPONSE_SIZE_R1, arg, NULL)) {
sd_state.BlockLen_bit = blocklength_bit;
sd_state.BlockLen = ((uint16_t *)arg)[0];
ret = blocklength_bit;
} else {
ret = SD_BLOCKLENGTH_INVALID;
}
/* unlock uart */
uart_unlock(UART_MODE_SPI);
return ret;
}
/*@} */
/*///////////////////////////////////////////////////////////////////////////// */
/* Public functions, Reading */
/*///////////////////////////////////////////////////////////////////////////// */
uint16_t
sd_align_address(uint32_t * pAddress)
{
uint16_t blMask = sd_state.BlockLen - 1;
uint16_t *lw = (uint16_t *)pAddress;
uint16_t offset = *lw & blMask;
*lw &= ~blMask;
return offset;
}
uint16_t
sd_read_block(void (*const pBuffer), const uint32_t address)
{
int s;
s = splhigh();
if(!_sd_read_start(SD_CMD_READ_SINGLE_BLOCK, address)) {
splx(s);
return FALSE;
}
sdspi_read(pBuffer, sd_state.BlockLen, TRUE);
/* receive CRC16 and finish */
_sd_read_stop(2);
splx(s);
return sd_state.BlockLen;
}
#if SD_READ_BYTE
bool
sd_read_byte(void *pBuffer, const uint32_t address)
{
if(sd_set_blocklength(0) == 0) {
return sd_read_block(pBuffer, address);
} else {
uint32_t blAdr = address;
uint16_t offset; /* bytes from aligned address to start of first byte to keep */
/* align */
offset = sd_align_address(&blAdr);
/* start */
if(!_sd_read_start(SD_CMD_READ_SINGLE_BLOCK, address)) {
return FALSE;
}
/* read */
sdspi_read(pBuffer, offset + 1, FALSE);
/* done */
_sd_read_stop(sd_state.BlockLen - offset - 1);
}
return TRUE;
}
#endif
#if SD_READ_ANY && !SD_CACHE
unsigned int
sd_read(void *pBuffer, unsigned long address, unsigned int size)
{
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 read_count; /* num bytes to read in one 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 char ret;
/* */
/* parameter processing */
/* */
if(size == 0) {
return 0;
}
/* align to block */
offset = sd_align_address(&address);
if((offset == 0) && (sd_state.BlockLen == size)) {
/* best case: perfectly block aligned, no chunking */
/* -> do shortcut */
return sd_read_block(pBuffer, address);
}
/* calculate first block */
if(size > sd_state.BlockLen) {
read_count = sd_state.BlockLen;
} else {
read_count = size;
}
/* */
/* Data transfer */
/* */
s = splhigh(s);
/* request data transfer */
ret = _sd_read_start(SD_CMD_READ_SINGLE_BLOCK, address);
if(!ret) {
splx(s);
return 0;
}
/* run to offset */
if(offset) {
sdspi_read(pBuffer, offset, FALSE); /* dump till offset */
dump_flag = ((read_count + offset) < sd_state.BlockLen);
if(!dump_flag) {
read_count = sd_state.BlockLen - offset; /* max bytes to read from first block */
}
} else {
dump_flag = (read_count < sd_state.BlockLen);
}
/* */
/* block read loop */
/* */
num_bytes_read = 0;
p = pBuffer;
do {
/* whole block will be processed */
size -= read_count; /* global counter */
/* read to receive buffer */
sdspi_read(p, read_count, TRUE);
p += read_count; /* increment buffer pointer */
num_bytes_read += read_count;
/* finish block */
if(dump_flag) {
/* cancel remaining bytes (last iteration) */
_sd_read_stop(sd_state.BlockLen - read_count - offset);
break;
/* unselect is included in send_cmd */
} else {
sdspi_idle(2); /* receive CRC16 */
if(size != 0) {
/* address calculation for next block */
offset = 0;
address += sd_state.BlockLen;
if(size > sd_state.BlockLen) {
read_count = sd_state.BlockLen;
dump_flag = FALSE;
} else {
read_count = size;
dump_flag = TRUE;
}
sdspi_unselect();
ret = _sd_read_start(SD_CMD_READ_SINGLE_BLOCK, address);
if(!ret) {
splx(s);
return 0;
}
} else {
/* finished */
_sd_read_stop(0);
break;
}
}
} while(1);
splx(s);
return num_bytes_read;
}
#endif /* SD_READ_ANY */
/*///////////////////////////////////////////////////////////////////////////// */
/* Public functions, Writing */
/*///////////////////////////////////////////////////////////////////////////// */
#if SD_WRITE
enum sd_write_ret
_sd_write_finish(void)
{
uint16_t r2;
uint8_t ret;
enum sd_write_ret result = SD_WRITE_STORE_ERR;
uint16_t i;
int s;
#if SPI_DMA_WRITE
sdspi_dma_wait();
sdspi_dma_lock = FALSE;
#endif
s = splhigh();
/* dummy crc */
sdspi_idle(2);
/* receive data response (ZZS___ 3 bits crc response) */
for(i = 0; i < SD_TIMEOUT_NCR; i++) {
ret = sdspi_rx();
if((ret > 0) && (ret < 0xFF)) {
while(ret & 0x80) {
ret <<= 1;
}
ret = ((ret & 0x70) == 0x20);
break;
}
}
/* wait for data to be written */
_sd_wait_standby(NULL);
splx(s);
sdspi_unselect();
if(ret) {
/* data transfer to sd card buffer was successful */
/* query for result of actual write operation */
ret = _sd_send_cmd(SD_CMD_SEND_STATUS, SD_RESPONSE_SIZE_R2, NULL, &r2);
if(ret && (r2 == 0)) {
result = SD_WRITE_SUCCESS;
}
} else {
/* data transfer to sd card buffer failed */
}
/* unlock uart (locked from every write operation) */
uart_unlock(UART_MODE_SPI);
return result;
}
enum sd_write_ret
sd_write_flush(void)
{
#if SPI_DMA_WRITE
if(!sdspi_dma_lock) {
return SD_WRITE_DMA_ERR;
} else {
return _sd_write_finish();
}
#else
return SD_WRITE_SUCCESS;
#endif
}
enum sd_write_ret
_sd_write_block(const uint32_t * pAddress, const void *pBuffer, int increment)
{
uint8_t r1, ret;
int s;
/* block write-access on write protection */
if(sd_protected()) {
return SD_WRITE_PROTECTED_ERR;
}
/* acquire uart */
if(!uart_lock_wait(UART_MODE_SPI)) {
return SD_WRITE_INTERFACE_ERR;
}
/* start write */
s = splhigh();
SD_LED_WRITE_ON;
r1 = 0;
ret = _sd_send_cmd(SD_CMD_WRITE_SINGLE_BLOCK, SD_RESPONSE_SIZE_R1,
pAddress, &r1);
if(!ret || r1) {
leds_on(LEDS_ALL);
_sd_reset(NULL);
splx(s);
uart_unlock(UART_MODE_SPI);
SD_LED_WRITE_OFF;
return SD_WRITE_COMMAND_ERR;
}
/* write data */
sdspi_select();
sdspi_tx(0xFF);
sdspi_tx(SD_TOKEN_WRITE);
sdspi_write(pBuffer, sd_state.BlockLen, increment);
SD_LED_WRITE_OFF;
/* finish write */
#if SPI_DMA_WRITE
sdspi_dma_lock = TRUE;
splx(s);
return SD_WRITE_SUCCESS;
#else
ret = _sd_write_finish();
splx(s);
return ret;
#endif
}
enum sd_write_ret
sd_set_block(const uint32_t address, const char (*const pChar))
{
return _sd_write_block(&address, pChar, FALSE);
}
enum sd_write_ret
sd_write_block(const uint32_t address, void const (*const pBuffer))
{
return _sd_write_block(&address, pBuffer, TRUE);
}
#endif
/*///////////////////////////////////////////////////////////////////////////// */
/* Supporting functions */
/*///////////////////////////////////////////////////////////////////////////// */
/**
* @brief Reads operating condition from SD or MMC card.
* \internal
* \Note Should allow to find out the card type on first run if needed.
*/
inline bool _sd_get_op_cond(struct sd_response_r1 * pResponse)
{
bool ret;
/* SD style */
ret = _sd_send_cmd(SD_CMD_APP_SECIFIC_CMD, SD_RESPONSE_SIZE_R1, NULL,
pResponse);
if(ret) {
uint32_t arg = SD_V_MASK;
ret = _sd_send_cmd(SD_ACMD_SEND_OP_COND, SD_RESPONSE_SIZE_R1, &arg,
pResponse);
} else {
/* MMC style init */
ret = _sd_send_cmd(SD_CMD_SEND_OP_COND, SD_RESPONSE_SIZE_R1, NULL,
pResponse);
if(*((uint8_t *)pResponse) & SD_R1_ERROR_MASK) {
ret = FALSE;
}
}
return ret;
}
/**
* @brief Wait for the card to enter standby state
* \internal
*/
bool
_sd_wait_standby(struct sd_response_r3 * pOpCond)
{
bool ret;
int i = SD_TIMEOUT_IDLE;
struct sd_response_r3 opCond;
struct sd_response_r3 *pR3 = pOpCond;
if(pR3 == NULL) {
pR3 = &opCond;
}
sdspi_wait_token(0xFF, 0xFF, 0xFF, SD_TIMEOUT_NCR);
do {
ret = _sd_get_op_cond((struct sd_response_r1 *)pR3);
if(ret && (pR3->r1.in_idle_state == 0)) {
ret = _sd_send_cmd(SD_CMD_READ_OCR, SD_RESPONSE_SIZE_R3, NULL, pR3);
if(ret && !SD_OCR_BUSY(pR3->ocr)) {
return TRUE;
}
}
i--;
} while(i);
return FALSE;
}
/**
* @brief Resets the card and (hopefully) returns with the card in standby state
* \internal
*/
int
_sd_reset(struct sd_response_r3 *pOpCond)
{
int i;
bool ret;
struct sd_response_r1 r1;
for(i = 0; i < SD_RESET_RETRY_COUNT; i++) {
ret = _sd_send_cmd(SD_CMD_GO_IDLE_STATE, SD_RESPONSE_SIZE_R1, NULL, &r1);
if(ret == 0 || r1.illegal_cmd) {
_sd_send_cmd(SD_CMD_STOP_TRANSMISSION, SD_RESPONSE_SIZE_R1, NULL, &r1);
} else {
ret = _sd_wait_standby(pOpCond);
if(ret) {
break;
}
}
}
return i;
}
/**
* @brief Used to send all kinds of commands to the card and return the response.
* \internal
*/
bool
_sd_send_cmd(const uint8_t command,
const int response_size,
const void *pArg, void (*const pResponse))
{
uint8_t cmd[6] = {
0x40, 0, 0, 0, 0, 0x95
};
uint8_t data; /* reception buffer */
int i; /* loop counter */
int s; /* interrupt state */
sdspi_select();
#if SD_WRITE && SPI_DMA_WRITE
sd_write_flush();
#endif
cmd[0] |= command;
if(pArg != NULL) {
cmd[1] = ((uint8_t *)pArg)[3];
cmd[2] = ((uint8_t *)pArg)[2];
cmd[3] = ((uint8_t *)pArg)[1];
cmd[4] = ((uint8_t *)pArg)[0];
}
s = splhigh();
sdspi_write(cmd, 6, 1);
/* wait for start bit */
i = SD_TIMEOUT_NCR;
do {
data = sdspi_rx();
if((data & 0x80) == 0) {
goto _sd_send_cmd_response;
}
} while(i--);
splx(s);
goto sd_send_cmd_fail;
_sd_send_cmd_response:
s = splhigh();
/* start bit received, read response with size i */
i = response_size - 1;
if(pResponse != NULL) {
/* copy response to response buffer */
do {
((uint8_t *)pResponse)[i] = data;
if(i == 0) {
break;
}
data = sdspi_rx();
i--;
} while(1);
} else {
/* receive and ignore response */
sdspi_read(&data, i, 0);
}
/* done successfully */
sdspi_unselect();
splx(s);
return TRUE;
sd_send_cmd_fail:
/* failed */
sdspi_unselect();
return FALSE;
}
/**
* @brief Read Card Register
* \internal
*/
uint16_t
_sd_read_register(void *pBuffer, uint8_t cmd, uint16_t size)
{
if(!_sd_read_start(cmd, 0)) {
return FALSE;
}
sdspi_read(pBuffer, size, TRUE);
_sd_read_stop(2);
return size;
}
/**
* @brief Begin block read operation
* \internal
*/
bool
_sd_read_start(uint8_t cmd, uint32_t address)
{
uint8_t r1;
uint8_t ret;
uint16_t i;
/* acquire uart */
if(!uart_lock_wait(UART_MODE_SPI)) {
return FALSE;
}
ret = _sd_send_cmd(cmd, SD_RESPONSE_SIZE_R1, &address, &r1);
if(!ret || r1) {
goto _sd_read_start_fail;
}
/* Wait for start bit (0) */
sdspi_select();
i = sdspi_wait_token(0xFF, 0xFF, SD_TOKEN_READ, SD_TIMEOUT_READ);
if(i < SD_TIMEOUT_READ) {
/* token received, data bytes follow */
SD_LED_READ_ON;
return TRUE;
}
_sd_read_start_fail:
sdspi_unselect();
uart_unlock(UART_MODE_SPI);
return FALSE;
}
/**
* @brief Finished with reading, stop transfer
* \internal
*/
void
_sd_read_stop(uint16_t count)
{
/* finish block + crc */
if(count) {
uint8_t dump;
sdspi_read(&dump, count + 2, FALSE);
sdspi_unselect();
}
SD_LED_READ_OFF;
/* wait for switch to standby mode */
if(!_sd_wait_standby(NULL)) {
_sd_reset(NULL);
}
/* unlock uart (locked from _sd_read_start) */
uart_unlock(UART_MODE_SPI);
}

View file

@ -1,392 +0,0 @@
/*
Copyright 2007, Freie Universitaet Berlin. All rights reserved.
These sources were developed at the Freie Universität Berlin, Computer
Systems and Telematics group.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Freie Universitaet Berlin (FUB) nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
This software is provided by FUB and the contributors on an "as is"
basis, without any representations or warranties of any kind, express
or implied including, but not limited to, representations or
warranties of non-infringement, merchantability or fitness for a
particular purpose. In no event shall FUB or contributors be liable
for any direct, indirect, incidental, special, exemplary, or
consequential damages (including, but not limited to, procurement of
substitute goods or services; loss of use, data, or profits; or
business interruption) however caused and on any theory of liability,
whether in contract, strict liability, or tort (including negligence
or otherwise) arising in any way out of the use of this software, even
if advised of the possibility of such damage.
This implementation was developed by the CST group at the FUB.
For documentation and questions please use the web site
http://scatterweb.mi.fu-berlin.de and the mailinglist
scatterweb@lists.spline.inf.fu-berlin.de (subscription via the Website).
Berlin, 2007
*/
/**
* @file ScatterWeb.Sd.h
* @ingroup libsd
* @brief MMC-/SD-Card library, Public interface
*
* @author Michael Baar <baar@inf.fu-berlin.de>
* @version $Revision: 1.6 $
*
* $Id: sd.h,v 1.6 2009/05/26 12:15:46 nvt-se Exp $
*/
/**
* @ingroup libsd
* @{
*/
#ifndef __SD_H__
#define __SD_H__
#include "contiki-conf.h"
#define SD_BLOCKLENGTH_INVALID 0xFF
#define SD_WRITE_BLOCKLENGTH_BIT 9
#define SD_WRITE_BLOCKLENGTH 0x200
/******************************************************************************
* @name Setup, initialisation, configuration
* @{
*/
/**
* @brief SD Flags
* @see sd_state_t
* @{
*/
enum sd_state_flags {
SD_READ_PARTIAL = 0x80,
SD_WRITE_PARTIAL = 0x40,
SD_INITIALIZED = 0x01
};
/** @} */
#ifdef __TI_COMPILER_VERSION__
#pragma pack(1)
#endif
/**
* @brief Card Identification Register
*/
#ifndef __TI_COMPILER_VERSION__
__attribute__ ((packed))
#endif
#if defined(__MSP430GCC__)
__attribute__ ((packed))
#endif
struct sd_cid {
uint8_t mid;
char oid[2];
char pnm[5];
uint8_t revision;
uint32_t psn;
uint16_t:4;
uint16_t mdt:12;
uint8_t crc7:7;
uint8_t:1;
};
#ifdef __TI_COMPILER_VERSION__
#pragma pack()
#endif
/**
* @name Card Specific Data register
* @{
*/
struct sd_csd {
uint8_t raw[16];
};
#define SD_CSD_READ_BL_LEN(csd) (( csd ).raw[5] & 0x0F) // uchar : 4
#define SD_CSD_READ_PARTIAL(csd) (( csd ).raw[ 6] & 0x80) // bool
#define SD_CSD_CCC(csd) ( (( csd ).raw[4]<<4) | (( csd ).raw[5]>>4) ) // uchar
#define SD_CSD_WRITE_PARTIAL(csd) (( csd ).raw[13] & 0x04) // bool
#define SD_CSD_C_SIZE(csd) ( ((( csd ).raw[6] & 0x03)<<10) | (( csd ).raw[7]<<2) | (( csd ).raw[8]>>6) ) // uint : 12
#define SD_CSD_C_MULT(csd) ( ((( csd ).raw[9] & 0x03)<<1) | (( csd ).raw[10]>>7) ) // uchar : 4
/** @} */
/// Card access library state
#define SD_CACHE_LOCKED 0x01
#define SD_CACHE_DIRTY 0x02
typedef struct {
char buffer[SD_WRITE_BLOCKLENGTH];
uint32_t address;
uint8_t state;
} sd_cache_t;
typedef struct {
uint16_t MinBlockLen_bit:4; ///< minimum supported blocklength
uint16_t MaxBlockLen_bit:4; ///< maximum supported blocklength
uint16_t Flags:8; ///< feature flags
uint8_t BlockLen_bit; ///< currently selected blocklength as bit value (n where BlockLen is 2^n)
uint16_t BlockLen; ///< currently selected blocklength for reading and writing
#if SD_CACHE
sd_cache_t *Cache;
#endif
} sd_state_t;
extern volatile sd_state_t sd_state; ///< Card access library state
/**
* @brief Library initialisation
*/
void sd_init(void);
/**
* @brief Setup ports for sd card communication
*
* This function needs to be called once before any other library function.
* It invokes ::Spi_enable to configure UART1 for SPI communication.
*
* If you need to reconfigure the UART for other operations only call
* ::Spi_enable to return to SPI mode. ::sd_setup needs to be run only once.
*/
void sd_init_platform(void);
/**
* @brief Return value of ::sd_init function
*/
enum sd_init_ret {
SD_INIT_SUCCESS = 0,
SD_INIT_NOCARD = 1,
SD_INIT_FAILED = 2,
SD_INIT_NOTSUPP = 3
};
/**
* @brief Return value of write functions
* @see ::sd_write, ::sd_write_block
*/
enum sd_write_ret {
SD_WRITE_SUCCESS = 0, ///< writing successfull
SD_WRITE_PROTECTED_ERR = 1, ///< card write protected
SD_WRITE_INTERFACE_ERR = 2, ///< error in UART SPI interface
SD_WRITE_COMMAND_ERR = 3, ///< error in write command or command arguments (e.g. target address)
SD_WRITE_STORE_ERR = 4, ///< storing written data to persistant memory on card failed
SD_WRITE_DMA_ERR = 5
};
/**
* @brief Initialize card and state
* @return one of sd_init_ret
*
* Initializes the memory card, checks supported voltage range and
* functionality. Initializes the global state struct sd_state.
* Should be invoked once immediately after ::sd_setup.
*/
enum sd_init_ret sd_init_card(sd_cache_t * pCache);
/**
* @brief Last operation to call when finished with using the card.
*/
void sd_close(void);
/**
* @brief SD Card physically present?
* @return if no card present returns 0
*/
#define sd_detected() ((P2IN & 0x40) == 0)
/**
* @brief SD Card locked by switch?
* @return if card is not locked returns 0
*/
#define sd_protected() ((P2IN & 0x80) != 0)
/**
* @brief Set blocklength to 2 ^ n
*
* Tries to set the card's blocklength for reading and writing to any
* 2^n value, where n shall be between 0 and 11.
* Be aware that a card may or may not support different blocksizes.
*
* 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 let ::sd_read do the rest. If the blocklength is already set to the new
* value nothing is done.
*
* \Note
* The default blocklength is 512 (n=9). SD Cards usually support partial blocks
* with a blocklength of 1 to 512 (n=0 to n=9), MMC cards don't.
* Large cards support blocklength up to 2048 (n=11).
* The supported range of blocklengths can be read as n-value from
* sd_state.BlockLenMin_bit and sd_state.BlockLneMax_bit. The current value
* is available as n-value in sd_state.Blocsd_state.BlockLen_bit and as byte-value
* in sd_state.BlockLen.
*
* @param[in] blocklength_bit blocklength as n-value of 2^n
*
* @return Returns blocklength_bit if set operation was successful or
* SD_BLOCKLENGTH_INVALID otherwise.
*
*/
uint8_t sd_set_blocklength(const uint8_t blocklength_bit);
/**
* @brief Align byte address to current blocklength
* @param[in,out] pAddress address to align, will be modified to be block aligned
* @return Offset from aligned address to original address
*/
uint16_t sd_align_address(uint32_t * pAddress);
/**
* @brief Read one complete block from a block aligned address into buffer
*
* This function reads a single block of the currently set blocklength
* from a block aligned address.
*
* \Note: If address is not block aligned the card will respond with an error
* and no bytes will be read.
*
* @param[out] pBuffer Pointer to a buffer to which data is read. It should be least
* 1 byte large
* @param[in] address The address of the first byte that shall be read to pBuffer
*
* @return Number of bytes read (should always be = sd_state.BlockLen)
*/
uint16_t sd_read_block(void (*const pBuffer), const uint32_t address);
#if SD_READ_BYTE
/**
* @brief Read one byte from any address
* This function reads a single byte from any address. It is optimized for best speed
* at any blocklength.
* \Note: blocklength is modified
*
* @param[out] pBuffer Pointer to a buffer to which data is read. It should be least
* 1 byte large
* @param[in] address The address of the byte that shall be read to pBuffer
*
* @return Number of bytes read (usually 1)
*/
bool sd_read_byte(void *pBuffer, const uint32_t address);
#endif
#if SD_WRITE
/**
* @brief Write one complete block at a block aligned address from buffer to card
*
* @param[in] address block aligned address to write to
* @param[in] pBuffer pointer to buffer with a block of data to write
* @return result code (see enum #sd_write_ret)
*
* \Note
* Only supported block size for writing is usually 512 bytes.
*/
enum sd_write_ret sd_write_block(const uint32_t address,
void const (*const pBuffer));
/**
* @brief Fill one complete block at a block aligned address with
* a single character.
*
* @param[in] address block aligned address to write to
* @param[in] pChar pointer to buffer with a character to write
* @return result code (see enum #sd_write_ret)
*
* @note Use this for settings blocks to 0x00.
* Only supported block size for writing is usually 512 bytes.
*/
enum sd_write_ret sd_set_block(const uint32_t address,
const char (*const pChar));
/**
* @brief Flush the DMA write buffer
*
* Wait for a running DMA write operation to finish
*/
enum sd_write_ret sd_write_flush(void);
#endif
#if SD_CACHE
#define SD_WAIT_LOCK(x) while( x ->state & SD_CACHE_LOCKED ) { _NOP(); }
#define SD_GET_LOCK(x) do { while( x ->state & SD_CACHE_LOCKED ) { _NOP(); }; x ->state |= SD_CACHE_LOCKED; } while(0)
#define SD_FREE_LOCK(x) do { x ->state &= ~SD_CACHE_LOCKED; } while(0)
/**
* @brief Flush the sd cache
*
* Writes back the cache buffer, if it has been modified. Call this if
* a high level operation has finished and you want to store all data
* persistantly. The write back operation does not use timers.
*/
void sd_cache_flush(void);
/**
* @brief Read a block into the cache buffer
* @internal
*
* You won't usually need this operation.
*/
sd_cache_t *sd_cache_read_block(const uint32_t * blAdr);
#endif
/**
* @brief Erase (clear) blocks of data
* @param[in] address Starting address of first block to erase
* @param[in] numBlocks Number of blocks to erase (starting at address)
* @return true if successful
* @note Data can only be erased in whole blocks. All bytes will be set
* predifined character (see CSD). Common cards use 0xFF.
*/
bool sd_erase_blocks(const uint32_t address, const uint16_t numBlocks);
/**
* @brief Read card identification register (CID)
* @param[out] pCID Pointer to buffer for CID
* @return Number of bytes read (= size of CID) or 0 if failed
*
* @see ::sd_cid_t
*/
uint16_t sd_read_cid(struct sd_cid *pCID);
/**
* @brief Read size of card
* @return Number of bytes available
*
* Reads the number of bytes in the card memory from the CSD register.
*/
uint32_t sd_get_size(void);
#if SD_READ_ANY
/**
* @brief Read any number of bytes from any address into buffer
*
* @param[out] pBuffer Pointer to a buffer to which data is read. It should be least
* size bytes large
* @param[in] address The address of the first byte that shall be read to pBuffer
* @param[in] size Number of bytes which shall be read starting at address */
uint16_t sd_read(void *pBuffer, uint32_t address, uint16_t size);
#endif
#if SD_WRITE
uint16_t sd_write(uint32_t address, void *pBuffer, uint16_t size);
#endif
#endif /*__SD_H__*/
/** @} */

View file

@ -1,204 +0,0 @@
/*
Copyright 2007, Freie Universitaet Berlin. All rights reserved.
These sources were developed at the Freie Universität Berlin, Computer
Systems and Telematics group.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Freie Universitaet Berlin (FUB) nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
This software is provided by FUB and the contributors on an "as is"
basis, without any representations or warranties of any kind, express
or implied including, but not limited to, representations or
warranties of non-infringement, merchantability or fitness for a
particular purpose. In no event shall FUB or contributors be liable
for any direct, indirect, incidental, special, exemplary, or
consequential damages (including, but not limited to, procurement of
substitute goods or services; loss of use, data, or profits; or
business interruption) however caused and on any theory of liability,
whether in contract, strict liability, or tort (including negligence
or otherwise) arising in any way out of the use of this software, even
if advised of the possibility of such damage.
This implementation was developed by the CST group at the FUB.
For documentation and questions please use the web site
http://scatterweb.mi.fu-berlin.de and the mailinglist
scatterweb@lists.spline.inf.fu-berlin.de (subscription via the Website).
Berlin, 2007
*/
/**
* @file ScatterWeb.Sd.cache.c
* @ingroup libsd
* @brief MMC-/SD-Card library, cached read and write
*
* @author Michael Baar <baar@inf.fu-berlin.de>
* @version $Revision: 1.5 $
*
* $Id: sd_cache.c,v 1.5 2009/05/26 12:15:46 nvt-se Exp $
*/
/**
* @addtogroup libsd
* @{
*/
#include "sd.h"
#include "sd_internals.h"
#if SD_CACHE
void
_sd_cache_init(void)
{
uint32_t addr = 0;
sd_state.Cache->address = 1;
sd_state.Cache->state = 0;
/* pre-read first block */
sd_cache_read_block(&addr);
SD_FREE_LOCK(sd_state.Cache);
}
void
_sd_cache_flush(void)
{
#if SD_WRITE
SD_GET_LOCK(sd_state.Cache);
if(sd_state.Cache->state & SD_CACHE_DIRTY) {
sd_set_blocklength(SD_WRITE_BLOCKLENGTH_BIT);
sd_write_block(sd_state.Cache->address, sd_state.Cache->buffer);
sd_state.Cache->state &= ~SD_CACHE_DIRTY;
}
SD_FREE_LOCK(sd_state.Cache);
#endif
}
sd_cache_t *
sd_cache_read_block(const uint32_t *pblAdr)
{
SD_GET_LOCK(sd_state.Cache);
if(sd_state.Cache->address != *pblAdr) {
sd_set_blocklength(SD_WRITE_BLOCKLENGTH_BIT);
if(sd_state.Cache->state & SD_CACHE_DIRTY) {
sd_write_block(sd_state.Cache->address, sd_state.Cache->buffer);
sd_state.Cache->state &= ~SD_CACHE_DIRTY;
}
sd_state.Cache->address = *pblAdr;
if(!sd_read_block(sd_state.Cache->buffer, *pblAdr)) {
SD_FREE_LOCK(sd_state.Cache);
return NULL;
}
}
return sd_state.Cache;
}
#if SD_READ_ANY
uint16_t
sd_read(void *pBuffer, uint32_t address, uint16_t size)
{
uint16_t offset; /* bytes from aligned address to start of first byte to keep */
char *p; /* pointer to current pos in receive buffer */
uint16_t bytes_left; /* num bytes to read */
uint16_t read_count; /* num bytes to read from current block */
/* parameter processing */
p = (char *)pBuffer;
bytes_left = size;
/* align to block */
offset = sd_align_address(&address);
/* Data transfer */
do {
/* calculate block */
if((offset == 0) && (bytes_left >= sd_state.BlockLen)) {
read_count = sd_state.BlockLen;
sd_read_block(p, address);
} else {
sd_cache_read_block(&address);
read_count = bytes_left + offset;
if(read_count > sd_state.BlockLen) {
read_count = sd_state.BlockLen - offset;
} else {
read_count = bytes_left;
}
memcpy(p, sd_state.Cache->buffer + offset, read_count);
SD_FREE_LOCK(sd_state.Cache);
}
bytes_left -= read_count;
if(bytes_left == 0) {
return size;
}
p += read_count;
address += sd_state.BlockLen;
} while(1);
}
#endif /* SD_READ_ANY */
#if SD_WRITE
uint16_t
sd_write(uint32_t address, void *pBuffer, uint16_t size)
{
uint16_t offset; /* bytes from aligned address to start of first byte to keep */
char *p; /* pointer to current pos in receive buffer */
uint16_t bytes_left; /* num bytes to read */
uint16_t read_count; /* num bytes to read from current block */
/* parameter processing */
p = (char *)pBuffer;
bytes_left = size;
/* align to block */
offset = sd_align_address(&address);
sd_set_blocklength(SD_WRITE_BLOCKLENGTH_BIT);
/* Data transfer */
do {
/* calculate block */
if((offset == 0) && (bytes_left >= sd_state.BlockLen)) {
read_count = sd_state.BlockLen;
sd_write_block(address, p);
} else {
sd_cache_read_block(&address);
read_count = bytes_left + offset;
if(read_count > sd_state.BlockLen) {
read_count = sd_state.BlockLen - offset;
} else {
read_count = bytes_left;
}
memcpy(sd_state.Cache->buffer + offset, p, read_count);
sd_state.Cache->state |= SD_CACHE_DIRTY;
SD_FREE_LOCK(sd_state.Cache);
}
if(bytes_left == 0) {
return size;
}
p += read_count;
bytes_left -= read_count;
address += sd_state.BlockLen;
} while(1);
}
#endif /* SD_WRITE */
#endif /* SD_CACHE */
/** @} */

View file

@ -1,98 +0,0 @@
/*
Copyright 2007, Freie Universitaet Berlin. All rights reserved.
These sources were developed at the Freie Universität Berlin, Computer
Systems and Telematics group.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Freie Universitaet Berlin (FUB) nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
This software is provided by FUB and the contributors on an "as is"
basis, without any representations or warranties of any kind, express
or implied including, but not limited to, representations or
warranties of non-infringement, merchantability or fitness for a
particular purpose. In no event shall FUB or contributors be liable
for any direct, indirect, incidental, special, exemplary, or
consequential damages (including, but not limited to, procurement of
substitute goods or services; loss of use, data, or profits; or
business interruption) however caused and on any theory of liability,
whether in contract, strict liability, or tort (including negligence
or otherwise) arising in any way out of the use of this software, even
if advised of the possibility of such damage.
This implementation was developed by the CST group at the FUB.
For documentation and questions please use the web site
http://scatterweb.mi.fu-berlin.de and the mailinglist
scatterweb@lists.spline.inf.fu-berlin.de (subscription via the Website).
Berlin, 2007
*/
/**
* @file ScatterWeb.Sd.erase.c
* @ingroup libsd
* @brief MMC-/SD-Card library, Block erase
*
* @author Michael Baar <baar@inf.fu-berlin.de>
* @version $Revision: 1.5 $
*
* $Id: sd_erase.c,v 1.5 2009/05/26 12:15:46 nvt-se Exp $
*/
/**
* @addtogroup libsd
* @{
*/
#include "sd_internals.h"
#include "sd.h"
bool
sd_erase_blocks(uint32_t address, uint16_t numBlocks)
{
uint8_t ret, r1;
uint32_t endAdr;
if(sd_protected()) {
return FALSE;
}
if(!uart_lock(UART_MODE_SPI)) {
return FALSE;
}
ret = _sd_send_cmd(SD_CMD_ERASE_WR_BLK_START_ADDR, SD_RESPONSE_SIZE_R1,
&address, &r1);
if(!ret | r1) {
uart_unlock(UART_MODE_SPI);
return FALSE;
}
endAdr = (numBlocks - 1) * sd_state.BlockLen;
endAdr += address;
ret = _sd_send_cmd(SD_CMD_ERASE_WR_BLK_END_ADDR, SD_RESPONSE_SIZE_R1,
&endAdr, &r1);
if(!ret | r1) {
uart_unlock(UART_MODE_SPI);
return FALSE;
}
ret = _sd_send_cmd(SD_CMD_ERASE, SD_RESPONSE_SIZE_R1, NULL, &r1);
uart_unlock(UART_MODE_SPI);
return ret;
}
/** @} */

View file

@ -1,88 +0,0 @@
/*
Copyright 2007, Freie Universitaet Berlin. All rights reserved.
These sources were developed at the Freie Universität Berlin, Computer
Systems and Telematics group.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Freie Universitaet Berlin (FUB) nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
This software is provided by FUB and the contributors on an "as is"
basis, without any representations or warranties of any kind, express
or implied including, but not limited to, representations or
warranties of non-infringement, merchantability or fitness for a
particular purpose. In no event shall FUB or contributors be liable
for any direct, indirect, incidental, special, exemplary, or
consequential damages (including, but not limited to, procurement of
substitute goods or services; loss of use, data, or profits; or
business interruption) however caused and on any theory of liability,
whether in contract, strict liability, or tort (including negligence
or otherwise) arising in any way out of the use of this software, even
if advised of the possibility of such damage.
This implementation was developed by the CST group at the FUB.
For documentation and questions please use the web site
http://scatterweb.mi.fu-berlin.de and the mailinglist
scatterweb@lists.spline.inf.fu-berlin.de (subscription via the Website).
Berlin, 2007
*/
/**
* @file ScatterWeb.Sd.info.c
* @ingroup libsd
* @brief MMC-/SD-Card library, Additional Information
*
* @author Michael Baar <baar@inf.fu-berlin.de>
* @version $Revision: 1.4 $
*
* $Id: sd_info.c,v 1.4 2009/05/26 12:15:46 nvt-se Exp $
*/
/**
* @addtogroup libsd
* @{
*/
#include "sd_internals.h"
#include "sd.h"
unsigned int
sd_read_cid(struct sd_cid *pCID)
{
return _sd_read_register(pCID, SD_CMD_SEND_CID, sizeof (struct sd_cid));
}
unsigned long
sd_get_size(void)
{
uint32_t size = 0;
if(uart_lock(UART_MODE_SPI)) {
struct sd_csd 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_MULT(csd);
size <<= 2;
size <<= sd_state.MaxBlockLen_bit;
}
uart_unlock(UART_MODE_SPI);
}
return size;
}
/** @} */

View file

@ -1,236 +0,0 @@
/*
Copyright 2007, Freie Universitaet Berlin. All rights reserved.
These sources were developed at the Freie Universität Berlin, Computer
Systems and Telematics group.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Freie Universitaet Berlin (FUB) nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
This software is provided by FUB and the contributors on an "as is"
basis, without any representations or warranties of any kind, express
or implied including, but not limited to, representations or
warranties of non-infringement, merchantability or fitness for a
particular purpose. In no event shall FUB or contributors be liable
for any direct, indirect, incidental, special, exemplary, or
consequential damages (including, but not limited to, procurement of
substitute goods or services; loss of use, data, or profits; or
business interruption) however caused and on any theory of liability,
whether in contract, strict liability, or tort (including negligence
or otherwise) arising in any way out of the use of this software, even
if advised of the possibility of such damage.
This implementation was developed by the CST group at the FUB.
For documentation and questions please use the web site
http://scatterweb.mi.fu-berlin.de and the mailinglist
scatterweb@lists.spline.inf.fu-berlin.de (subscription via the Website).
Berlin, 2007
*/
/**
* @file ScatterWeb.Sd.internals.h
* @ingroup libsd
* @brief MMC-/SD-Card library
*
* @author Michael Baar <baar@inf.fu-berlin.de>
* @version $Revision: 1.2 $
*
* Header file containing private declarations used MMC-/SD-Card library.
*
* $Id: sd_internals.h,v 1.2 2008/03/28 15:58:44 nvt-se Exp $
*/
#ifndef SD_INT_H_
#define SD_INT_H_
#include <string.h>
#include "sd_platform.h"
#define RETF(x) if( ! x ) return FALSE;
/**
* @name SD Card SPI responses
*/
struct sd_response_r1 {
uint8_t in_idle_state:1;
uint8_t erase_reset:1;
uint8_t illegal_cmd:1;
uint8_t crc_err:1;
uint8_t erase_seq_err:1;
uint8_t address_err:1;
uint8_t param_err:1;
uint8_t start_bit:1;
};
struct sd_response_r2 {
uint16_t in_idle_state:1;
uint16_t erase_reset:1;
uint16_t illegal_cmd:1;
uint16_t crc_err:1;
uint16_t erase_seq_err:1;
uint16_t address_err:1;
uint16_t param_err:1;
uint16_t start_bit:1;
uint16_t card_locked:1;
uint16_t write_failed:1;
uint16_t unspecified_err:1;
uint16_t controller_err:1;
uint16_t ecc_failed:1;
uint16_t protect_violation:1;
uint16_t erase_param:1;
uint16_t out_of_range:1;
};
#ifdef __TI_COMPILER_VERSION__
#pragma pack(1)
#endif
struct sd_response_r3 {
struct sd_response_r1 r1;
#ifdef __GNUC__
__attribute__ ((packed))
#endif
uint32_t ocr;
};
#ifdef __TI_COMPILER_VERSION__
#pragma pack()
#endif
struct sd_read_error_token {
uint8_t unspecified_err:1;
uint8_t controller_err:1;
uint8_t ecc_failed:1;
uint8_t out_of_range:1;
uint8_t card_locked:1;
uint8_t:3;
};
struct sd_data_error_token {
uint8_t error:1;
uint8_t cc_error:1;
uint8_t ecc_error:1;
uint8_t out_of_range:1;
uint8_t:4; // always 0 (-> SD_DATA_ERROR_TOKEN_MASK)
};
typedef struct sd_read_error_token sd_read_error_token_t;
typedef struct sd_data_error_token sd_data_error_t;
#define SD_DATA_ERROR_TOKEN_MASK 0x0F ///< mask for error token
#define SD_R1_ERROR_MASK 0x7C ///< mask for error bits in r1 response
///@}
/**
* @name Private interface
*/
/// Reset card
int _sd_reset(struct sd_response_r3 *pOpCond);
/// Send command and read response
bool _sd_send_cmd(const uint8_t command,
const int response_size,
const void *pArg, void (*const pResponse)
);
/// Wait for card to leave idle mode
bool _sd_wait_standby(struct sd_response_r3 *pOpCond);
/// Read card register
uint16_t _sd_read_register(void (*const pBuffer), const uint8_t cmd,
const uint16_t size);
/// Begin block read operation
bool _sd_read_start(const uint8_t cmd, const uint32_t address);
/// Cancel block read operation
void _sd_read_stop(const uint16_t count);
#if SD_WRITE
enum sd_write_ret _sd_write_block(const uint32_t * pAddress,
const void *pBuffer, int increment);
#endif
#if SD_CACHE
void _sd_cache_init();
void _sd_cache_flush();
#endif
///@}
#define SD_TOKEN_READ 0xFE
#define SD_TOKEN_WRITE 0xFE
#define SD_TOKEN_ZP 0xFF
#define SD_TIMEOUT_IDLE 1000 // # of poll-cycles for reset procedure (takes some time)
#define SD_TIMEOUT_READ 20000
#define SD_TIMEOUT_NCR 8 // 8-64 cycles
#define SD_RESET_RETRY_COUNT 4
#define SD_OCR_BUSY(ocr) ((ocr & 0x80000000) == 0)
#define SD_V_MASK 0x003E0000 // 3,4 - 2,9 V
#define SD_HCR_BIT 0x40000000
#define SD_RESPONSE_SIZE_R1 1
#define SD_RESPONSE_SIZE_R2 2
#define SD_RESPONSE_SIZE_R3 5
/**
* @name Command classes
* @{
*/
#define SD_CCC_BASIC BIT0
#define SD_CCC_BLOCK_READ BIT2
#define SD_CCC_BLOCK_WRITE BIT4
#define SD_CCC_APP_SPECIFIC BIT8
#if SD_WRITE
#define SD_DEFAULT_MINCCC (SD_CCC_BASIC | \
SD_CCC_BLOCK_READ | \
SD_CCC_APP_SPECIFIC | \
SD_CCC_BLOCK_WRITE)
#else
#define SD_DEFAULT_MINCCC (SD_CCC_BASIC | \
SD_CCC_BLOCK_READ | \
SD_CCC_APP_SPECIFIC)
#endif
//@}
/**
* @name Commands
* @{
*/
#define SD_CMD_GO_IDLE_STATE 0 // R1 "reset command"
#define SD_CMD_SEND_OP_COND 1 // R1 (MMC only!)
#define SD_CMD_SEND_CSD 9 // R1
#define SD_CMD_SEND_CID 10 // R1
#define SD_CMD_STOP_TRANSMISSION 12 // R1b
#define SD_CMD_SEND_STATUS 13 // R2
#define SD_CMD_SET_BLOCKLENGTH 16
#define SD_CMD_READ_SINGLE_BLOCK 17 // R1
#define SD_CMD_READ_MULTI_BLOCK 18 // R1
#define SD_CMD_WRITE_SINGLE_BLOCK 24 // R1
#define SD_CMD_ERASE_WR_BLK_START_ADDR 32 // R1
#define SD_CMD_ERASE_WR_BLK_END_ADDR 33 // R1
#define SD_CMD_ERASE 38 // R1b
#define SD_CMD_APP_SECIFIC_CMD 55
#define SD_CMD_READ_OCR 58 // R3
#define SD_ACMD_SEND_OP_COND 41 // R1
//@}
#endif /*SD_INT_H_ */

View file

@ -1,91 +0,0 @@
/*
Copyright 2007, Freie Universitaet Berlin. All rights reserved.
These sources were developed at the Freie Universität Berlin, Computer
Systems and Telematics group.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Freie Universitaet Berlin (FUB) nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
This software is provided by FUB and the contributors on an "as is"
basis, without any representations or warranties of any kind, express
or implied including, but not limited to, representations or
warranties of non-infringement, merchantability or fitness for a
particular purpose. In no event shall FUB or contributors be liable
for any direct, indirect, incidental, special, exemplary, or
consequential damages (including, but not limited to, procurement of
substitute goods or services; loss of use, data, or profits; or
business interruption) however caused and on any theory of liability,
whether in contract, strict liability, or tort (including negligence
or otherwise) arising in any way out of the use of this software, even
if advised of the possibility of such damage.
This implementation was developed by the CST group at the FUB.
For documentation and questions please use the web site
http://scatterweb.mi.fu-berlin.de and the mailinglist
scatterweb@lists.spline.inf.fu-berlin.de (subscription via the Website).
Berlin, 2007
*/
/**
* @file ScatterWeb.Sd.MSB430.c
* @ingroup libsd
* @brief MMC-/SD-Card library initialisation for MSB430
*
* @author Michael Baar <baar@inf.fu-berlin.de>
* @date Jan 2007
* @version $Revision: 1.2 $
*
* Replace this file for use on another platform.
*
* $Id: sd_msb430.c,v 1.2 2008/03/28 23:03:05 nvt-se Exp $
*/
#include "sd_internals.h"
void
sd_init_platform(void)
{
sdspi_init();
P5SEL |= 0x0E; // 00 00 11 10 -> Dout, Din, Clk = peripheral (now done in UART module)
P5SEL &= ~0x01; // 00 00 00 01 -> Cs = I/O
P5OUT |= 0x01; // 00 00 00 01 -> Cs = High
P5DIR |= 0x0D; // 00 00 11 01 -> Dout, Clk, Cs = output
P5DIR &= ~0x02; // 00 00 00 10 -> Din = Input
P2SEL &= ~0x40; // 11 00 00 00 -> protect, detect = I/O
P2DIR &= ~0x40; // 11 00 00 00 -> protect, detect = input
}
/**
* @brief Activate SD Card on SPI Bus
* \internal
*/
__inline void
sdspi_select()
{
P5OUT &= ~0x01; // Card Select
}
__inline void
sdspi_unselect()
{
UART_WAIT_TXDONE();
P5OUT |= 0x01; // Card Deselect
sdspi_tx(0xFF);
}

View file

@ -1,64 +0,0 @@
/*
Copyright 2007, Freie Universitaet Berlin. All rights reserved.
These sources were developed at the Freie Universität Berlin, Computer
Systems and Telematics group.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Freie Universitaet Berlin (FUB) nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
This software is provided by FUB and the contributors on an "as is"
basis, without any representations or warranties of any kind, express
or implied including, but not limited to, representations or
warranties of non-infringement, merchantability or fitness for a
particular purpose. In no event shall FUB or contributors be liable
for any direct, indirect, incidental, special, exemplary, or
consequential damages (including, but not limited to, procurement of
substitute goods or services; loss of use, data, or profits; or
business interruption) however caused and on any theory of liability,
whether in contract, strict liability, or tort (including negligence
or otherwise) arising in any way out of the use of this software, even
if advised of the possibility of such damage.
This implementation was developed by the CST group at the FUB.
For documentation and questions please use the web site
http://scatterweb.mi.fu-berlin.de and the mailinglist
scatterweb@lists.spline.inf.fu-berlin.de (subscription via the Website).
Berlin, 2007
*/
/**
* @file ScatterWeb.Sd.Platform.h
* @ingroup libsd
* @brief MMC-/SD-Card library initialisation for MSB430
*
* @author Michael Baar <baar@inf.fu-berlin.de>
* @date Jan 2007
* @version $Revision: 1.2 $
*
* Replace this file for use on another platform.
*
* $Id: sd_platform.h,v 1.2 2008/03/28 23:03:05 nvt-se Exp $
*/
#ifndef __SCATTERWEB_SD_PLATFORM__
#define __SCATTERWEB_SD_PLATFORM__
#include <msp430x16x.h>
#include "contiki.h"
#include "dev/msb430-uart1.h"
#endif

View file

@ -1,238 +0,0 @@
/*
Copyright 2007, Freie Universitaet Berlin. All rights reserved.
These sources were developed at the Freie Universität Berlin, Computer
Systems and Telematics group.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Freie Universitaet Berlin (FUB) nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
This software is provided by FUB and the contributors on an "as is"
basis, without any representations or warranties of any kind, express
or implied including, but not limited to, representations or
warranties of non-infringement, merchantability or fitness for a
particular purpose. In no event shall FUB or contributors be liable
for any direct, indirect, incidental, special, exemplary, or
consequential damages (including, but not limited to, procurement of
substitute goods or services; loss of use, data, or profits; or
business interruption) however caused and on any theory of liability,
whether in contract, strict liability, or tort (including negligence
or otherwise) arising in any way out of the use of this software, even
if advised of the possibility of such damage.
This implementation was developed by the CST group at the FUB.
For documentation and questions please use the web site
http://scatterweb.mi.fu-berlin.de and the mailinglist
scatterweb@lists.spline.inf.fu-berlin.de (subscription via the Website).
Berlin, 2007
*/
/**
* @file ScatterWeb.Spi.c
* @ingroup libsdspi
* @brief Serial Peripheral Interface for SD library
*
* @author Michael Baar <baar@inf.fu-berlin.de>
* @version $Revision: 1.4 $
*
* $Id: sdspi.c,v 1.4 2009/05/26 12:15:46 nvt-se Exp $
*/
#include <msp430x16x.h>
#include "contiki-msb430.h"
#if SPI_DMA_WRITE
uint8_t sdspi_dma_lock;
#endif
#ifndef U1IFG
#define U1IFG IFG2
#endif
#define SPI_IDLE_SYMBOL 0xFF
void
sdspi_init(void)
{
#if SPI_DMA_WRITE
sdspi_dma_lock = FALSE;
#endif
/*
* 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
* 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
* for SPI mode and is recommended to be set to 000h. The UCLK frequency is
* given by:
* Baud rate = BRCLK / UxBR with UxBR= [UxBR1, UxBR0]
*/
uart_set_speed(UART_MODE_SPI, 0x02, 0x00, 0x00);
}
uint8_t
sdspi_rx(void)
{
UART_TX = SPI_IDLE_SYMBOL;
UART_WAIT_RX();
return (UART_RX);
}
void
sdspi_tx(register const uint8_t c)
{
UART_TX = c;
UART_WAIT_TXDONE();
}
#if SPI_DMA_READ || SPI_DMA_WRITE
void
sdspi_dma_wait(void)
{
/* Wait until a previous transfer is complete */
while(DMA0CTL & DMAEN) {
_NOP();
}
}
#endif
void
sdspi_read(void *pDestination, const uint16_t size, const bool incDest)
{
int s;
s = splhigh();
#if SPI_DMA_READ
sdspi_dma_wait();
UART_RESET_RXTX(); /* clear interrupts */
/* Configure the DMA transfer */
DMA0SA = (uint16_t) & UART_RX; /* source DMA address */
DMA0DA = (uint16_t) pDestination; /* destination DMA address */
DMA0SZ = size; /* number of bytes to be transferred */
DMA1SA = (uint16_t) & UART_TX; /* source DMA address (constant 0xff) */
DMA1DA = DMA1SA; /* destination DMA address */
DMA1SZ = size - 1; /* number of bytes to be transferred */
DMACTL0 = DMA0TSEL_9 | DMA1TSEL_9; /* trigger is UART1 receive for both DMA0 and DMA1 */
DMA0CTL = DMADT_0 | /* Single transfer mode */
DMASBDB | /* Byte mode */
DMADSTINCR0 | DMADSTINCR1 | /* Increment destination */
DMAEN; /* Enable DMA */
if(!incDest) {
DMA0CTL &= ~(DMADSTINCR0 | DMADSTINCR1);
}
DMA1CTL = DMADT_0 | /* Single transfer mode */
DMASBDB | /* Byte mode */
DMAEN; /* Enable DMA */
UART_TX = SPI_IDLE_SYMBOL; /* Initiate transfer by sending the first byte */
sdspi_dma_wait();
#else
register uint8_t *p = (uint8_t *)pDestination;
register uint16_t i = size;
do {
UART_TX = SPI_IDLE_SYMBOL;
UART_WAIT_RX();
*p = UART_RX;
if(incDest) {
p++;
}
i--;
} while(i);
#endif
splx(s);
}
#if SPI_WRITE
void
sdspi_write(const void *pSource, const uint16_t size, const int increment)
{
int s;
s = splhigh();
#if SPI_DMA_WRITE
sdspi_dma_wait();
UART_RESET_RXTX(); /* clear interrupts */
/* Configure the DMA transfer */
DMA0SA = ((uint16_t) pSource) + 1; /* source DMA address */
DMA0DA = (uint16_t) & UART_TX; /* destination DMA address */
DMA0SZ = size - 1; /* number of bytes to be transferred */
DMACTL0 = DMA0TSEL_9; /* trigger is UART1 receive */
DMA0CTL = DMADT_0 | /* Single transfer mode */
DMASBDB | /* Byte mode */
DMASRCINCR_3 | /* Increment source */
DMAEN; /* Enable DMA */
if(increment == 0) {
DMA0CTL &= ~DMASRCINCR_3;
}
sdspi_dma_lock = TRUE;
SPI_TX = ((uint8_t *)pSource)[0];
#else
register uint8_t *p = (uint8_t *)pSource;
register uint16_t i = size;
do {
UART_TX = *p;
UART_WAIT_TXDONE();
UART_RX;
p += increment;
i--;
} while(i);
#endif
splx(s);
}
#endif
void
sdspi_idle(register const uint16_t clocks)
{
register uint16_t i = clocks;
do {
UART_TX = SPI_IDLE_SYMBOL;
UART_WAIT_RX();
UART_RX;
i--;
} while(i);
}
uint16_t
sdspi_wait_token(const uint8_t feed, const uint8_t mask,
const uint8_t token, const uint16_t timeout)
{
uint16_t i = 0;
uint8_t rx;
do {
UART_TX = feed;
UART_WAIT_RX();
rx = UART_RX;
i++;
} while(((rx & mask) != token) && (i < timeout));
return i;
}

View file

@ -1,143 +0,0 @@
/*
Copyright 2007, Freie Universitaet Berlin. All rights reserved.
These sources were developed at the Freie Universität Berlin, Computer
Systems and Telematics group.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Freie Universitaet Berlin (FUB) nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
This software is provided by FUB and the contributors on an "as is"
basis, without any representations or warranties of any kind, express
or implied including, but not limited to, representations or
warranties of non-infringement, merchantability or fitness for a
particular purpose. In no event shall FUB or contributors be liable
for any direct, indirect, incidental, special, exemplary, or
consequential damages (including, but not limited to, procurement of
substitute goods or services; loss of use, data, or profits; or
business interruption) however caused and on any theory of liability,
whether in contract, strict liability, or tort (including negligence
or otherwise) arising in any way out of the use of this software, even
if advised of the possibility of such damage.
This implementation was developed by the CST group at the FUB.
For documentation and questions please use the web site
http://scatterweb.mi.fu-berlin.de and the mailinglist
scatterweb@lists.spline.inf.fu-berlin.de (subscription via the Website).
Berlin, 2007
*/
/**
* @addtogroup uart1
* @ingroup libsd_spi
* @{
*/
/**
* @file ScatterWeb.Spi.h
* @ingroup libsdspi
* @brief Serial Peripheral Interface
*
* @author Michael Baar <baar@inf.fu-berlin.de>
* @version $Revision: 1.1 $
*
* $Id: sdspi.h,v 1.1 2008/03/28 15:58:44 nvt-se Exp $
*/
#ifndef __SPI_H__
#define __SPI_H__
#ifndef SPI_DMA_READ
#define SPI_DMA_READ 0
#endif
#ifndef SPI_DMA_WRITE
#define SPI_DMA_WRITE 0
#endif
#ifndef SPI_WRITE
#define SPI_WRITE 1
#endif
/**
* @brief Init SPI driver
*/
void sdspi_init(void);
/// chipselect
__inline void sdspi_select();
__inline void sdspi_unselect();
/**
* @brief Receive one byte from SPI
*/
uint8_t sdspi_rx(void);
/**
* @brief Send one byte to SPI
*
* @param[in] c Byte to send
*/
void sdspi_tx(const uint8_t c);
/**
* @brief Read a number of bytes from SPI
*
* @param[in] pDestination Pointer to buffer to store bytestream
* @param[in] size Number of bytes to store in pDestination
* @param[in] incDest Increment destination pointer after each byte by one (or not)
*/
void sdspi_read(void *pDestination, const uint16_t size, const bool incDest);
#if SPI_DMA_WRITE
extern uint8_t sdspi_dma_lock;
#endif
#if SPI_DMA_READ || SPI_DMA_WRITE
void sdspi_dma_wait(void);
#endif
#if SPI_WRITE
/**
* @brief Write a number of bytes to SPI
*
* @param[in] pSource Pointer to buffer with data to send
* @param[in] size Number of bytes to send
* @param[in] startToken First byte to send before starting to send size bytes from pSource
* @param[in] incSource Increment source pointer after each byte by one (or not)
*/
void sdspi_write(const void *pSource,
const uint16_t size, const int increment);
#endif
/**
* @brief Wait a number of clock cycles
*
* @param[in] clocks Wait clocks x 8 cycles
*/
void sdspi_idle(const uint16_t clocks);
/**
* @brief Read bytes from SPI until token is received
*
* @param[in] token Token to wait for
* @param[in] timeout Maximum number of bytes to read
* @return true if token received, false otherwise
*/
uint16_t sdspi_wait_token(const uint8_t feed, const uint8_t mask,
const uint8_t token, const uint16_t timeout);
#endif /*__SPI_H__*/
/** @} */