o add fat filesystem test for arm lpc2148

This commit is contained in:
david
2009-02-14 17:52:52 +01:00
parent 45548384d4
commit 3e4abc9b01
115 changed files with 26014 additions and 0 deletions

View File

@@ -0,0 +1,270 @@
/*****************************************************************************\
* efs - General purpose Embedded Filesystem library *
* --------------------------------------------------------- *
* *
* Filename : at91_spi.c *
* Description : This file contains the functions needed to use efs for *
* accessing files on an SD-card connected to an AT91(SAM7) *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; version 2 *
* of the License. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* As a special exception, if other files instantiate templates or *
* use macros or inline functions from this file, or you compile this *
* file and link it with other works to produce a work based on this file, *
* this file does not by itself cause the resulting work to be covered *
* by the GNU General Public License. However the source code for this *
* file must still be made available in accordance with section (3) of *
* the GNU General Public License. *
* *
* This exception does not invalidate any other reasons why a work based *
* on this file might be covered by the GNU General Public License. *
* *
* (c)2006 Martin Thomas *
\*****************************************************************************/
/*
TODO:
- Driver uses simple mode -> implement "DMA"
- use 16-bit mode
- check CPOL
*/
/*****************************************************************************/
#include "interfaces/AT91SAM7S_regs.h"
#include "config.h"
#include "interfaces/arm_spi.h"
#include "interfaces/sd.h"
/*****************************************************************************/
/* Define the following to enable fixed peripheral chip-select.
This is not a config.h-value since variable peripheral select
is prefered so other devices can be attached to the AT91 SPI-interface. */
/* #define FIXED_PERIPH */
/*
AT91SAM7S64 SPI Pins: Function (A/B)
PA12 - MISO - AT91C_PA12_MISO (1/0)
PA13 - MOSI - AT91C_PA13_MOSI (1/0)
PA14 - SCK - AT91C_PA14_SPCK (1/0)
Chip-Selects (available on different pins)
PA11 - NPCS0 - AT91C_PA11_NPCS0 (1/0)
PA31 - NPCS1 - AT91C_PA31_NPCS1 (1/0)
PA09 - NPCS1 - AT91C_PA9_NPCS1 (1/0)
...AT91C_PA3_NPCS3 (0/1)
...AT91C_PA5_NPCS3 (0/1)
...AT91C_PA10_NPCS2 (0/1)
...AT91C_PA22_NPCS3 (0/1)
...AT91C_PA30_NPCS2 (0/1)
*/
/* here: use NCPS0 @ PA11: */
#define NCPS_PDR_BIT AT91C_PA11_NPCS0
#define NCPS_ASR_BIT AT91C_PA11_NPCS0
#define NPCS_BSR_BIT 0
#define SPI_CSR_NUM 0
/* PCS_0 for NPCS0, PCS_1 for NPCS1 ... */
#define PCS_0 ((0<<0)|(1<<1)|(1<<2)|(1<<3))
#define PCS_1 ((1<<1)|(0<<1)|(1<<2)|(1<<3))
#define PCS_2 ((1<<1)|(1<<1)|(0<<2)|(1<<3))
#define PCS_3 ((1<<1)|(1<<1)|(1<<2)|(0<<3))
/* TODO: ## */
#if (SPI_CSR_NUM == 0)
#define SPI_MR_PCS PCS_0
#elif (SPI_CSR_NUM == 1)
#define SPI_MR_PCS PCS_1
#elif (SPI_CSR_NUM == 2)
#define SPI_MR_PCS PCS_2
#elif (SPI_CSR_NUM == 3)
#define SPI_MR_PCS PCS_3
#else
#error "SPI_CSR_NUM invalid"
// not realy - when using an external address decoder...
// but this code takes over the complete SPI-interace anyway
#endif
/* in variable periph. select PSDEC=1 is used
so the already defined values for SPC_MR_PCS can be
reused */
#define SPI_TDR_PCS SPI_MR_PCS
/* SPI prescaler lower limit (the smaller the faster) */
#define SPI_SCBR_MIN 2
esint8 if_initInterface(hwInterface* file, eint8* opts)
{
euint32 sc;
if_spiInit(file);
if(sd_Init(file)<0) {
DBG((TXT("Card failed to init, breaking up...\n")));
return(-1);
}
if(sd_State(file)<0){
DBG((TXT("Card didn't return the ready state, breaking up...\n")));
return(-2);
}
/* file->sectorCount=4; */ /* FIXME ASAP!! */
/* mthomas: - somehow done - see below */
sd_getDriveSize(file, &sc);
file->sectorCount = sc/512;
if( (sc%512) != 0) {
file->sectorCount--;
}
DBG((TXT("Card Capacity is %lu Bytes (%lu Sectors)\n"), sc, file->sectorCount));
if_spiSetSpeed(SPI_SCBR_MIN);
// if_spiSetSpeed(100); /* debug - slower */
return(0);
}
/*****************************************************************************/
/* parts of this function inspired by a spi example found at olimex.com
not much (nothing?) left from the olimex-code (since too many hardcoded values)
*/
void if_spiInit(hwInterface *iface)
{
euint8 i;
AT91PS_SPI pSPI = AT91C_BASE_SPI;
AT91PS_PIO pPIOA = AT91C_BASE_PIOA;
AT91PS_PMC pPMC = AT91C_BASE_PMC;
// not used: AT91PS_PDC pPDC_SPI = AT91C_BASE_PDC_SPI;
// disable PIO from controlling MOSI, MISO, SCK (=hand over to SPI)
// keep CS untouched - used as GPIO pin during init
pPIOA->PIO_PDR = AT91C_PA12_MISO | AT91C_PA13_MOSI | AT91C_PA14_SPCK; // | NCPS_PDR_BIT;
// set pin-functions in PIO Controller
pPIOA->PIO_ASR = AT91C_PA12_MISO | AT91C_PA13_MOSI | AT91C_PA14_SPCK; /// not here: | NCPS_ASR_BIT;
/// not here: pPIOA->PIO_BSR = NPCS_BSR_BIT;
// set chip-select as output high (unselect card)
pPIOA->PIO_PER = NCPS_PDR_BIT; // enable GPIO of CS-pin
pPIOA->PIO_SODR = NCPS_PDR_BIT; // set high
pPIOA->PIO_OER = NCPS_PDR_BIT; // output enable
// enable peripheral clock for SPI ( PID Bit 5 )
pPMC->PMC_PCER = ( (euint32) 1 << AT91C_ID_SPI ); // n.b. IDs are just bit-numbers
// SPI enable and reset
pSPI->SPI_CR = AT91C_SPI_SPIEN | AT91C_SPI_SWRST;
#ifdef FIXED_PERIPH
// SPI mode: master, fixed periph. sel., FDIV=0, fault detection disabled
pSPI->SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_PS_FIXED | AT91C_SPI_MODFDIS;
// set PCS for fixed select
// pSPI->SPI_MR &= 0xFFF0FFFF; // clear old PCS - redundant (AT91lib)
pSPI->SPI_MR |= ( (SPI_MR_PCS<<16) & AT91C_SPI_PCS ); // set PCS
#else
// SPI mode: master, variable periph. sel., FDIV=0, fault detection disabled
// Chip-Select-Decoder Mode (write state of CS-Lines in TDR)
pSPI->SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | AT91C_SPI_PCSDEC ;
#endif
// set chip-select-register
// 8 bits per transfer, CPOL=1, ClockPhase=0, DLYBCT = 0
// TODO: Why has CPOL to be active here and non-active on LPC2000?
// Take closer look on timing diagrams in datasheets.
// not working pSPI->SPI_CSR[SPI_CSR_NUM] = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | AT91C_SPI_NCPHA;
// not working pSPI->SPI_CSR[SPI_CSR_NUM] = AT91C_SPI_BITS_8 | AT91C_SPI_NCPHA;
pSPI->SPI_CSR[SPI_CSR_NUM] = AT91C_SPI_CPOL | AT91C_SPI_BITS_8;
// not working pSPI->SPI_CSR[SPI_CSR_NUM] = AT91C_SPI_BITS_8;
// slow during init
if_spiSetSpeed(0xFE);
// enable
pSPI->SPI_CR = AT91C_SPI_SPIEN;
#if 0
// a PDC-init has been in the Olimex-code - not needed since
// the PDC is not used by this version of the interface
// (Olimex did not use PDC either)
// enable PDC transmit and receive in "PERIPH_PTCR" (SPI_PTCR)
pPDC_SPI->PDC_PTCR = AT91C_PDC_TXTEN | AT91C_PDC_RXTEN;
pSPI->SPI_PTCR = AT91C_PDC_TXTEN | AT91C_PDC_RXTEN;
#endif
/* Send 20 spi commands with card not selected */
for(i=0;i<21;i++) {
if_spiSend(iface,0xFF);
}
/* enable automatic chip-select */
// reset PIO-registers of CS-pin to default
pPIOA->PIO_ODR = NCPS_PDR_BIT; // input
pPIOA->PIO_CODR = NCPS_PDR_BIT; // clear
// disable PIO from controlling the CS pin (=hand over to SPI)
pPIOA->PIO_PDR = NCPS_PDR_BIT;
// set pin-functions in PIO Controller (function NCPS for CS-pin)
pPIOA->PIO_ASR = NCPS_ASR_BIT;
pPIOA->PIO_BSR = NPCS_BSR_BIT;
}
/*****************************************************************************/
void if_spiSetSpeed(euint8 speed)
{
euint32 reg;
AT91PS_SPI pSPI = AT91C_BASE_SPI;
if ( speed < SPI_SCBR_MIN ) speed = SPI_SCBR_MIN;
if ( speed > 1 ) speed &= 0xFE;
reg = pSPI->SPI_CSR[SPI_CSR_NUM];
reg = ( reg & ~(AT91C_SPI_SCBR) ) | ( (euint32)speed << 8 );
pSPI->SPI_CSR[SPI_CSR_NUM] = reg;
}
/*****************************************************************************/
euint8 if_spiSend(hwInterface *iface, euint8 outgoing)
{
euint8 incoming;
AT91PS_SPI pSPI = AT91C_BASE_SPI;
while( !( pSPI->SPI_SR & AT91C_SPI_TDRE ) ); // transfer compl. wait
#ifdef FIXED_PERIPH
pSPI->SPI_TDR = (euint16)( outgoing );
#else
pSPI->SPI_TDR = ( (euint16)(outgoing) | ((euint32)(SPI_TDR_PCS)<<16) );
#endif
while( !( pSPI->SPI_SR & AT91C_SPI_RDRF ) ); // wait for char
incoming = (euint8)( pSPI->SPI_RDR );
return incoming;
}
/*****************************************************************************/
esint8 if_readBuf(hwInterface* file,euint32 address,euint8* buf)
{
return(sd_readSector(file,address,buf,512));
}
/*****************************************************************************/
esint8 if_writeBuf(hwInterface* file, euint32 address, euint8* buf)
{
return( sd_writeSector(file, address, buf) );
}
/*****************************************************************************/
esint8 if_setPos(hwInterface* file,euint32 address)
{
return(0);
}
/*****************************************************************************/

View File

@@ -0,0 +1,110 @@
/*****************************************************************************\
* efs - General purpose Embedded Filesystem library *
* --------------------- ----------------------------------- *
* *
* Filename : atmega128.c *
* Description : This file contains the functions needed to use efs for *
* accessing files on an SD-card connected to an ATMega128. *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; version 2 *
* of the License. *
*
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* As a special exception, if other files instantiate templates or *
* use macros or inline functions from this file, or you compile this *
* file and link it with other works to produce a work based on this file, *
* this file does not by itself cause the resulting work to be covered *
* by the GNU General Public License. However the source code for this *
* file must still be made available in accordance with section (3) of *
* the GNU General Public License. *
* *
* This exception does not invalidate any other reasons why a work based *
* on this file might be covered by the GNU General Public License. *
* *
* (c)2006 Lennart Yseboodt *
* (c)2006 Michael De Nil *
\*****************************************************************************/
/*****************************************************************************/
#include "interfaces/atmega128.h"
#include "interfaces/sd.h"
/*****************************************************************************/
esint8 if_initInterface(hwInterface* file, eint8* opts)
{
if_spiInit(file);
if(sd_Init(file)<0) {
DBG((TXT("Card failed to init, breaking up...\n")));
return(-1);
}
if(sd_State(file)<0){
DBG((TXT("Card didn't return the ready state, breaking up...\n")));
return(-2);
}
file->sectorCount=4; /* FIXME ASAP!! */
DBG((TXT("Init done...\n")));
return(0);
}
/*****************************************************************************/
esint8 if_readBuf(hwInterface* file,euint32 address,euint8* buf)
{
return(sd_readSector(file,address,buf,512));
}
/*****************************************************************************/
esint8 if_writeBuf(hwInterface* file,euint32 address,euint8* buf)
{
return(sd_writeSector(file,address, buf));
}
/*****************************************************************************/
esint8 if_setPos(hwInterface* file,euint32 address)
{
return(0);
}
/*****************************************************************************/
void if_spiInit(hwInterface *iface)
{
euint8 i;
/* Unselect card */
PORTB |= 0x01;
/* Set as master, clock and chip select output */
DDR_SPI = (1<<DD_MOSI) | (1<<DD_SCK) | 1;
/* Enable SPI, master, set clock rate to fck/2 */
SPCR = (1<<SPE) | (1<<MSTR); /* fsck / 4 */
SPSR = 1; /* fsck / 2 */
/* Send 10 spi commands with card not selected */
for(i=0;i<10;i++)
if_spiSend(iface,0xff);
/* Select card */
PORTB &= 0xFE;
}
/*****************************************************************************/
euint8 if_spiSend(hwInterface *iface, euint8 outgoing)
{
euint8 incoming=0;
PORTB &= 0xFE;
SPDR = outgoing;
while(!(SPSR & (1<<SPIF)));
incoming = SPDR;
PORTB |= 0x01;
return(incoming);
}
/*****************************************************************************/

View File

@@ -0,0 +1,93 @@
/*****************************************************************************\
* efs - General purpose Embedded Filesystem library *
* --------------------- ----------------------------------- *
* *
* Filename : dsp67xx.c *
* Revision : Initial developement *
* Description : This file contains the functions needed to use efs for *
* accessing files on an SD-card connected to a TI 67 *
* series DSP. *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; version 2 *
* of the License. *
*
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* As a special exception, if other files instantiate templates or *
* use macros or inline functions from this file, or you compile this *
* file and link it with other works to produce a work based on this file, *
* this file does not by itself cause the resulting work to be covered *
* by the GNU General Public License. However the source code for this *
* file must still be made available in accordance with section (3) of *
* the GNU General Public License. *
* *
* This exception does not invalidate any other reasons why a work based *
* on this file might be covered by the GNU General Public License. *
* *
* (c)2006 Lennart Yseboodt *
* (c)2006 Michael De Nil *
\*****************************************************************************/
/*****************************************************************************/
#include "interfaces/dsp67xx.h"
#include "interfaces/sd.h"
#include <stdio.h>
/*****************************************************************************/
short if_initInterface(hwInterface* file, char* opts)
{
file->sectorCount=0;
return(if_spiInit(file));
}
/*****************************************************************************/
short if_writeBuf(hwInterface* file,unsigned long address,unsigned char* buf)
{
return(0);
}
/*****************************************************************************/
short if_setPos(hwInterface* file,unsigned long address)
{
return(0);
}
/*****************************************************************************/
signed char if_spiInit(hwInterface *iface)
{
return(sd_Init(iface));
}
/*****************************************************************************/
unsigned char if_spiSend(hwInterface *iface, euint8 outgoing)
{
unsigned char r;
/* while((*(unsigned volatile long*)McBSP0_SPCR & 0x20000)==0);
*(unsigned volatile char*)McBSP0_DXR=outgoing;
while(((*(unsigned volatile long*)McBSP0_SPCR & 0x2)==0));
r=*(unsigned volatile char*)McBSP0_DRR; */
while(!MCBSP_xrdy(iface->port->hBsp));
MCBSP_write(iface->port->hBsp,outgoing);
while(!MCBSP_rrdy(iface->port->hBsp));
r=MCBSP_read(iface->port->hBsp);
return(r);
}
/*****************************************************************************/
short if_readBuf(hwInterface* file,euint32 address,unsigned char* buf)
{
short r;
r=sd_readSector(file,address,buf,512);
if(r!=0)printf("ERROR READING SECTOR %i\n",address);
return(r);
}
/*****************************************************************************/

View File

@@ -0,0 +1,243 @@
//#########################################################################
// printf.c
//
// *** printf() based on sprintf() from gcctest9.c Volker Oth
//
// *** Changes made by Holger Klabunde
// Now takes format strings from FLASH (was into RAM ! before)
// Fixed bug for %i, %I. u_val was used before it had the right value
// Added %d, %D (is same as %i, %I)
// Support for long variables %li, %ld, %Lu, %LX ....
// %x, %X now gives upper case hex characters A,B,C,D,E,F
// Output can be redirected in a single function: myputchar()
// Make printf() smaller by commenting out a few #defines
// Added some SPACE and ZERO padding %02x or % 3u up to 9 characters
//
// Todo:
// %f, %F for floating point numbers
//
// *** Changes made by Martin Thomas for the efsl debug output:
// - removed AVR "progmem"
// - added function pointer for "putchar"
// - devopen function
//
//#########################################################################
#include <stdarg.h>
#include <string.h>
#include "interfaces/efsl_dbg_printf_arm.h"
#define SCRATCH 12 //32Bits go up to 4GB + 1 Byte for \0
//Spare some program space by making a comment of all not used format flag lines
#define USE_LONG // %lx, %Lu and so on, else only 16 bit integer is allowed
//#define USE_OCTAL // %o, %O Octal output. Who needs this ?
#define USE_STRING // %s, %S Strings as parameters
#define USE_CHAR // %c, %C Chars as parameters
#define USE_INTEGER // %i, %I Remove this format flag. %d, %D does the same
#define USE_HEX // %x, %X Hexadezimal output
#define USE_UPPERHEX // %x, %X outputs A,B,C... else a,b,c...
#ifndef USE_HEX
#undef USE_UPPERHEX // ;)
#endif
#define USE_UPPER // uncommenting this removes %C,%D,%I,%O,%S,%U,%X and %L..
// only lowercase format flags are used
#define PADDING //SPACE and ZERO padding
static int (*putcharfunc)(int c);
void efsl_debug_devopen_arm( int(*put)(int) )
{
putcharfunc = put;
}
static void myputchar(unsigned char c)
{
if(c == '\n') putcharfunc('\r');
putcharfunc(c);
}
void efsl_debug_printf_arm(char const *format, ...)
{
unsigned char scratch[SCRATCH];
unsigned char format_flag;
unsigned short base;
unsigned char *ptr;
unsigned char issigned=0;
va_list ap;
#ifdef USE_LONG
unsigned char islong=0;
unsigned long u_val=0;
long s_val=0;
#else
unsigned int u_val=0;
int s_val=0;
#endif
unsigned char fill;
unsigned char width;
va_start (ap, format);
for (;;){
while ((format_flag = *(format++)) != '%'){ // Until '%' or '\0'
if (!format_flag){va_end (ap); return;}
myputchar(format_flag);
}
issigned=0; //default unsigned
base = 10;
format_flag = *format++; //get char after '%'
#ifdef PADDING
width=0; //no formatting
fill=0; //no formatting
if(format_flag=='0' || format_flag==' ') //SPACE or ZERO padding ?
{
fill=format_flag;
format_flag = *format++; //get char after padding char
if(format_flag>='0' && format_flag<='9')
{
width=format_flag-'0';
format_flag = *format++; //get char after width char
}
}
#endif
#ifdef USE_LONG
islong=0; //default int value
#ifdef USE_UPPER
if(format_flag=='l' || format_flag=='L') //Long value
#else
if(format_flag=='l') //Long value
#endif
{
islong=1;
format_flag = *format++; //get char after 'l' or 'L'
}
#endif
switch (format_flag)
{
#ifdef USE_CHAR
case 'c':
#ifdef USE_UPPER
case 'C':
#endif
format_flag = va_arg(ap,int);
// no break -> run into default
#endif
default:
myputchar(format_flag);
continue;
#ifdef USE_STRING
#ifdef USE_UPPER
case 'S':
#endif
case 's':
ptr = (unsigned char*)va_arg(ap,char *);
while(*ptr) { myputchar(*ptr); ptr++; }
continue;
#endif
#ifdef USE_OCTAL
case 'o':
#ifdef USE_UPPER
case 'O':
#endif
base = 8;
myputchar('0');
goto CONVERSION_LOOP;
#endif
#ifdef USE_INTEGER //don't use %i, is same as %d
case 'i':
#ifdef USE_UPPER
case 'I':
#endif
#endif
case 'd':
#ifdef USE_UPPER
case 'D':
#endif
issigned=1;
// no break -> run into next case
case 'u':
#ifdef USE_UPPER
case 'U':
#endif
//don't insert some case below this if USE_HEX is undefined !
//or put goto CONVERSION_LOOP; before next case.
#ifdef USE_HEX
goto CONVERSION_LOOP;
case 'x':
#ifdef USE_UPPER
case 'X':
#endif
base = 16;
#endif
CONVERSION_LOOP:
if(issigned) //Signed types
{
#ifdef USE_LONG
if(islong) { s_val = va_arg(ap,long); }
else { s_val = va_arg(ap,int); }
#else
s_val = va_arg(ap,int);
#endif
if(s_val < 0) //Value negativ ?
{
s_val = - s_val; //Make it positiv
myputchar('-'); //Output sign
}
u_val = (unsigned long)s_val;
}
else //Unsigned types
{
#ifdef USE_LONG
if(islong) { u_val = va_arg(ap,unsigned long); }
else { u_val = va_arg(ap,unsigned int); }
#else
u_val = va_arg(ap,unsigned int);
#endif
}
ptr = scratch + SCRATCH;
*--ptr = 0;
do
{
char ch = u_val % base + '0';
#ifdef USE_HEX
if (ch > '9')
{
ch += 'a' - '9' - 1;
#ifdef USE_UPPERHEX
ch-=0x20;
#endif
}
#endif
*--ptr = ch;
u_val /= base;
#ifdef PADDING
if(width) width--; //calculate number of padding chars
#endif
} while (u_val);
#ifdef PADDING
while(width--) *--ptr = fill; //insert padding chars
#endif
while(*ptr) { myputchar(*ptr); ptr++; }
}
}
}

View File

@@ -0,0 +1,94 @@
/*****************************************************************************\
* efs - General purpose Embedded Filesystem library *
* --------------------- ----------------------------------- *
* *
* Filename : helper.c *
* Description : These functions may NOT BE USED ANYWHERE ! They are helper *
* functions for the Linux based developement. They use the GNU *
* C library and headers. *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; version 2 *
* of the License. *
*
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* As a special exception, if other files instantiate templates or *
* use macros or inline functions from this file, or you compile this *
* file and link it with other works to produce a work based on this file, *
* this file does not by itself cause the resulting work to be covered *
* by the GNU General Public License. However the source code for this *
* file must still be made available in accordance with section (3) of *
* the GNU General Public License. *
* *
* This exception does not invalidate any other reasons why a work based *
* on this file might be covered by the GNU General Public License. *
* *
* (c)2006 Lennart Yseboodt *
* (c)2006 Michael De Nil *
\*****************************************************************************/
#include "interfaces/helper.h"
void* Malloc(eint32 size)
{
void*x;
if((x=malloc(size))==NULL){
perror("Malloc: ");
exit(-1);
}
return(x);
}
void Fopen(FILE **f,eint8* filename)
{
*f=fopen(filename,"r+");
if(*f==NULL){
perror("Fopen: ");
exit(-1);
}
}
void MMap(eint8* filename,void**x,eint32 *size)
{
FILE *tmp;
eint32 filesize,c;
Fopen(&tmp,filename);
filesize=getFileSize(tmp);
*x=Malloc(filesize);
for(c=0;c<filesize;c++)*((char*)(*x)+c)=fgetc(tmp);
*size=filesize;
fclose(tmp);
}
int getFileSize(FILE* file)
{
eint32 c=0;
fseek(file,0,SEEK_END);
c=ftell(file);
return(c);
}
void PrintBuf(euint8* buf)
{
euint16 c,cc;
for(c=0 ; c<32 ; c++){
printf("\n%4x : ",c*16);
for(cc=0;cc<16;cc++){
printf("%2x ",buf[c*16+cc]);
}
printf(" ");
for(cc=0;cc<16;cc++){
printf("%c",buf[c*16+cc]>=32?buf[c*16+cc]:'*');
}
}
printf("\n");
}

View File

@@ -0,0 +1,112 @@
/*****************************************************************************\
* efs - General purpose Embedded Filesystem library *
* --------------------- ----------------------------------- *
* *
* Filename : linuxfile.c *
* Description : This file contains the functions needed to use efs for *
* accessing files under linux. This interface is meant *
* to be used for debugging purposes. *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; version 2 *
* of the License. *
*
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* As a special exception, if other files instantiate templates or *
* use macros or inline functions from this file, or you compile this *
* file and link it with other works to produce a work based on this file, *
* this file does not by itself cause the resulting work to be covered *
* by the GNU General Public License. However the source code for this *
* file must still be made available in accordance with section (3) of *
* the GNU General Public License. *
* *
* This exception does not invalidate any other reasons why a work based *
* on this file might be covered by the GNU General Public License. *
* *
* (c)2006 Lennart Yseboodt *
* (c)2006 Michael De Nil *
\*****************************************************************************/
/*****************************************************************************/
#include "interfaces/linuxfile.h"
/*****************************************************************************/
/* ****************************************************************************
* short if_initInterface(hwInterface* file, char* fileName)
* Description: This function should bring the hardware described in file in a
* ready state to receive and retrieve data.
* Return value: Return 0 on succes and -1 on failure.
*/
esint8 if_initInterface(hwInterface* file, eint8* fileName)
{
eint32 sc;
Fopen(&(file->imageFile),fileName);
sc=getFileSize(file->imageFile);
file->sectorCount=sc/512;
file->readCount=file->writeCount=0;
if(sc%512!=0)
file->sectorCount--;
return(0);
}
/*****************************************************************************/
/* ****************************************************************************
* short if_readBuf(hwInterface* file,unsigned long address,unsigned char* buf)
* Description: This function should fill the characterpointer buf with 512
* bytes, offset by address*512 bytes. Adress is thus a LBA address.
* Return value: Return 0 on success and -1 on failure.
*/
esint8 if_readBuf(hwInterface* file,euint32 address,euint8* buf)
{
/*printf("READ %li\n",address);*/
if(if_setPos(file,address))return(-1);
if( fread((void*)buf,512,1,file->imageFile) != 1) return(-1);
file->readCount++;
return(0);
}
/*****************************************************************************/
/* ****************************************************************************
* short if_writeBuf(hwInterface* file,unsigned long address,unsigned char* buf)
* Description: This function writes 512 bytes from uchar* buf to the hardware
* disc described in file. The write offset should be address sectors of 512 bytes.
* Return value: Return 0 on success and -1 on failure.
*/
esint8 if_writeBuf(hwInterface* file,euint32 address,euint8* buf)
{
/*printf("WRITE %li\n",address);*/
if_setPos(file,address);
if((fwrite((void*)buf,512,1,file->imageFile))!=1){
perror("cf_writeBuf:");
exit(-1);
}
fflush(file->imageFile);
file->writeCount++;
return(0);
}
/*****************************************************************************/
/* ****************************************************************************
* short if_setPos(hwInterface* file,unsigned long address)
* Description: This function may or may not be required. It would set the write
* or read buffer offset by 512*address bytes from the beginning of the disc.
* Return value: Return 0 on success and -1 on failure.
*/
esint8 if_setPos(hwInterface* file,euint32 address)
{
if(address>(file->sectorCount-1)){
DBG((TXT("Illegal address\n")));
exit(-1);
}
if((fseek(file->imageFile,512*address,SEEK_SET))!=0){
perror("cf_setPos:");
exit(-1);
}
return(0);
}
/*****************************************************************************/

View File

@@ -0,0 +1,291 @@
/*****************************************************************************\
* efs - General purpose Embedded Filesystem library *
* --------------------- ----------------------------------- *
* *
* Filename : lpc2000_spi.c *
* Description : This file contains the functions needed to use efs for *
* accessing files on an SD-card connected to an LPC2xxx. *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; version 2 *
* of the License. *
*
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* As a special exception, if other files instantiate templates or *
* use macros or inline functions from this file, or you compile this *
* file and link it with other works to produce a work based on this file, *
* this file does not by itself cause the resulting work to be covered *
* by the GNU General Public License. However the source code for this *
* file must still be made available in accordance with section (3) of *
* the GNU General Public License. *
* *
* This exception does not invalidate any other reasons why a work based *
* on this file might be covered by the GNU General Public License. *
* *
* (c)2005 Martin Thomas *
\*****************************************************************************/
/*****************************************************************************/
#include "interfaces/LPC2000_regs.h"
#include "interfaces/arm_spi.h"
#include "interfaces/sd.h"
#include "config.h"
/*****************************************************************************/
#ifndef HW_ENDPOINT_LPC2000_SPINUM
#error "HW_ENDPOINT_LPC2000_SPINUM has to be defined in config.h"
#endif
#if ( HW_ENDPOINT_LPC2000_SPINUM == 0 )
// LPC213x ### SPI0 ###
// SP0SPCR Bit-Definitions
#define CPHA 3
#define CPOL 4
#define MSTR 5
// SP0SPSR Bit-Definitions
#define SPIF 7
#define SPI_IODIR IODIR0
#define SPI_SCK_PIN 4 /* Clock P0.4 out */
#define SPI_MISO_PIN 5 /* from Card P0.5 in */
#define SPI_MOSI_PIN 6 /* to Card P0.6 out */
#define SPI_SS_PIN 7 /* Card-Select P0.7 - GPIO out */
#define SPI_PINSEL PINSEL0
#define SPI_SCK_FUNCBIT 8
#define SPI_MISO_FUNCBIT 10
#define SPI_MOSI_FUNCBIT 12
#define SPI_SS_FUNCBIT 14
#define SPI_PRESCALE_REG S0SPCCR
#define SPI_PRESCALE_MIN 8
#define SELECT_CARD() IOCLR0 = (1<<SPI_SS_PIN)
#define UNSELECT_CARD() IOSET0 = (1<<SPI_SS_PIN)
#elif ( HW_ENDPOINT_LPC2000_SPINUM == 1 )
// LPC213x ### SSP ### ("SPI1")
// SSPCR0 Bit-Definitions
#define CPOL 6
#define CPHA 7
// SSPCR1 Bit-Defintions
#define SSE 1
#define MS 2
#define SCR 8
// SSPSR Bit-Definitions
#define TNF 1
#define RNE 2
#define BSY 4
#define SPI_IODIR IODIR0
#define SPI_SCK_PIN 17 /* Clock P0.17 out */
#define SPI_MISO_PIN 18 /* from Card P0.18 in */
#define SPI_MOSI_PIN 19 /* to Card P0.19 out */
/* Card-Select P0.20 - GPIO out during startup
Function 03 during normal operation */
#define SPI_SS_PIN 20
#define SPI_PINSEL PINSEL1
#define SPI_SCK_FUNCBIT 2
#define SPI_MISO_FUNCBIT 4
#define SPI_MOSI_FUNCBIT 6
#define SPI_SS_FUNCBIT 8
#define SPI_PRESCALE_REG SSPCPSR
/// TODO: too fast on prototyp wires #define SPI_PRESCALE_MIN 2
#define SPI_PRESCALE_MIN 4
/* only needed during init: */
#define SELECT_CARD() IOCLR0 = (1<<SPI_SS_PIN)
#define UNSELECT_CARD() IOSET0 = (1<<SPI_SS_PIN)
#else
#error "Invalid Interface-Number"
#endif
esint8 if_initInterface(hwInterface* file, eint8* opts)
{
euint32 sc;
if_spiInit(file); /* init at low speed */
if(sd_Init(file)<0) {
DBG((TXT("Card failed to init, breaking up...\n")));
return(-1);
}
if(sd_State(file)<0){
DBG((TXT("Card didn't return the ready state, breaking up...\n")));
return(-2);
}
// file->sectorCount=4; /* FIXME ASAP!! */
sd_getDriveSize(file, &sc);
file->sectorCount = sc/512;
if( (sc%512) != 0) {
file->sectorCount--;
}
DBG((TXT("Drive Size is %lu Bytes (%lu Sectors)\n"), sc, file->sectorCount));
/* increase speed after init */
#if ( HW_ENDPOINT_LPC2000_SPINUM == 1 )
SSPCR0 = ((8-1)<<0) | (0<<CPOL);
#endif
if_spiSetSpeed(SPI_PRESCALE_MIN);
// if_spiSetSpeed(100); /* debug - slower */
DBG((TXT("Init done...\n")));
return(0);
}
/*****************************************************************************/
esint8 if_readBuf(hwInterface* file,euint32 address,euint8* buf)
{
return(sd_readSector(file,address,buf,512));
}
/*****************************************************************************/
esint8 if_writeBuf(hwInterface* file,euint32 address,euint8* buf)
{
return(sd_writeSector(file,address, buf));
}
/*****************************************************************************/
esint8 if_setPos(hwInterface* file,euint32 address)
{
return(0);
}
/*****************************************************************************/
// Utility-functions which does not toogle CS.
// Only needed during card-init. During init
// the automatic chip-select is disabled for SSP
static euint8 my_if_spiSend(hwInterface *iface, euint8 outgoing)
{
euint8 incoming;
// SELECT_CARD(); // not here!
#if ( HW_ENDPOINT_LPC2000_SPINUM == 0 )
S0SPDR = outgoing;
while( !(S0SPSR & (1<<SPIF)) ) ;
incoming = S0SPDR;
#endif
#if ( HW_ENDPOINT_LPC2000_SPINUM == 1 )
while( !(SSPSR & (1<<TNF)) ) ;
SSPDR = outgoing;
while( !(SSPSR & (1<<RNE)) ) ;
incoming = SSPDR;
#endif
// UNSELECT_CARD(); // not here!
return(incoming);
}
/*****************************************************************************/
void if_spiInit(hwInterface *iface)
{
euint8 i;
// setup GPIO
SPI_IODIR |= (1<<SPI_SCK_PIN)|(1<<SPI_MOSI_PIN)|(1<<SPI_SS_PIN);
SPI_IODIR &= ~(1<<SPI_MISO_PIN);
// set Chip-Select high - unselect card
UNSELECT_CARD();
// reset Pin-Functions
SPI_PINSEL &= ~( (3<<SPI_SCK_FUNCBIT) | (3<<SPI_MISO_FUNCBIT) |
(3<<SPI_MOSI_FUNCBIT) | (3<<SPI_SS_FUNCBIT) );
#if ( HW_ENDPOINT_LPC2000_SPINUM == 0 )
DBG((TXT("spiInit for SPI(0)\n")));
SPI_PINSEL |= ( (1<<SPI_SCK_FUNCBIT) | (1<<SPI_MISO_FUNCBIT) |
(1<<SPI_MOSI_FUNCBIT) );
// enable SPI-Master
S0SPCR = (1<<MSTR)|(0<<CPOL); // TODO: check CPOL
#endif
#if ( HW_ENDPOINT_LPC2000_SPINUM == 1 )
DBG((TXT("spiInit for SSP/SPI1\n")));
// setup Pin-Functions - keep automatic CS disabled during init
SPI_PINSEL |= ( (2<<SPI_SCK_FUNCBIT) | (2<<SPI_MISO_FUNCBIT) |
(2<<SPI_MOSI_FUNCBIT) | (0<<SPI_SS_FUNCBIT) );
// enable SPI-Master - slowest speed
SSPCR0 = ((8-1)<<0) | (0<<CPOL) | (0x20<<SCR); // (0xff<<SCR);
SSPCR1 = (1<<SSE);
#endif
// low speed during init
if_spiSetSpeed(254);
/* Send 20 spi commands with card not selected */
for(i=0;i<21;i++)
my_if_spiSend(iface,0xff);
#if ( HW_ENDPOINT_LPC2000_SPINUM == 0 )
// SPI0 does not offer automatic CS for slaves on LPC2138
// ( the SSEL-Pin is input-only )
// SELECT_CARD();
#endif
#if ( HW_ENDPOINT_LPC2000_SPINUM == 1 )
// enable automatic slave CS for SSP
SSPCR1 &= ~(1<<SSE); // disable interface
SPI_PINSEL |= ( (2<<SPI_SCK_FUNCBIT) | (2<<SPI_MISO_FUNCBIT) |
(2<<SPI_MOSI_FUNCBIT) | (2<<SPI_SS_FUNCBIT) );
SSPCR1 |= (1<<SSE); // enable interface
#endif
}
/*****************************************************************************/
void if_spiSetSpeed(euint8 speed)
{
speed &= 0xFE;
if ( speed < SPI_PRESCALE_MIN ) speed = SPI_PRESCALE_MIN ;
SPI_PRESCALE_REG = speed;
}
/*****************************************************************************/
euint8 if_spiSend(hwInterface *iface, euint8 outgoing)
{
euint8 incoming;
#if ( HW_ENDPOINT_LPC2000_SPINUM == 0 )
SELECT_CARD();
S0SPDR = outgoing;
while( !(S0SPSR & (1<<SPIF)) ) ;
incoming = S0SPDR;
UNSELECT_CARD();
#endif
#if ( HW_ENDPOINT_LPC2000_SPINUM == 1 )
// SELECT_CARD(); // done by hardware
while( !(SSPSR & (1<<TNF)) ) ;
SSPDR = outgoing;
while( !(SSPSR & (1<<RNE)) ) ;
incoming = SSPDR;
// UNSELECT_CARD(); // done by hardware
#endif
return(incoming);
}
/*****************************************************************************/

View File

@@ -0,0 +1,124 @@
/*****************************************************************************\
* efs - General purpose Embedded Filesystem library *
* --------------------- ----------------------------------- *
* *
* Filename : nios2.c *
* Description : This file contains the functions needed to use efs for *
* accessing files on an SD-card connected to an Altera FPGA *
* running on NIOS2. *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; version 2 *
* of the License. *
*
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* As a special exception, if other files instantiate templates or *
* use macros or inline functions from this file, or you compile this *
* file and link it with other works to produce a work based on this file, *
* this file does not by itself cause the resulting work to be covered *
* by the GNU General Public License. However the source code for this *
* file must still be made available in accordance with section (3) of *
* the GNU General Public License. *
* *
* This exception does not invalidate any other reasons why a work based *
* on this file might be covered by the GNU General Public License. *
* *
* (c)2005 Marcio Troccoli *
\*****************************************************************************/
/*****************************************************************************/
#include "interfaces/nios2.h"
#include "interfaces/sd.h"
#include "altera_avalon_spi_regs.h"
#include "altera_avalon_spi.h"
#include "system.h"
/*****************************************************************************/
esint8 if_initInterface(hwInterface* file, eint8* opts)
{
if_spiInit(file);
if(sd_Init(file)<0) {
DBG((TXT("Card failed to init, breaking up...\n")));
return(-1);
}
if(sd_State(file)<0){
DBG((TXT("Card didn't return the ready state, breaking up...\n")));
return(-2);
}
file->sectorCount=4; /* FIXME ASAP!! */
DBG((TXT("Init done...\n")));
return(0);
}
/*****************************************************************************/
esint8 if_readBuf(hwInterface* file,euint32 address,euint8* buf)
{
return(sd_readSector(file,address,buf,512));
}
/*****************************************************************************/
esint8 if_writeBuf(hwInterface* file,euint32 address,euint8* buf)
{
return(sd_writeSector(file,address, buf));
}
/*****************************************************************************/
esint8 if_setPos(hwInterface* file,euint32 address)
{
return(0);
}
/*****************************************************************************/
void if_spiInit(hwInterface *iface)
{
euint8 i;
printf("\n spi ini");
}
/*****************************************************************************/
euint8 if_spiSend(hwInterface *iface, euint8 outgoing)
{
euint8 incoming=0;
alt_u8 SD_Data=0,status;
IOWR_ALTERA_AVALON_SPI_SLAVE_SEL(SD_SPI_BASE, 1 );
/* Set the SSO bit (force chipselect) */
IOWR_ALTERA_AVALON_SPI_CONTROL(SD_SPI_BASE, 0x400);
do{
status = IORD_ALTERA_AVALON_SPI_STATUS(SD_SPI_BASE);//get status
}while (((status & ALTERA_AVALON_SPI_STATUS_TRDY_MSK) == 0 ) &&
(status & ALTERA_AVALON_SPI_STATUS_RRDY_MSK) == 0);
/* wait till transmit and ready ok */
IOWR_ALTERA_AVALON_SPI_TXDATA(SD_SPI_BASE, outgoing);
/* Wait until the interface has finished transmitting */
do{status = IORD_ALTERA_AVALON_SPI_STATUS(SD_SPI_BASE);}
while ((status & ALTERA_AVALON_SPI_STATUS_TMT_MSK) == 0);
/* reciver ready */
if (((status & 0x80) != 0) ){
SD_Data = IORD_ALTERA_AVALON_SPI_RXDATA(SD_SPI_BASE);
}
else{
printf("\n no recive after transmit");
}
IOWR_ALTERA_AVALON_SPI_SLAVE_SEL(SD_SPI_BASE, 1);
IOWR_ALTERA_AVALON_SPI_CONTROL(SD_SPI_BASE, 0);
if( (status & 0x100) !=0)
printf("\n error in spi error in spi");
return (SD_Data);
}
/*****************************************************************************/

View File

@@ -0,0 +1,350 @@
/*****************************************************************************\
* efs - General purpose Embedded Filesystem library *
* --------------------- ----------------------------------- *
* *
* Filename : sd.c *
* Revision : Initial developement *
* Description : This file contains the functions needed to use efs for *
* accessing files on an SD-card. *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; version 2 *
* of the License. *
*
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* As a special exception, if other files instantiate templates or *
* use macros or inline functions from this file, or you compile this *
* file and link it with other works to produce a work based on this file, *
* this file does not by itself cause the resulting work to be covered *
* by the GNU General Public License. However the source code for this *
* file must still be made available in accordance with section (3) of *
* the GNU General Public License. *
* *
* This exception does not invalidate any other reasons why a work based *
* on this file might be covered by the GNU General Public License. *
* *
* (c)2006 Lennart Yseboodt *
* (c)2006 Michael De Nil *
* *
* in Driver-Size: use if_spiSend instead for sd_Resp8b as proposed in *
* sf.net bug-tracker (applied by mthomas) *
\*****************************************************************************/
/*****************************************************************************/
#include "interfaces/sd.h"
/*****************************************************************************/
esint8 sd_Init(hwInterface *iface)
{
esint16 i;
euint8 resp;
/* Try to send reset command up to 100 times */
i=100;
do {
sd_Command(iface, 0, 0, 0);
resp=sd_Resp8b(iface);
}
while(resp!=1 && i--);
if(resp!=1){
DBG((TXT("CMD0 fail.\n")));
if(resp==0xff){
return(-1);
}
else{
sd_Resp8bError(iface,resp);
return(-2);
}
}
/* Wait till card is ready initialising (returns 0 on CMD1) */
/* Try up to 32000 times. */
i=32000;
do{
sd_Command(iface,1, 0, 0);
resp=sd_Resp8b(iface);
if(resp!=0)
sd_Resp8bError(iface,resp);
}
while(resp==1 && i--);
if(resp!=0){
sd_Resp8bError(iface,resp);
return(-3);
}
return(0);
}
/*****************************************************************************/
void sd_Command(hwInterface *iface,euint8 cmd, euint16 paramx, euint16 paramy)
{
if_spiSend(iface,0xff);
if_spiSend(iface,0x40 | cmd);
if_spiSend(iface,(euint8) (paramx >> 8)); /* MSB of parameter x */
if_spiSend(iface,(euint8) (paramx)); /* LSB of parameter x */
if_spiSend(iface,(euint8) (paramy >> 8)); /* MSB of parameter y */
if_spiSend(iface,(euint8) (paramy)); /* LSB of parameter y */
if_spiSend(iface,0x95); /* Checksum (should be only valid for first command (0) */
if_spiSend(iface,0xff); /* eat empty command - response */
}
/*****************************************************************************/
euint8 sd_Resp8b(hwInterface *iface)
{
euint8 i;
euint8 resp;
/* Respone will come after 1 - 8 pings */
for ( i=0; i<8; i++ ) {
resp = if_spiSend(iface,0xff);
if(resp != 0xff)
return(resp);
}
return(resp);
}
/*****************************************************************************/
euint16 sd_Resp16b(hwInterface *iface)
{
euint16 resp;
resp = ( sd_Resp8b(iface) << 8 ) & 0xff00;
resp |= if_spiSend(iface,0xff);
return(resp);
}
/*****************************************************************************/
void sd_Resp8bError(hwInterface *iface,euint8 value)
{
switch(value)
{
case 0x40:
DBG((TXT("Argument out of bounds.\n")));
break;
case 0x20:
DBG((TXT("Address out of bounds.\n")));
break;
case 0x10:
DBG((TXT("Error during erase sequence.\n")));
break;
case 0x08:
DBG((TXT("CRC failed.\n")));
break;
case 0x04:
DBG((TXT("Illegal command.\n")));
break;
case 0x02:
DBG((TXT("Erase reset (see SanDisk docs p5-13).\n")));
break;
case 0x01:
DBG((TXT("Card is initialising.\n")));
break;
default:
DBG((TXT("Unknown error 0x%x (see SanDisk docs p5-13).\n"),value));
break;
}
}
/*****************************************************************************/
esint8 sd_State(hwInterface *iface)
{
eint16 value;
sd_Command(iface,13, 0, 0);
value=sd_Resp16b(iface);
switch(value)
{
case 0x000:
return(1);
break;
case 0x0001:
DBG((TXT("Card is Locked.\n")));
break;
case 0x0002:
DBG((TXT("WP Erase Skip, Lock/Unlock Cmd Failed.\n")));
break;
case 0x0004:
DBG((TXT("General / Unknown error -- card broken?.\n")));
break;
case 0x0008:
DBG((TXT("Internal card controller error.\n")));
break;
case 0x0010:
DBG((TXT("Card internal ECC was applied, but failed to correct the data.\n")));
break;
case 0x0020:
DBG((TXT("Write protect violation.\n")));
break;
case 0x0040:
DBG((TXT("An invalid selection, sectors for erase.\n")));
break;
case 0x0080:
DBG((TXT("Out of Range, CSD_Overwrite.\n")));
break;
default:
if(value>0x00FF)
sd_Resp8bError(iface,(euint8) (value>>8));
else
DBG((TXT("Unknown error: 0x%x (see SanDisk docs p5-14).\n"),value));
break;
}
return(-1);
}
/*****************************************************************************/
/* ****************************************************************************
* WAIT ?? -- FIXME
* CMDWRITE
* WAIT
* CARD RESP
* WAIT
* DATA BLOCK OUT
* START BLOCK
* DATA
* CHKS (2B)
* BUSY...
*/
esint8 sd_writeSector(hwInterface *iface,euint32 address, euint8* buf)
{
euint32 place;
euint16 i;
euint16 t=0;
/*DBG((TXT("Trying to write %u to sector %u.\n"),(void *)&buf,address));*/
place=512*address;
sd_Command(iface,CMDWRITE, (euint16) (place >> 16), (euint16) place);
sd_Resp8b(iface); /* Card response */
if_spiSend(iface,0xfe); /* Start block */
for(i=0;i<512;i++)
if_spiSend(iface,buf[i]); /* Send data */
if_spiSend(iface,0xff); /* Checksum part 1 */
if_spiSend(iface,0xff); /* Checksum part 2 */
if_spiSend(iface,0xff);
while(if_spiSend(iface,0xff)!=0xff){
t++;
/* Removed NOP */
}
/*DBG((TXT("Nopp'ed %u times.\n"),t));*/
return(0);
}
/*****************************************************************************/
/* ****************************************************************************
* WAIT ?? -- FIXME
* CMDCMD
* WAIT
* CARD RESP
* WAIT
* DATA BLOCK IN
* START BLOCK
* DATA
* CHKS (2B)
*/
esint8 sd_readSector(hwInterface *iface,euint32 address, euint8* buf, euint16 len)
{
euint8 cardresp;
euint8 firstblock;
euint8 c;
euint16 fb_timeout=0xffff;
euint32 i;
euint32 place;
/*DBG((TXT("sd_readSector::Trying to read sector %u and store it at %p.\n"),address,&buf[0]));*/
place=512*address;
sd_Command(iface,CMDREAD, (euint16) (place >> 16), (euint16) place);
cardresp=sd_Resp8b(iface); /* Card response */
/* Wait for startblock */
do
firstblock=sd_Resp8b(iface);
while(firstblock==0xff && fb_timeout--);
if(cardresp!=0x00 || firstblock!=0xfe){
sd_Resp8bError(iface,firstblock);
return(-1);
}
for(i=0;i<512;i++){
c = if_spiSend(iface,0xff);
if(i<len)
buf[i] = c;
}
/* Checksum (2 byte) - ignore for now */
if_spiSend(iface,0xff);
if_spiSend(iface,0xff);
return(0);
}
/*****************************************************************************/
/* ****************************************************************************
calculates size of card from CSD
(extension by Martin Thomas, inspired by code from Holger Klabunde)
*/
esint8 sd_getDriveSize(hwInterface *iface, euint32* drive_size )
{
euint8 cardresp, i, by;
euint8 iob[16];
euint16 c_size, c_size_mult, read_bl_len;
sd_Command(iface, CMDREADCSD, 0, 0);
do {
cardresp = sd_Resp8b(iface);
} while ( cardresp != 0xFE );
DBG((TXT("CSD:")));
for( i=0; i<16; i++) {
#warning "inofficial CSD-read patch active sd_Resp8b->if_spiSend"
/* iob[i] = sd_Resp8b(iface); */
iob[i] = if_spiSend(iface,0xff);
DBG((TXT(" %02x"), iob[i]));
}
DBG((TXT("\n")));
if_spiSend(iface,0xff);
if_spiSend(iface,0xff);
c_size = iob[6] & 0x03; // bits 1..0
c_size <<= 10;
c_size += (euint16)iob[7]<<2;
c_size += iob[8]>>6;
by= iob[5] & 0x0F;
read_bl_len = 1;
read_bl_len <<= by;
by=iob[9] & 0x03;
by <<= 1;
by += iob[10] >> 7;
c_size_mult = 1;
c_size_mult <<= (2+by);
*drive_size = (euint32)(c_size+1) * (euint32)c_size_mult * (euint32)read_bl_len;
return 0;
}