Start of new demo added. Still a long way to go.

This commit is contained in:
Richard Barry 2010-01-24 21:00:36 +00:00
parent 9849c9ccab
commit ef57fa8947
34 changed files with 9830 additions and 0 deletions

View File

@ -0,0 +1,772 @@
/* 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;
}

View File

@ -0,0 +1,772 @@
/* 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;
}

View File

@ -0,0 +1,78 @@
/*-----------------------------------------------------------------------
/ 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 */
void disk_init_spi( void );
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

View File

@ -0,0 +1,77 @@
/*-----------------------------------------------------------------------
/ 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

View File

@ -0,0 +1,166 @@
/*---------------------------------------------------------------------------/
/ 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 437
/* 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 */

View File

@ -0,0 +1,166 @@
/*---------------------------------------------------------------------------/
/ 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 */

View File

@ -0,0 +1,165 @@
/*
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.
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#include "LPC17xx.h"
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*----------------------------------------------------------*/
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )
#define configUSE_TICK_HOOK 1
#define configCPU_CLOCK_HZ ( ( unsigned long ) 99000000 )
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 80 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 19 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 12 )
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 0
#define configUSE_CO_ROUTINES 0
#define configUSE_MUTEXES 1
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
#define configUSE_COUNTING_SEMAPHORES 0
#define configUSE_ALTERNATIVE_API 0
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configUSE_RECURSIVE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 10
#define configGENERATE_RUN_TIME_STATS 1
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
/*-----------------------------------------------------------
* Ethernet configuration.
*-----------------------------------------------------------*/
/* MAC address configuration. */
#define configMAC_ADDR0 0x00
#define configMAC_ADDR1 0x12
#define configMAC_ADDR2 0x13
#define configMAC_ADDR3 0x10
#define configMAC_ADDR4 0x15
#define configMAC_ADDR5 0x11
/* IP address configuration. */
#define configIP_ADDR0 192
#define configIP_ADDR1 168
#define configIP_ADDR2 0
#define configIP_ADDR3 201
/* Netmask configuration. */
#define configNET_MASK0 255
#define configNET_MASK1 255
#define configNET_MASK2 255
#define configNET_MASK3 0
/* Use the system definition, if there is one */
#ifdef __NVIC_PRIO_BITS
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 5 /* 32 priority levels */
#endif
/* The lowest priority. */
#define configKERNEL_INTERRUPT_PRIORITY ( 31 << (8 - configPRIO_BITS) )
/* Priority 5, or 160 as only the top three bits are implemented. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( 5 << (8 - configPRIO_BITS) )
/* Priorities passed to NVIC_SetPriority() do not require shifting as the
function does the shifting itself. Note these priorities need to be equal to
or lower than configMAX_SYSCALL_INTERRUPT_PRIORITY - therefore the numeric
value needs to be equal to or greater than 5 (on the Cortex M3 the lower the
numeric value the higher the interrupt priority). */
#define configEMAC_INTERRUPT_PRIORITY 5
#define configUSB_INTERRUPT_PRIORITY 6
/*-----------------------------------------------------------
* Macros required to setup the timer for the run time stats.
*-----------------------------------------------------------*/
extern void vConfigureTimerForRunTimeStats( void );
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats()
#define portGET_RUN_TIME_COUNTER_VALUE() TIM0->TC
/* The structure that is passed on the xLCDQueue. Put here for convenience. */
typedef struct
{
char *pcMessage;
} xLCDMessage;
#endif /* FREERTOS_CONFIG_H */

View File

@ -0,0 +1,61 @@
/*
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.
*/
#ifndef LED_HH
#define LED_HH
void vToggleLED( unsigned long ulLED );
void vSetLEDState( unsigned long ulLED, long lState );
long lGetLEDState( unsigned long ulLED );
#endif

View File

@ -0,0 +1,364 @@
/*****************************************************************************
* Copyright (c) 2009 Rowley Associates Limited. *
* *
* This file may be distributed under the terms of the License Agreement *
* provided with this software. *
* *
* THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE *
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
*****************************************************************************/
/*****************************************************************************
* Preprocessor Definitions
* ------------------------
*
* STARTUP_FROM_RESET
*
* If defined, the program will startup from power-on/reset. If not defined
* the program will just loop endlessly from power-on/reset.
*
* This definition is not defined by default on this target because the
* debugger is unable to reset this target and maintain control of it over the
* JTAG interface. The advantage of doing this is that it allows the debugger
* to reset the CPU and run programs from a known reset CPU state on each run.
* It also acts as a safety net if you accidently download a program in FLASH
* that crashes and prevents the debugger from taking control over JTAG
* rendering the target unusable over JTAG. The obvious disadvantage of doing
* this is that your application will not startup without the debugger.
*
* We advise that on this target you keep STARTUP_FROM_RESET undefined whilst
* you are developing and only define STARTUP_FROM_RESET when development is
* complete.A
*
*
* CONFIGURE_USB
*
* If defined, the USB clock will be configured.
*
*****************************************************************************/
#include <LPC1000.h>
#if OSCILLATOR_CLOCK_FREQUENCY==12000000
#ifdef FULL_SPEED
/* Fosc = 12Mhz, Fcco = 400Mhz, cclk = 100Mhz */
#ifndef PLL0CFG_VAL
#define PLL0CFG_VAL ((49 << PLL0CFG_MSEL0_BIT) | (2 << PLL0CFG_NSEL0_BIT))
#endif
#ifndef CCLKCFG_VAL
#define CCLKCFG_VAL 3
#endif
#ifndef FLASHCFG_VAL
#define FLASHCFG_VAL 0x0000403A
#endif
#else
/* Fosc = 12Mhz, Fcco = 288Mhz, cclk = 72Mhz */
#ifndef PLL0CFG_VAL
#define PLL0CFG_VAL ((11 << PLL0CFG_MSEL0_BIT) | (0 << PLL0CFG_NSEL0_BIT))
#endif
#ifndef CCLKCFG_VAL
#define CCLKCFG_VAL 3
#endif
#ifndef FLASHCFG_VAL
#define FLASHCFG_VAL 0x0000303A
#endif
#endif
/* Fosc = 12Mhz, Fcco = 192Mhz, usbclk = 48Mhz */
#ifndef PLL1CFG_VAL
#define PLL1CFG_VAL ((3 << PLL1CFG_MSEL1_BIT) | (1 << PLL1CFG_PSEL1_BIT))
#endif
#endif
.global reset_handler
.syntax unified
.section .vectors, "ax"
.code 16
.align 0
.global _vectors
.macro DEFAULT_ISR_HANDLER name=
.thumb_func
.weak \name
\name:
1: b 1b /* endless loop */
.endm
.extern xPortPendSVHandler
.extern xPortSysTickHandler
.extern vPortSVCHandler
.extern vEMAC_ISR;
_vectors:
.word __stack_end__
#ifdef STARTUP_FROM_RESET
.word reset_handler
#else
.word reset_wait
#endif /* STARTUP_FROM_RESET */
.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
.word UsageFault_Handler
.word 0 // Reserved
.word 0 // Reserved
.word 0 // Reserved
.word 0 // Reserved
.word vPortSVCHandler
.word DebugMon_Handler
.word 0 // Reserved
.word xPortPendSVHandler
.word xPortSysTickHandler
.word WDT_IRQHandler
.word TIMER0_IRQHandler
.word TIMER1_IRQHandler
.word TIMER2_IRQHandler
.word TIMER3_IRQHandler
.word UART0_IRQHandler
.word UART1_IRQHandler
.word UART2_IRQHandler
.word UART3_IRQHandler
.word PWM1_IRQHandler
.word I2C0_IRQHandler
.word I2C1_IRQHandler
.word I2C2_IRQHandler
.word SPI_IRQHandler
.word SSP0_IRQHandler
.word SSP1_IRQHandler
.word PLL0_IRQHandler
.word RTC_IRQHandler
.word EINT0_IRQHandler
.word EINT1_IRQHandler
.word EINT2_IRQHandler
.word EINT3_IRQHandler
.word ADC_IRQHandler
.word BOD_IRQHandler
.word USB_IRQHandler
.word CAN_IRQHandler
.word GPDMA_IRQHandler
.word I2S_IRQHandler
.word vEMAC_ISR
.word RIT_IRQHandler
.word MCPWM_IRQHandler
.word QEI_IRQHandler
.word PLL1_IRQHandler
.word USBACT_IRQHandler
.word CANACT_IRQHandler
.section .init, "ax"
.thumb_func
reset_handler:
#ifndef __FLASH_BUILD
/* If this is a RAM build, configure vector table offset register to point
to the RAM vector table. */
ldr r0, =0xE000ED08
ldr r1, =_vectors
str r1, [r0]
#endif
ldr r0, =SC_BASE_ADDRESS
/* Configure PLL0 Multiplier/Divider */
ldr r1, [r0, #PLL0STAT_OFFSET]
tst r1, #PLL0STAT_PLLC0_STAT
beq 1f
/* Disconnect PLL0 */
ldr r1, =PLL0CON_PLLE0
str r1, [r0, #PLL0CON_OFFSET]
mov r1, #0xAA
str r1, [r0, #PLL0FEED_OFFSET]
mov r1, #0x55
str r1, [r0, #PLL0FEED_OFFSET]
1:
/* Disable PLL0 */
ldr r1, =0
str r1, [r0, #PLL0CON_OFFSET]
mov r1, #0xAA
str r1, [r0, #PLL0FEED_OFFSET]
mov r1, #0x55
str r1, [r0, #PLL0FEED_OFFSET]
/* Enable main oscillator */
ldr r1, [r0, #SCS_OFFSET]
orr r1, r1, #SCS_OSCEN
str r1, [r0, #SCS_OFFSET]
1:
ldr r1, [r0, #SCS_OFFSET]
tst r1, #SCS_OSCSTAT
beq 1b
/* Select main oscillator as the PLL0 clock source */
ldr r1, =1
str r1, [r0, #CLKSRCSEL_OFFSET]
/* Set PLL0CFG */
ldr r1, =PLL0CFG_VAL
str r1, [r0, #PLL0CFG_OFFSET]
mov r1, #0xAA
str r1, [r0, #PLL0FEED_OFFSET]
mov r1, #0x55
str r1, [r0, #PLL0FEED_OFFSET]
/* Enable PLL0 */
ldr r1, =PLL0CON_PLLE0
str r1, [r0, #PLL0CON_OFFSET]
mov r1, #0xAA
str r1, [r0, #PLL0FEED_OFFSET]
mov r1, #0x55
str r1, [r0, #PLL0FEED_OFFSET]
#ifdef CCLKCFG_VAL
/* Set the CPU clock divider */
ldr r1, =CCLKCFG_VAL
str r1, [r0, #CCLKCFG_OFFSET]
#endif
#ifdef FLASHCFG_VAL
/* Configure the FLASH accelerator */
ldr r1, =FLASHCFG_VAL
str r1, [r0, #FLASHCFG_OFFSET]
#endif
/* Wait for PLL0 to lock */
1:
ldr r1, [r0, #PLL0STAT_OFFSET]
tst r1, #PLL0STAT_PLOCK0
beq 1b
/* PLL0 Locked, connect PLL as clock source */
mov r1, #(PLL0CON_PLLE0 | PLL0CON_PLLC0)
str r1, [r0, #PLL0CON_OFFSET]
mov r1, #0xAA
str r1, [r0, #PLL0FEED_OFFSET]
mov r1, #0x55
str r1, [r0, #PLL0FEED_OFFSET]
/* Wait for PLL0 to connect */
1:
ldr r1, [r0, #PLL0STAT_OFFSET]
tst r1, #PLL0STAT_PLLC0_STAT
beq 1b
#ifdef CONFIGURE_USB
/* Configure PLL1 Multiplier/Divider */
ldr r1, [r0, #PLL1STAT_OFFSET]
tst r1, #PLL1STAT_PLLC1_STAT
beq 1f
/* Disconnect PLL1 */
ldr r1, =PLL1CON_PLLE1
str r1, [r0, #PLL1CON_OFFSET]
mov r1, #0xAA
str r1, [r0, #PLL1FEED_OFFSET]
mov r1, #0x55
str r1, [r0, #PLL1FEED_OFFSET]
1:
/* Disable PLL1 */
ldr r1, =0
str r1, [r0, #PLL1CON_OFFSET]
mov r1, #0xAA
str r1, [r0, #PLL1FEED_OFFSET]
mov r1, #0x55
str r1, [r0, #PLL1FEED_OFFSET]
/* Set PLL1CFG */
ldr r1, =PLL1CFG_VAL
str r1, [r0, #PLL1CFG_OFFSET]
mov r1, #0xAA
str r1, [r0, #PLL1FEED_OFFSET]
mov r1, #0x55
str r1, [r0, #PLL1FEED_OFFSET]
/* Enable PLL1 */
ldr r1, =PLL1CON_PLLE1
str r1, [r0, #PLL1CON_OFFSET]
mov r1, #0xAA
str r1, [r0, #PLL1FEED_OFFSET]
mov r1, #0x55
str r1, [r0, #PLL1FEED_OFFSET]
/* Wait for PLL1 to lock */
1:
ldr r1, [r0, #PLL1STAT_OFFSET]
tst r1, #PLL1STAT_PLOCK1
beq 1b
/* PLL1 Locked, connect PLL as clock source */
mov r1, #(PLL1CON_PLLE1 | PLL1CON_PLLC1)
str r1, [r0, #PLL1CON_OFFSET]
mov r1, #0xAA
str r1, [r0, #PLL1FEED_OFFSET]
mov r1, #0x55
str r1, [r0, #PLL1FEED_OFFSET]
/* Wait for PLL1 to connect */
1:
ldr r1, [r0, #PLL1STAT_OFFSET]
tst r1, #PLL1STAT_PLLC1_STAT
beq 1b
#endif
b _start
DEFAULT_ISR_HANDLER NMI_Handler
DEFAULT_ISR_HANDLER HardFault_Handler
DEFAULT_ISR_HANDLER MemManage_Handler
DEFAULT_ISR_HANDLER BusFault_Handler
DEFAULT_ISR_HANDLER UsageFault_Handler
DEFAULT_ISR_HANDLER SVC_Handler
DEFAULT_ISR_HANDLER DebugMon_Handler
DEFAULT_ISR_HANDLER PendSV_Handler
DEFAULT_ISR_HANDLER SysTick_Handler
DEFAULT_ISR_HANDLER WDT_IRQHandler
DEFAULT_ISR_HANDLER TIMER0_IRQHandler
DEFAULT_ISR_HANDLER TIMER1_IRQHandler
DEFAULT_ISR_HANDLER TIMER2_IRQHandler
DEFAULT_ISR_HANDLER TIMER3_IRQHandler
DEFAULT_ISR_HANDLER UART0_IRQHandler
DEFAULT_ISR_HANDLER UART1_IRQHandler
DEFAULT_ISR_HANDLER UART2_IRQHandler
DEFAULT_ISR_HANDLER UART3_IRQHandler
DEFAULT_ISR_HANDLER PWM1_IRQHandler
DEFAULT_ISR_HANDLER I2C0_IRQHandler
DEFAULT_ISR_HANDLER I2C1_IRQHandler
DEFAULT_ISR_HANDLER I2C2_IRQHandler
DEFAULT_ISR_HANDLER SPI_IRQHandler
DEFAULT_ISR_HANDLER SSP0_IRQHandler
DEFAULT_ISR_HANDLER SSP1_IRQHandler
DEFAULT_ISR_HANDLER PLL0_IRQHandler
DEFAULT_ISR_HANDLER RTC_IRQHandler
DEFAULT_ISR_HANDLER EINT0_IRQHandler
DEFAULT_ISR_HANDLER EINT1_IRQHandler
DEFAULT_ISR_HANDLER EINT2_IRQHandler
DEFAULT_ISR_HANDLER EINT3_IRQHandler
DEFAULT_ISR_HANDLER ADC_IRQHandler
DEFAULT_ISR_HANDLER BOD_IRQHandler
DEFAULT_ISR_HANDLER USB_IRQHandler
DEFAULT_ISR_HANDLER CAN_IRQHandler
DEFAULT_ISR_HANDLER GPDMA_IRQHandler
DEFAULT_ISR_HANDLER I2S_IRQHandler
DEFAULT_ISR_HANDLER ENET_IRQHandler
DEFAULT_ISR_HANDLER RIT_IRQHandler
DEFAULT_ISR_HANDLER MCPWM_IRQHandler
DEFAULT_ISR_HANDLER QEI_IRQHandler
DEFAULT_ISR_HANDLER PLL1_IRQHandler
DEFAULT_ISR_HANDLER USBACT_IRQHandler
DEFAULT_ISR_HANDLER CANACT_IRQHandler
#ifndef STARTUP_FROM_RESET
DEFAULT_ISR_HANDLER reset_wait
#endif /* STARTUP_FROM_RESET */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,460 @@
/*
LPCUSB, an USB device driver for LPC microcontrollers
Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
Minimal implementation of a USB serial port, using the CDC class.
This example application simply echoes everything it receives right back
to the host.
Windows:
Extract the usbser.sys file from .cab file in C:\WINDOWS\Driver Cache\i386
and store it somewhere (C:\temp is a good place) along with the usbser.inf
file. Then plug in the LPC176x and direct windows to the usbser driver.
Windows then creates an extra COMx port that you can open in a terminal
program, like hyperterminal. [Note for FreeRTOS users - the required .inf
file is included in the project directory.]
Linux:
The device should be recognised automatically by the cdc_acm driver,
which creates a /dev/ttyACMx device file that acts just like a regular
serial port.
*/
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include <stdio.h>
#include <string.h>
#include "usbapi.h"
#include "usbdebug.h"
#include "usbstruct.h"
#include "LPC17xx.h"
#define usbMAX_SEND_BLOCK ( 20 / portTICK_RATE_MS )
#define usbBUFFER_LEN ( 20 )
#define INCREMENT_ECHO_BY 1
#define BAUD_RATE 115200
#define INT_IN_EP 0x81
#define BULK_OUT_EP 0x05
#define BULK_IN_EP 0x82
#define MAX_PACKET_SIZE 64
#define LE_WORD(x) ((x)&0xFF),((x)>>8)
// CDC definitions
#define CS_INTERFACE 0x24
#define CS_ENDPOINT 0x25
#define SET_LINE_CODING 0x20
#define GET_LINE_CODING 0x21
#define SET_CONTROL_LINE_STATE 0x22
// data structure for GET_LINE_CODING / SET_LINE_CODING class requests
typedef struct {
unsigned long dwDTERate;
unsigned char bCharFormat;
unsigned char bParityType;
unsigned char bDataBits;
} TLineCoding;
static TLineCoding LineCoding = {115200, 0, 0, 8};
static unsigned char abBulkBuf[64];
static unsigned char abClassReqData[8];
static xQueueHandle xRxedChars = NULL, xCharsForTx = NULL;
// forward declaration of interrupt handler
void USBIntHandler(void);
static const unsigned char abDescriptors[] = {
// device descriptor
0x12,
DESC_DEVICE,
LE_WORD(0x0101), // bcdUSB
0x02, // bDeviceClass
0x00, // bDeviceSubClass
0x00, // bDeviceProtocol
MAX_PACKET_SIZE0, // bMaxPacketSize
LE_WORD(0xFFFF), // idVendor
LE_WORD(0x0005), // idProduct
LE_WORD(0x0100), // bcdDevice
0x01, // iManufacturer
0x02, // iProduct
0x03, // iSerialNumber
0x01, // bNumConfigurations
// configuration descriptor
0x09,
DESC_CONFIGURATION,
LE_WORD(67), // wTotalLength
0x02, // bNumInterfaces
0x01, // bConfigurationValue
0x00, // iConfiguration
0xC0, // bmAttributes
0x32, // bMaxPower
// control class interface
0x09,
DESC_INTERFACE,
0x00, // bInterfaceNumber
0x00, // bAlternateSetting
0x01, // bNumEndPoints
0x02, // bInterfaceClass
0x02, // bInterfaceSubClass
0x01, // bInterfaceProtocol, linux requires value of 1 for the cdc_acm module
0x00, // iInterface
// header functional descriptor
0x05,
CS_INTERFACE,
0x00,
LE_WORD(0x0110),
// call management functional descriptor
0x05,
CS_INTERFACE,
0x01,
0x01, // bmCapabilities = device handles call management
0x01, // bDataInterface
// ACM functional descriptor
0x04,
CS_INTERFACE,
0x02,
0x02, // bmCapabilities
// union functional descriptor
0x05,
CS_INTERFACE,
0x06,
0x00, // bMasterInterface
0x01, // bSlaveInterface0
// notification EP
0x07,
DESC_ENDPOINT,
INT_IN_EP, // bEndpointAddress
0x03, // bmAttributes = intr
LE_WORD(8), // wMaxPacketSize
0x0A, // bInterval
// data class interface descriptor
0x09,
DESC_INTERFACE,
0x01, // bInterfaceNumber
0x00, // bAlternateSetting
0x02, // bNumEndPoints
0x0A, // bInterfaceClass = data
0x00, // bInterfaceSubClass
0x00, // bInterfaceProtocol
0x00, // iInterface
// data EP OUT
0x07,
DESC_ENDPOINT,
BULK_OUT_EP, // bEndpointAddress
0x02, // bmAttributes = bulk
LE_WORD(MAX_PACKET_SIZE), // wMaxPacketSize
0x00, // bInterval
// data EP in
0x07,
DESC_ENDPOINT,
BULK_IN_EP, // bEndpointAddress
0x02, // bmAttributes = bulk
LE_WORD(MAX_PACKET_SIZE), // wMaxPacketSize
0x00, // bInterval
// string descriptors
0x04,
DESC_STRING,
LE_WORD(0x0409),
0x0E,
DESC_STRING,
'L', 0, 'P', 0, 'C', 0, 'U', 0, 'S', 0, 'B', 0,
0x14,
DESC_STRING,
'U', 0, 'S', 0, 'B', 0, 'S', 0, 'e', 0, 'r', 0, 'i', 0, 'a', 0, 'l', 0,
0x12,
DESC_STRING,
'D', 0, 'E', 0, 'A', 0, 'D', 0, 'C', 0, '0', 0, 'D', 0, 'E', 0,
// terminating zero
0
};
/**
Local function to handle incoming bulk data
@param [in] bEP
@param [in] bEPStatus
*/
static void BulkOut(unsigned char bEP, unsigned char bEPStatus)
{
int i, iLen;
long lHigherPriorityTaskWoken = pdFALSE;
( void ) bEPStatus;
// get data from USB into intermediate buffer
iLen = USBHwEPRead(bEP, abBulkBuf, sizeof(abBulkBuf));
for (i = 0; i < iLen; i++) {
// put into queue
xQueueSendFromISR( xRxedChars, &( abBulkBuf[ i ] ), &lHigherPriorityTaskWoken );
}
portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );
}
/**
Local function to handle outgoing bulk data
@param [in] bEP
@param [in] bEPStatus
*/
static void BulkIn(unsigned char bEP, unsigned char bEPStatus)
{
int i, iLen;
long lHigherPriorityTaskWoken = pdFALSE;
( void ) bEPStatus;
if (uxQueueMessagesWaitingFromISR( xCharsForTx ) == 0) {
// no more data, disable further NAK interrupts until next USB frame
USBHwNakIntEnable(0);
return;
}
// get bytes from transmit FIFO into intermediate buffer
for (i = 0; i < MAX_PACKET_SIZE; i++) {
if( xQueueReceiveFromISR( xCharsForTx, ( &abBulkBuf[i] ), &lHigherPriorityTaskWoken ) != pdPASS )
{
break;
}
}
iLen = i;
// send over USB
if (iLen > 0) {
USBHwEPWrite(bEP, abBulkBuf, iLen);
}
portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );
}
/**
Local function to handle the USB-CDC class requests
@param [in] pSetup
@param [out] piLen
@param [out] ppbData
*/
static BOOL HandleClassRequest(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData)
{
switch (pSetup->bRequest) {
// set line coding
case SET_LINE_CODING:
DBG("SET_LINE_CODING\n");
memcpy((unsigned char *)&LineCoding, *ppbData, 7);
*piLen = 7;
DBG("dwDTERate=%u, bCharFormat=%u, bParityType=%u, bDataBits=%u\n",
LineCoding.dwDTERate,
LineCoding.bCharFormat,
LineCoding.bParityType,
LineCoding.bDataBits);
break;
// get line coding
case GET_LINE_CODING:
DBG("GET_LINE_CODING\n");
*ppbData = (unsigned char *)&LineCoding;
*piLen = 7;
break;
// set control line state
case SET_CONTROL_LINE_STATE:
// bit0 = DTR, bit = RTS
DBG("SET_CONTROL_LINE_STATE %X\n", pSetup->wValue);
break;
default:
return FALSE;
}
return TRUE;
}
/**
Writes one character to VCOM port
@param [in] c character to write
@returns character written, or EOF if character could not be written
*/
int VCOM_putchar(int c)
{
char cc = ( char ) c;
if( xQueueSend( xCharsForTx, &cc, usbMAX_SEND_BLOCK ) == pdPASS )
{
return c;
}
else
{
return EOF;
}
}
/**
Reads one character from VCOM port
@returns character read, or EOF if character could not be read
*/
int VCOM_getchar(void)
{
unsigned char c;
/* Block the task until a character is available. */
xQueueReceive( xRxedChars, &c, portMAX_DELAY );
return c;
}
/**
Interrupt handler
Simply calls the USB ISR
*/
//void USBIntHandler(void)
void USB_IRQHandler(void)
{
USBHwISR();
}
static void USBFrameHandler(unsigned short wFrame)
{
( void ) wFrame;
if( uxQueueMessagesWaitingFromISR( xCharsForTx ) > 0 )
{
// data available, enable NAK interrupt on bulk in
USBHwNakIntEnable(INACK_BI);
}
}
// CodeRed - added CPUcpsie
unsigned long CPUcpsie(void)
{
unsigned long ulRet;
//
// Read PRIMASK and enable interrupts.
//
__asm(" mrs %0, PRIMASK\n"
" cpsie i\n"
" bx lr\n"
: "=r" (ulRet));
//
// The return is handled in the inline assembly, but the compiler will
// still complain if there is not an explicit return here (despite the fact
// that this does not result in any code being produced because of the
// naked attribute).
//
return(ulRet);
}
void vUSBTask( void *pvParameters )
{
int c;
/* Just to prevent compiler warnings about the unused parameter. */
( void ) pvParameters;
DBG("Initialising USB stack\n");
xRxedChars = xQueueCreate( usbBUFFER_LEN, sizeof( char ) );
xCharsForTx = xQueueCreate( usbBUFFER_LEN, sizeof( char ) );
if( ( xRxedChars == NULL ) || ( xCharsForTx == NULL ) )
{
/* Not enough heap available to create the buffer queues, can't do
anything so just delete ourselves. */
vTaskDelete( NULL );
}
// initialise stack
USBInit();
// register descriptors
USBRegisterDescriptors(abDescriptors);
// register class request handler
USBRegisterRequestHandler(REQTYPE_TYPE_CLASS, HandleClassRequest, abClassReqData);
// register endpoint handlers
USBHwRegisterEPIntHandler(INT_IN_EP, NULL);
USBHwRegisterEPIntHandler(BULK_IN_EP, BulkIn);
USBHwRegisterEPIntHandler(BULK_OUT_EP, BulkOut);
// register frame handler
USBHwRegisterFrameHandler(USBFrameHandler);
// enable bulk-in interrupts on NAKs
USBHwNakIntEnable(INACK_BI);
DBG("Starting USB communication\n");
NVIC_SetPriority( USB_IRQn, configUSB_INTERRUPT_PRIORITY );
NVIC_EnableIRQ( USB_IRQn );
// connect to bus
DBG("Connecting to USB bus\n");
USBHwConnect(TRUE);
// echo any character received (do USB stuff in interrupt)
for( ;; )
{
c = VCOM_getchar();
if (c != EOF)
{
// Echo character back with INCREMENT_ECHO_BY offset, so for example if
// INCREMENT_ECHO_BY is 1 and 'A' is received, 'B' will be echoed back.
VCOM_putchar(c + INCREMENT_ECHO_BY );
}
}
}

View File

@ -0,0 +1,38 @@
/*****************************************************************************
* type.h: Type definition Header file for NXP LPC17xx Family
* Microprocessors
*
* Copyright(C) 2008, NXP Semiconductor
* All rights reserved.
*
* History
* 2008.08.21 ver 1.00 Prelimnary version, first Release
*
******************************************************************************/
#ifndef __TYPE_H__
#define __TYPE_H__
#ifndef NULL
#define NULL ((void *)0)
#endif
#ifndef FALSE
#define FALSE (0)
#endif
#ifndef TRUE
#define TRUE (1)
#endif
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef unsigned int BOOL;
typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;
typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
/* Pointer to Function returning Void (any number of parameters) */
typedef void (*PFV)();
#endif /* __TYPE_H__ */

View File

@ -0,0 +1,118 @@
/*
LPCUSB, an USB device driver for LPC microcontrollers
Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
@file
*/
#include "usbstruct.h" // for TSetupPacket
/*************************************************************************
USB configuration
**************************************************************************/
#define MAX_PACKET_SIZE0 64 /**< maximum packet size for EP 0 */
/*************************************************************************
USB hardware interface
**************************************************************************/
// endpoint status sent through callback
#define EP_STATUS_DATA (1<<0) /**< EP has data */
#define EP_STATUS_STALLED (1<<1) /**< EP is stalled */
#define EP_STATUS_SETUP (1<<2) /**< EP received setup packet */
#define EP_STATUS_ERROR (1<<3) /**< EP data was overwritten by setup packet */
#define EP_STATUS_NACKED (1<<4) /**< EP sent NAK */
// device status sent through callback
#define DEV_STATUS_CONNECT (1<<0) /**< device just got connected */
#define DEV_STATUS_SUSPEND (1<<2) /**< device entered suspend state */
#define DEV_STATUS_RESET (1<<4) /**< device just got reset */
// interrupt bits for NACK events in USBHwNakIntEnable
// (these bits conveniently coincide with the LPC176x USB controller bit)
#define INACK_CI (1<<1) /**< interrupt on NACK for control in */
#define INACK_CO (1<<2) /**< interrupt on NACK for control out */
#define INACK_II (1<<3) /**< interrupt on NACK for interrupt in */
#define INACK_IO (1<<4) /**< interrupt on NACK for interrupt out */
#define INACK_BI (1<<5) /**< interrupt on NACK for bulk in */
#define INACK_BO (1<<6) /**< interrupt on NACK for bulk out */
BOOL USBHwInit (void);
void USBHwISR (void);
void USBHwNakIntEnable (unsigned char bIntBits);
void USBHwConnect (BOOL fConnect);
void USBHwSetAddress (unsigned char bAddr);
void USBHwConfigDevice (BOOL fConfigured);
// endpoint operations
void USBHwEPConfig (unsigned char bEP, unsigned short wMaxPacketSize);
int USBHwEPRead (unsigned char bEP, unsigned char *pbBuf, int iMaxLen);
int USBHwEPWrite (unsigned char bEP, unsigned char *pbBuf, int iLen);
void USBHwEPStall (unsigned char bEP, BOOL fStall);
unsigned char USBHwEPGetStatus (unsigned char bEP);
/** Endpoint interrupt handler callback */
typedef void (TFnEPIntHandler) (unsigned char bEP, unsigned char bEPStatus);
void USBHwRegisterEPIntHandler (unsigned char bEP, TFnEPIntHandler *pfnHandler);
/** Device status handler callback */
typedef void (TFnDevIntHandler) (unsigned char bDevStatus);
void USBHwRegisterDevIntHandler (TFnDevIntHandler *pfnHandler);
/** Frame event handler callback */
typedef void (TFnFrameHandler)(unsigned short wFrame);
void USBHwRegisterFrameHandler(TFnFrameHandler *pfnHandler);
/*************************************************************************
USB application interface
**************************************************************************/
// initialise the complete stack, including HW
BOOL USBInit(void);
/** Request handler callback (standard, vendor, class) */
typedef BOOL (TFnHandleRequest)(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData);
void USBRegisterRequestHandler(int iType, TFnHandleRequest *pfnHandler, unsigned char *pbDataStore);
void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler);
/** Descriptor handler callback */
typedef BOOL (TFnGetDescriptor)(unsigned short wTypeIndex, unsigned short wLangID, int *piLen, unsigned char **ppbData);
/** Default standard request handler */
BOOL USBHandleStandardRequest(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData);
/** Default EP0 handler */
void USBHandleControlTransfer(unsigned char bEP, unsigned char bEPStat);
/** Descriptor handling */
void USBRegisterDescriptors(const unsigned char *pabDescriptors);
BOOL USBGetDescriptor(unsigned short wTypeIndex, unsigned short wLangID, int *piLen, unsigned char **ppbData);

View File

@ -0,0 +1,247 @@
/*
LPCUSB, an USB device driver for LPC microcontrollers
Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @file
Control transfer handler.
This module handles control transfers and is normally installed on the
endpoint 0 callback.
Control transfers can be of the following type:
0 Standard;
1 Class;
2 Vendor;
3 Reserved.
A callback can be installed for each of these control transfers using
USBRegisterRequestHandler.
When an OUT request arrives, data is collected in the data store provided
with the USBRegisterRequestHandler call. When the transfer is done, the
callback is called.
When an IN request arrives, the callback is called immediately to either
put the control transfer data in the data store, or to get a pointer to
control transfer data. The data is then packetised and sent to the host.
*/
#include "usbdebug.h"
#include "usbstruct.h"
#include "usbapi.h"
#define MAX_CONTROL_SIZE 128 /**< maximum total size of control transfer data */
#define MAX_REQ_HANDLERS 4 /**< standard, class, vendor, reserved */
static TSetupPacket Setup; /**< setup packet */
static unsigned char *pbData; /**< pointer to data buffer */
static int iResidue; /**< remaining bytes in buffer */
static int iLen; /**< total length of control transfer */
/** Array of installed request handler callbacks */
static TFnHandleRequest *apfnReqHandlers[4] = {NULL, NULL, NULL, NULL};
/** Array of installed request data pointers */
static unsigned char *apbDataStore[4] = {NULL, NULL, NULL, NULL};
/**
Local function to handle a request by calling one of the installed
request handlers.
In case of data going from host to device, the data is at *ppbData.
In case of data going from device to host, the handler can either
choose to write its data at *ppbData or update the data pointer.
@param [in] pSetup The setup packet
@param [in,out] *piLen Pointer to data length
@param [in,out] ppbData Data buffer.
@return TRUE if the request was handles successfully
*/
static BOOL _HandleRequest(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData)
{
TFnHandleRequest *pfnHandler;
int iType;
iType = REQTYPE_GET_TYPE(pSetup->bmRequestType);
pfnHandler = apfnReqHandlers[iType];
if (pfnHandler == NULL) {
DBG("No handler for reqtype %d\n", iType);
return FALSE;
}
return pfnHandler(pSetup, piLen, ppbData);
}
/**
Local function to stall the control endpoint
@param [in] bEPStat Endpoint status
*/
static void StallControlPipe(unsigned char bEPStat)
{
unsigned char *pb;
int i;
( void ) bEPStat;
USBHwEPStall(0x80, TRUE);
// dump setup packet
DBG("STALL on [");
pb = (unsigned char *)&Setup;
for (i = 0; i < 8; i++) {
DBG(" %02x", *pb++);
}
DBG("] stat=%x\n", bEPStat);
}
/**
Sends next chunk of data (possibly 0 bytes) to host
*/
static void DataIn(void)
{
int iChunk;
if( MAX_PACKET_SIZE0 < iResidue )
{
iChunk = MAX_PACKET_SIZE0;
}
else
{
iChunk = iResidue;
}
USBHwEPWrite(0x80, pbData, iChunk);
pbData += iChunk;
iResidue -= iChunk;
}
/**
* Handles IN/OUT transfers on EP0
*
* @param [in] bEP Endpoint address
* @param [in] bEPStat Endpoint status
*/
void USBHandleControlTransfer(unsigned char bEP, unsigned char bEPStat)
{
int iChunk, iType;
if (bEP == 0x00) {
// OUT transfer
if (bEPStat & EP_STATUS_SETUP) {
// setup packet, reset request message state machine
USBHwEPRead(0x00, (unsigned char *)&Setup, sizeof(Setup));
DBG("S%x", Setup.bRequest);
// defaults for data pointer and residue
iType = REQTYPE_GET_TYPE(Setup.bmRequestType);
pbData = apbDataStore[iType];
iResidue = Setup.wLength;
iLen = Setup.wLength;
if ((Setup.wLength == 0) ||
(REQTYPE_GET_DIR(Setup.bmRequestType) == REQTYPE_DIR_TO_HOST)) {
// ask installed handler to process request
if (!_HandleRequest(&Setup, &iLen, &pbData)) {
DBG("_HandleRequest1 failed\n");
StallControlPipe(bEPStat);
return;
}
// send smallest of requested and offered length
if( iLen < Setup.wLength )
{
iResidue = iLen;
}
else
{
iResidue = Setup.wLength;
}
// send first part (possibly a zero-length status message)
DataIn();
}
}
else {
if (iResidue > 0) {
// store data
iChunk = USBHwEPRead(0x00, pbData, iResidue);
if (iChunk < 0) {
StallControlPipe(bEPStat);
return;
}
pbData += iChunk;
iResidue -= iChunk;
if (iResidue == 0) {
// received all, send data to handler
iType = REQTYPE_GET_TYPE(Setup.bmRequestType);
pbData = apbDataStore[iType];
if (!_HandleRequest(&Setup, &iLen, &pbData)) {
DBG("_HandleRequest2 failed\n");
StallControlPipe(bEPStat);
return;
}
// send status to host
DataIn();
}
}
else {
// absorb zero-length status message
iChunk = USBHwEPRead(0x00, NULL, 0);
DBG(iChunk > 0 ? "?" : "");
}
}
}
else if (bEP == 0x80) {
// IN transfer
// send more data if available (possibly a 0-length packet)
DataIn();
}
else {
ASSERT(FALSE);
}
}
/**
Registers a callback for handling requests
@param [in] iType Type of request, e.g. REQTYPE_TYPE_STANDARD
@param [in] *pfnHandler Callback function pointer
@param [in] *pbDataStore Data storage area for this type of request
*/
void USBRegisterRequestHandler(int iType, TFnHandleRequest *pfnHandler, unsigned char *pbDataStore)
{
ASSERT(iType >= 0);
ASSERT(iType < 4);
apfnReqHandlers[iType] = pfnHandler;
apbDataStore[iType] = pbDataStore;
}

View File

@ -0,0 +1,41 @@
/*
LPCUSB, an USB device driver for LPC microcontrollers
Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// CodeRed - comment out this printf, as will use real one from stdio.h
// to implement output via semihosting
//int printf(const char *format, ...);
# include <stdio.h>
#ifdef _DEBUG
#define DBG printf
#define ASSERT(x) if(!(x)){DBG("\nAssertion '%s' failed in %s:%s#%d!\n",#x,__FILE__,__FUNCTION__,__LINE__);while(1);}
#else
#define DBG(x ...)
#define ASSERT(x)
#endif

View File

@ -0,0 +1,521 @@
/*
LPCUSB, an USB device driver for LPC microcontrollers
Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @file
USB hardware layer
*/
#include "usbdebug.h"
#include "usbhw_lpc.h"
#include "usbapi.h"
/** Installed device interrupt handler */
static TFnDevIntHandler *_pfnDevIntHandler = NULL;
/** Installed endpoint interrupt handlers */
static TFnEPIntHandler *_apfnEPIntHandlers[16];
/** Installed frame interrupt handlers */
static TFnFrameHandler *_pfnFrameHandler = NULL;
/** convert from endpoint address to endpoint index */
#define EP2IDX(bEP) ((((bEP)&0xF)<<1)|(((bEP)&0x80)>>7))
/** convert from endpoint index to endpoint address */
#define IDX2EP(idx) ((((idx)<<7)&0x80)|(((idx)>>1)&0xF))
/**
Local function to wait for a device interrupt (and clear it)
@param [in] dwIntr Bitmask of interrupts to wait for
*/
static void Wait4DevInt(unsigned long dwIntr)
{
// wait for specific interrupt
while ((USB->USBDevIntSt & dwIntr) != dwIntr);
// clear the interrupt bits
USB->USBDevIntClr = dwIntr;
}
/**
Local function to send a command to the USB protocol engine
@param [in] bCmd Command to send
*/
static void USBHwCmd(unsigned char bCmd)
{
// clear CDFULL/CCEMTY
USB->USBDevIntClr = CDFULL | CCEMTY;
// write command code
USB->USBCmdCode = 0x00000500 | (bCmd << 16);
Wait4DevInt(CCEMTY);
}
/**
Local function to send a command + data to the USB protocol engine
@param [in] bCmd Command to send
@param [in] bData Data to send
*/
static void USBHwCmdWrite(unsigned char bCmd, unsigned short bData)
{
// write command code
USBHwCmd(bCmd);
// write command data
USB->USBCmdCode = 0x00000100 | (bData << 16);
Wait4DevInt(CCEMTY);
}
/**
Local function to send a command to the USB protocol engine and read data
@param [in] bCmd Command to send
@return the data
*/
static unsigned char USBHwCmdRead(unsigned char bCmd)
{
// write command code
USBHwCmd(bCmd);
// get data
USB->USBCmdCode = 0x00000200 | (bCmd << 16);
Wait4DevInt(CDFULL);
return USB->USBCmdData;
}
/**
'Realizes' an endpoint, meaning that buffer space is reserved for
it. An endpoint needs to be realised before it can be used.
From experiments, it appears that a USB reset causes USBReEP to
re-initialise to 3 (= just the control endpoints).
However, a USB bus reset does not disturb the USBMaxPSize settings.
@param [in] idx Endpoint index
@param [in] wMaxPSize Maximum packet size for this endpoint
*/
static void USBHwEPRealize(int idx, unsigned short wMaxPSize)
{
USB->USBReEP |= (1 << idx);
USB->USBEpInd = idx;
USB->USBMaxPSize = wMaxPSize;
Wait4DevInt(EP_RLZED);
}
/**
Enables or disables an endpoint
@param [in] idx Endpoint index
@param [in] fEnable TRUE to enable, FALSE to disable
*/
static void USBHwEPEnable(int idx, BOOL fEnable)
{
USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fEnable ? 0 : EP_DA);
}
/**
Configures an endpoint and enables it
@param [in] bEP Endpoint number
@param [in] wMaxPacketSize Maximum packet size for this EP
*/
void USBHwEPConfig(unsigned char bEP, unsigned short wMaxPacketSize)
{
int idx;
idx = EP2IDX(bEP);
// realise EP
USBHwEPRealize(idx, wMaxPacketSize);
// enable EP
USBHwEPEnable(idx, TRUE);
}
/**
Registers an endpoint event callback
@param [in] bEP Endpoint number
@param [in] pfnHandler Callback function
*/
void USBHwRegisterEPIntHandler(unsigned char bEP, TFnEPIntHandler *pfnHandler)
{
int idx;
idx = EP2IDX(bEP);
ASSERT(idx<32);
/* add handler to list of EP handlers */
_apfnEPIntHandlers[idx / 2] = pfnHandler;
/* enable EP interrupt */
USB->USBEpIntEn |= (1 << idx);
USB->USBDevIntEn |= EP_SLOW;
DBG("Registered handler for EP 0x%x\n", bEP);
}
/**
Registers an device status callback
@param [in] pfnHandler Callback function
*/
void USBHwRegisterDevIntHandler(TFnDevIntHandler *pfnHandler)
{
_pfnDevIntHandler = pfnHandler;
// enable device interrupt
USB->USBDevIntEn |= DEV_STAT;
DBG("Registered handler for device status\n");
}
/**
Registers the frame callback
@param [in] pfnHandler Callback function
*/
void USBHwRegisterFrameHandler(TFnFrameHandler *pfnHandler)
{
_pfnFrameHandler = pfnHandler;
// enable device interrupt
USB->USBDevIntEn |= FRAME;
DBG("Registered handler for frame\n");
}
/**
Sets the USB address.
@param [in] bAddr Device address to set
*/
void USBHwSetAddress(unsigned char bAddr)
{
USBHwCmdWrite(CMD_DEV_SET_ADDRESS, DEV_EN | bAddr);
}
/**
Connects or disconnects from the USB bus
@param [in] fConnect If TRUE, connect, otherwise disconnect
*/
void USBHwConnect(BOOL fConnect)
{
USBHwCmdWrite(CMD_DEV_STATUS, fConnect ? CON : 0);
}
/**
Enables interrupt on NAK condition
For IN endpoints a NAK is generated when the host wants to read data
from the device, but none is available in the endpoint buffer.
For OUT endpoints a NAK is generated when the host wants to write data
to the device, but the endpoint buffer is still full.
The endpoint interrupt handlers can distinguish regular (ACK) interrupts
from NAK interrupt by checking the bits in their bEPStatus argument.
@param [in] bIntBits Bitmap indicating which NAK interrupts to enable
*/
void USBHwNakIntEnable(unsigned char bIntBits)
{
USBHwCmdWrite(CMD_DEV_SET_MODE, bIntBits);
}
/**
Gets the status from a specific endpoint.
@param [in] bEP Endpoint number
@return Endpoint status byte (containing EP_STATUS_xxx bits)
*/
unsigned char USBHwEPGetStatus(unsigned char bEP)
{
int idx = EP2IDX(bEP);
return USBHwCmdRead(CMD_EP_SELECT | idx);
}
/**
Sets the stalled property of an endpoint
@param [in] bEP Endpoint number
@param [in] fStall TRUE to stall, FALSE to unstall
*/
void USBHwEPStall(unsigned char bEP, BOOL fStall)
{
int idx = EP2IDX(bEP);
USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fStall ? EP_ST : 0);
}
/**
Writes data to an endpoint buffer
@param [in] bEP Endpoint number
@param [in] pbBuf Endpoint data
@param [in] iLen Number of bytes to write
@return TRUE if the data was successfully written or <0 in case of error.
*/
int USBHwEPWrite(unsigned char bEP, unsigned char *pbBuf, int iLen)
{
int idx;
idx = EP2IDX(bEP);
// set write enable for specific endpoint
USB->USBCtrl = WR_EN | ((bEP & 0xF) << 2);
// set packet length
USB->USBTxPLen = iLen;
// write data
while (USB->USBCtrl & WR_EN) {
USB->USBTxData = (pbBuf[3] << 24) | (pbBuf[2] << 16) | (pbBuf[1] << 8) | pbBuf[0];
pbBuf += 4;
}
// select endpoint and validate buffer
USBHwCmd(CMD_EP_SELECT | idx);
USBHwCmd(CMD_EP_VALIDATE_BUFFER);
return iLen;
}
/**
Reads data from an endpoint buffer
@param [in] bEP Endpoint number
@param [in] pbBuf Endpoint data
@param [in] iMaxLen Maximum number of bytes to read
@return the number of bytes available in the EP (possibly more than iMaxLen),
or <0 in case of error.
*/
int USBHwEPRead(unsigned char bEP, unsigned char *pbBuf, int iMaxLen)
{
unsigned int i, idx;
unsigned long dwData, dwLen;
idx = EP2IDX(bEP);
// set read enable bit for specific endpoint
USB->USBCtrl = RD_EN | ((bEP & 0xF) << 2);
// wait for PKT_RDY
do {
dwLen = USB->USBRxPLen;
} while ((dwLen & PKT_RDY) == 0);
// packet valid?
if ((dwLen & DV) == 0) {
return -1;
}
// get length
dwLen &= PKT_LNGTH_MASK;
// get data
dwData = 0;
for (i = 0; i < dwLen; i++) {
if ((i % 4) == 0) {
dwData = USB->USBRxData;
}
if ((pbBuf != NULL) && ((int)i < iMaxLen)) {
pbBuf[i] = dwData & 0xFF;
}
dwData >>= 8;
}
// make sure RD_EN is clear
USB->USBCtrl = 0;
// select endpoint and clear buffer
USBHwCmd(CMD_EP_SELECT | idx);
USBHwCmd(CMD_EP_CLEAR_BUFFER);
return dwLen;
}
/**
Sets the 'configured' state.
All registered endpoints are 'realised' and enabled, and the
'configured' bit is set in the device status register.
@param [in] fConfigured If TRUE, configure device, else unconfigure
*/
void USBHwConfigDevice(BOOL fConfigured)
{
// set configured bit
USBHwCmdWrite(CMD_DEV_CONFIG, fConfigured ? CONF_DEVICE : 0);
}
/**
USB interrupt handler
@todo Get all 11 bits of frame number instead of just 8
Endpoint interrupts are mapped to the slow interrupt
*/
void USBHwISR(void)
{
unsigned long dwStatus;
unsigned long dwIntBit;
unsigned char bEPStat, bDevStat, bStat;
int i;
unsigned short wFrame;
// handle device interrupts
dwStatus = USB->USBDevIntSt;
// frame interrupt
if (dwStatus & FRAME) {
// clear int
USB->USBDevIntClr = FRAME;
// call handler
if (_pfnFrameHandler != NULL) {
wFrame = USBHwCmdRead(CMD_DEV_READ_CUR_FRAME_NR);
_pfnFrameHandler(wFrame);
}
}
// device status interrupt
if (dwStatus & DEV_STAT) {
/* Clear DEV_STAT interrupt before reading DEV_STAT register.
This prevents corrupted device status reads, see
LPC2148 User manual revision 2, 25 july 2006.
*/
USB->USBDevIntClr = DEV_STAT;
bDevStat = USBHwCmdRead(CMD_DEV_STATUS);
if (bDevStat & (CON_CH | SUS_CH | RST)) {
// convert device status into something HW independent
bStat = ((bDevStat & CON) ? DEV_STATUS_CONNECT : 0) |
((bDevStat & SUS) ? DEV_STATUS_SUSPEND : 0) |
((bDevStat & RST) ? DEV_STATUS_RESET : 0);
// call handler
if (_pfnDevIntHandler != NULL) {
_pfnDevIntHandler(bStat);
}
}
}
// endpoint interrupt
if (dwStatus & EP_SLOW) {
// clear EP_SLOW
USB->USBDevIntClr = EP_SLOW;
// check all endpoints
for (i = 0; i < 32; i++) {
dwIntBit = (1 << i);
if (USB->USBEpIntSt & dwIntBit) {
// clear int (and retrieve status)
USB->USBEpIntClr = dwIntBit;
Wait4DevInt(CDFULL);
bEPStat = USB->USBCmdData;
// convert EP pipe stat into something HW independent
bStat = ((bEPStat & EPSTAT_FE) ? EP_STATUS_DATA : 0) |
((bEPStat & EPSTAT_ST) ? EP_STATUS_STALLED : 0) |
((bEPStat & EPSTAT_STP) ? EP_STATUS_SETUP : 0) |
((bEPStat & EPSTAT_EPN) ? EP_STATUS_NACKED : 0) |
((bEPStat & EPSTAT_PO) ? EP_STATUS_ERROR : 0);
// call handler
if (_apfnEPIntHandlers[i / 2] != NULL) {
_apfnEPIntHandlers[i / 2](IDX2EP(i), bStat);
}
}
}
}
}
/**
Initialises the USB hardware
@return TRUE if the hardware was successfully initialised
*/
BOOL USBHwInit(void)
{
// P2.9 -> USB_CONNECT
PINCON->PINSEL4 &= ~0x000C0000;
PINCON->PINSEL4 |= 0x00040000;
// P1.18 -> USB_UP_LED
// P1.30 -> VBUS
PINCON->PINSEL3 &= ~0x30000030;
PINCON->PINSEL3 |= 0x20000010;
// P0.29 -> USB_D+
// P0.30 -> USB_D-
PINCON->PINSEL1 &= ~0x3C000000;
PINCON->PINSEL1 |= 0x14000000;
// enable PUSB
SC->PCONP |= (1 << 31);
USB->OTGClkCtrl = 0x12; /* Dev clock, AHB clock enable */
while ((USB->OTGClkSt & 0x12) != 0x12);
// disable/clear all interrupts for now
USB->USBDevIntEn = 0;
USB->USBDevIntClr = 0xFFFFFFFF;
USB->USBDevIntPri = 0;
USB->USBEpIntEn = 0;
USB->USBEpIntClr = 0xFFFFFFFF;
USB->USBEpIntPri = 0;
// by default, only ACKs generate interrupts
USBHwNakIntEnable(0);
return TRUE;
}

View File

@ -0,0 +1,149 @@
/*
LPCUSB, an USB device driver for LPC microcontrollers
Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
Hardware definitions for the LPC176x USB controller
These are private to the usbhw module
*/
// CodeRed - pull in defines from NXP header file
//#include "NXP\LPC17xx\LPC17xx.h"
#include "LPC17xx.h"
// CodeRed - these registers have been renamed on LPC176x
#define USBReEP USBReEp
#define OTG_CLK_CTRL USBClkCtrl
#define OTG_CLK_STAT USBClkSt
/* USBIntSt bits */
#define USB_INT_REQ_LP (1<<0)
#define USB_INT_REQ_HP (1<<1)
#define USB_INT_REQ_DMA (1<<2)
#define USB_need_clock (1<<8)
#define EN_USB_BITS (1<<31)
/* USBDevInt... bits */
#define FRAME (1<<0)
#define EP_FAST (1<<1)
#define EP_SLOW (1<<2)
#define DEV_STAT (1<<3)
#define CCEMTY (1<<4)
#define CDFULL (1<<5)
#define RxENDPKT (1<<6)
#define TxENDPKT (1<<7)
#define EP_RLZED (1<<8)
#define ERR_INT (1<<9)
/* USBRxPLen bits */
#define PKT_LNGTH (1<<0)
#define PKT_LNGTH_MASK 0x3FF
#define DV (1<<10)
#define PKT_RDY (1<<11)
/* USBCtrl bits */
#define RD_EN (1<<0)
#define WR_EN (1<<1)
#define LOG_ENDPOINT (1<<2)
/* protocol engine command codes */
/* device commands */
#define CMD_DEV_SET_ADDRESS 0xD0
#define CMD_DEV_CONFIG 0xD8
#define CMD_DEV_SET_MODE 0xF3
#define CMD_DEV_READ_CUR_FRAME_NR 0xF5
#define CMD_DEV_READ_TEST_REG 0xFD
#define CMD_DEV_STATUS 0xFE /* read/write */
#define CMD_DEV_GET_ERROR_CODE 0xFF
#define CMD_DEV_READ_ERROR_STATUS 0xFB
/* endpoint commands */
#define CMD_EP_SELECT 0x00
#define CMD_EP_SELECT_CLEAR 0x40
#define CMD_EP_SET_STATUS 0x40
#define CMD_EP_CLEAR_BUFFER 0xF2
#define CMD_EP_VALIDATE_BUFFER 0xFA
/* set address command */
#define DEV_ADDR (1<<0)
#define DEV_EN (1<<7)
/* configure device command */
#define CONF_DEVICE (1<<0)
/* set mode command */
#define AP_CLK (1<<0)
#define INAK_CI (1<<1)
#define INAK_CO (1<<2)
#define INAK_II (1<<3)
#define INAK_IO (1<<4)
#define INAK_BI (1<<5)
#define INAK_BO (1<<6)
/* set get device status command */
#define CON (1<<0)
#define CON_CH (1<<1)
#define SUS (1<<2)
#define SUS_CH (1<<3)
#define RST (1<<4)
/* get error code command */
// ...
/* Select Endpoint command read bits */
#define EPSTAT_FE (1<<0)
#define EPSTAT_ST (1<<1)
#define EPSTAT_STP (1<<2)
#define EPSTAT_PO (1<<3)
#define EPSTAT_EPN (1<<4)
#define EPSTAT_B1FULL (1<<5)
#define EPSTAT_B2FULL (1<<6)
/* CMD_EP_SET_STATUS command */
#define EP_ST (1<<0)
#define EP_DA (1<<5)
#define EP_RF_MO (1<<6)
#define EP_CND_ST (1<<7)
/* read error status command */
#define PID_ERR (1<<0)
#define UEPKT (1<<1)
#define DCRC (1<<2)
#define TIMEOUT (1<<3)
#define EOP (1<<4)
#define B_OVRN (1<<5)
#define BTSTF (1<<6)
#define TGL_ERR (1<<7)

View File

@ -0,0 +1,82 @@
/*
LPCUSB, an USB device driver for LPC microcontrollers
Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @file
USB stack initialisation
*/
#include "usbdebug.h"
#include "usbapi.h"
/** data storage area for standard requests */
static unsigned char abStdReqData[8];
/**
USB reset handler
@param [in] bDevStatus Device status
*/
static void HandleUsbReset(unsigned char bDevStatus)
{
if (bDevStatus & DEV_STATUS_RESET) {
DBG("\n!");
}
}
/**
Initialises the USB hardware and sets up the USB stack by
installing default callbacks.
@return TRUE if initialisation was successful
*/
BOOL USBInit(void)
{
// init hardware
USBHwInit();
// register bus reset handler
USBHwRegisterDevIntHandler(HandleUsbReset);
// register control transfer handler on EP0
USBHwRegisterEPIntHandler(0x00, USBHandleControlTransfer);
USBHwRegisterEPIntHandler(0x80, USBHandleControlTransfer);
// setup control endpoints
USBHwEPConfig(0x00, MAX_PACKET_SIZE0);
USBHwEPConfig(0x80, MAX_PACKET_SIZE0);
// register standard request handler
USBRegisterRequestHandler(REQTYPE_TYPE_STANDARD, USBHandleStandardRequest, abStdReqData);
return TRUE;
}

View File

@ -0,0 +1,431 @@
/*
LPCUSB, an USB device driver for LPC microcontrollers
Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @file
Standard request handler.
This modules handles the 'chapter 9' processing, specifically the
standard device requests in table 9-3 from the universal serial bus
specification revision 2.0
Specific types of devices may specify additional requests (for example
HID devices add a GET_DESCRIPTOR request for interfaces), but they
will not be part of this module.
@todo some requests have to return a request error if device not configured:
@todo GET_INTERFACE, GET_STATUS, SET_INTERFACE, SYNCH_FRAME
@todo this applies to the following if endpoint != 0:
@todo SET_FEATURE, GET_FEATURE
*/
#include "usbdebug.h"
#include "usbstruct.h"
#include "usbapi.h"
#define MAX_DESC_HANDLERS 4 /**< device, interface, endpoint, other */
/* general descriptor field offsets */
#define DESC_bLength 0 /**< length offset */
#define DESC_bDescriptorType 1 /**< descriptor type offset */
/* config descriptor field offsets */
#define CONF_DESC_wTotalLength 2 /**< total length offset */
#define CONF_DESC_bConfigurationValue 5 /**< configuration value offset */
#define CONF_DESC_bmAttributes 7 /**< configuration characteristics */
/* interface descriptor field offsets */
#define INTF_DESC_bAlternateSetting 3 /**< alternate setting offset */
/* endpoint descriptor field offsets */
#define ENDP_DESC_bEndpointAddress 2 /**< endpoint address offset */
#define ENDP_DESC_wMaxPacketSize 4 /**< maximum packet size offset */
/** Currently selected configuration */
static unsigned char bConfiguration = 0;
/** Installed custom request handler */
static TFnHandleRequest *pfnHandleCustomReq = NULL;
/** Pointer to registered descriptors */
static const unsigned char *pabDescrip = NULL;
/**
Registers a pointer to a descriptor block containing all descriptors
for the device.
@param [in] pabDescriptors The descriptor byte array
*/
void USBRegisterDescriptors(const unsigned char *pabDescriptors)
{
pabDescrip = pabDescriptors;
}
/**
Parses the list of installed USB descriptors and attempts to find
the specified USB descriptor.
@param [in] wTypeIndex Type and index of the descriptor
@param [in] wLangID Language ID of the descriptor (currently unused)
@param [out] *piLen Descriptor length
@param [out] *ppbData Descriptor data
@return TRUE if the descriptor was found, FALSE otherwise
*/
BOOL USBGetDescriptor(unsigned short wTypeIndex, unsigned short wLangID, int *piLen, unsigned char **ppbData)
{
unsigned char bType, bIndex;
unsigned char *pab;
int iCurIndex;
( void ) wLangID;
ASSERT(pabDescrip != NULL);
bType = GET_DESC_TYPE(wTypeIndex);
bIndex = GET_DESC_INDEX(wTypeIndex);
pab = (unsigned char *)pabDescrip;
iCurIndex = 0;
while (pab[DESC_bLength] != 0) {
if (pab[DESC_bDescriptorType] == bType) {
if (iCurIndex == bIndex) {
// set data pointer
*ppbData = pab;
// get length from structure
if (bType == DESC_CONFIGURATION) {
// configuration descriptor is an exception, length is at offset 2 and 3
*piLen = (pab[CONF_DESC_wTotalLength]) |
(pab[CONF_DESC_wTotalLength + 1] << 8);
}
else {
// normally length is at offset 0
*piLen = pab[DESC_bLength];
}
return TRUE;
}
iCurIndex++;
}
// skip to next descriptor
pab += pab[DESC_bLength];
}
// nothing found
DBG("Desc %x not found!\n", wTypeIndex);
return FALSE;
}
/**
Configures the device according to the specified configuration index and
alternate setting by parsing the installed USB descriptor list.
A configuration index of 0 unconfigures the device.
@param [in] bConfigIndex Configuration index
@param [in] bAltSetting Alternate setting number
@todo function always returns TRUE, add stricter checking?
@return TRUE if successfully configured, FALSE otherwise
*/
static BOOL USBSetConfiguration(unsigned char bConfigIndex, unsigned char bAltSetting)
{
unsigned char *pab;
unsigned char bCurConfig, bCurAltSetting;
unsigned char bEP;
unsigned short wMaxPktSize;
ASSERT(pabDescrip != NULL);
if (bConfigIndex == 0) {
// unconfigure device
USBHwConfigDevice(FALSE);
}
else {
// configure endpoints for this configuration/altsetting
pab = (unsigned char *)pabDescrip;
bCurConfig = 0xFF;
bCurAltSetting = 0xFF;
while (pab[DESC_bLength] != 0) {
switch (pab[DESC_bDescriptorType]) {
case DESC_CONFIGURATION:
// remember current configuration index
bCurConfig = pab[CONF_DESC_bConfigurationValue];
break;
case DESC_INTERFACE:
// remember current alternate setting
bCurAltSetting = pab[INTF_DESC_bAlternateSetting];
break;
case DESC_ENDPOINT:
if ((bCurConfig == bConfigIndex) &&
(bCurAltSetting == bAltSetting)) {
// endpoint found for desired config and alternate setting
bEP = pab[ENDP_DESC_bEndpointAddress];
wMaxPktSize = (pab[ENDP_DESC_wMaxPacketSize]) |
(pab[ENDP_DESC_wMaxPacketSize + 1] << 8);
// configure endpoint
USBHwEPConfig(bEP, wMaxPktSize);
}
break;
default:
break;
}
// skip to next descriptor
pab += pab[DESC_bLength];
}
// configure device
USBHwConfigDevice(TRUE);
}
return TRUE;
}
/**
Local function to handle a standard device request
@param [in] pSetup The setup packet
@param [in,out] *piLen Pointer to data length
@param [in,out] ppbData Data buffer.
@return TRUE if the request was handled successfully
*/
static BOOL HandleStdDeviceReq(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData)
{
unsigned char *pbData = *ppbData;
switch (pSetup->bRequest) {
case REQ_GET_STATUS:
// bit 0: self-powered
// bit 1: remote wakeup = not supported
pbData[0] = 0;
pbData[1] = 0;
*piLen = 2;
break;
case REQ_SET_ADDRESS:
USBHwSetAddress(pSetup->wValue);
break;
case REQ_GET_DESCRIPTOR:
DBG("D%x", pSetup->wValue);
return USBGetDescriptor(pSetup->wValue, pSetup->wIndex, piLen, ppbData);
case REQ_GET_CONFIGURATION:
// indicate if we are configured
pbData[0] = bConfiguration;
*piLen = 1;
break;
case REQ_SET_CONFIGURATION:
if (!USBSetConfiguration(pSetup->wValue & 0xFF, 0)) {
DBG("USBSetConfiguration failed!\n");
return FALSE;
}
// configuration successful, update current configuration
bConfiguration = pSetup->wValue & 0xFF;
break;
case REQ_CLEAR_FEATURE:
case REQ_SET_FEATURE:
if (pSetup->wValue == FEA_REMOTE_WAKEUP) {
// put DEVICE_REMOTE_WAKEUP code here
}
if (pSetup->wValue == FEA_TEST_MODE) {
// put TEST_MODE code here
}
return FALSE;
case REQ_SET_DESCRIPTOR:
DBG("Device req %d not implemented\n", pSetup->bRequest);
return FALSE;
default:
DBG("Illegal device req %d\n", pSetup->bRequest);
return FALSE;
}
return TRUE;
}
/**
Local function to handle a standard interface request
@param [in] pSetup The setup packet
@param [in,out] *piLen Pointer to data length
@param [in] ppbData Data buffer.
@return TRUE if the request was handled successfully
*/
static BOOL HandleStdInterfaceReq(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData)
{
unsigned char *pbData = *ppbData;
switch (pSetup->bRequest) {
case REQ_GET_STATUS:
// no bits specified
pbData[0] = 0;
pbData[1] = 0;
*piLen = 2;
break;
case REQ_CLEAR_FEATURE:
case REQ_SET_FEATURE:
// not defined for interface
return FALSE;
case REQ_GET_INTERFACE: // TODO use bNumInterfaces
// there is only one interface, return n-1 (= 0)
pbData[0] = 0;
*piLen = 1;
break;
case REQ_SET_INTERFACE: // TODO use bNumInterfaces
// there is only one interface (= 0)
if (pSetup->wValue != 0) {
return FALSE;
}
*piLen = 0;
break;
default:
DBG("Illegal interface req %d\n", pSetup->bRequest);
return FALSE;
}
return TRUE;
}
/**
Local function to handle a standard endpoint request
@param [in] pSetup The setup packet
@param [in,out] *piLen Pointer to data length
@param [in] ppbData Data buffer.
@return TRUE if the request was handled successfully
*/
static BOOL HandleStdEndPointReq(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData)
{
unsigned char *pbData = *ppbData;
switch (pSetup->bRequest) {
case REQ_GET_STATUS:
// bit 0 = endpointed halted or not
pbData[0] = (USBHwEPGetStatus(pSetup->wIndex) & EP_STATUS_STALLED) ? 1 : 0;
pbData[1] = 0;
*piLen = 2;
break;
case REQ_CLEAR_FEATURE:
if (pSetup->wValue == FEA_ENDPOINT_HALT) {
// clear HALT by unstalling
USBHwEPStall(pSetup->wIndex, FALSE);
break;
}
// only ENDPOINT_HALT defined for endpoints
return FALSE;
case REQ_SET_FEATURE:
if (pSetup->wValue == FEA_ENDPOINT_HALT) {
// set HALT by stalling
USBHwEPStall(pSetup->wIndex, TRUE);
break;
}
// only ENDPOINT_HALT defined for endpoints
return FALSE;
case REQ_SYNCH_FRAME:
DBG("EP req %d not implemented\n", pSetup->bRequest);
return FALSE;
default:
DBG("Illegal EP req %d\n", pSetup->bRequest);
return FALSE;
}
return TRUE;
}
/**
Default handler for standard ('chapter 9') requests
If a custom request handler was installed, this handler is called first.
@param [in] pSetup The setup packet
@param [in,out] *piLen Pointer to data length
@param [in] ppbData Data buffer.
@return TRUE if the request was handled successfully
*/
BOOL USBHandleStandardRequest(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData)
{
// try the custom request handler first
if ((pfnHandleCustomReq != NULL) && pfnHandleCustomReq(pSetup, piLen, ppbData)) {
return TRUE;
}
switch (REQTYPE_GET_RECIP(pSetup->bmRequestType)) {
case REQTYPE_RECIP_DEVICE: return HandleStdDeviceReq(pSetup, piLen, ppbData);
case REQTYPE_RECIP_INTERFACE: return HandleStdInterfaceReq(pSetup, piLen, ppbData);
case REQTYPE_RECIP_ENDPOINT: return HandleStdEndPointReq(pSetup, piLen, ppbData);
default: return FALSE;
}
}
/**
Registers a callback for custom device requests
In USBHandleStandardRequest, the custom request handler gets a first
chance at handling the request before it is handed over to the 'chapter 9'
request handler.
This can be used for example in HID devices, where a REQ_GET_DESCRIPTOR
request is sent to an interface, which is not covered by the 'chapter 9'
specification.
@param [in] pfnHandler Callback function pointer
*/
void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler)
{
pfnHandleCustomReq = pfnHandler;
}

View File

@ -0,0 +1,119 @@
/*
LPCUSB, an USB device driver for LPC microcontrollers
Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
Definitions of structures of standard USB packets
*/
#ifndef _USBSTRUCT_H_
#define _USBSTRUCT_H_
// CodeRed - include the LPCUSB type.h file rather than NXP one directly
#include "type.h"
/** setup packet definitions */
typedef struct {
unsigned char bmRequestType; /**< characteristics of the specific request */
unsigned char bRequest; /**< specific request */
unsigned short wValue; /**< request specific parameter */
unsigned short wIndex; /**< request specific parameter */
unsigned short wLength; /**< length of data transfered in data phase */
} TSetupPacket;
#define REQTYPE_GET_DIR(x) (((x)>>7)&0x01)
#define REQTYPE_GET_TYPE(x) (((x)>>5)&0x03)
#define REQTYPE_GET_RECIP(x) ((x)&0x1F)
#define REQTYPE_DIR_TO_DEVICE 0
#define REQTYPE_DIR_TO_HOST 1
#define REQTYPE_TYPE_STANDARD 0
#define REQTYPE_TYPE_CLASS 1
#define REQTYPE_TYPE_VENDOR 2
#define REQTYPE_TYPE_RESERVED 3
#define REQTYPE_RECIP_DEVICE 0
#define REQTYPE_RECIP_INTERFACE 1
#define REQTYPE_RECIP_ENDPOINT 2
#define REQTYPE_RECIP_OTHER 3
/* standard requests */
#define REQ_GET_STATUS 0x00
#define REQ_CLEAR_FEATURE 0x01
#define REQ_SET_FEATURE 0x03
#define REQ_SET_ADDRESS 0x05
#define REQ_GET_DESCRIPTOR 0x06
#define REQ_SET_DESCRIPTOR 0x07
#define REQ_GET_CONFIGURATION 0x08
#define REQ_SET_CONFIGURATION 0x09
#define REQ_GET_INTERFACE 0x0A
#define REQ_SET_INTERFACE 0x0B
#define REQ_SYNCH_FRAME 0x0C
/* class requests HID */
#define HID_GET_REPORT 0x01
#define HID_GET_IDLE 0x02
#define HID_GET_PROTOCOL 0x03
#define HID_SET_REPORT 0x09
#define HID_SET_IDLE 0x0A
#define HID_SET_PROTOCOL 0x0B
/* feature selectors */
#define FEA_ENDPOINT_HALT 0x00
#define FEA_REMOTE_WAKEUP 0x01
#define FEA_TEST_MODE 0x02
/*
USB descriptors
*/
/** USB descriptor header */
typedef struct {
unsigned char bLength; /**< descriptor length */
unsigned char bDescriptorType; /**< descriptor type */
} TUSBDescHeader;
#define DESC_DEVICE 1
#define DESC_CONFIGURATION 2
#define DESC_STRING 3
#define DESC_INTERFACE 4
#define DESC_ENDPOINT 5
#define DESC_DEVICE_QUALIFIER 6
#define DESC_OTHER_SPEED 7
#define DESC_INTERFACE_POWER 8
#define DESC_HID_HID 0x21
#define DESC_HID_REPORT 0x22
#define DESC_HID_PHYSICAL 0x23
#define GET_DESC_TYPE(x) (((x)>>8)&0xFF)
#define GET_DESC_INDEX(x) ((x)&0xFF)
#endif /* _USBSTRUCT_H_ */

View File

@ -0,0 +1,159 @@
/*
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;
}
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,159 @@
/*
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;
}
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,71 @@
<!DOCTYPE CrossStudio_Project_File>
<solution Name="RTOSDemo" version="2">
<project Name="RTOSDemo">
<configuration Name="Common" Target="LPC1768" arm_architecture="v7M" arm_core_type="Cortex-M3" arm_linker_heap_size="128" arm_linker_process_stack_size="0" arm_linker_stack_size="128" arm_simulator_memory_simulation_filename="$(TargetsDir)/LPC1000/LPC1000SimulatorMemory.dll" arm_simulator_memory_simulation_parameter="0x80000;0x8000;0x8000" arm_target_debug_interface_type="ADIv5" arm_target_loader_parameter="12000000" c_enforce_ansi_checking="No" c_only_additional_options="-Wall;-Wextra" c_preprocessor_definitions="PACK_STRUCT_END=__attribute((packed));ALIGN_STRUCT_END=__attribute((aligned(4)));CONFIGURE_USB;FULL_SPEED" c_user_include_directories="$(TargetsDir)/LPC1000/include;../../Source/include;../Common/include;../../Source/portable/GCC/ARM_CM3;../Common/ethernet/uIP/uip-1.0/uip;.;./webserver;./LPCUSB;./FatFs-port-files;../Common/FileSystem/FatFs-0.7e/src" link_include_startup_code="No" linker_additional_files="$(TargetsDir)/LPC1000/lib/liblpc1000$(LibExt)$(LIB);$(TargetsDir)/LPC1000/lib/cmsis$(LibExt)$(LIB)" linker_memory_map_file="$(TargetsDir)/LPC1000/LPC1768_MemoryMap.xml" linker_printf_fmt_level="int" linker_printf_width_precision_supported="No" linker_section_placement_file="$(ProjectDir)/flash_placement.xml" oscillator_frequency="12MHz" project_directory="" project_type="Executable" property_groups_file_path="$(TargetsDir)/LPC1000/propertyGroups.xml"/>
<configuration Name="RAM" Placement="RAM" linker_section_placement_file="$(StudioDir)/targets/Cortex_M/ram_placement.xml" target_reset_script="SRAMReset()"/>
<configuration Name="Flash" Placement="Flash" arm_target_flash_loader_file_path="$(TargetsDir)/LPC1000/Release/Loader_rpc.elf" arm_target_flash_loader_type="LIBMEM RPC Loader" linker_patch_build_command="$(StudioDir)/bin/crossscript &quot;load(\&quot;$(TargetsDir)/LPC1000/LPC1000_LinkPatch.js\&quot;);patch(\&quot;$(TargetPath)\&quot;);&quot;" linker_section_placement_file="$(ProjectDir)/flash_placement.xml" target_reset_script="FLASHReset()"/>
<folder Name="Source Files">
<configuration Name="Common" filter="c;cpp;cxx;cc;h;s;asm;inc"/>
<folder Name="FreeRTOS">
<file file_name="../../Source/tasks.c"/>
<file file_name="../../Source/list.c"/>
<file file_name="../../Source/queue.c"/>
<file file_name="../../Source/portable/GCC/ARM_CM3/port.c"/>
<file file_name="../../Source/portable/MemMang/heap_2.c"/>
</folder>
<folder Name="Common Demo Tasks">
<file file_name="../Common/Minimal/recmutex.c"/>
<file file_name="../Common/Minimal/semtest.c"/>
<file file_name="../Common/Minimal/BlockQ.c"/>
<file file_name="../Common/Minimal/blocktim.c"/>
<file file_name="../Common/Minimal/flash.c"/>
<file file_name="../Common/Minimal/GenQTest.c"/>
<file file_name="../Common/Minimal/integer.c"/>
<file file_name="../Common/Minimal/QPeek.c"/>
<file file_name="../Common/Minimal/PollQ.c"/>
</folder>
<file file_name="main.c"/>
<folder Name="WEB Server" file_name="">
<file file_name="../Common/ethernet/uIP/uip-1.0/uip/uip.c"/>
<file file_name="../Common/ethernet/uIP/uip-1.0/uip/uip_arp.c"/>
<file file_name="../Common/ethernet/uIP/uip-1.0/uip/psock.c"/>
<file file_name="../Common/ethernet/uIP/uip-1.0/uip/timer.c"/>
<file file_name="webserver/uIP_Task.c"/>
<file file_name="webserver/emac.c">
<configuration Name="THUMB Flash Debug" build_exclude_from_build="No"/>
</file>
<file file_name="webserver/httpd.c"/>
<file file_name="webserver/httpd-cgi.c"/>
<file file_name="webserver/httpd-fs.c"/>
<file file_name="webserver/http-strings.c"/>
</folder>
<file file_name="ParTest.c"/>
<file file_name="printf-stdarg.c"/>
<folder Name="LPCUSB">
<file file_name="LPCUSB/usbstdreq.c"/>
<file file_name="LPCUSB/USB_CDC.c"/>
<file file_name="LPCUSB/usbcontrol.c"/>
<file file_name="LPCUSB/usbhw_lpc.c"/>
<file file_name="LPCUSB/usbinit.c"/>
</folder>
<folder Name="FatFS">
<file file_name="../Common/FileSystem/FatFs-0.7e/src/ff.c"/>
<file file_name="../Common/FileSystem/FatFs-0.7e/src/option/syncobj.c"/>
<file file_name="FatFs-port-files/diskio.c"/>
</folder>
</folder>
<folder Name="System Files">
<file file_name="$(StudioDir)/source/thumb_crt0.s"/>
<file file_name="$(TargetsDir)/LPC1000/LPC1700_Target.js">
<configuration Name="Common" file_type="Reset Script"/>
</file>
<file file_name="LPC1700_Startup.s"/>
</folder>
</project>
<configuration Name="THUMB Flash Debug" inherited_configurations="THUMB;Flash;Debug"/>
<configuration Name="THUMB" Platform="ARM" arm_instruction_set="THUMB" arm_library_instruction_set="THUMB" c_preprocessor_definitions="__THUMB" hidden="Yes"/>
<configuration Name="Flash" c_preprocessor_definitions="__FLASH_BUILD" hidden="Yes"/>
<configuration Name="Debug" build_debug_information="Yes" c_preprocessor_definitions="DEBUG" gcc_optimization_level="None" hidden="Yes" link_include_startup_code="No"/>
<configuration Name="THUMB Flash Release" inherited_configurations="THUMB;Flash;Release"/>
<configuration Name="Release" build_debug_information="No" c_additional_options="-g1" c_preprocessor_definitions="NDEBUG" gcc_optimization_level="Level 1" hidden="Yes" link_include_startup_code="No"/>
</solution>

View File

@ -0,0 +1,68 @@
<!DOCTYPE CrossStudio_for_ARM_Session_File>
<session>
<Bookmarks/>
<Breakpoints>
<BreakpointListItem line="1409" action="" hardwareBreakpoint="" trigger="" useHWbreakpoint="false" group="Breakpoints" type="Breakpoint" state="4" counter="0" isFunctionBreakpoint="false" filename="C:\E\Dev\FreeRTOS\WorkingCopy\Demo\Common\FileSystem\FatFs-0.7e\src\ff.c" expression="" />
<BreakpointListItem line="271" action="" hardwareBreakpoint="" trigger="" useHWbreakpoint="false" group="Breakpoints" type="Breakpoint" state="2" counter="0" isFunctionBreakpoint="false" filename="C:\E\Dev\FreeRTOS\WorkingCopy\Demo\CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB\main.c" expression="" />
<BreakpointListItem line="184" action="" hardwareBreakpoint="" trigger="" useHWbreakpoint="false" group="Breakpoints" type="Breakpoint" state="4" counter="0" isFunctionBreakpoint="false" filename="C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_LPC1768_GCC_Rowley\UsbHost\Host\usbhost_lpc17xx.c" expression="" />
<BreakpointListItem line="46" action="" hardwareBreakpoint="" trigger="" useHWbreakpoint="false" group="Breakpoints" type="Breakpoint" state="4" counter="0" isFunctionBreakpoint="false" filename="C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_LPC1768_GCC_Rowley\UsbHost\Main\usbhost_task.c" expression="" />
</Breakpoints>
<ExecutionCountWindow/>
<Memory1>
<MemoryWindow autoEvaluate="0" addressText="0x10003c24" numColumns="8" sizeText="100" dataSize="1" radix="16" addressSpace="" />
</Memory1>
<Memory2>
<MemoryWindow autoEvaluate="0" addressText="" numColumns="8" sizeText="" dataSize="1" radix="16" addressSpace="" />
</Memory2>
<Memory3>
<MemoryWindow autoEvaluate="0" addressText="" numColumns="8" sizeText="" dataSize="1" radix="16" addressSpace="" />
</Memory3>
<Memory4>
<MemoryWindow autoEvaluate="0" addressText="" numColumns="8" sizeText="" dataSize="1" radix="16" addressSpace="" />
</Memory4>
<Project>
<ProjectSessionItem path="RTOSDemo" name="unnamed" />
<ProjectSessionItem path="RTOSDemo;RTOSDemo" name="unnamed" />
<ProjectSessionItem path="RTOSDemo;RTOSDemo;Source Files" name="unnamed" />
<ProjectSessionItem path="RTOSDemo;RTOSDemo;Source Files;FatFS" name="unnamed" />
<ProjectSessionItem path="RTOSDemo;RTOSDemo;Source Files;WEB Server" name="unnamed" />
</Project>
<Register1>
<RegisterWindow openNodes="CPU;CPU/xPSR;CPU/CFBP;CPU/CFBP/CONTROL[0];CPU/CFBP/CONTROL[1]" binaryNodes="" unsignedNodes="" visibleGroups="CPU" decimalNodes="" octalNodes="" asciiNodes="" />
</Register1>
<Register2>
<RegisterWindow openNodes="SPI0/S0SPCR;SPI0/S0SPSR;SC" binaryNodes="" unsignedNodes="" visibleGroups="SPI0;SC;GPIO" decimalNodes="" octalNodes="" asciiNodes="" />
</Register2>
<Register3>
<RegisterWindow openNodes="" binaryNodes="" unsignedNodes="" visibleGroups="" decimalNodes="" octalNodes="" asciiNodes="" />
</Register3>
<Register4>
<RegisterWindow openNodes="" binaryNodes="" unsignedNodes="" visibleGroups="" decimalNodes="" octalNodes="" asciiNodes="" />
</Register4>
<TargetWindow programAction="" uploadFileType="" programLoadAddress="" programSize="" uploadFileName="" uploadMemoryInterface="" programFileName="" uploadStartAddress="" programFileType="" uploadSize="" programMemoryInterface="" />
<TraceWindow>
<Trace enabled="Yes" />
</TraceWindow>
<Watch1>
<Watches active="1" update="Never" >
<Watchpoint evalMode="3" linenumber="0" evalType="0" radix="16" name="c" expression="c" filename="" />
</Watches>
</Watch1>
<Watch2>
<Watches active="0" update="Never" />
</Watch2>
<Watch3>
<Watches active="0" update="Never" />
</Watch3>
<Watch4>
<Watches active="0" update="Never" />
</Watch4>
<Files>
<SessionOpenFile useTextEdit="1" useBinaryEdit="0" codecName="Latin1" x="0" debugPath="C:\E\Dev\FreeRTOS\WorkingCopy\Demo\CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB\webserver\httpd-fs.c" y="0" path="C:\E\Dev\FreeRTOS\WorkingCopy\Demo\CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB\webserver\httpd-fs.c" left="0" selected="0" name="unnamed" top="93" />
<SessionOpenFile useTextEdit="1" useBinaryEdit="0" codecName="Latin1" x="0" debugPath="C:\E\Dev\FreeRTOS\WorkingCopy\Demo\CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB\webserver\httpd-fsdata.c" y="0" path="C:\E\Dev\FreeRTOS\WorkingCopy\Demo\CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB\webserver\httpd-fsdata.c" left="0" selected="0" name="unnamed" top="518" />
<SessionOpenFile useTextEdit="1" useBinaryEdit="0" codecName="Latin1" x="40" debugPath="C:\E\Dev\FreeRTOS\WorkingCopy\Demo\CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB\webserver\httpd.c" y="81" path="C:\E\Dev\FreeRTOS\WorkingCopy\Demo\CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB\webserver\httpd.c" left="0" selected="0" name="unnamed" top="57" />
<SessionOpenFile useTextEdit="1" useBinaryEdit="0" codecName="Latin1" x="0" debugPath="C:\E\Dev\FreeRTOS\WorkingCopy\Demo\CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB\webserver\uIP_Task.c" y="0" path="C:\E\Dev\FreeRTOS\WorkingCopy\Demo\CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB\webserver\uIP_Task.c" left="0" selected="0" name="unnamed" top="184" />
<SessionOpenFile useTextEdit="1" useBinaryEdit="0" codecName="Latin1" x="0" debugPath="C:\E\Dev\FreeRTOS\WorkingCopy\Demo\CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB\FatFs-port-files\diskio.c" y="750" path="C:\E\Dev\FreeRTOS\WorkingCopy\Demo\CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB\FatFs-port-files\diskio.c" left="0" selected="1" name="unnamed" top="733" />
</Files>
<ARMCrossStudioWindow activeProject="RTOSDemo" autoConnectTarget="USB CrossConnect for ARM" debugSearchFileMap="" fileDialogInitialDirectory="C:\E\Dev\FreeRTOS\WorkingCopy\Demo\CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB\FatFs-port-files" fileDialogDefaultFilter="*.*" autoConnectCapabilities="388991" debugSearchPath="" buildConfiguration="THUMB Flash Debug" />
</session>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
<!DOCTYPE Linker_Placement_File>
<Root name="Flash Section Placement">
<MemorySegment name="FLASH">
<ProgramSection load="Yes" inputsections="*(.vectors .vectors.*)" name=".vectors"/>
<ProgramSection alignment="4" load="Yes" inputsections="*(.init .init.*)" name=".init"/>
<ProgramSection alignment="4" load="Yes" inputsections="*(.text .text.* .glue_7t .glue_7 .gnu.linkonce.t.* .gcc_except_table)" name=".text"/>
<ProgramSection alignment="4" load="Yes" inputsections="KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors))" name=".dtors"/>
<ProgramSection alignment="4" load="Yes" inputsections="KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors))" name=".ctors"/>
<ProgramSection alignment="4" load="Yes" inputsections="*(.rodata .rodata.* .gnu.linkonce.r.*)" name=".rodata"/>
<ProgramSection alignment="4" load="Yes" runin=".fast_run" inputsections="*(.fast .fast.*)" name=".fast"/>
<ProgramSection alignment="4" load="Yes" runin=".data_run" inputsections="*(.data .data.* .gnu.linkonce.d.*)" name=".data"/>
</MemorySegment>
<MemorySegment name="RAM">
<ProgramSection alignment="4" load="No" name=".fast_run"/>
<ProgramSection alignment="4" load="No" name=".data_run"/>
<ProgramSection alignment="4" load="No" inputsections="*(.bss .bss.* .gnu.linkonce.b.*) *(COMMON)" name=".bss"/>
<ProgramSection alignment="4" load="No" inputsections="*(.non_init .non_init.*)" name=".non_init"/>
<ProgramSection alignment="4" size="__HEAPSIZE__" load="No" name=".heap"/>
<ProgramSection alignment="4" size="__STACKSIZE__" load="No" name=".stack"/>
<ProgramSection alignment="4" size="__STACKSIZE_PROCESS__" load="No" name=".stack_process"/>
</MemorySegment>
<MemorySegment name="AHBSRAM0">
<ProgramSection alignment="4" load="No" name=".ethram"/>
</MemorySegment>
<MemorySegment name="AHBSRAM1">
<ProgramSection alignment="4" load="No" name=".usbram"/>
</MemorySegment>
<MemorySegment name="FLASH2">
<ProgramSection alignment="4" load="Yes" inputsections="*(.text2 .text2.*)" name=".text2"/>
<ProgramSection alignment="4" load="Yes" inputsections="*(.rodata2 .rodata2.*)" name=".rodata2"/>
<ProgramSection alignment="4" load="Yes" runin=".data2_run" inputsections="*(.data2 .data2.*)" name=".data2"/>
</MemorySegment>
<MemorySegment name="RAM2">
<ProgramSection alignment="4" load="No" name=".data2_run"/>
<ProgramSection alignment="4" load="No" inputsections="*(.bss2 .bss2.*" name=".bss2"/>
</MemorySegment>
</Root>

View File

@ -0,0 +1,319 @@
/*
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 );
__asm volatile( "NOP" );
}
}
/*-----------------------------------------------------------*/
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;
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,318 @@
/*
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;
}
/*-----------------------------------------------------------*/

View File

@ -0,0 +1,293 @@
/*
Copyright 2001, 2002 Georges Menie (www.menie.org)
stdarg version contributed by Christian Ettinger
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
putchar is the only external dependency for this file,
if you have a working putchar, leave it commented out.
If not, uncomment the define below and
replace outbyte(c) by your own function call.
*/
#define putchar(c) c
#include <stdarg.h>
static void printchar(char **str, int c)
{
//extern int putchar(int c);
if (str) {
**str = (char)c;
++(*str);
}
else
{
(void)putchar(c);
}
}
#define PAD_RIGHT 1
#define PAD_ZERO 2
static int prints(char **out, const char *string, int width, int pad)
{
register int pc = 0, padchar = ' ';
if (width > 0) {
register int len = 0;
register const char *ptr;
for (ptr = string; *ptr; ++ptr) ++len;
if (len >= width) width = 0;
else width -= len;
if (pad & PAD_ZERO) padchar = '0';
}
if (!(pad & PAD_RIGHT)) {
for ( ; width > 0; --width) {
printchar (out, padchar);
++pc;
}
}
for ( ; *string ; ++string) {
printchar (out, *string);
++pc;
}
for ( ; width > 0; --width) {
printchar (out, padchar);
++pc;
}
return pc;
}
/* the following should be enough for 32 bit int */
#define PRINT_BUF_LEN 12
static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase)
{
char print_buf[PRINT_BUF_LEN];
register char *s;
register int t, neg = 0, pc = 0;
register unsigned int u = (unsigned int)i;
if (i == 0) {
print_buf[0] = '0';
print_buf[1] = '\0';
return prints (out, print_buf, width, pad);
}
if (sg && b == 10 && i < 0) {
neg = 1;
u = (unsigned int)-i;
}
s = print_buf + PRINT_BUF_LEN-1;
*s = '\0';
while (u) {
t = (unsigned int)u % b;
if( t >= 10 )
t += letbase - '0' - 10;
*--s = (char)(t + '0');
u /= b;
}
if (neg) {
if( width && (pad & PAD_ZERO) ) {
printchar (out, '-');
++pc;
--width;
}
else {
*--s = '-';
}
}
return pc + prints (out, s, width, pad);
}
static int print( char **out, const char *format, va_list args )
{
register int width, pad;
register int pc = 0;
char scr[2];
for (; *format != 0; ++format) {
if (*format == '%') {
++format;
width = pad = 0;
if (*format == '\0') break;
if (*format == '%') goto out;
if (*format == '-') {
++format;
pad = PAD_RIGHT;
}
while (*format == '0') {
++format;
pad |= PAD_ZERO;
}
for ( ; *format >= '0' && *format <= '9'; ++format) {
width *= 10;
width += *format - '0';
}
if( *format == 's' ) {
register char *s = (char *)va_arg( args, int );
pc += prints (out, s?s:"(null)", width, pad);
continue;
}
if( *format == 'd' ) {
pc += printi (out, va_arg( args, int ), 10, 1, width, pad, 'a');
continue;
}
if( *format == 'x' ) {
pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'a');
continue;
}
if( *format == 'X' ) {
pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'A');
continue;
}
if( *format == 'u' ) {
pc += printi (out, va_arg( args, int ), 10, 0, width, pad, 'a');
continue;
}
if( *format == 'c' ) {
/* char are converted to int then pushed on the stack */
scr[0] = (char)va_arg( args, int );
scr[1] = '\0';
pc += prints (out, scr, width, pad);
continue;
}
}
else {
out:
printchar (out, *format);
++pc;
}
}
if (out) **out = '\0';
va_end( args );
return pc;
}
int printf(const char *format, ...)
{
va_list args;
va_start( args, format );
return print( 0, format, args );
}
int sprintf(char *out, const char *format, ...)
{
va_list args;
va_start( args, format );
return print( &out, format, args );
}
int snprintf( char *buf, unsigned int count, const char *format, ... )
{
va_list args;
( void ) count;
va_start( args, format );
return print( &buf, format, args );
}
#ifdef TEST_PRINTF
int main(void)
{
char *ptr = "Hello world!";
char *np = 0;
int i = 5;
unsigned int bs = sizeof(int)*8;
int mi;
char buf[80];
mi = (1 << (bs-1)) + 1;
printf("%s\n", ptr);
printf("printf test\n");
printf("%s is null pointer\n", np);
printf("%d = 5\n", i);
printf("%d = - max int\n", mi);
printf("char %c = 'a'\n", 'a');
printf("hex %x = ff\n", 0xff);
printf("hex %02x = 00\n", 0);
printf("signed %d = unsigned %u = hex %x\n", -3, -3, -3);
printf("%d %s(s)%", 0, "message");
printf("\n");
printf("%d %s(s) with %%\n", 0, "message");
sprintf(buf, "justif: \"%-10s\"\n", "left"); printf("%s", buf);
sprintf(buf, "justif: \"%10s\"\n", "right"); printf("%s", buf);
sprintf(buf, " 3: %04d zero padded\n", 3); printf("%s", buf);
sprintf(buf, " 3: %-4d left justif.\n", 3); printf("%s", buf);
sprintf(buf, " 3: %4d right justif.\n", 3); printf("%s", buf);
sprintf(buf, "-3: %04d zero padded\n", -3); printf("%s", buf);
sprintf(buf, "-3: %-4d left justif.\n", -3); printf("%s", buf);
sprintf(buf, "-3: %4d right justif.\n", -3); printf("%s", buf);
return 0;
}
/*
* if you compile this file with
* gcc -Wall $(YOUR_C_OPTIONS) -DTEST_PRINTF -c printf.c
* you will get a normal warning:
* printf.c:214: warning: spurious trailing `%' in format
* this line is testing an invalid % at the end of the format string.
*
* this should display (on 32bit int machine) :
*
* Hello world!
* printf test
* (null) is null pointer
* 5 = 5
* -2147483647 = - max int
* char a = 'a'
* hex ff = ff
* hex 00 = 00
* signed -3 = unsigned 4294967293 = hex fffffffd
* 0 message(s)
* 0 message(s) with %
* justif: "left "
* justif: " right"
* 3: 0003 zero padded
* 3: 3 left justif.
* 3: 3 right justif.
* -3: -003 zero padded
* -3: -3 left justif.
* -3: -3 right justif.
*/
#endif
/* To keep linker happy. */
int write( int i, char* c, int n)
{
(void)i;
(void)n;
(void)c;
return 0;
}

View File

@ -0,0 +1,40 @@
/******************************************************************************
* @file: system_LPC17xx.h
* @purpose: CMSIS Cortex-M3 Device Peripheral Access Layer Header File
* for the NXP LPC17xx Device Series
* @version: V1.0
* @date: 25. Nov. 2008
*----------------------------------------------------------------------------
*
* Copyright (C) 2008 ARM Limited. All rights reserved.
*
* ARM Limited (ARM) is supplying this software for use with Cortex-M3
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/
#ifndef __SYSTEM_LPC17xx_H
#define __SYSTEM_LPC17xx_H
extern uint32_t SystemFrequency; /*!< System Clock Frequency (Core Clock) */
/**
* Initialize the system
*
* @param none
* @return none
*
* @brief Setup the microcontroller system.
* Initialize the System and update the SystemFrequency variable.
*/
extern void SystemInit (void);
#endif

View File

@ -0,0 +1,45 @@
[Version]
Signature="$Windows NT$"
Class=Ports
ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
Provider=%LINUX%
DriverVer=08/17/2004,0.0.2.0
; Copyright (C) 2004 Al Borchers (alborchers@steinerpoint.com)
; released under GNU General Public License
[Manufacturer]
%LINUX%=GSerialDeviceList
[GSerialDeviceList]
%GSERIAL%=GSerialInstall, USB\VID_FFFF&PID_0005
[DestinationDirs]
DefaultDestDir=10,System32\Drivers
[GSerialInstall]
CopyFiles=GSerialCopyFiles
AddReg=GSerialAddReg
[GSerialCopyFiles]
usbser.sys
[GSerialAddReg]
HKR,,DevLoader,,*ntkern
HKR,,NTMPDriver,,usbser.sys
HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
[GSerialInstall.Services]
AddService = usbser,0x0002,GSerialService
[GSerialService]
DisplayName = %GSERIAL_DISPLAY_NAME%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %10%\System32\Drivers\usbser.sys
LoadOrderGroup = Base
[Strings]
LINUX = "Linux"
GSERIAL = "USB CDC serial port emulation"
GSERIAL_DISPLAY_NAME = "USB CDC serial port emulation"

View File

@ -0,0 +1,111 @@
/*
* @file: EthDev.h
* @purpose: Ethernet Device Definitions
* @version: V1.10
* @date: 24. Feb. 2009
*----------------------------------------------------------------------------
*
* Copyright (C) 2009 ARM Limited. All rights reserved.
*
* ARM Limited (ARM) is supplying this software for use with Cortex-M3
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
*/
#ifndef _ETHDEV__H
#define _ETHDEV__H
#ifndef NULL
#define NULL 0
#endif
/*----------------------------------------------------------------------------
Ethernet Device Defines
*----------------------------------------------------------------------------*/
#define EthDev_ADDR_SIZE 6 /*!< Ethernet Address size in bytes */
#define EthDev_MTU_SIZE 1514 /*!< Maximum Transmission Unit */
/*----------------------------------------------------------------------------
Ethernet Device Configuration and Control Command Defines
*----------------------------------------------------------------------------*/
typedef enum {
EthDev_LINK_DOWN = 0, /*!< Ethernet link not established */
EthDev_LINK_UP = 1, /*!< Ethernet link established */
} EthDev_LINK;
typedef enum {
EthDev_SPEED_10M = 0, /*!< 10.0 Mbps link speed */
EthDev_SPEED_100M = 1, /*!< 100.0 Mbps link speed */
EthDev_SPEED_1000M = 2, /*!< 1.0 Gbps link speed */
} EthDev_SPEED;
typedef enum {
EthDev_DUPLEX_HALF = 0, /*!< Link half duplex */
EthDev_DUPLEX_FULL = 1, /*!< Link full duplex */
} EthDev_DUPLEX;
typedef enum {
EthDev_MODE_AUTO = 0,
EthDev_MODE_10M_FULL = 1,
EthDev_MODE_10M_HALF = 2,
EthDev_MODE_100M_FULL = 3,
EthDev_MODE_100M_HALF = 4,
EthDev_MODE_1000M_FULL = 5,
EthDev_MODE_1000M_HALF = 6,
} EthDev_MODE;
typedef struct {
EthDev_LINK Link : 1;
EthDev_DUPLEX Duplex : 1;
EthDev_SPEED Speed : 2;
} EthDev_STATUS;
/*----------------------------------------------------------------------------
Ethernet Device IO Block Structure
*----------------------------------------------------------------------------*/
typedef struct {
/* Initialized by the user application before call to Init. */
EthDev_MODE Mode;
unsigned char HwAddr[EthDev_ADDR_SIZE];
void *(*RxFrame) (int size);
void (*RxFrameReady) (int size);
/* Initialized by Ethernet driver. */
int (*Init) (void);
int (*UnInit) (void);
int (*SetMCFilter)(int NumHwAddr, unsigned char *pHwAddr);
int (*TxFrame) (void *pData, int size);
void (*Lock) (void);
void (*UnLock) (void);
EthDev_STATUS (*LinkChk) (void);
} EthDev_IOB;
/*
* Look for received data. If data is found then uip_buf is assigned to the
* new data and the length of the data is returned. If no data is found then
* uip_buf is not updated and 0 is returned.
*/
unsigned long ulGetEMACRxData( void );
/*
* Send usTxDataLen bytes from uip_buf.
*/
void vSendEMACTxData( unsigned short usTxDataLen );
/*
* Prepare the Ethernet hardware ready for TCP/IP comms.
*/
long lEMACInit(void);
#endif

View File

@ -0,0 +1,331 @@
/*
* @file: EthDev_LPC17xx.h
* @purpose: Ethernet Device Definitions for NXP LPC17xx
* @version: V0.01
* @date: 14. May 2009
*----------------------------------------------------------------------------
*
* Copyright (C) 2009 ARM Limited. All rights reserved.
*
* ARM Limited (ARM) is supplying this software for use with Cortex-M3
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
*/
#ifndef __ETHDEV_LPC17XX_H
#define __ETHDEV_LPC17XX_H
#include <stdint.h>
/* EMAC Memory Buffer configuration for 16K Ethernet RAM. */
#define NUM_RX_FRAG 3 /* Num.of RX Fragments. */
#define NUM_TX_FRAG 2 /* Num.of TX Fragments. */
#define ETH_FRAG_SIZE 1536 /* Packet Fragment size 1536 Bytes */
#define ETH_MAX_FLEN 1536 /* Max. Ethernet Frame Size */
typedef struct { /* RX Descriptor struct */
uint32_t Packet;
uint32_t Ctrl;
} RX_DESC_TypeDef;
typedef struct { /* RX Status struct */
uint32_t Info;
uint32_t HashCRC;
} RX_STAT_TypeDef;
typedef struct { /* TX Descriptor struct */
uint32_t Packet;
uint32_t Ctrl;
} TX_DESC_TypeDef;
typedef struct { /* TX Status struct */
uint32_t Info;
} TX_STAT_TypeDef;
/* EMAC variables located in AHB SRAM bank 1*/
#define AHB_SRAM_BANK1_BASE 0x2007c000UL
#define RX_DESC_BASE (AHB_SRAM_BANK1_BASE )
#define RX_STAT_BASE (RX_DESC_BASE + NUM_RX_FRAG*(2*4)) /* 2 * uint32_t, see RX_DESC_TypeDef */
#define TX_DESC_BASE (RX_STAT_BASE + NUM_RX_FRAG*(2*4)) /* 2 * uint32_t, see RX_STAT_TypeDef */
#define TX_STAT_BASE (TX_DESC_BASE + NUM_TX_FRAG*(2*4)) /* 2 * uint32_t, see TX_DESC_TypeDef */
#define ETH_BUF_BASE (TX_STAT_BASE + NUM_TX_FRAG*(1*4)) /* 1 * uint32_t, see TX_STAT_TypeDef */
/* RX and TX descriptor and status definitions. */
#define RX_DESC_PACKET(i) (*(unsigned int *)(RX_DESC_BASE + 8*i))
#define RX_DESC_CTRL(i) (*(unsigned int *)(RX_DESC_BASE+4 + 8*i))
#define RX_STAT_INFO(i) (*(unsigned int *)(RX_STAT_BASE + 8*i))
#define RX_STAT_HASHCRC(i) (*(unsigned int *)(RX_STAT_BASE+4 + 8*i))
#define TX_DESC_PACKET(i) (*(unsigned int *)(TX_DESC_BASE + 8*i))
#define TX_DESC_CTRL(i) (*(unsigned int *)(TX_DESC_BASE+4 + 8*i))
#define TX_STAT_INFO(i) (*(unsigned int *)(TX_STAT_BASE + 4*i))
#define ETH_BUF(i) ( ETH_BUF_BASE + ETH_FRAG_SIZE*i )
#define ETH_NUM_BUFFERS ( NUM_TX_FRAG + NUM_RX_FRAG + 1 ) /* There are in fact 2 more buffers than descriptors as the two Tx descriptors use the same buffer to speed up the uip Tx. */
/* MAC Configuration Register 1 */
#define MAC1_REC_EN 0x00000001 /* Receive Enable */
#define MAC1_PASS_ALL 0x00000002 /* Pass All Receive Frames */
#define MAC1_RX_FLOWC 0x00000004 /* RX Flow Control */
#define MAC1_TX_FLOWC 0x00000008 /* TX Flow Control */
#define MAC1_LOOPB 0x00000010 /* Loop Back Mode */
#define MAC1_RES_TX 0x00000100 /* Reset TX Logic */
#define MAC1_RES_MCS_TX 0x00000200 /* Reset MAC TX Control Sublayer */
#define MAC1_RES_RX 0x00000400 /* Reset RX Logic */
#define MAC1_RES_MCS_RX 0x00000800 /* Reset MAC RX Control Sublayer */
#define MAC1_SIM_RES 0x00004000 /* Simulation Reset */
#define MAC1_SOFT_RES 0x00008000 /* Soft Reset MAC */
/* MAC Configuration Register 2 */
#define MAC2_FULL_DUP 0x00000001 /* Full Duplex Mode */
#define MAC2_FRM_LEN_CHK 0x00000002 /* Frame Length Checking */
#define MAC2_HUGE_FRM_EN 0x00000004 /* Huge Frame Enable */
#define MAC2_DLY_CRC 0x00000008 /* Delayed CRC Mode */
#define MAC2_CRC_EN 0x00000010 /* Append CRC to every Frame */
#define MAC2_PAD_EN 0x00000020 /* Pad all Short Frames */
#define MAC2_VLAN_PAD_EN 0x00000040 /* VLAN Pad Enable */
#define MAC2_ADET_PAD_EN 0x00000080 /* Auto Detect Pad Enable */
#define MAC2_PPREAM_ENF 0x00000100 /* Pure Preamble Enforcement */
#define MAC2_LPREAM_ENF 0x00000200 /* Long Preamble Enforcement */
#define MAC2_NO_BACKOFF 0x00001000 /* No Backoff Algorithm */
#define MAC2_BACK_PRESSURE 0x00002000 /* Backoff Presurre / No Backoff */
#define MAC2_EXCESS_DEF 0x00004000 /* Excess Defer */
/* Back-to-Back Inter-Packet-Gap Register */
#define IPGT_FULL_DUP 0x00000015 /* Recommended value for Full Duplex */
#define IPGT_HALF_DUP 0x00000012 /* Recommended value for Half Duplex */
/* Non Back-to-Back Inter-Packet-Gap Register */
#define IPGR_DEF 0x00000012 /* Recommended value */
/* Collision Window/Retry Register */
#define CLRT_DEF 0x0000370F /* Default value */
/* PHY Support Register */
#define SUPP_SPEED 0x00000100 /* Reduced MII Logic Current Speed */
#define SUPP_RES_RMII 0x00000800 /* Reset Reduced MII Logic */
/* Test Register */
#define TEST_SHCUT_PQUANTA 0x00000001 /* Shortcut Pause Quanta */
#define TEST_TST_PAUSE 0x00000002 /* Test Pause */
#define TEST_TST_BACKP 0x00000004 /* Test Back Pressure */
/* MII Management Configuration Register */
#define MCFG_SCAN_INC 0x00000001 /* Scan Increment PHY Address */
#define MCFG_SUPP_PREAM 0x00000002 /* Suppress Preamble */
#define MCFG_CLK_SEL 0x0000003C /* Clock Select Mask */
#define MCFG_RES_MII 0x00008000 /* Reset MII Management Hardware */
/* MII Management Command Register */
#define MCMD_READ 0x00000001 /* MII Read */
#define MCMD_SCAN 0x00000002 /* MII Scan continuously */
#define MII_WR_TOUT 0x00050000 /* MII Write timeout count */
#define MII_RD_TOUT 0x00050000 /* MII Read timeout count */
/* MII Management Address Register */
#define MADR_REG_ADR 0x0000001F /* MII Register Address Mask */
#define MADR_PHY_ADR 0x00001F00 /* PHY Address Mask */
/* MII Management Indicators Register */
#define MIND_BUSY 0x00000001 /* MII is Busy */
#define MIND_SCAN 0x00000002 /* MII Scanning in Progress */
#define MIND_NOT_VAL 0x00000004 /* MII Read Data not valid */
#define MIND_MII_LINK_FAIL 0x00000008 /* MII Link Failed */
/* Command Register */
#define CR_RX_EN 0x00000001 /* Enable Receive */
#define CR_TX_EN 0x00000002 /* Enable Transmit */
#define CR_REG_RES 0x00000008 /* Reset Host Registers */
#define CR_TX_RES 0x00000010 /* Reset Transmit Datapath */
#define CR_RX_RES 0x00000020 /* Reset Receive Datapath */
#define CR_PASS_RUNT_FRM 0x00000040 /* Pass Runt Frames */
#define CR_PASS_RX_FILT 0x00000080 /* Pass RX Filter */
#define CR_TX_FLOW_CTRL 0x00000100 /* TX Flow Control */
#define CR_RMII 0x00000200 /* Reduced MII Interface */
#define CR_FULL_DUP 0x00000400 /* Full Duplex */
/* Status Register */
#define SR_RX_EN 0x00000001 /* Enable Receive */
#define SR_TX_EN 0x00000002 /* Enable Transmit */
/* Transmit Status Vector 0 Register */
#define TSV0_CRC_ERR 0x00000001 /* CRC error */
#define TSV0_LEN_CHKERR 0x00000002 /* Length Check Error */
#define TSV0_LEN_OUTRNG 0x00000004 /* Length Out of Range */
#define TSV0_DONE 0x00000008 /* Tramsmission Completed */
#define TSV0_MCAST 0x00000010 /* Multicast Destination */
#define TSV0_BCAST 0x00000020 /* Broadcast Destination */
#define TSV0_PKT_DEFER 0x00000040 /* Packet Deferred */
#define TSV0_EXC_DEFER 0x00000080 /* Excessive Packet Deferral */
#define TSV0_EXC_COLL 0x00000100 /* Excessive Collision */
#define TSV0_LATE_COLL 0x00000200 /* Late Collision Occured */
#define TSV0_GIANT 0x00000400 /* Giant Frame */
#define TSV0_UNDERRUN 0x00000800 /* Buffer Underrun */
#define TSV0_BYTES 0x0FFFF000 /* Total Bytes Transferred */
#define TSV0_CTRL_FRAME 0x10000000 /* Control Frame */
#define TSV0_PAUSE 0x20000000 /* Pause Frame */
#define TSV0_BACK_PRESS 0x40000000 /* Backpressure Method Applied */
#define TSV0_VLAN 0x80000000 /* VLAN Frame */
/* Transmit Status Vector 1 Register */
#define TSV1_BYTE_CNT 0x0000FFFF /* Transmit Byte Count */
#define TSV1_COLL_CNT 0x000F0000 /* Transmit Collision Count */
/* Receive Status Vector Register */
#define RSV_BYTE_CNT 0x0000FFFF /* Receive Byte Count */
#define RSV_PKT_IGNORED 0x00010000 /* Packet Previously Ignored */
#define RSV_RXDV_SEEN 0x00020000 /* RXDV Event Previously Seen */
#define RSV_CARR_SEEN 0x00040000 /* Carrier Event Previously Seen */
#define RSV_REC_CODEV 0x00080000 /* Receive Code Violation */
#define RSV_CRC_ERR 0x00100000 /* CRC Error */
#define RSV_LEN_CHKERR 0x00200000 /* Length Check Error */
#define RSV_LEN_OUTRNG 0x00400000 /* Length Out of Range */
#define RSV_REC_OK 0x00800000 /* Frame Received OK */
#define RSV_MCAST 0x01000000 /* Multicast Frame */
#define RSV_BCAST 0x02000000 /* Broadcast Frame */
#define RSV_DRIB_NIBB 0x04000000 /* Dribble Nibble */
#define RSV_CTRL_FRAME 0x08000000 /* Control Frame */
#define RSV_PAUSE 0x10000000 /* Pause Frame */
#define RSV_UNSUPP_OPC 0x20000000 /* Unsupported Opcode */
#define RSV_VLAN 0x40000000 /* VLAN Frame */
/* Flow Control Counter Register */
#define FCC_MIRR_CNT 0x0000FFFF /* Mirror Counter */
#define FCC_PAUSE_TIM 0xFFFF0000 /* Pause Timer */
/* Flow Control Status Register */
#define FCS_MIRR_CNT 0x0000FFFF /* Mirror Counter Current */
/* Receive Filter Control Register */
#define RFC_UCAST_EN 0x00000001 /* Accept Unicast Frames Enable */
#define RFC_BCAST_EN 0x00000002 /* Accept Broadcast Frames Enable */
#define RFC_MCAST_EN 0x00000004 /* Accept Multicast Frames Enable */
#define RFC_UCAST_HASH_EN 0x00000008 /* Accept Unicast Hash Filter Frames */
#define RFC_MCAST_HASH_EN 0x00000010 /* Accept Multicast Hash Filter Fram.*/
#define RFC_PERFECT_EN 0x00000020 /* Accept Perfect Match Enable */
#define RFC_MAGP_WOL_EN 0x00001000 /* Magic Packet Filter WoL Enable */
#define RFC_PFILT_WOL_EN 0x00002000 /* Perfect Filter WoL Enable */
/* Receive Filter WoL Status/Clear Registers */
#define WOL_UCAST 0x00000001 /* Unicast Frame caused WoL */
#define WOL_BCAST 0x00000002 /* Broadcast Frame caused WoL */
#define WOL_MCAST 0x00000004 /* Multicast Frame caused WoL */
#define WOL_UCAST_HASH 0x00000008 /* Unicast Hash Filter Frame WoL */
#define WOL_MCAST_HASH 0x00000010 /* Multicast Hash Filter Frame WoL */
#define WOL_PERFECT 0x00000020 /* Perfect Filter WoL */
#define WOL_RX_FILTER 0x00000080 /* RX Filter caused WoL */
#define WOL_MAG_PACKET 0x00000100 /* Magic Packet Filter caused WoL */
/* Interrupt Status/Enable/Clear/Set Registers */
#define INT_RX_OVERRUN 0x00000001 /* Overrun Error in RX Queue */
#define INT_RX_ERR 0x00000002 /* Receive Error */
#define INT_RX_FIN 0x00000004 /* RX Finished Process Descriptors */
#define INT_RX_DONE 0x00000008 /* Receive Done */
#define INT_TX_UNDERRUN 0x00000010 /* Transmit Underrun */
#define INT_TX_ERR 0x00000020 /* Transmit Error */
#define INT_TX_FIN 0x00000040 /* TX Finished Process Descriptors */
#define INT_TX_DONE 0x00000080 /* Transmit Done */
#define INT_SOFT_INT 0x00001000 /* Software Triggered Interrupt */
#define INT_WAKEUP 0x00002000 /* Wakeup Event Interrupt */
/* Power Down Register */
#define PD_POWER_DOWN 0x80000000 /* Power Down MAC */
/* RX Descriptor Control Word */
#define RCTRL_SIZE 0x000007FF /* Buffer size mask */
#define RCTRL_INT 0x80000000 /* Generate RxDone Interrupt */
/* RX Status Hash CRC Word */
#define RHASH_SA 0x000001FF /* Hash CRC for Source Address */
#define RHASH_DA 0x001FF000 /* Hash CRC for Destination Address */
/* RX Status Information Word */
#define RINFO_SIZE 0x000007FF /* Data size in bytes */
#define RINFO_CTRL_FRAME 0x00040000 /* Control Frame */
#define RINFO_VLAN 0x00080000 /* VLAN Frame */
#define RINFO_FAIL_FILT 0x00100000 /* RX Filter Failed */
#define RINFO_MCAST 0x00200000 /* Multicast Frame */
#define RINFO_BCAST 0x00400000 /* Broadcast Frame */
#define RINFO_CRC_ERR 0x00800000 /* CRC Error in Frame */
#define RINFO_SYM_ERR 0x01000000 /* Symbol Error from PHY */
#define RINFO_LEN_ERR 0x02000000 /* Length Error */
#define RINFO_RANGE_ERR 0x04000000 /* Range Error (exceeded max. size) */
#define RINFO_ALIGN_ERR 0x08000000 /* Alignment Error */
#define RINFO_OVERRUN 0x10000000 /* Receive overrun */
#define RINFO_NO_DESCR 0x20000000 /* No new Descriptor available */
#define RINFO_LAST_FLAG 0x40000000 /* Last Fragment in Frame */
#define RINFO_ERR 0x80000000 /* Error Occured (OR of all errors) */
#define RINFO_ERR_MASK (RINFO_FAIL_FILT | RINFO_CRC_ERR | RINFO_SYM_ERR | \
RINFO_LEN_ERR | RINFO_ALIGN_ERR | RINFO_OVERRUN)
/* TX Descriptor Control Word */
#define TCTRL_SIZE 0x000007FF /* Size of data buffer in bytes */
#define TCTRL_OVERRIDE 0x04000000 /* Override Default MAC Registers */
#define TCTRL_HUGE 0x08000000 /* Enable Huge Frame */
#define TCTRL_PAD 0x10000000 /* Pad short Frames to 64 bytes */
#define TCTRL_CRC 0x20000000 /* Append a hardware CRC to Frame */
#define TCTRL_LAST 0x40000000 /* Last Descriptor for TX Frame */
#define TCTRL_INT 0x80000000 /* Generate TxDone Interrupt */
/* TX Status Information Word */
#define TINFO_COL_CNT 0x01E00000 /* Collision Count */
#define TINFO_DEFER 0x02000000 /* Packet Deferred (not an error) */
#define TINFO_EXCESS_DEF 0x04000000 /* Excessive Deferral */
#define TINFO_EXCESS_COL 0x08000000 /* Excessive Collision */
#define TINFO_LATE_COL 0x10000000 /* Late Collision Occured */
#define TINFO_UNDERRUN 0x20000000 /* Transmit Underrun */
#define TINFO_NO_DESCR 0x40000000 /* No new Descriptor available */
#define TINFO_ERR 0x80000000 /* Error Occured (OR of all errors) */
/* ENET Device Revision ID */
#define OLD_EMAC_MODULE_ID 0x39022000 /* Rev. ID for first rev '-' */
/* DP83848C PHY Registers */
#define PHY_REG_BMCR 0x00 /* Basic Mode Control Register */
#define PHY_REG_BMSR 0x01 /* Basic Mode Status Register */
#define PHY_REG_IDR1 0x02 /* PHY Identifier 1 */
#define PHY_REG_IDR2 0x03 /* PHY Identifier 2 */
#define PHY_REG_ANAR 0x04 /* Auto-Negotiation Advertisement */
#define PHY_REG_ANLPAR 0x05 /* Auto-Neg. Link Partner Abitily */
#define PHY_REG_ANER 0x06 /* Auto-Neg. Expansion Register */
#define PHY_REG_ANNPTR 0x07 /* Auto-Neg. Next Page TX */
/* PHY Extended Registers */
#define PHY_REG_STS 0x10 /* Status Register */
#define PHY_REG_MICR 0x11 /* MII Interrupt Control Register */
#define PHY_REG_MISR 0x12 /* MII Interrupt Status Register */
#define PHY_REG_FCSCR 0x14 /* False Carrier Sense Counter */
#define PHY_REG_RECR 0x15 /* Receive Error Counter */
#define PHY_REG_PCSR 0x16 /* PCS Sublayer Config. and Status */
#define PHY_REG_RBR 0x17 /* RMII and Bypass Register */
#define PHY_REG_LEDCR 0x18 /* LED Direct Control Register */
#define PHY_REG_PHYCR 0x19 /* PHY Control Register */
#define PHY_REG_10BTSCR 0x1A /* 10Base-T Status/Control Register */
#define PHY_REG_CDCTRL1 0x1B /* CD Test Control and BIST Extens. */
#define PHY_REG_EDCR 0x1D /* Energy Detect Control Register */
#define PHY_FULLD_100M 0x2100 /* Full Duplex 100Mbit */
#define PHY_HALFD_100M 0x2000 /* Half Duplex 100Mbit */
#define PHY_FULLD_10M 0x0100 /* Full Duplex 10Mbit */
#define PHY_HALFD_10M 0x0000 /* Half Duplex 10MBit */
#define PHY_AUTO_NEG 0x3000 /* Select Auto Negotiation */
#define PHY_AUTO_NEG_COMPLETE 0x0020 /* Auto negotiation have finished. */
#define DP83848C_DEF_ADR 0x0100 /* Default PHY device address */
#define DP83848C_ID 0x20005C90 /* PHY Identifier */
#endif
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,604 @@
/*
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.
*/
/* Originally adapted from file written by Andreas Dannenberg. Supplied with permission. */
/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/* Hardware specific includes. */
#include "EthDev_LPC17xx.h"
/* Time to wait between each inspection of the link status. */
#define emacWAIT_FOR_LINK_TO_ESTABLISH ( 500 / portTICK_RATE_MS )
/* Short delay used in several places during the initialisation process. */
#define emacSHORT_DELAY ( 2 )
/* Hardware specific bit definitions. */
#define emacLINK_ESTABLISHED ( 0x0001 )
#define emacFULL_DUPLEX_ENABLED ( 0x0004 )
#define emac10BASE_T_MODE ( 0x0002 )
#define emacPINSEL2_VALUE ( 0x50150105 )
/* If no buffers are available, then wait this long before looking again.... */
#define emacBUFFER_WAIT_DELAY ( 3 / portTICK_RATE_MS )
/* ...and don't look more than this many times. */
#define emacBUFFER_WAIT_ATTEMPTS ( 30 )
/* Index to the Tx descriptor that is always used first for every Tx. The second
descriptor is then used to re-send in order to speed up the uIP Tx process. */
#define emacTX_DESC_INDEX ( 0 )
/*-----------------------------------------------------------*/
/*
* Configure both the Rx and Tx descriptors during the init process.
*/
static void prvInitDescriptors( void );
/*
* Setup the IO and peripherals required for Ethernet communication.
*/
static void prvSetupEMACHardware( void );
/*
* Control the auto negotiate process.
*/
static void prvConfigurePHY( void );
/*
* Wait for a link to be established, then setup the PHY according to the link
* parameters.
*/
static long prvSetupLinkStatus( void );
/*
* Search the pool of buffers to find one that is free. If a buffer is found
* mark it as in use before returning its address.
*/
static unsigned char *prvGetNextBuffer( void );
/*
* Return an allocated buffer to the pool of free buffers.
*/
static void prvReturnBuffer( unsigned char *pucBuffer );
/*
* Send lValue to the lPhyReg within the PHY.
*/
static long prvWritePHY( long lPhyReg, long lValue );
/*
* Read a value from ucPhyReg within the PHY. *plStatus will be set to
* pdFALSE if there is an error.
*/
static unsigned short prvReadPHY( unsigned char ucPhyReg, long *plStatus );
/*-----------------------------------------------------------*/
/* The semaphore used to wake the uIP task when data arrives. */
extern xSemaphoreHandle xEMACSemaphore;
/* Each ucBufferInUse index corresponds to a position in the pool of buffers.
If the index contains a 1 then the buffer within pool is in use, if it
contains a 0 then the buffer is free. */
static unsigned char ucBufferInUse[ ETH_NUM_BUFFERS ] = { pdFALSE };
/* The uip_buffer is not a fixed array, but instead gets pointed to the buffers
allocated within this file. */
unsigned char * uip_buf;
/* Store the length of the data being sent so the data can be sent twice. The
value will be set back to 0 once the data has been sent twice. */
static unsigned short usSendLen = 0;
/*-----------------------------------------------------------*/
long lEMACInit( void )
{
long lReturn = pdPASS;
unsigned long ulID1, ulID2;
/* Reset peripherals, configure port pins and registers. */
prvSetupEMACHardware();
/* Check the PHY part number is as expected. */
ulID1 = prvReadPHY( PHY_REG_IDR1, &lReturn );
ulID2 = prvReadPHY( PHY_REG_IDR2, &lReturn );
if( ( (ulID1 << 16UL ) | ( ulID2 & 0xFFF0UL ) ) == DP83848C_ID )
{
/* Set the Ethernet MAC Address registers */
EMAC->SA0 = ( configMAC_ADDR0 << 8 ) | configMAC_ADDR1;
EMAC->SA1 = ( configMAC_ADDR2 << 8 ) | configMAC_ADDR3;
EMAC->SA2 = ( configMAC_ADDR4 << 8 ) | configMAC_ADDR5;
/* Initialize Tx and Rx DMA Descriptors */
prvInitDescriptors();
/* Receive broadcast and perfect match packets */
EMAC->RxFilterCtrl = RFC_UCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN;
/* Setup the PHY. */
prvConfigurePHY();
}
else
{
lReturn = pdFAIL;
}
/* Check the link status. */
if( lReturn == pdPASS )
{
lReturn = prvSetupLinkStatus();
}
if( lReturn == pdPASS )
{
/* Initialise uip_buf to ensure it points somewhere valid. */
uip_buf = prvGetNextBuffer();
/* Reset all interrupts */
EMAC->IntClear = ( INT_RX_OVERRUN | INT_RX_ERR | INT_RX_FIN | INT_RX_DONE | INT_TX_UNDERRUN | INT_TX_ERR | INT_TX_FIN | INT_TX_DONE | INT_SOFT_INT | INT_WAKEUP );
/* Enable receive and transmit mode of MAC Ethernet core */
EMAC->Command |= ( CR_RX_EN | CR_TX_EN );
EMAC->MAC1 |= MAC1_REC_EN;
}
return lReturn;
}
/*-----------------------------------------------------------*/
static unsigned char *prvGetNextBuffer( void )
{
long x;
unsigned char *pucReturn = NULL;
unsigned long ulAttempts = 0;
while( pucReturn == NULL )
{
/* Look through the buffers to find one that is not in use by
anything else. */
for( x = 0; x < ETH_NUM_BUFFERS; x++ )
{
if( ucBufferInUse[ x ] == pdFALSE )
{
ucBufferInUse[ x ] = pdTRUE;
pucReturn = ( unsigned char * ) ETH_BUF( x );
break;
}
}
/* Was a buffer found? */
if( pucReturn == NULL )
{
ulAttempts++;
if( ulAttempts >= emacBUFFER_WAIT_ATTEMPTS )
{
break;
}
/* Wait then look again. */
vTaskDelay( emacBUFFER_WAIT_DELAY );
}
}
return pucReturn;
}
/*-----------------------------------------------------------*/
static void prvInitDescriptors( void )
{
long x, lNextBuffer = 0;
for( x = 0; x < NUM_RX_FRAG; x++ )
{
/* Allocate the next Ethernet buffer to this descriptor. */
RX_DESC_PACKET( x ) = ETH_BUF( lNextBuffer );
RX_DESC_CTRL( x ) = RCTRL_INT | ( ETH_FRAG_SIZE - 1 );
RX_STAT_INFO( x ) = 0;
RX_STAT_HASHCRC( x ) = 0;
/* The Ethernet buffer is now in use. */
ucBufferInUse[ lNextBuffer ] = pdTRUE;
lNextBuffer++;
}
/* Set EMAC Receive Descriptor Registers. */
EMAC->RxDescriptor = RX_DESC_BASE;
EMAC->RxStatus = RX_STAT_BASE;
EMAC->RxDescriptorNumber = NUM_RX_FRAG - 1;
/* Rx Descriptors Point to 0 */
EMAC->RxConsumeIndex = 0;
/* A buffer is not allocated to the Tx descriptors until they are actually
used. */
for( x = 0; x < NUM_TX_FRAG; x++ )
{
TX_DESC_PACKET( x ) = ( unsigned long ) NULL;
TX_DESC_CTRL( x ) = 0;
TX_STAT_INFO( x ) = 0;
}
/* Set EMAC Transmit Descriptor Registers. */
EMAC->TxDescriptor = TX_DESC_BASE;
EMAC->TxStatus = TX_STAT_BASE;
EMAC->TxDescriptorNumber = NUM_TX_FRAG - 1;
/* Tx Descriptors Point to 0 */
EMAC->TxProduceIndex = 0;
}
/*-----------------------------------------------------------*/
static void prvSetupEMACHardware( void )
{
unsigned short us;
long x, lDummy;
/* Enable P1 Ethernet Pins. */
PINCON->PINSEL2 = emacPINSEL2_VALUE;
PINCON->PINSEL3 = ( PINCON->PINSEL3 & ~0x0000000F ) | 0x00000005;
/* Power Up the EMAC controller. */
SC->PCONP |= PCONP_PCENET;
vTaskDelay( emacSHORT_DELAY );
/* Reset all EMAC internal modules. */
EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES;
EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM;
/* A short delay after reset. */
vTaskDelay( emacSHORT_DELAY );
/* Initialize MAC control registers. */
EMAC->MAC1 = MAC1_PASS_ALL;
EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
EMAC->MAXF = ETH_MAX_FLEN;
EMAC->CLRT = CLRT_DEF;
EMAC->IPGR = IPGR_DEF;
/* Enable Reduced MII interface. */
EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM;
/* Reset Reduced MII Logic. */
EMAC->SUPP = SUPP_RES_RMII;
vTaskDelay( emacSHORT_DELAY );
EMAC->SUPP = 0;
/* Put the PHY in reset mode */
prvWritePHY( PHY_REG_BMCR, MCFG_RES_MII );
prvWritePHY( PHY_REG_BMCR, MCFG_RES_MII );
/* Wait for hardware reset to end. */
for( x = 0; x < 100; x++ )
{
vTaskDelay( emacSHORT_DELAY * 5 );
us = prvReadPHY( PHY_REG_BMCR, &lDummy );
if( !( us & MCFG_RES_MII ) )
{
/* Reset complete */
break;
}
}
}
/*-----------------------------------------------------------*/
static void prvConfigurePHY( void )
{
unsigned short us;
long x, lDummy;
/* Auto negotiate the configuration. */
if( prvWritePHY( PHY_REG_BMCR, PHY_AUTO_NEG ) )
{
vTaskDelay( emacSHORT_DELAY * 5 );
for( x = 0; x < 10; x++ )
{
us = prvReadPHY( PHY_REG_BMSR, &lDummy );
if( us & PHY_AUTO_NEG_COMPLETE )
{
break;
}
vTaskDelay( emacWAIT_FOR_LINK_TO_ESTABLISH );
}
}
}
/*-----------------------------------------------------------*/
static long prvSetupLinkStatus( void )
{
long lReturn = pdFAIL, x;
unsigned short usLinkStatus;
/* Wait with timeout for the link to be established. */
for( x = 0; x < 10; x++ )
{
usLinkStatus = prvReadPHY( PHY_REG_STS, &lReturn );
if( usLinkStatus & emacLINK_ESTABLISHED )
{
/* Link is established. */
lReturn = pdPASS;
break;
}
vTaskDelay( emacWAIT_FOR_LINK_TO_ESTABLISH );
}
if( lReturn == pdPASS )
{
/* Configure Full/Half Duplex mode. */
if( usLinkStatus & emacFULL_DUPLEX_ENABLED )
{
/* Full duplex is enabled. */
EMAC->MAC2 |= MAC2_FULL_DUP;
EMAC->Command |= CR_FULL_DUP;
EMAC->IPGT = IPGT_FULL_DUP;
}
else
{
/* Half duplex mode. */
EMAC->IPGT = IPGT_HALF_DUP;
}
/* Configure 100MBit/10MBit mode. */
if( usLinkStatus & emac10BASE_T_MODE )
{
/* 10MBit mode. */
EMAC->SUPP = 0;
}
else
{
/* 100MBit mode. */
EMAC->SUPP = SUPP_SPEED;
}
}
return lReturn;
}
/*-----------------------------------------------------------*/
static void prvReturnBuffer( unsigned char *pucBuffer )
{
unsigned long ul;
/* Return a buffer to the pool of free buffers. */
for( ul = 0; ul < ETH_NUM_BUFFERS; ul++ )
{
if( ETH_BUF( ul ) == ( unsigned long ) pucBuffer )
{
ucBufferInUse[ ul ] = pdFALSE;
break;
}
}
}
/*-----------------------------------------------------------*/
unsigned long ulGetEMACRxData( void )
{
unsigned long ulLen = 0;
long lIndex;
if( EMAC->RxProduceIndex != EMAC->RxConsumeIndex )
{
/* Mark the current buffer as free as uip_buf is going to be set to
the buffer that contains the received data. */
prvReturnBuffer( uip_buf );
ulLen = ( RX_STAT_INFO( EMAC->RxConsumeIndex ) & RINFO_SIZE ) - 3;
uip_buf = ( unsigned char * ) RX_DESC_PACKET( EMAC->RxConsumeIndex );
/* Allocate a new buffer to the descriptor. */
RX_DESC_PACKET( EMAC->RxConsumeIndex ) = ( unsigned long ) prvGetNextBuffer();
/* Move the consume index onto the next position, ensuring it wraps to
the beginning at the appropriate place. */
lIndex = EMAC->RxConsumeIndex;
lIndex++;
if( lIndex >= NUM_RX_FRAG )
{
lIndex = 0;
}
EMAC->RxConsumeIndex = lIndex;
}
return ulLen;
}
/*-----------------------------------------------------------*/
void vSendEMACTxData( unsigned short usTxDataLen )
{
unsigned long ulAttempts = 0UL;
/* Check to see if the Tx descriptor is free, indicated by its buffer being
NULL. */
while( TX_DESC_PACKET( emacTX_DESC_INDEX ) != ( unsigned long ) NULL )
{
/* Wait for the Tx descriptor to become available. */
vTaskDelay( emacBUFFER_WAIT_DELAY );
ulAttempts++;
if( ulAttempts > emacBUFFER_WAIT_ATTEMPTS )
{
/* Something has gone wrong as the Tx descriptor is still in use.
Clear it down manually, the data it was sending will probably be
lost. */
prvReturnBuffer( ( unsigned char * ) TX_DESC_PACKET( emacTX_DESC_INDEX ) );
break;
}
}
/* Setup the Tx descriptor for transmission. Remember the length of the
data being sent so the second descriptor can be used to send it again from
within the ISR. */
usSendLen = usTxDataLen;
TX_DESC_PACKET( emacTX_DESC_INDEX ) = ( unsigned long ) uip_buf;
TX_DESC_CTRL( emacTX_DESC_INDEX ) = ( usTxDataLen | TCTRL_LAST | TCTRL_INT );
EMAC->TxProduceIndex = ( emacTX_DESC_INDEX + 1 );
/* uip_buf is being sent by the Tx descriptor. Allocate a new buffer. */
uip_buf = prvGetNextBuffer();
}
/*-----------------------------------------------------------*/
static long prvWritePHY( long lPhyReg, long lValue )
{
const long lMaxTime = 10;
long x;
EMAC->MADR = DP83848C_DEF_ADR | lPhyReg;
EMAC->MWTD = lValue;
x = 0;
for( x = 0; x < lMaxTime; x++ )
{
if( ( EMAC->MIND & MIND_BUSY ) == 0 )
{
/* Operation has finished. */
break;
}
vTaskDelay( emacSHORT_DELAY );
}
if( x < lMaxTime )
{
return pdPASS;
}
else
{
return pdFAIL;
}
}
/*-----------------------------------------------------------*/
static unsigned short prvReadPHY( unsigned char ucPhyReg, long *plStatus )
{
long x;
const long lMaxTime = 10;
EMAC->MADR = DP83848C_DEF_ADR | ucPhyReg;
EMAC->MCMD = MCMD_READ;
for( x = 0; x < lMaxTime; x++ )
{
/* Operation has finished. */
if( ( EMAC->MIND & MIND_BUSY ) == 0 )
{
break;
}
vTaskDelay( emacSHORT_DELAY );
}
EMAC->MCMD = 0;
if( x >= lMaxTime )
{
*plStatus = pdFAIL;
}
return( EMAC->MRDD );
}
/*-----------------------------------------------------------*/
void vEMAC_ISR( void )
{
unsigned long ulStatus;
long lHigherPriorityTaskWoken = pdFALSE;
ulStatus = EMAC->IntStatus;
/* Clear the interrupt. */
EMAC->IntClear = ulStatus;
if( ulStatus & INT_RX_DONE )
{
/* Ensure the uIP task is not blocked as data has arrived. */
xSemaphoreGiveFromISR( xEMACSemaphore, &lHigherPriorityTaskWoken );
}
if( ulStatus & INT_TX_DONE )
{
if( usSendLen > 0 )
{
/* Send the data again, using the second descriptor. As there are
only two descriptors the index is set back to 0. */
TX_DESC_PACKET( ( emacTX_DESC_INDEX + 1 ) ) = TX_DESC_PACKET( emacTX_DESC_INDEX );
TX_DESC_CTRL( ( emacTX_DESC_INDEX + 1 ) ) = ( usSendLen | TCTRL_LAST | TCTRL_INT );
EMAC->TxProduceIndex = ( emacTX_DESC_INDEX );
/* This is the second Tx so set usSendLen to 0 to indicate that the
Tx descriptors will be free again. */
usSendLen = 0UL;
}
else
{
/* The Tx buffer is no longer required. */
prvReturnBuffer( ( unsigned char * ) TX_DESC_PACKET( emacTX_DESC_INDEX ) );
TX_DESC_PACKET( emacTX_DESC_INDEX ) = ( unsigned long ) NULL;
}
}
portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );
}