Remove the .bak files that were accidentally added to the repository.
parent
61dacf99ab
commit
06c89adf1e
@ -1,772 +0,0 @@
|
||||
/* Based on MMCv3/SDv1/SDv2 (in SPI mode) control module (C)ChaN, 2009
|
||||
Modifications (C) 2010 Real Time Engineers ltd. */
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "diskio.h"
|
||||
|
||||
void disk_init_spi( void );
|
||||
|
||||
/* Definitions for MMC/SDC command */
|
||||
#define CMD0 ( 0x40 + 0 ) /* GO_IDLE_STATE */
|
||||
#define CMD1 ( 0x40 + 1 ) /* SEND_OP_COND (MMC) */
|
||||
#define ACMD41 ( 0xC0 + 41 ) /* SEND_OP_COND (SDC) */
|
||||
#define CMD8 ( 0x40 + 8 ) /* SEND_IF_COND */
|
||||
#define CMD9 ( 0x40 + 9 ) /* SEND_CSD */
|
||||
#define CMD10 ( 0x40 + 10 ) /* SEND_CID */
|
||||
#define CMD12 ( 0x40 + 12 ) /* STOP_TRANSMISSION */
|
||||
#define ACMD13 ( 0xC0 + 13 ) /* SD_STATUS (SDC) */
|
||||
#define CMD16 ( 0x40 + 16 ) /* SET_BLOCKLEN */
|
||||
#define CMD17 ( 0x40 + 17 ) /* READ_SINGLE_BLOCK */
|
||||
#define CMD18 ( 0x40 + 18 ) /* READ_MULTIPLE_BLOCK */
|
||||
#define CMD23 ( 0x40 + 23 ) /* SET_BLOCK_COUNT (MMC) */
|
||||
#define ACMD23 ( 0xC0 + 23 ) /* SET_WR_BLK_ERASE_COUNT (SDC) */
|
||||
#define CMD24 ( 0x40 + 24 ) /* WRITE_BLOCK */
|
||||
#define CMD25 ( 0x40 + 25 ) /* WRITE_MULTIPLE_BLOCK */
|
||||
#define CMD55 ( 0x40 + 55 ) /* APP_CMD */
|
||||
#define CMD58 ( 0x40 + 58 ) /* READ_OCR */
|
||||
|
||||
/* Port Controls (Platform dependent) */
|
||||
#define CS_LOW() GPIO0->FIOCLR = ( 1 << 16 ) /* MMC CS = L */
|
||||
#define CS_HIGH() GPIO0->FIOSET = ( 1 << 16 ) /* MMC CS = H */
|
||||
|
||||
#define SOCKWP ( 0 ) /* Write protect switch. */
|
||||
#define SOCKINS ( 1 << 29 ) /* Card detect switch. */
|
||||
#define SOCKPORT ( GPIO4->FIOPIN )
|
||||
#define FCLK_SLOW() /* Set slow clock (100k-400k) */
|
||||
#define FCLK_FAST() /* Set fast clock (depends on the CSD) */
|
||||
|
||||
#define xmit_spi( dat ) xchg_spi( dat )
|
||||
#define rcvr_spi() xchg_spi( 0xFF )
|
||||
#define rcvr_spi_m( p ) \
|
||||
SPI->SPDR = 0xFF; \
|
||||
while( !( SPI->SPSR & ( 1 << 7 ) ) ); /* Check SPIF bit. */ \
|
||||
*( p ) = ( BYTE ) SPI->SPDR;
|
||||
|
||||
/*-------------------------------------------------------------------------- */
|
||||
|
||||
static volatile DSTATUS Stat = STA_NOINIT; /* Disk status */
|
||||
static volatile UINT Timer1, Timer2; /* 1000Hz decrement timer */
|
||||
static UINT CardType;
|
||||
|
||||
static BYTE xchg_spi( BYTE dat )
|
||||
{
|
||||
SPI->SPDR = dat;
|
||||
while( !( SPI->SPSR & ( 1 << 7 ) ) ); /* Check SPIF bit. */
|
||||
return( BYTE ) SPI->SPDR;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* Wait for card ready */
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static BYTE wait_ready( void )
|
||||
{
|
||||
BYTE res;
|
||||
|
||||
Timer2 = 500; /* Wait for ready in timeout of 500ms */
|
||||
rcvr_spi();
|
||||
do
|
||||
{
|
||||
res = rcvr_spi();
|
||||
} while( (res != 0xFF) && Timer2 );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* Deselect the card and release SPI bus */
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static void deselect( void )
|
||||
{
|
||||
CS_HIGH();
|
||||
rcvr_spi();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* Select the card and wait ready */
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static BOOL select( void ) /* TRUE:Successful, FALSE:Timeout */
|
||||
{
|
||||
CS_LOW();
|
||||
if( wait_ready() != 0xFF )
|
||||
{
|
||||
deselect();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* Power Control (Platform dependent) */
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* When the target system does not support socket power control, there */
|
||||
|
||||
/* is nothing to do in these functions and chk_power always returns 1. */
|
||||
static void power_on( void )
|
||||
{
|
||||
#if 0
|
||||
/* Enable SPI1 */
|
||||
SPI1CON1 = 0x013B;
|
||||
SPI1CON2 = 0x0000;
|
||||
_SPIEN = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void power_off( void )
|
||||
{
|
||||
#if 0
|
||||
select(); /* Wait for card ready */
|
||||
deselect();
|
||||
|
||||
_SPIEN = 0; /* Disable SPI1 */
|
||||
|
||||
Stat |= STA_NOINIT; /* Set STA_NOINIT */
|
||||
#endif
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* Receive a data packet from MMC */
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static BOOL rcvr_datablock( BYTE *buff, /* Data buffer to store received data */ UINT btr /* Byte count (must be multiple of 4) */ )
|
||||
{
|
||||
BYTE token;
|
||||
|
||||
Timer1 = 100;
|
||||
do
|
||||
{ /* Wait for data packet in timeout of 100ms */
|
||||
token = rcvr_spi();
|
||||
} while( (token == 0xFF) && Timer1 );
|
||||
|
||||
if( token != 0xFE )
|
||||
{
|
||||
return FALSE; /* If not valid data token, retutn with error */
|
||||
}
|
||||
|
||||
do
|
||||
{ /* Receive the data block into buffer */
|
||||
rcvr_spi_m( buff++ );
|
||||
rcvr_spi_m( buff++ );
|
||||
rcvr_spi_m( buff++ );
|
||||
rcvr_spi_m( buff++ );
|
||||
} while( btr -= 4 );
|
||||
rcvr_spi(); /* Discard CRC */
|
||||
rcvr_spi();
|
||||
|
||||
return TRUE; /* Return with success */
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* Send a data packet to MMC */
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
#if _READONLY == 0
|
||||
static BOOL xmit_datablock( const BYTE *buff, /* 512 byte data block to be transmitted */ BYTE token /* Data/Stop token */ )
|
||||
{
|
||||
BYTE resp;
|
||||
UINT bc = 512;
|
||||
|
||||
if( wait_ready() != 0xFF )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
xmit_spi( token ); /* Xmit data token */
|
||||
if( token != 0xFD )
|
||||
{ /* Is data token */
|
||||
do
|
||||
{ /* Xmit the 512 byte data block to MMC */
|
||||
xmit_spi( *buff++ );
|
||||
xmit_spi( *buff++ );
|
||||
} while( bc -= 2 );
|
||||
xmit_spi( 0xFF ); /* CRC (Dummy) */
|
||||
xmit_spi( 0xFF );
|
||||
resp = rcvr_spi(); /* Receive data response */
|
||||
if( (resp & 0x1F) != 0x05 )
|
||||
{ /* If not accepted, return with error */
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif /* _READONLY */
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* Send a command packet to MMC */
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static BYTE send_cmd( BYTE cmd, /* Command byte */ DWORD arg /* Argument */ )
|
||||
{
|
||||
BYTE n, res;
|
||||
|
||||
if( cmd & 0x80 )
|
||||
{ /* ACMD<n> is the command sequense of CMD55-CMD<n> */
|
||||
cmd &= 0x7F;
|
||||
res = send_cmd( CMD55, 0 );
|
||||
if( res > 1 )
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/* Select the card and wait for ready */
|
||||
deselect();
|
||||
if( !select() )
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
/* Send command packet */
|
||||
xmit_spi( cmd ); /* Start + Command index */
|
||||
xmit_spi( (BYTE) (arg >> 24) ); /* Argument[31..24] */
|
||||
xmit_spi( (BYTE) (arg >> 16) ); /* Argument[23..16] */
|
||||
xmit_spi( (BYTE) (arg >> 8) ); /* Argument[15..8] */
|
||||
xmit_spi( (BYTE) arg ); /* Argument[7..0] */
|
||||
n = 0x01; /* Dummy CRC + Stop */
|
||||
if( cmd == CMD0 )
|
||||
{
|
||||
n = 0x95; /* Valid CRC for CMD0(0) */
|
||||
}
|
||||
|
||||
if( cmd == CMD8 )
|
||||
{
|
||||
n = 0x87; /* Valid CRC for CMD8(0x1AA) */
|
||||
}
|
||||
|
||||
xmit_spi( n );
|
||||
|
||||
/* Receive command response */
|
||||
if( cmd == CMD12 )
|
||||
{
|
||||
rcvr_spi(); /* Skip a stuff byte when stop reading */
|
||||
}
|
||||
|
||||
n = 10; /* Wait for a valid response in timeout of 10 attempts */
|
||||
do
|
||||
{
|
||||
res = rcvr_spi();
|
||||
} while( (res & 0x80) && --n );
|
||||
|
||||
return res; /* Return with the response value */
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
Public Functions
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* Initialize Disk Drive */
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
DSTATUS disk_initialize( BYTE drv /* Physical drive nmuber (0) */ )
|
||||
{
|
||||
BYTE n, cmd, ty, ocr[4];
|
||||
|
||||
if( drv )
|
||||
{
|
||||
return STA_NOINIT; /* Supports only single drive */
|
||||
}
|
||||
|
||||
if( Stat & STA_NODISK )
|
||||
{
|
||||
return Stat; /* No card in the socket */
|
||||
}
|
||||
|
||||
power_on(); /* Force socket power on */
|
||||
FCLK_SLOW();
|
||||
for( n = 10; n; n-- )
|
||||
{
|
||||
rcvr_spi(); /* 80 dummy clocks */
|
||||
}
|
||||
|
||||
ty = 0;
|
||||
if( send_cmd(CMD0, 0) == 1 )
|
||||
{ /* Enter Idle state */
|
||||
Timer1 = 1000; /* Initialization timeout of 1000 msec */
|
||||
if( send_cmd(CMD8, 0x1AA) == 1 )
|
||||
{ /* SDv2? */
|
||||
for( n = 0; n < 4; n++ )
|
||||
{
|
||||
ocr[n] = rcvr_spi(); /* Get trailing return value of R7 resp */
|
||||
}
|
||||
|
||||
if( ocr[2] == 0x01 && ocr[3] == 0xAA )
|
||||
{ /* The card can work at vdd range of 2.7-3.6V */
|
||||
while( Timer1 && send_cmd(ACMD41, 1UL << 30) );
|
||||
|
||||
/* Wait for leaving idle state (ACMD41 with HCS bit) */
|
||||
if( Timer1 && send_cmd(CMD58, 0) == 0 )
|
||||
{ /* Check CCS bit in the OCR */
|
||||
for( n = 0; n < 4; n++ )
|
||||
{
|
||||
ocr[n] = rcvr_spi();
|
||||
}
|
||||
|
||||
ty = ( ocr[0] & 0x40 ) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 (HC/SC) */
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* SDv1 or MMCv3 */
|
||||
if( send_cmd(ACMD41, 0) <= 1 )
|
||||
{
|
||||
ty = CT_SD1;
|
||||
cmd = ACMD41; /* SDv1 */
|
||||
}
|
||||
else
|
||||
{
|
||||
ty = CT_MMC;
|
||||
cmd = CMD1; /* MMCv3 */
|
||||
}
|
||||
|
||||
while( Timer1 && send_cmd(cmd, 0) );
|
||||
|
||||
/* Wait for leaving idle state */
|
||||
if( !Timer1 || send_cmd(CMD16, 512) != 0 )
|
||||
{ /* Set R/W block length to 512 */
|
||||
ty = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CardType = ty;
|
||||
deselect();
|
||||
|
||||
if( ty )
|
||||
{ /* Initialization succeded */
|
||||
Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
|
||||
FCLK_FAST();
|
||||
}
|
||||
else
|
||||
{ /* Initialization failed */
|
||||
power_off();
|
||||
}
|
||||
|
||||
return Stat;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* Get Disk Status */
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
DSTATUS disk_status( BYTE drv /* Physical drive nmuber (0) */ )
|
||||
{
|
||||
if( drv )
|
||||
{
|
||||
return STA_NOINIT; /* Supports only single drive */
|
||||
}
|
||||
|
||||
return Stat;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* Read Sector(s) */
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
DRESULT disk_read
|
||||
(
|
||||
BYTE drv, /* Physical drive nmuber (0) */
|
||||
BYTE *buff, /* Pointer to the data buffer to store read data */
|
||||
DWORD sector, /* Start sector number (LBA) */
|
||||
BYTE count /* Sector count (1..255) */
|
||||
)
|
||||
{
|
||||
if( drv || !count )
|
||||
{
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
||||
if( Stat & STA_NOINIT )
|
||||
{
|
||||
return RES_NOTRDY;
|
||||
}
|
||||
|
||||
if( !(CardType & CT_BLOCK) )
|
||||
{
|
||||
sector *= 512; /* Convert to byte address if needed */
|
||||
}
|
||||
|
||||
if( count == 1 )
|
||||
{ /* Single block read */
|
||||
if( (send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */ && rcvr_datablock(buff, 512) )
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* Multiple block read */
|
||||
if( send_cmd(CMD18, sector) == 0 )
|
||||
{ /* READ_MULTIPLE_BLOCK */
|
||||
do
|
||||
{
|
||||
if( !rcvr_datablock(buff, 512) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
buff += 512;
|
||||
} while( --count );
|
||||
send_cmd( CMD12, 0 ); /* STOP_TRANSMISSION */
|
||||
}
|
||||
}
|
||||
|
||||
deselect();
|
||||
|
||||
return count ? RES_ERROR : RES_OK;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* Write Sector(s) */
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
#if _READONLY == 0
|
||||
DRESULT disk_write
|
||||
(
|
||||
BYTE drv, /* Physical drive nmuber (0) */
|
||||
const BYTE *buff, /* Pointer to the data to be written */
|
||||
DWORD sector, /* Start sector number (LBA) */
|
||||
BYTE count /* Sector count (1..255) */
|
||||
)
|
||||
{
|
||||
if( drv || !count )
|
||||
{
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
||||
if( Stat & STA_NOINIT )
|
||||
{
|
||||
return RES_NOTRDY;
|
||||
}
|
||||
|
||||
if( Stat & STA_PROTECT )
|
||||
{
|
||||
return RES_WRPRT;
|
||||
}
|
||||
|
||||
if( !(CardType & CT_BLOCK) )
|
||||
{
|
||||
sector *= 512; /* Convert to byte address if needed */
|
||||
}
|
||||
|
||||
if( count == 1 )
|
||||
{ /* Single block write */
|
||||
if( (send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */ && xmit_datablock(buff, 0xFE) )
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* Multiple block write */
|
||||
if( CardType & CT_SDC )
|
||||
{
|
||||
send_cmd( ACMD23, count );
|
||||
}
|
||||
|
||||
if( send_cmd(CMD25, sector) == 0 )
|
||||
{ /* WRITE_MULTIPLE_BLOCK */
|
||||
do
|
||||
{
|
||||
if( !xmit_datablock(buff, 0xFC) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
buff += 512;
|
||||
} while( --count );
|
||||
if( !xmit_datablock(0, 0xFD) )
|
||||
{ /* STOP_TRAN token */
|
||||
count = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deselect();
|
||||
|
||||
return count ? RES_ERROR : RES_OK;
|
||||
}
|
||||
|
||||
#endif /* _READONLY */
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* Miscellaneous Functions */
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
DRESULT disk_ioctl
|
||||
(
|
||||
BYTE drv, /* Physical drive nmuber (0) */
|
||||
BYTE ctrl, /* Control code */
|
||||
void *buff /* Buffer to send/receive data block */
|
||||
)
|
||||
{
|
||||
DRESULT res;
|
||||
BYTE n, csd[16], *ptr = buff;
|
||||
DWORD csize;
|
||||
|
||||
if( drv )
|
||||
{
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
||||
if( Stat & STA_NOINIT )
|
||||
{
|
||||
return RES_NOTRDY;
|
||||
}
|
||||
|
||||
res = RES_ERROR;
|
||||
switch( ctrl )
|
||||
{
|
||||
case CTRL_SYNC: /* Flush dirty buffer if present */
|
||||
if( select() )
|
||||
{
|
||||
res = RES_OK;
|
||||
deselect();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case GET_SECTOR_COUNT: /* Get number of sectors on the disk (WORD) */
|
||||
if( (send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16) )
|
||||
{
|
||||
if( (csd[0] >> 6) == 1 )
|
||||
{ /* SDv2? */
|
||||
csize = csd[9] + ( (WORD) csd[8] << 8 ) + 1;
|
||||
*( DWORD * ) buff = ( DWORD ) csize << 10;
|
||||
}
|
||||
else
|
||||
{ /* SDv1 or MMCv2 */
|
||||
n = ( csd[5] & 15 ) + ( (csd[10] & 128) >> 7 ) + ( (csd[9] & 3) << 1 ) + 2;
|
||||
csize = ( csd[8] >> 6 ) + ( (WORD) csd[7] << 2 ) + ( (WORD) (csd[6] & 3) << 10 ) + 1;
|
||||
*( DWORD * ) buff = ( DWORD ) csize << ( n - 9 );
|
||||
}
|
||||
|
||||
res = RES_OK;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case GET_SECTOR_SIZE: /* Get sectors on the disk (WORD) */
|
||||
* ( WORD * ) buff = 512;
|
||||
res = RES_OK;
|
||||
break;
|
||||
|
||||
case GET_BLOCK_SIZE: /* Get erase block size in unit of sectors (DWORD) */
|
||||
if( CardType & CT_SD2 )
|
||||
{ /* SDv2? */
|
||||
if( send_cmd(ACMD13, 0) == 0 )
|
||||
{ /* Read SD status */
|
||||
rcvr_spi();
|
||||
if( rcvr_datablock(csd, 16) )
|
||||
{ /* Read partial block */
|
||||
for( n = 64 - 16; n; n-- )
|
||||
{
|
||||
rcvr_spi(); /* Purge trailing data */
|
||||
}
|
||||
|
||||
* ( DWORD * ) buff = 16UL << ( csd[10] >> 4 );
|
||||
res = RES_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* SDv1 or MMCv3 */
|
||||
if( (send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16) )
|
||||
{ /* Read CSD */
|
||||
if( CardType & CT_SD1 )
|
||||
{ /* SDv1 */
|
||||
*( DWORD * ) buff = ( ((csd[10] & 63) << 1) + ((WORD) (csd[11] & 128) >> 7) + 1 ) << ( (csd[13] >> 6) - 1 );
|
||||
}
|
||||
else
|
||||
{ /* MMCv3 */
|
||||
*( DWORD * ) buff = ( (WORD) ((csd[10] & 124) >> 2) + 1 ) * ( ((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1 );
|
||||
}
|
||||
|
||||
res = RES_OK;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MMC_GET_TYPE: /* Get card type flags (1 byte) */
|
||||
*ptr = CardType;
|
||||
res = RES_OK;
|
||||
break;
|
||||
|
||||
case MMC_GET_CSD: /* Receive CSD as a data block (16 bytes) */
|
||||
if( (send_cmd(CMD9, 0) == 0) /* READ_CSD */ && rcvr_datablock(buff, 16) )
|
||||
{
|
||||
res = RES_OK;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MMC_GET_CID: /* Receive CID as a data block (16 bytes) */
|
||||
if( (send_cmd(CMD10, 0) == 0) /* READ_CID */ && rcvr_datablock(buff, 16) )
|
||||
{
|
||||
res = RES_OK;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MMC_GET_OCR: /* Receive OCR as an R3 resp (4 bytes) */
|
||||
if( send_cmd(CMD58, 0) == 0 )
|
||||
{ /* READ_OCR */
|
||||
for( n = 0; n < 4; n++ )
|
||||
{
|
||||
*( ( BYTE * ) buff + n ) = rcvr_spi();
|
||||
}
|
||||
|
||||
res = RES_OK;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MMC_GET_SDSTAT: /* Receive SD statsu as a data block (64 bytes) */
|
||||
if( send_cmd(ACMD13, 0) == 0 )
|
||||
{ /* SD_STATUS */
|
||||
rcvr_spi();
|
||||
if( rcvr_datablock(buff, 64) )
|
||||
{
|
||||
res = RES_OK;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
res = RES_PARERR;
|
||||
}
|
||||
|
||||
deselect();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* Device Timer Interrupt Procedure (Platform dependent) */
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* This function must be called in period of 1ms */
|
||||
void disk_timerproc( void )
|
||||
{
|
||||
static unsigned long pv;
|
||||
unsigned long p;
|
||||
BYTE s;
|
||||
UINT n;
|
||||
|
||||
n = Timer1; /* 1000Hz decrement timer */
|
||||
if( n )
|
||||
{
|
||||
Timer1 = --n;
|
||||
}
|
||||
|
||||
n = Timer2;
|
||||
if( n )
|
||||
{
|
||||
Timer2 = --n;
|
||||
}
|
||||
|
||||
p = pv;
|
||||
pv = SOCKPORT & ( SOCKWP | SOCKINS ); /* Sample socket switch */
|
||||
|
||||
if( p == pv )
|
||||
{ /* Have contacts stabled? */
|
||||
s = Stat;
|
||||
|
||||
if( p & SOCKWP )
|
||||
{ /* WP is H (write protected) */
|
||||
s |= STA_PROTECT;
|
||||
}
|
||||
else
|
||||
{ /* WP is L (write enabled) */
|
||||
s &= ~STA_PROTECT;
|
||||
}
|
||||
|
||||
if( p & SOCKINS )
|
||||
{ /* INS = H (Socket empty) */
|
||||
s |= ( STA_NODISK | STA_NOINIT );
|
||||
}
|
||||
else
|
||||
{ /* INS = L (Card inserted) */
|
||||
s &= ~STA_NODISK;
|
||||
}
|
||||
|
||||
Stat = s;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD get_fattime( void )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void disk_init_spi( void )
|
||||
{
|
||||
volatile unsigned long ulDummy;
|
||||
|
||||
/* The SD card is connected using SPI0. Start by enabling power to the
|
||||
SPI peripheral. */
|
||||
SC->PCONP |= PCONP_PCSPI;
|
||||
|
||||
/* Also enable the clock to the peripheral. */
|
||||
SC->PCLKSEL0 &= ~( 0x03 << 16 );
|
||||
SC->PCLKSEL0 |= ( 0x01 << 16 );
|
||||
|
||||
/* Configure P0.15 as the clock. */
|
||||
PINCON->PINSEL0 |= ( 0x03 << 30 );
|
||||
|
||||
/* Configure P0.16 as SSEL. */
|
||||
GPIO0->FIODIR |= ( 0x01 << 16 );
|
||||
PINCON->PINSEL1 &= ~( 0x03 );
|
||||
|
||||
/* Configure P0.17 as MISO. */
|
||||
PINCON->PINSEL1 |= ( 0x03 << 2 );
|
||||
|
||||
/* Configure P0.18 as MOSI. */
|
||||
PINCON->PINSEL1 |= ( 0x03 << 4 );
|
||||
|
||||
/* Configure P4.29 as (presumably) the card detect input. */
|
||||
// GPIO4->FIODIR &= ~( 1 << 29 );
|
||||
|
||||
/* Set outputs to outputs... */
|
||||
GPIO0->FIODIR |= ( (1 << 15) | (1 << 16) | (1 << 18) );
|
||||
|
||||
/* ... and inputs to inputs. */
|
||||
GPIO0->FIODIR &= ~( 1 << 17 );
|
||||
|
||||
/* Ensure SSEL is high. */
|
||||
CS_HIGH();
|
||||
|
||||
/* Set SPI to master mode. */
|
||||
SPI->SPCR |= ( 1 << 5 );
|
||||
|
||||
/* Clear all status bits. */
|
||||
ulDummy = SPI->SPSR;
|
||||
|
||||
/* Set the serial clock frequency. 100MHz / 250 = 400KHz. */
|
||||
SPI->SPCCR = configCPU_CLOCK_HZ / 250;
|
||||
}
|
||||
|
||||
|
@ -1,77 +0,0 @@
|
||||
/*-----------------------------------------------------------------------
|
||||
/ Low level disk interface modlue include file R0.07 (C)ChaN, 2009
|
||||
/-----------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _DISKIO
|
||||
|
||||
#define _READONLY 0 /* 1: Read-only mode */
|
||||
#define _USE_IOCTL 1
|
||||
|
||||
#include "fat_integer.h"
|
||||
|
||||
|
||||
/* Status of Disk Functions */
|
||||
typedef BYTE DSTATUS;
|
||||
|
||||
/* Results of Disk Functions */
|
||||
typedef enum {
|
||||
RES_OK = 0, /* 0: Successful */
|
||||
RES_ERROR, /* 1: R/W Error */
|
||||
RES_WRPRT, /* 2: Write Protected */
|
||||
RES_NOTRDY, /* 3: Not Ready */
|
||||
RES_PARERR /* 4: Invalid Parameter */
|
||||
} DRESULT;
|
||||
|
||||
|
||||
/*---------------------------------------*/
|
||||
/* Prototypes for disk control functions */
|
||||
|
||||
BOOL assign_drives (int argc, char *argv[]);
|
||||
DSTATUS disk_initialize (BYTE);
|
||||
DSTATUS disk_status (BYTE);
|
||||
DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
|
||||
#if _READONLY == 0
|
||||
DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
|
||||
#endif
|
||||
DRESULT disk_ioctl (BYTE, BYTE, void*);
|
||||
|
||||
|
||||
|
||||
/* Disk Status Bits (DSTATUS) */
|
||||
|
||||
#define STA_NOINIT 0x01 /* Drive not initialized */
|
||||
#define STA_NODISK 0x02 /* No medium in the drive */
|
||||
#define STA_PROTECT 0x04 /* Write protected */
|
||||
|
||||
|
||||
/* Command code for disk_ioctrl() */
|
||||
|
||||
/* Generic command */
|
||||
#define CTRL_SYNC 0 /* Mandatory for write functions */
|
||||
#define GET_SECTOR_COUNT 1 /* Mandatory for only f_mkfs() */
|
||||
#define GET_SECTOR_SIZE 2 /* Mandatory for multiple sector size cfg */
|
||||
#define GET_BLOCK_SIZE 3 /* Mandatory for only f_mkfs() */
|
||||
#define CTRL_POWER 4
|
||||
#define CTRL_LOCK 5
|
||||
#define CTRL_EJECT 6
|
||||
/* MMC/SDC command */
|
||||
#define MMC_GET_TYPE 10
|
||||
#define MMC_GET_CSD 11
|
||||
#define MMC_GET_CID 12
|
||||
#define MMC_GET_OCR 13
|
||||
#define MMC_GET_SDSTAT 14
|
||||
/* ATA/CF command */
|
||||
#define ATA_GET_REV 20
|
||||
#define ATA_GET_MODEL 21
|
||||
#define ATA_GET_SN 22
|
||||
|
||||
/* Card type definitions (CardType) */
|
||||
|
||||
#define CT_MMC 0x01
|
||||
#define CT_SD1 0x02
|
||||
#define CT_SD2 0x04
|
||||
#define CT_SDC (CT_SD1|CT_SD2)
|
||||
#define CT_BLOCK 0x08
|
||||
|
||||
#define _DISKIO
|
||||
#endif
|
@ -1,166 +0,0 @@
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ FatFs - FAT file system module configuration file R0.07e (C)ChaN, 2009
|
||||
/----------------------------------------------------------------------------/
|
||||
/
|
||||
/ CAUTION! Do not forget to make clean the project after any changes to
|
||||
/ the configuration options.
|
||||
/
|
||||
/----------------------------------------------------------------------------*/
|
||||
#ifndef _FFCONFIG
|
||||
#define _FFCONFIG 0x007E
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Function and Buffer Configurations
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#define _FS_TINY 0 /* 0 or 1 */
|
||||
/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system
|
||||
/ object instead of the sector buffer in the individual file object for file
|
||||
/ data transfer. This reduces memory consumption 512 bytes each file object. */
|
||||
|
||||
|
||||
#define _FS_READONLY 0 /* 0 or 1 */
|
||||
/* Setting _FS_READONLY to 1 defines read only configuration. This removes
|
||||
/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
|
||||
/ f_truncate and useless f_getfree. */
|
||||
|
||||
|
||||
#define _FS_MINIMIZE 0 /* 0, 1, 2 or 3 */
|
||||
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
|
||||
/
|
||||
/ 0: Full function.
|
||||
/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename
|
||||
/ are removed.
|
||||
/ 2: f_opendir and f_readdir are removed in addition to level 1.
|
||||
/ 3: f_lseek is removed in addition to level 2. */
|
||||
|
||||
|
||||
#define _USE_STRFUNC 0 /* 0, 1 or 2 */
|
||||
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
|
||||
|
||||
|
||||
#define _USE_MKFS 0 /* 0 or 1 */
|
||||
/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
|
||||
|
||||
|
||||
#define _USE_FORWARD 0 /* 0 or 1 */
|
||||
/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Locale and Namespace Configurations
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#define _CODE_PAGE 1250
|
||||
/* The _CODE_PAGE specifies the OEM code page to be used on the target system.
|
||||
/ Incorrect setting of the code page can cause a file open failure.
|
||||
/
|
||||
/ 932 - Japanese Shift-JIS (DBCS, OEM, Windows)
|
||||
/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows)
|
||||
/ 949 - Korean (DBCS, OEM, Windows)
|
||||
/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
|
||||
/ 1250 - Central Europe (Windows)
|
||||
/ 1251 - Cyrillic (Windows)
|
||||
/ 1252 - Latin 1 (Windows)
|
||||
/ 1253 - Greek (Windows)
|
||||
/ 1254 - Turkish (Windows)
|
||||
/ 1255 - Hebrew (Windows)
|
||||
/ 1256 - Arabic (Windows)
|
||||
/ 1257 - Baltic (Windows)
|
||||
/ 1258 - Vietnam (OEM, Windows)
|
||||
/ 437 - U.S. (OEM)
|
||||
/ 720 - Arabic (OEM)
|
||||
/ 737 - Greek (OEM)
|
||||
/ 775 - Baltic (OEM)
|
||||
/ 850 - Multilingual Latin 1 (OEM)
|
||||
/ 858 - Multilingual Latin 1 + Euro (OEM)
|
||||
/ 852 - Latin 2 (OEM)
|
||||
/ 855 - Cyrillic (OEM)
|
||||
/ 866 - Russian (OEM)
|
||||
/ 857 - Turkish (OEM)
|
||||
/ 862 - Hebrew (OEM)
|
||||
/ 874 - Thai (OEM, Windows)
|
||||
/ 1 - ASCII only (Valid for non LFN cfg.)
|
||||
*/
|
||||
|
||||
|
||||
#define _USE_LFN 0 /* 0, 1 or 2 */
|
||||
#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */
|
||||
/* The _USE_LFN option switches the LFN support.
|
||||
/
|
||||
/ 0: Disable LFN. _MAX_LFN and _LFN_UNICODE have no effect.
|
||||
/ 1: Enable LFN with static working buffer on the bss. NOT REENTRANT.
|
||||
/ 2: Enable LFN with dynamic working buffer on the STACK.
|
||||
/
|
||||
/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. When enable LFN,
|
||||
/ two Unicode handling functions ff_convert() and ff_wtoupper() must be added
|
||||
/ to the project. */
|
||||
|
||||
|
||||
#define _LFN_UNICODE 0 /* 0 or 1 */
|
||||
/* To switch the character code set on FatFs API to Unicode,
|
||||
/ enable LFN feature and set _LFN_UNICODE to 1.
|
||||
*/
|
||||
|
||||
|
||||
#define _FS_RPATH 0 /* 0 or 1 */
|
||||
/* When _FS_RPATH is set to 1, relative path feature is enabled and f_chdir,
|
||||
/ f_chdrive function are available.
|
||||
/ Note that output of the f_readdir fnction is affected by this option. */
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Physical Drive Configurations
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#define _DRIVES 1
|
||||
/* Number of volumes (logical drives) to be used. */
|
||||
|
||||
|
||||
#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */
|
||||
/* Maximum sector size to be handled.
|
||||
/ Always set 512 for memory card and hard disk but a larger value may be
|
||||
/ required for floppy disk (512/1024) and optical disk (512/2048).
|
||||
/ When _MAX_SS is larger than 512, GET_SECTOR_SIZE command must be implememted
|
||||
/ to the disk_ioctl function. */
|
||||
|
||||
|
||||
#define _MULTI_PARTITION 0 /* 0 or 1 */
|
||||
/* When _MULTI_PARTITION is set to 0, each volume is bound to the same physical
|
||||
/ drive number and can mount only first primaly partition. When it is set to 1,
|
||||
/ each volume is tied to the partitions listed in Drives[]. */
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ System Configurations
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#define _WORD_ACCESS 0 /* 0 or 1 */
|
||||
/* The _WORD_ACCESS option defines which access method is used to the word
|
||||
/ data on the FAT volume.
|
||||
/
|
||||
/ 0: Byte-by-byte access. Always compatible with all platforms.
|
||||
/ 1: Word access. Do not choose this unless following condition is met.
|
||||
/
|
||||
/ When the byte order on the memory is big-endian or address miss-aligned
|
||||
/ word access results incorrect behavior, the _WORD_ACCESS must be set to 0.
|
||||
/ If it is not the case, the value can also be set to 1 to improve the
|
||||
/ performance and code size. */
|
||||
|
||||
|
||||
#define _FS_REENTRANT 1 /* 0 or 1 */
|
||||
#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */
|
||||
#define _SYNC_t void * /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */
|
||||
/* The _FS_REENTRANT option switches the reentrancy of the FatFs module.
|
||||
/
|
||||
/ 0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect.
|
||||
/ 1: Enable reentrancy. Also user provided synchronization handlers,
|
||||
/ ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj
|
||||
/ function must be added to the project. */
|
||||
|
||||
|
||||
#endif /* _FFCONFIG */
|
@ -1,159 +0,0 @@
|
||||
/*
|
||||
FreeRTOS V6.0.2 - Copyright (C) 2010 Real Time Engineers Ltd.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* If you are: *
|
||||
* *
|
||||
* + New to FreeRTOS, *
|
||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
||||
* + Looking for basic training, *
|
||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
||||
* *
|
||||
* then take a look at the FreeRTOS eBook *
|
||||
* *
|
||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* A pdf reference manual is also available. Both are usually delivered *
|
||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
||||
* exceptional circumstances). Thank you for your support! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
||||
***NOTE*** The exception to the GPL is included to allow you to distribute
|
||||
a combined work that includes FreeRTOS without being obliged to provide the
|
||||
source code for proprietary components outside of the FreeRTOS kernel.
|
||||
FreeRTOS 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. You should have received a copy of the GNU General Public
|
||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
||||
by writing to Richard Barry, contact details for whom are available on the
|
||||
FreeRTOS WEB site.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
||||
contact details.
|
||||
|
||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
||||
critical systems.
|
||||
|
||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
||||
licensing and training services.
|
||||
*/
|
||||
|
||||
/* FreeRTOS.org includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
/* Demo application includes. */
|
||||
#include "partest.h"
|
||||
|
||||
#define partstFIRST_IO ( ( unsigned long ) 0x04 )
|
||||
#define partstFIO2_BITS ( ( unsigned long ) 0x0000007C )
|
||||
#define partstFIO1_BITS ( ( unsigned long ) 0xB0000000 )
|
||||
#define partstNUM_LEDS ( 5 )
|
||||
#define partstALL_OUTPUTS_OFF ( ( unsigned long ) 0xff )
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Simple parallel port IO routines.
|
||||
*-----------------------------------------------------------*/
|
||||
|
||||
void vParTestInitialise( void )
|
||||
{
|
||||
/* LEDs on ports 1 and 2 to output. */
|
||||
GPIO2->FIODIR = partstFIO2_BITS;
|
||||
GPIO1->FIODIR = partstFIO1_BITS;
|
||||
|
||||
/* Start will all LEDs off. */
|
||||
GPIO2->FIOCLR = partstFIO2_BITS;
|
||||
GPIO1->FIOCLR = partstFIO1_BITS;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vParTestSetLED( unsigned long ulLEDIn, signed long xValue )
|
||||
{
|
||||
unsigned long ulLED = partstFIRST_IO;
|
||||
|
||||
/* Used to set and clear LEDs on FIO2. */
|
||||
|
||||
if( ulLEDIn < partstNUM_LEDS )
|
||||
{
|
||||
/* Rotate to the wanted bit of port */
|
||||
ulLED <<= ( unsigned long ) ulLEDIn;
|
||||
|
||||
/* Set of clear the output. */
|
||||
if( xValue )
|
||||
{
|
||||
GPIO2->FIOCLR = ulLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
GPIO2->FIOSET = ulLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vParTestToggleLED( unsigned long ulLEDIn )
|
||||
{
|
||||
unsigned long ulLED = partstFIRST_IO, ulCurrentState;
|
||||
|
||||
/* Used to toggle LEDs on FIO2. */
|
||||
|
||||
if( ulLEDIn < partstNUM_LEDS )
|
||||
{
|
||||
/* Rotate to the wanted bit of port 0. Only P10 to P13 have an LED
|
||||
attached. */
|
||||
ulLED <<= ( unsigned long ) ulLEDIn;
|
||||
|
||||
/* If this bit is already set, clear it, and visa versa. */
|
||||
ulCurrentState = GPIO2->FIOPIN;
|
||||
if( ulCurrentState & ulLED )
|
||||
{
|
||||
GPIO2->FIOCLR = ulLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
GPIO2->FIOSET = ulLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
long lParTestGetLEDState( void )
|
||||
{
|
||||
/* Returns the state of the LEDs on FIO1. */
|
||||
if( ( GPIO1->FIOPIN & partstFIO1_BITS ) != 0 )
|
||||
{
|
||||
return pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return pdTRUE;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vParTestSetLEDState( long lState )
|
||||
{
|
||||
/* Used to set and clear the LEDs on FIO1. */
|
||||
if( lState != pdFALSE )
|
||||
{
|
||||
GPIO1->FIOSET = partstFIO1_BITS;
|
||||
}
|
||||
else
|
||||
{
|
||||
GPIO1->FIOCLR = partstFIO1_BITS;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
@ -1,318 +0,0 @@
|
||||
/*
|
||||
FreeRTOS V6.0.2 - Copyright (C) 2010 Real Time Engineers Ltd.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* If you are: *
|
||||
* *
|
||||
* + New to FreeRTOS, *
|
||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
||||
* + Looking for basic training, *
|
||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
||||
* *
|
||||
* then take a look at the FreeRTOS eBook *
|
||||
* *
|
||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* A pdf reference manual is also available. Both are usually delivered *
|
||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
||||
* exceptional circumstances). Thank you for your support! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
||||
***NOTE*** The exception to the GPL is included to allow you to distribute
|
||||
a combined work that includes FreeRTOS without being obliged to provide the
|
||||
source code for proprietary components outside of the FreeRTOS kernel.
|
||||
FreeRTOS 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. You should have received a copy of the GNU General Public
|
||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
||||
by writing to Richard Barry, contact details for whom are available on the
|
||||
FreeRTOS WEB site.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
||||
contact details.
|
||||
|
||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
||||
critical systems.
|
||||
|
||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
||||
licensing and training services.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Creates all the demo application tasks, then starts the scheduler. The WEB
|
||||
* documentation provides more details of the standard demo application tasks
|
||||
* (which just exist to test the kernel port and provide an example of how to use
|
||||
* each FreeRTOS API function).
|
||||
*
|
||||
* In addition to the standard demo tasks, the following tasks and tests are
|
||||
* defined and/or created within this file:
|
||||
*
|
||||
* "Check" hook - This only executes fully every five seconds from the tick
|
||||
* hook. Its main function is to check that all the standard demo tasks are
|
||||
* still operational. The status can be viewed using on the Task Stats page
|
||||
* served by the WEB server.
|
||||
*
|
||||
* "uIP" task - This is the task that handles the uIP stack. All TCP/IP
|
||||
* processing is performed in this task.
|
||||
*
|
||||
* "USB" task - Enumerates the USB device as a CDC class, then echoes back all
|
||||
* received characters with a configurable offset (for example, if the offset
|
||||
* is 1 and 'A' is received then 'B' will be sent back). A dumb terminal such
|
||||
* as Hyperterminal can be used to talk to the USB task.
|
||||
*/
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Demo app includes. */
|
||||
#include "BlockQ.h"
|
||||
#include "integer.h"
|
||||
#include "blocktim.h"
|
||||
#include "flash.h"
|
||||
#include "partest.h"
|
||||
#include "semtest.h"
|
||||
#include "PollQ.h"
|
||||
#include "GenQTest.h"
|
||||
#include "QPeek.h"
|
||||
#include "recmutex.h"
|
||||
|
||||
/* File system includes. */
|
||||
#include "diskio.h"
|
||||
#include "ff.h"
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The time between cycles of the 'check' functionality (defined within the
|
||||
tick hook). */
|
||||
#define mainCHECK_DELAY ( ( portTickType ) 5000 / portTICK_RATE_MS )
|
||||
|
||||
/* Task priorities. */
|
||||
#define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
||||
#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
||||
#define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
||||
#define mainUIP_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
|
||||
#define mainINTEGER_TASK_PRIORITY ( tskIDLE_PRIORITY )
|
||||
#define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY )
|
||||
#define mainFLASH_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
||||
|
||||
/* The WEB server has a larger stack as it utilises stack hungry string
|
||||
handling library calls. */
|
||||
#define mainBASIC_WEB_STACK_SIZE ( configMINIMAL_STACK_SIZE * 4 )
|
||||
|
||||
/* The message displayed by the WEB server when all tasks are executing
|
||||
without an error being reported. */
|
||||
#define mainPASS_STATUS_MESSAGE "All tasks are executing without error."
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Configure the hardware for the demo.
|
||||
*/
|
||||
static void prvSetupHardware( void );
|
||||
|
||||
/*
|
||||
* The task that handles the uIP stack. All TCP/IP processing is performed in
|
||||
* this task.
|
||||
*/
|
||||
extern void vuIP_Task( void *pvParameters );
|
||||
|
||||
/*
|
||||
* The task that handles the USB stack.
|
||||
*/
|
||||
extern void vUSBTask( void *pvParameters );
|
||||
|
||||
/*
|
||||
* Simply returns the current status message for display on served WEB pages.
|
||||
*/
|
||||
char *pcGetTaskStatusMessage( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Holds the status message displayed by the WEB server. */
|
||||
static char *pcStatusMessage = mainPASS_STATUS_MESSAGE;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
int main( void )
|
||||
{
|
||||
/* Configure the hardware for use by this demo. */
|
||||
prvSetupHardware();
|
||||
|
||||
/* Start the standard demo tasks. These are just here to exercise the
|
||||
kernel port and provide examples of how the FreeRTOS API can be used. */
|
||||
vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );
|
||||
vCreateBlockTimeTasks();
|
||||
vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );
|
||||
vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );
|
||||
vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY );
|
||||
vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY );
|
||||
vStartQueuePeekTasks();
|
||||
vStartRecursiveMutexTasks();
|
||||
vStartLEDFlashTasks( mainFLASH_TASK_PRIORITY );
|
||||
|
||||
/* Create the USB task. */
|
||||
xTaskCreate( vUSBTask, ( signed char * ) "USB", configMINIMAL_STACK_SIZE, ( void * ) NULL, tskIDLE_PRIORITY, NULL );
|
||||
|
||||
/* Create the uIP task. The WEB server runs in this task. */
|
||||
xTaskCreate( vuIP_Task, ( signed char * ) "uIP", mainBASIC_WEB_STACK_SIZE, ( void * ) NULL, mainUIP_TASK_PRIORITY, NULL );
|
||||
|
||||
/* Start the scheduler. */
|
||||
vTaskStartScheduler();
|
||||
|
||||
/* Will only get here if there was insufficient memory to create the idle
|
||||
task. The idle task is created within vTaskStartScheduler(). */
|
||||
for( ;; );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vApplicationTickHook( void )
|
||||
{
|
||||
static unsigned long ulTicksSinceLastDisplay = 0;
|
||||
|
||||
/* Called from every tick interrupt as described in the comments at the top
|
||||
of this file.
|
||||
|
||||
Have enough ticks passed to make it time to perform our health status
|
||||
check again? */
|
||||
ulTicksSinceLastDisplay++;
|
||||
if( ulTicksSinceLastDisplay >= mainCHECK_DELAY )
|
||||
{
|
||||
/* Reset the counter so these checks run again in mainCHECK_DELAY
|
||||
ticks time. */
|
||||
ulTicksSinceLastDisplay = 0;
|
||||
|
||||
/* Has an error been found in any task? */
|
||||
if( xAreGenericQueueTasksStillRunning() != pdTRUE )
|
||||
{
|
||||
pcStatusMessage = "An error has been detected in the Generic Queue test/demo.";
|
||||
}
|
||||
else if( xAreQueuePeekTasksStillRunning() != pdTRUE )
|
||||
{
|
||||
pcStatusMessage = "An error has been detected in the Peek Queue test/demo.";
|
||||
}
|
||||
else if( xAreBlockingQueuesStillRunning() != pdTRUE )
|
||||
{
|
||||
pcStatusMessage = "An error has been detected in the Block Queue test/demo.";
|
||||
}
|
||||
else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )
|
||||
{
|
||||
pcStatusMessage = "An error has been detected in the Block Time test/demo.";
|
||||
}
|
||||
else if( xAreSemaphoreTasksStillRunning() != pdTRUE )
|
||||
{
|
||||
pcStatusMessage = "An error has been detected in the Semaphore test/demo.";
|
||||
}
|
||||
else if( xArePollingQueuesStillRunning() != pdTRUE )
|
||||
{
|
||||
pcStatusMessage = "An error has been detected in the Poll Queue test/demo.";
|
||||
}
|
||||
else if( xAreIntegerMathsTaskStillRunning() != pdTRUE )
|
||||
{
|
||||
pcStatusMessage = "An error has been detected in the Int Math test/demo.";
|
||||
}
|
||||
else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )
|
||||
{
|
||||
pcStatusMessage = "An error has been detected in the Mutex test/demo.";
|
||||
}
|
||||
}
|
||||
|
||||
disk_timerproc();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
char *pcGetTaskStatusMessage( void )
|
||||
{
|
||||
/* Not bothered about a critical section here. */
|
||||
return pcStatusMessage;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void prvSetupHardware( void )
|
||||
{
|
||||
/* Disable peripherals power. */
|
||||
SC->PCONP = 0;
|
||||
|
||||
/* Enable GPIO power. */
|
||||
SC->PCONP = PCONP_PCGPIO;
|
||||
|
||||
/* Disable TPIU. */
|
||||
PINCON->PINSEL10 = 0;
|
||||
|
||||
/* Setup the peripheral bus to be the same as the PLL output (64 MHz). */
|
||||
SC->PCLKSEL0 = 0x05555555;
|
||||
|
||||
/* Configure the LEDs. */
|
||||
vParTestInitialise();
|
||||
|
||||
/* Configure the SPI for communicating with the SD card. */
|
||||
disk_init_spi();
|
||||
|
||||
{
|
||||
FATFS fs;
|
||||
FIL f;
|
||||
static char c[ 2048 ];
|
||||
UINT BytesRead;
|
||||
|
||||
f_mount( 0, &fs );
|
||||
f_open( &f, "/test.htm", FA_READ );
|
||||
f_read( &f, c, 2048, &BytesRead );
|
||||
}
|
||||
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName )
|
||||
{
|
||||
/* This function will get called if a task overflows its stack. */
|
||||
|
||||
( void ) pxTask;
|
||||
( void ) pcTaskName;
|
||||
|
||||
for( ;; );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vConfigureTimerForRunTimeStats( void )
|
||||
{
|
||||
const unsigned long TCR_COUNT_RESET = 2, CTCR_CTM_TIMER = 0x00, TCR_COUNT_ENABLE = 0x01;
|
||||
|
||||
/* This function configures a timer that is used as the time base when
|
||||
collecting run time statistical information - basically the percentage
|
||||
of CPU time that each task is utilising. It is called automatically when
|
||||
the scheduler is started (assuming configGENERATE_RUN_TIME_STATS is set
|
||||
to 1). */
|
||||
|
||||
/* Power up and feed the timer. */
|
||||
SC->PCONP |= 0x02UL;
|
||||
SC->PCLKSEL0 = (SC->PCLKSEL0 & (~(0x3<<2))) | (0x01 << 2);
|
||||
|
||||
/* Reset Timer 0 */
|
||||
TIM0->TCR = TCR_COUNT_RESET;
|
||||
|
||||
/* Just count up. */
|
||||
TIM0->CTCR = CTCR_CTM_TIMER;
|
||||
|
||||
/* Prescale to a frequency that is good enough to get a decent resolution,
|
||||
but not too fast so as to overflow all the time. */
|
||||
TIM0->PR = ( configCPU_CLOCK_HZ / 10000UL ) - 1UL;
|
||||
|
||||
/* Start the counter. */
|
||||
TIM0->TCR = TCR_COUNT_ENABLE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
Loading…
Reference in New Issue