o add fat filesystem test for arm lpc2148
This commit is contained in:
270
poc/lpc2148_efsl/src/interfaces/at91_spi.c
Normal file
270
poc/lpc2148_efsl/src/interfaces/at91_spi.c
Normal 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);
|
||||
}
|
||||
/*****************************************************************************/
|
||||
110
poc/lpc2148_efsl/src/interfaces/atmega128.c
Normal file
110
poc/lpc2148_efsl/src/interfaces/atmega128.c
Normal 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);
|
||||
}
|
||||
/*****************************************************************************/
|
||||
|
||||
93
poc/lpc2148_efsl/src/interfaces/dsp67xx.c
Normal file
93
poc/lpc2148_efsl/src/interfaces/dsp67xx.c
Normal 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);
|
||||
}
|
||||
/*****************************************************************************/
|
||||
|
||||
243
poc/lpc2148_efsl/src/interfaces/efsl_dbg_printf_arm.c
Normal file
243
poc/lpc2148_efsl/src/interfaces/efsl_dbg_printf_arm.c
Normal 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++; }
|
||||
}
|
||||
}
|
||||
}
|
||||
94
poc/lpc2148_efsl/src/interfaces/helper.c
Normal file
94
poc/lpc2148_efsl/src/interfaces/helper.c
Normal 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");
|
||||
}
|
||||
112
poc/lpc2148_efsl/src/interfaces/linuxfile.c
Normal file
112
poc/lpc2148_efsl/src/interfaces/linuxfile.c
Normal 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);
|
||||
}
|
||||
/*****************************************************************************/
|
||||
|
||||
291
poc/lpc2148_efsl/src/interfaces/lpc2000_spi.c
Normal file
291
poc/lpc2148_efsl/src/interfaces/lpc2000_spi.c
Normal 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);
|
||||
}
|
||||
/*****************************************************************************/
|
||||
|
||||
124
poc/lpc2148_efsl/src/interfaces/nios2.c
Normal file
124
poc/lpc2148_efsl/src/interfaces/nios2.c
Normal 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);
|
||||
}
|
||||
/*****************************************************************************/
|
||||
|
||||
350
poc/lpc2148_efsl/src/interfaces/sd.c
Normal file
350
poc/lpc2148_efsl/src/interfaces/sd.c
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user