added a simple driver for using SD devices through the SPI.

This commit is contained in:
nvt-se 2009-09-22 15:20:51 +00:00
parent a71cd04144
commit ea56edc5c2
7 changed files with 765 additions and 3 deletions

View file

@ -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

View file

@ -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();

View file

@ -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 */

60
platform/msb430/dev/sd-arch.c Executable file
View file

@ -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 <nvt@sics.se>
*/
#include "contiki.h"
#include "sd-arch.h"
#include <string.h>
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;
}

73
platform/msb430/dev/sd-arch.h Executable file
View file

@ -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 <nvt@sics.se>
*/
#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 */

527
platform/msb430/dev/sd.c Executable file
View file

@ -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 <nvt@sics.se>
*/
#include "contiki.h"
#include "msb430-uart1.h"
#include "sd.h"
#include <string.h>
#define DEBUG 0
#if DEBUG
#include <stdio.h>
#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;
}
/*---------------------------------------------------------------------------*/

79
platform/msb430/dev/sd.h Normal file
View file

@ -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 <nvt@sics.se>
*/
#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 */