From ea56edc5c234d730af98af5803cf5575aad6c46a Mon Sep 17 00:00:00 2001 From: nvt-se Date: Tue, 22 Sep 2009 15:20:51 +0000 Subject: [PATCH] added a simple driver for using SD devices through the SPI. --- platform/msb430/Makefile.msb430 | 3 +- platform/msb430/contiki-msb430-main.c | 21 +- platform/msb430/contiki-msb430.h | 5 + platform/msb430/dev/sd-arch.c | 60 +++ platform/msb430/dev/sd-arch.h | 73 ++++ platform/msb430/dev/sd.c | 527 ++++++++++++++++++++++++++ platform/msb430/dev/sd.h | 79 ++++ 7 files changed, 765 insertions(+), 3 deletions(-) create mode 100755 platform/msb430/dev/sd-arch.c create mode 100755 platform/msb430/dev/sd-arch.h create mode 100755 platform/msb430/dev/sd.c create mode 100644 platform/msb430/dev/sd.h diff --git a/platform/msb430/Makefile.msb430 b/platform/msb430/Makefile.msb430 index 4301a4a65..8b610c2a6 100644 --- a/platform/msb430/Makefile.msb430 +++ b/platform/msb430/Makefile.msb430 @@ -2,7 +2,8 @@ SENSORS = sensors.c irq.c sht11.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 + msb430-slip-arch.c sd.c sd-arch.c \ + cfs-coffee.c cfs-coffee-arch.c CONTIKI_TARGET_DIRS = . dev apps loader ifndef CONTIKI_TARGET_MAIN diff --git a/platform/msb430/contiki-msb430-main.c b/platform/msb430/contiki-msb430-main.c index bfeb65cc2..a2f835de5 100644 --- a/platform/msb430/contiki-msb430-main.c +++ b/platform/msb430/contiki-msb430-main.c @@ -46,6 +46,7 @@ #include "contiki.h" #include "contiki-msb430.h" #include "dev/adc.h" +#include "dev/sd.h" #include "dev/serial-line.h" #include "dev/sht11.h" #include "dev/watchdog.h" @@ -82,11 +83,10 @@ main(void) leds_init(); leds_on(LEDS_ALL); - // low level irq_init(); process_init(); - // serial interface + /* serial interface */ rs232_set_input(serial_line_input_byte); rs232_init(); serial_line_init(); @@ -97,6 +97,23 @@ main(void) slip_arch_init(BAUD2UBR(115200)); #endif + +#if WITH_SD + r = sd_initialize(); + if(r < 0) { + printf("Failed to initialize the SD driver: %s\n", sd_error_string(r)); + } else { + sd_offset_t capacity; + printf("The SD driver was successfully initialized\n"); + capacity = sd_get_capacity(); + if(capacity < 0) { + printf("Failed to get the card capacity: %s\n", sd_error_string(r)); + } else { + printf("Card capacity: %lu\n", (unsigned long)capacity); + } + } +#endif + /* System services */ process_start(&etimer_process, NULL); ctimer_init(); diff --git a/platform/msb430/contiki-msb430.h b/platform/msb430/contiki-msb430.h index bc7733bd5..d8b803d09 100644 --- a/platform/msb430/contiki-msb430.h +++ b/platform/msb430/contiki-msb430.h @@ -47,8 +47,13 @@ #include "dev/rs232.h" #include "dev/serial-line.h" #include "dev/slip.h" + #include "lib/sensors.h" #include "net/rime.h" #include "node-id.h" +#if WITH_SD +#include "dev/sd.h" +#endif /* WITH_SD */ + #endif /* !CONTIKI_MSB430_H */ diff --git a/platform/msb430/dev/sd-arch.c b/platform/msb430/dev/sd-arch.c new file mode 100755 index 000000000..b26a3de42 --- /dev/null +++ b/platform/msb430/dev/sd-arch.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2009, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the Institute 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 THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE 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 file is part of the Contiki operating system. + * + */ + +/** + * \file + * Architecture-dependent functions for SD over SPI. + * \author + * Nicolas Tsiftes + */ + +#include "contiki.h" +#include "sd-arch.h" + +#include + +int +sd_arch_init(void) +{ + P2SEL &= ~64; + P2DIR &= ~64; + + P5SEL |= 14; + P5SEL &= ~1; + P5OUT |= 1; + P5DIR |= 13; + P5DIR &= ~2; + + uart_set_speed(UART_MODE_SPI, 2, 0, 0); + + return 0; +} diff --git a/platform/msb430/dev/sd-arch.h b/platform/msb430/dev/sd-arch.h new file mode 100755 index 000000000..2ab793f7f --- /dev/null +++ b/platform/msb430/dev/sd-arch.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2009, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the Institute 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 THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE 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 file is part of the Contiki operating system. + * + */ + +/** + * \file + * SD driver implementation using SPI. + * \author + * Nicolas Tsiftes + */ + +#ifndef SD_ARCH_H +#define SD_ARCH_H + +#include "msb430-uart1.h" + +#define MS_DELAY(x) clock_delay(354 * (x)) + +/* Machine-dependent macros. */ +#define LOCK_SPI() do { \ + if(!uart_lock(UART_MODE_SPI)) {\ + return 0; \ + } \ + } while(0) +#define UNLOCK_SPI() do { \ + uart_unlock(UART_MODE_SPI); \ + } while(0) + +#define SD_CONNECTED() !(P2IN & 0x40) +#define LOWER_CS() (P5OUT &= ~0x01) +#define RAISE_CS() do { \ + UART_WAIT_TXDONE(); \ + P5OUT |= 0x01; \ + UART_TX = SPI_IDLE; \ + UART_WAIT_TXDONE(); \ + } while(0) + +/* Configuration parameters. */ +#define SD_TRANSACTION_ATTEMPTS 512 +#define SD_READ_RESPONSE_ATTEMPTS 8 +#define SD_READ_BLOCK_ATTEMPTS 2 + +int sd_arch_init(void); + +#endif /* !SD_ARCH_H */ diff --git a/platform/msb430/dev/sd.c b/platform/msb430/dev/sd.c new file mode 100755 index 000000000..512644348 --- /dev/null +++ b/platform/msb430/dev/sd.c @@ -0,0 +1,527 @@ +/* + * Copyright (c) 2009, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the Institute 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 THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE 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 file is part of the Contiki operating system. + * + */ + +/** + * \file + * SD driver implementation using SPI. + * \author + * Nicolas Tsiftes + */ + +#include "contiki.h" +#include "msb430-uart1.h" +#include "sd.h" + +#include + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif /* MIN */ + +#define SPI_IDLE 0xff + +/* SD commands */ +#define GO_IDLE_STATE 0 +#define SEND_OP_COND 1 +#define SWITCH_FUNC 6 +#define SEND_IF_COND 8 +#define SEND_CSD 9 +#define SEND_CID 10 +#define STOP_TRANSMISSION 12 +#define SEND_STATUS 13 +#define READ_SINGLE_BLOCK 17 +#define WRITE_BLOCK 24 +#define READ_OCR 58 + +/* SD response lengths. */ +#define R1 1 +#define R2 2 +#define R3 5 +#define R7 5 + +#define START_BLOCK_TOKEN 0xfe + +/* Status codes returned after writing a block. */ +#define DATA_ACCEPTED 2 +#define DATA_CRC_ERROR 5 +#define DATA_WRITE_ERROR 6 + +/*---------------------------------------------------------------------------*/ +static void +spi_write(int c) +{ + UART_TX = c; + UART_WAIT_TXDONE(); +} +/*---------------------------------------------------------------------------*/ +static unsigned +spi_read(void) +{ + UART_TX = SPI_IDLE; + UART_WAIT_RX(); + return UART_RX; +} +/*---------------------------------------------------------------------------*/ +static void +spi_write_block(uint8_t *bytes, int amount) +{ + int i; + + for(i = 0; i < amount; i++) { + UART_TX = bytes[i]; + UART_WAIT_TXDONE(); + UART_RX; + } +} +/*---------------------------------------------------------------------------*/ +static int +send_command(uint8_t cmd, uint32_t argument) +{ + uint8_t req[6]; + + req[0] = 0x40 | cmd; + req[1] = argument >> 24; + req[2] = argument >> 16; + req[3] = argument >> 8; + req[4] = argument; + /* The CRC hard-wired to 0x95 is only needed for the initial + GO_IDLE_STATE command. */ + req[5] = 0x95; + + spi_write(SPI_IDLE); + spi_write_block(req, sizeof(req)); + spi_write(SPI_IDLE); + + return 0; +} +/*---------------------------------------------------------------------------*/ +static uint8_t * +get_response(int length) +{ + int i; + int x; + static uint8_t r[R7]; + + for(i = 0; i < SD_READ_RESPONSE_ATTEMPTS; i++) { + x = spi_read(); + if((x & 0x80) == 0) { + /* A get_response byte is indicated by the MSB being 0. */ + r[0] = x; + break; + } + } + + if(i == SD_READ_RESPONSE_ATTEMPTS) { + return NULL; + } + + for(i = 1; i < length; i++) { + r[i] = spi_read(); + } + + return r; +} +/*---------------------------------------------------------------------------*/ +static unsigned char * +transaction(int command, unsigned long argument, + int response_type, unsigned attempts) +{ + unsigned i; + unsigned char *r; + + LOCK_SPI(); + r = NULL; + for(i = 0; i < attempts; i++) { + LOWER_CS(); + send_command(command, argument); + r = get_response(response_type); + RAISE_CS(); + if(r != NULL) { + break; + } + } + UNLOCK_SPI(); + + return r; +} +/*---------------------------------------------------------------------------*/ +int +sd_initialize(void) +{ + int i; + uint8_t *r; + + if(sd_arch_init() < 0) { + return SD_INIT_ERROR_ARCH; + } + + if(SD_CONNECTED() < 0) { + return SD_INIT_ERROR_NO_CARD; + } + + r = transaction(GO_IDLE_STATE, 0, R1, SD_TRANSACTION_ATTEMPTS); + if(r != NULL) { + PRINTF("Go-idle result: %d\n", r[0]); + } else { + PRINTF("Failed to get go-idle response\n"); + } + + r = transaction(SEND_IF_COND, 0, R7, SD_TRANSACTION_ATTEMPTS); + if(r != NULL) { + PRINTF("IF cond: %d %d %d %d %d\n", r[0], r[1], r[2], r[3], r[4]); + } else { + PRINTF("failed to get IF cond\n"); + return SD_INIT_ERROR_NO_IF_COND; + } + + LOCK_SPI(); + + for(i = 0; i < SD_TRANSACTION_ATTEMPTS; i++) { + LOWER_CS(); + send_command(SEND_OP_COND, 0); + r = get_response(R1); + RAISE_CS(); + if(r != NULL && !(r[0] & 1)) { + break; + } + } + + UNLOCK_SPI(); + + if(r != NULL) { + PRINTF("OP cond: %d (%d iterations)\n", r[0], i); + } else { + PRINTF("Failed to get OP cond get_response\n"); + } + + LOCK_SPI(); + + for(i = 0; i < 10000; i++) { + LOWER_CS(); + send_command(READ_OCR, 0); + r = get_response(R3); + RAISE_CS(); + if(r != NULL) { + break; + } + } + + UNLOCK_SPI(); + + if(r != NULL) { + PRINTF("OCR: %d %d %d %d %d\n", r[0], r[1], r[2], r[3], r[4]); + } + + /* XXX Arbitrary wait time here. Need to investigate why this is needed. */ + MS_DELAY(5); + + return SD_OK; +} +/*---------------------------------------------------------------------------*/ +int +sd_write_block(sd_offset_t offset, char *buf) +{ + unsigned char *r; + int retval; + int i; + unsigned char data_response; + unsigned char status_code; + + LOCK_SPI(); + r = NULL; + retval = SD_WRITE_ERROR_NO_CMD_RESPONSE; + for(i = 0; i < SD_TRANSACTION_ATTEMPTS; i++) { + LOWER_CS(); + send_command(WRITE_BLOCK, offset); + r = get_response(R1); + if(r != NULL) { + break; + } + RAISE_CS(); + } + + if(r != NULL && r[0] == 0) { + /* We received an R1 response with no errors. + Send a start block token to the card now. */ + spi_write(START_BLOCK_TOKEN); + + /* Write the data block. */ + spi_write_block(buf, SD_BLOCK_SIZE); + + /* Get a response from the card. */ + retval = SD_WRITE_ERROR_NO_BLOCK_RESPONSE; + for(i = 0; i < SD_TRANSACTION_ATTEMPTS; i++) { + data_response = spi_read(); + if((data_response & 0x11) == 1) { + /* Data response token received. */ + status_code = (data_response >> 1) & 0x7; + if(status_code == DATA_ACCEPTED) { + retval = SD_BLOCK_SIZE; + } else { + retval = SD_WRITE_ERROR_PROGRAMMING; + } + break; + } + } + } + + RAISE_CS(); + UNLOCK_SPI(); + + return retval; +} +/*---------------------------------------------------------------------------*/ +static int +read_block(unsigned read_cmd, sd_offset_t offset, char *buf, int len) +{ + unsigned char *r; + int i; + int token; + int retval; + + LOCK_SPI(); + + r = NULL; + for(i = 0; i < SD_TRANSACTION_ATTEMPTS; i++) { + LOWER_CS(); + send_command(read_cmd, offset); + r = get_response(R1); + if(r != NULL) { + break; + } + RAISE_CS(); + } + + if(r != NULL && r[0] == 0) { + /* We received an R1 response with no errors. + Get a token from the card now. */ + for(i = 0; i < SD_TRANSACTION_ATTEMPTS; i++) { + token = spi_read(); + if(token == START_BLOCK_TOKEN || (token > 0 && token <= 8)) { + break; + } + } + + if(token == START_BLOCK_TOKEN) { + /* A start block token has been received. Read the block now. */ + for(i = 0; i < len; i++) { + buf[i] = spi_read(); + } + + /* Consume CRC. TODO: Validate the block. */ + spi_read(); + spi_read(); + + retval = SD_BLOCK_SIZE; + } else if(token > 0 && token <= 8) { + /* The card returned a data error token. */ + retval = SD_READ_ERROR_TOKEN; + } else { + /* The card never returned a token after our read attempts. */ + retval = SD_READ_ERROR_NO_TOKEN; + } + + RAISE_CS(); + UNLOCK_SPI(); + return retval; + } + + RAISE_CS(); + UNLOCK_SPI(); + + if(r != NULL) { + PRINTF("status during read: %d\n", r[0]); + } + + return SD_READ_ERROR_NO_CMD_RESPONSE; +} +/*---------------------------------------------------------------------------*/ +int +sd_read_block(sd_offset_t offset, char *buf) +{ + return read_block(READ_SINGLE_BLOCK, offset, buf, SD_BLOCK_SIZE); +} +/*---------------------------------------------------------------------------*/ +static int +read_register(int register_cmd, char *buf, int register_size) +{ + return read_block(register_cmd, 0, buf, register_size); +} +/*---------------------------------------------------------------------------*/ +unsigned +sd_get_block_size(void) +{ + return SD_BLOCK_SIZE; +} +/*---------------------------------------------------------------------------*/ +sd_offset_t +sd_get_capacity(void) +{ + unsigned char reg[16]; + int r; + uint16_t c_size; + uint8_t c_size_mult; + sd_offset_t block_nr; + sd_offset_t mult; + + r = read_register(SEND_CSD, reg, sizeof(reg)); + if(r < 0) { + return r; + } + + c_size = ((reg[6] & 3) << 10) + (reg[7] << 2) + (reg[8] & 3); + c_size_mult = ((reg[9] & 3) << 1) + ((reg[10] & 0x80) >> 7); + mult = 2 << (c_size_mult + 2); + block_nr = (c_size + 1) * mult; + + return block_nr * SD_BLOCK_SIZE; +} +/*---------------------------------------------------------------------------*/ +char * +sd_error_string(int error_code) +{ +#if DEBUG + switch(error_code) { + case SD_OK: + return "operation succeeded"; + case SD_INIT_ERROR_NO_CARD: + return "no card was found"; + case SD_INIT_ERROR_ARCH: + return "architecture-dependent initialization failed"; + case SD_INIT_ERROR_NO_IF_COND: + return "unable to obtain the interface condition"; + case SD_WRITE_ERROR_NO_CMD_RESPONSE: + return "no response from the card after submitting a write request"; + case SD_WRITE_ERROR_NO_BLOCK_RESPONSE: + return "no response from the card after sending a data block"; + case SD_WRITE_ERROR_PROGRAMMING: + return "the write request failed because of a card error"; + case SD_WRITE_ERROR_TOKEN: + return "the card is not ready to grant a write request"; + case SD_READ_ERROR_NO_TOKEN: + case SD_WRITE_ERROR_NO_TOKEN: + return "did not receive a start block token"; + case SD_READ_ERROR_INVALID_SIZE: + return "invalid read block size"; + case SD_READ_ERROR_TOKEN: + return "the card is not ready to read a data block"; + case SD_READ_ERROR_NO_CMD_RESPONSE: + return "no response from the card after submitting a read request"; + default: + break; + } +#endif + return "unspecified error"; +} +/*---------------------------------------------------------------------------*/ +int +sd_write(sd_offset_t offset, char *buf, size_t size) +{ + sd_offset_t address; + uint16_t offset_in_block; + int r, i; + size_t written; + size_t to_write; + char sd_buf[SD_BLOCK_SIZE]; + + /* Emulation of data writing using arbitrary offsets and chunk sizes. */ + memset(sd_buf, 0, sizeof(sd_buf)); + written = 0; + offset_in_block = offset % SD_BLOCK_SIZE; + + do { + to_write = MIN(size - written, SD_BLOCK_SIZE - offset_in_block); + address = (offset + written) & ~(SD_BLOCK_SIZE - 1); + + for(i = 0; i < SD_READ_BLOCK_ATTEMPTS; i++) { + r = sd_read_block(address, sd_buf); + if(r == sizeof(buf)) { + break; + } + } + if(r != sizeof(sd_buf)) { + return r; + } + + memcpy(&sd_buf[offset_in_block], &buf[written], to_write); + r = sd_write_block(address, sd_buf); + if(r != sizeof(sd_buf)) { + return r; + } + written += to_write; + offset_in_block = 0; + } while(written < size); + + return written; +} +/*---------------------------------------------------------------------------*/ +int +sd_read(sd_offset_t offset, char *buf, size_t size) +{ + size_t total_read; + size_t to_read; + char sd_buf[SD_BLOCK_SIZE]; + uint16_t offset_in_block; + int r, i; + + /* Emulation of data reading using arbitrary offsets and chunk sizes. */ + total_read = 0; + offset_in_block = offset % SD_BLOCK_SIZE; + + do { + to_read = MIN(size - total_read, SD_BLOCK_SIZE - offset_in_block); + for(i = 0; i < SD_READ_BLOCK_ATTEMPTS; i++) { + r = sd_read_block((offset + total_read) & ~(SD_BLOCK_SIZE - 1), sd_buf); + if(r == sizeof(sd_buf)) { + break; + } + } + if(r != sizeof(sd_buf)) { + return r; + } + + memcpy(&buf[total_read], &sd_buf[offset_in_block], to_read); + total_read += to_read; + offset_in_block = 0; + } while(total_read < size); + + return size; +} +/*---------------------------------------------------------------------------*/ diff --git a/platform/msb430/dev/sd.h b/platform/msb430/dev/sd.h new file mode 100644 index 000000000..a1470db48 --- /dev/null +++ b/platform/msb430/dev/sd.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2009, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the Institute 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 THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE 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 file is part of the Contiki operating system. + * + */ + +/** + * \file + * SD driver interface. + * \author + * Nicolas Tsiftes + */ + +#ifndef SD_H +#define SD_H + +#include "sd-arch.h" + +#define SD_BLOCK_SIZE 512 +#define SD_REGISTER_SIZE 16 + +/* API return codes. */ +#define SD_OK 1 + +#define SD_INIT_ERROR_NO_CARD -1 +#define SD_INIT_ERROR_ARCH -2 +#define SD_INIT_ERROR_NO_IF_COND -3 + +#define SD_WRITE_ERROR_NO_CMD_RESPONSE -4 +#define SD_WRITE_ERROR_NO_BLOCK_RESPONSE -5 +#define SD_WRITE_ERROR_PROGRAMMING -6 +#define SD_WRITE_ERROR_TOKEN -7 +#define SD_WRITE_ERROR_NO_TOKEN -8 + +#define SD_READ_ERROR_NO_CMD_RESPONSE -9 +#define SD_READ_ERROR_INVALID_SIZE -10 +#define SD_READ_ERROR_TOKEN -11 +#define SD_READ_ERROR_NO_TOKEN -12 + +/* Type definition. */ +typedef uint32_t sd_offset_t; + +/* API */ +int sd_initialize(void); +int sd_write(sd_offset_t, char *, unsigned); +int sd_read(sd_offset_t, char *, unsigned); +int sd_write_block(sd_offset_t, char *); +int sd_read_block(sd_offset_t, char *); +unsigned sd_get_block_size(void); +sd_offset_t sd_get_capacity(void); +char *sd_error_string(int); + +#endif /* !SD_H */