Not to be added for the next release, so removed to avoid confusion.
parent
416fcd3a3d
commit
2ce61bafdc
@ -1,772 +0,0 @@
|
|||||||
/* Based on MMCv3/SDv1/SDv2 (in SPI mode) control module (C)ChaN, 2009
|
|
||||||
Modifications (C) 2010 Real Time Engineers ltd. */
|
|
||||||
|
|
||||||
#include "FreeRTOS.h"
|
|
||||||
#include "diskio.h"
|
|
||||||
|
|
||||||
void disk_init_spi( void );
|
|
||||||
|
|
||||||
/* Definitions for MMC/SDC command */
|
|
||||||
#define CMD0 ( 0x40 + 0 ) /* GO_IDLE_STATE */
|
|
||||||
#define CMD1 ( 0x40 + 1 ) /* SEND_OP_COND (MMC) */
|
|
||||||
#define ACMD41 ( 0xC0 + 41 ) /* SEND_OP_COND (SDC) */
|
|
||||||
#define CMD8 ( 0x40 + 8 ) /* SEND_IF_COND */
|
|
||||||
#define CMD9 ( 0x40 + 9 ) /* SEND_CSD */
|
|
||||||
#define CMD10 ( 0x40 + 10 ) /* SEND_CID */
|
|
||||||
#define CMD12 ( 0x40 + 12 ) /* STOP_TRANSMISSION */
|
|
||||||
#define ACMD13 ( 0xC0 + 13 ) /* SD_STATUS (SDC) */
|
|
||||||
#define CMD16 ( 0x40 + 16 ) /* SET_BLOCKLEN */
|
|
||||||
#define CMD17 ( 0x40 + 17 ) /* READ_SINGLE_BLOCK */
|
|
||||||
#define CMD18 ( 0x40 + 18 ) /* READ_MULTIPLE_BLOCK */
|
|
||||||
#define CMD23 ( 0x40 + 23 ) /* SET_BLOCK_COUNT (MMC) */
|
|
||||||
#define ACMD23 ( 0xC0 + 23 ) /* SET_WR_BLK_ERASE_COUNT (SDC) */
|
|
||||||
#define CMD24 ( 0x40 + 24 ) /* WRITE_BLOCK */
|
|
||||||
#define CMD25 ( 0x40 + 25 ) /* WRITE_MULTIPLE_BLOCK */
|
|
||||||
#define CMD55 ( 0x40 + 55 ) /* APP_CMD */
|
|
||||||
#define CMD58 ( 0x40 + 58 ) /* READ_OCR */
|
|
||||||
|
|
||||||
/* Port Controls (Platform dependent) */
|
|
||||||
#define CS_LOW() GPIO0->FIOCLR = ( 1 << 16 ) /* MMC CS = L */
|
|
||||||
#define CS_HIGH() GPIO0->FIOSET = ( 1 << 16 ) /* MMC CS = H */
|
|
||||||
|
|
||||||
#define SOCKWP ( 0 ) /* Write protect switch. */
|
|
||||||
#define SOCKINS ( 1 << 29 ) /* Card detect switch. */
|
|
||||||
#define SOCKPORT ( GPIO4->FIOPIN )
|
|
||||||
#define FCLK_SLOW() /* Set slow clock (100k-400k) */
|
|
||||||
#define FCLK_FAST() /* Set fast clock (depends on the CSD) */
|
|
||||||
|
|
||||||
#define xmit_spi( dat ) xchg_spi( dat )
|
|
||||||
#define rcvr_spi() xchg_spi( 0xFF )
|
|
||||||
#define rcvr_spi_m( p ) \
|
|
||||||
SPI->SPDR = 0xFF; \
|
|
||||||
while( !( SPI->SPSR & ( 1 << 7 ) ) ); /* Check SPIF bit. */ \
|
|
||||||
*( p ) = ( BYTE ) SPI->SPDR;
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
static volatile DSTATUS Stat = STA_NOINIT; /* Disk status */
|
|
||||||
static volatile UINT Timer1, Timer2; /* 1000Hz decrement timer */
|
|
||||||
static UINT CardType;
|
|
||||||
|
|
||||||
static BYTE xchg_spi( BYTE dat )
|
|
||||||
{
|
|
||||||
SPI->SPDR = dat;
|
|
||||||
while( !( SPI->SPSR & ( 1 << 7 ) ) ); /* Check SPIF bit. */
|
|
||||||
return( BYTE ) SPI->SPDR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* Wait for card ready */
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
static BYTE wait_ready( void )
|
|
||||||
{
|
|
||||||
BYTE res;
|
|
||||||
|
|
||||||
Timer2 = 500; /* Wait for ready in timeout of 500ms */
|
|
||||||
rcvr_spi();
|
|
||||||
do
|
|
||||||
{
|
|
||||||
res = rcvr_spi();
|
|
||||||
} while( (res != 0xFF) && Timer2 );
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* Deselect the card and release SPI bus */
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
static void deselect( void )
|
|
||||||
{
|
|
||||||
CS_HIGH();
|
|
||||||
rcvr_spi();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* Select the card and wait ready */
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
static BOOL select( void ) /* TRUE:Successful, FALSE:Timeout */
|
|
||||||
{
|
|
||||||
CS_LOW();
|
|
||||||
if( wait_ready() != 0xFF )
|
|
||||||
{
|
|
||||||
deselect();
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* Power Control (Platform dependent) */
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* When the target system does not support socket power control, there */
|
|
||||||
|
|
||||||
/* is nothing to do in these functions and chk_power always returns 1. */
|
|
||||||
static void power_on( void )
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
/* Enable SPI1 */
|
|
||||||
SPI1CON1 = 0x013B;
|
|
||||||
SPI1CON2 = 0x0000;
|
|
||||||
_SPIEN = 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void power_off( void )
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
select(); /* Wait for card ready */
|
|
||||||
deselect();
|
|
||||||
|
|
||||||
_SPIEN = 0; /* Disable SPI1 */
|
|
||||||
|
|
||||||
Stat |= STA_NOINIT; /* Set STA_NOINIT */
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* Receive a data packet from MMC */
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
static BOOL rcvr_datablock( BYTE *buff, /* Data buffer to store received data */ UINT btr /* Byte count (must be multiple of 4) */ )
|
|
||||||
{
|
|
||||||
BYTE token;
|
|
||||||
|
|
||||||
Timer1 = 100;
|
|
||||||
do
|
|
||||||
{ /* Wait for data packet in timeout of 100ms */
|
|
||||||
token = rcvr_spi();
|
|
||||||
} while( (token == 0xFF) && Timer1 );
|
|
||||||
|
|
||||||
if( token != 0xFE )
|
|
||||||
{
|
|
||||||
return FALSE; /* If not valid data token, retutn with error */
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{ /* Receive the data block into buffer */
|
|
||||||
rcvr_spi_m( buff++ );
|
|
||||||
rcvr_spi_m( buff++ );
|
|
||||||
rcvr_spi_m( buff++ );
|
|
||||||
rcvr_spi_m( buff++ );
|
|
||||||
} while( btr -= 4 );
|
|
||||||
rcvr_spi(); /* Discard CRC */
|
|
||||||
rcvr_spi();
|
|
||||||
|
|
||||||
return TRUE; /* Return with success */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* Send a data packet to MMC */
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
#if _READONLY == 0
|
|
||||||
static BOOL xmit_datablock( const BYTE *buff, /* 512 byte data block to be transmitted */ BYTE token /* Data/Stop token */ )
|
|
||||||
{
|
|
||||||
BYTE resp;
|
|
||||||
UINT bc = 512;
|
|
||||||
|
|
||||||
if( wait_ready() != 0xFF )
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
xmit_spi( token ); /* Xmit data token */
|
|
||||||
if( token != 0xFD )
|
|
||||||
{ /* Is data token */
|
|
||||||
do
|
|
||||||
{ /* Xmit the 512 byte data block to MMC */
|
|
||||||
xmit_spi( *buff++ );
|
|
||||||
xmit_spi( *buff++ );
|
|
||||||
} while( bc -= 2 );
|
|
||||||
xmit_spi( 0xFF ); /* CRC (Dummy) */
|
|
||||||
xmit_spi( 0xFF );
|
|
||||||
resp = rcvr_spi(); /* Receive data response */
|
|
||||||
if( (resp & 0x1F) != 0x05 )
|
|
||||||
{ /* If not accepted, return with error */
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _READONLY */
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* Send a command packet to MMC */
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
static BYTE send_cmd( BYTE cmd, /* Command byte */ DWORD arg /* Argument */ )
|
|
||||||
{
|
|
||||||
BYTE n, res;
|
|
||||||
|
|
||||||
if( cmd & 0x80 )
|
|
||||||
{ /* ACMD<n> is the command sequense of CMD55-CMD<n> */
|
|
||||||
cmd &= 0x7F;
|
|
||||||
res = send_cmd( CMD55, 0 );
|
|
||||||
if( res > 1 )
|
|
||||||
{
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Select the card and wait for ready */
|
|
||||||
deselect();
|
|
||||||
if( !select() )
|
|
||||||
{
|
|
||||||
return 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send command packet */
|
|
||||||
xmit_spi( cmd ); /* Start + Command index */
|
|
||||||
xmit_spi( (BYTE) (arg >> 24) ); /* Argument[31..24] */
|
|
||||||
xmit_spi( (BYTE) (arg >> 16) ); /* Argument[23..16] */
|
|
||||||
xmit_spi( (BYTE) (arg >> 8) ); /* Argument[15..8] */
|
|
||||||
xmit_spi( (BYTE) arg ); /* Argument[7..0] */
|
|
||||||
n = 0x01; /* Dummy CRC + Stop */
|
|
||||||
if( cmd == CMD0 )
|
|
||||||
{
|
|
||||||
n = 0x95; /* Valid CRC for CMD0(0) */
|
|
||||||
}
|
|
||||||
|
|
||||||
if( cmd == CMD8 )
|
|
||||||
{
|
|
||||||
n = 0x87; /* Valid CRC for CMD8(0x1AA) */
|
|
||||||
}
|
|
||||||
|
|
||||||
xmit_spi( n );
|
|
||||||
|
|
||||||
/* Receive command response */
|
|
||||||
if( cmd == CMD12 )
|
|
||||||
{
|
|
||||||
rcvr_spi(); /* Skip a stuff byte when stop reading */
|
|
||||||
}
|
|
||||||
|
|
||||||
n = 10; /* Wait for a valid response in timeout of 10 attempts */
|
|
||||||
do
|
|
||||||
{
|
|
||||||
res = rcvr_spi();
|
|
||||||
} while( (res & 0x80) && --n );
|
|
||||||
|
|
||||||
return res; /* Return with the response value */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Public Functions
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* Initialize Disk Drive */
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
DSTATUS disk_initialize( BYTE drv /* Physical drive nmuber (0) */ )
|
|
||||||
{
|
|
||||||
BYTE n, cmd, ty, ocr[4];
|
|
||||||
|
|
||||||
if( drv )
|
|
||||||
{
|
|
||||||
return STA_NOINIT; /* Supports only single drive */
|
|
||||||
}
|
|
||||||
|
|
||||||
if( Stat & STA_NODISK )
|
|
||||||
{
|
|
||||||
return Stat; /* No card in the socket */
|
|
||||||
}
|
|
||||||
|
|
||||||
power_on(); /* Force socket power on */
|
|
||||||
FCLK_SLOW();
|
|
||||||
for( n = 10; n; n-- )
|
|
||||||
{
|
|
||||||
rcvr_spi(); /* 80 dummy clocks */
|
|
||||||
}
|
|
||||||
|
|
||||||
ty = 0;
|
|
||||||
if( send_cmd(CMD0, 0) == 1 )
|
|
||||||
{ /* Enter Idle state */
|
|
||||||
Timer1 = 1000; /* Initialization timeout of 1000 msec */
|
|
||||||
if( send_cmd(CMD8, 0x1AA) == 1 )
|
|
||||||
{ /* SDv2? */
|
|
||||||
for( n = 0; n < 4; n++ )
|
|
||||||
{
|
|
||||||
ocr[n] = rcvr_spi(); /* Get trailing return value of R7 resp */
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ocr[2] == 0x01 && ocr[3] == 0xAA )
|
|
||||||
{ /* The card can work at vdd range of 2.7-3.6V */
|
|
||||||
while( Timer1 && send_cmd(ACMD41, 1UL << 30) );
|
|
||||||
|
|
||||||
/* Wait for leaving idle state (ACMD41 with HCS bit) */
|
|
||||||
if( Timer1 && send_cmd(CMD58, 0) == 0 )
|
|
||||||
{ /* Check CCS bit in the OCR */
|
|
||||||
for( n = 0; n < 4; n++ )
|
|
||||||
{
|
|
||||||
ocr[n] = rcvr_spi();
|
|
||||||
}
|
|
||||||
|
|
||||||
ty = ( ocr[0] & 0x40 ) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 (HC/SC) */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ /* SDv1 or MMCv3 */
|
|
||||||
if( send_cmd(ACMD41, 0) <= 1 )
|
|
||||||
{
|
|
||||||
ty = CT_SD1;
|
|
||||||
cmd = ACMD41; /* SDv1 */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ty = CT_MMC;
|
|
||||||
cmd = CMD1; /* MMCv3 */
|
|
||||||
}
|
|
||||||
|
|
||||||
while( Timer1 && send_cmd(cmd, 0) );
|
|
||||||
|
|
||||||
/* Wait for leaving idle state */
|
|
||||||
if( !Timer1 || send_cmd(CMD16, 512) != 0 )
|
|
||||||
{ /* Set R/W block length to 512 */
|
|
||||||
ty = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CardType = ty;
|
|
||||||
deselect();
|
|
||||||
|
|
||||||
if( ty )
|
|
||||||
{ /* Initialization succeded */
|
|
||||||
Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
|
|
||||||
FCLK_FAST();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ /* Initialization failed */
|
|
||||||
power_off();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Stat;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* Get Disk Status */
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
DSTATUS disk_status( BYTE drv /* Physical drive nmuber (0) */ )
|
|
||||||
{
|
|
||||||
if( drv )
|
|
||||||
{
|
|
||||||
return STA_NOINIT; /* Supports only single drive */
|
|
||||||
}
|
|
||||||
|
|
||||||
return Stat;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* Read Sector(s) */
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
DRESULT disk_read
|
|
||||||
(
|
|
||||||
BYTE drv, /* Physical drive nmuber (0) */
|
|
||||||
BYTE *buff, /* Pointer to the data buffer to store read data */
|
|
||||||
DWORD sector, /* Start sector number (LBA) */
|
|
||||||
BYTE count /* Sector count (1..255) */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if( drv || !count )
|
|
||||||
{
|
|
||||||
return RES_PARERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( Stat & STA_NOINIT )
|
|
||||||
{
|
|
||||||
return RES_NOTRDY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !(CardType & CT_BLOCK) )
|
|
||||||
{
|
|
||||||
sector *= 512; /* Convert to byte address if needed */
|
|
||||||
}
|
|
||||||
|
|
||||||
if( count == 1 )
|
|
||||||
{ /* Single block read */
|
|
||||||
if( (send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */ && rcvr_datablock(buff, 512) )
|
|
||||||
{
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ /* Multiple block read */
|
|
||||||
if( send_cmd(CMD18, sector) == 0 )
|
|
||||||
{ /* READ_MULTIPLE_BLOCK */
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if( !rcvr_datablock(buff, 512) )
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
buff += 512;
|
|
||||||
} while( --count );
|
|
||||||
send_cmd( CMD12, 0 ); /* STOP_TRANSMISSION */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deselect();
|
|
||||||
|
|
||||||
return count ? RES_ERROR : RES_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* Write Sector(s) */
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
#if _READONLY == 0
|
|
||||||
DRESULT disk_write
|
|
||||||
(
|
|
||||||
BYTE drv, /* Physical drive nmuber (0) */
|
|
||||||
const BYTE *buff, /* Pointer to the data to be written */
|
|
||||||
DWORD sector, /* Start sector number (LBA) */
|
|
||||||
BYTE count /* Sector count (1..255) */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if( drv || !count )
|
|
||||||
{
|
|
||||||
return RES_PARERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( Stat & STA_NOINIT )
|
|
||||||
{
|
|
||||||
return RES_NOTRDY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( Stat & STA_PROTECT )
|
|
||||||
{
|
|
||||||
return RES_WRPRT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !(CardType & CT_BLOCK) )
|
|
||||||
{
|
|
||||||
sector *= 512; /* Convert to byte address if needed */
|
|
||||||
}
|
|
||||||
|
|
||||||
if( count == 1 )
|
|
||||||
{ /* Single block write */
|
|
||||||
if( (send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */ && xmit_datablock(buff, 0xFE) )
|
|
||||||
{
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ /* Multiple block write */
|
|
||||||
if( CardType & CT_SDC )
|
|
||||||
{
|
|
||||||
send_cmd( ACMD23, count );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( send_cmd(CMD25, sector) == 0 )
|
|
||||||
{ /* WRITE_MULTIPLE_BLOCK */
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if( !xmit_datablock(buff, 0xFC) )
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
buff += 512;
|
|
||||||
} while( --count );
|
|
||||||
if( !xmit_datablock(0, 0xFD) )
|
|
||||||
{ /* STOP_TRAN token */
|
|
||||||
count = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deselect();
|
|
||||||
|
|
||||||
return count ? RES_ERROR : RES_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _READONLY */
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* Miscellaneous Functions */
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
DRESULT disk_ioctl
|
|
||||||
(
|
|
||||||
BYTE drv, /* Physical drive nmuber (0) */
|
|
||||||
BYTE ctrl, /* Control code */
|
|
||||||
void *buff /* Buffer to send/receive data block */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
DRESULT res;
|
|
||||||
BYTE n, csd[16], *ptr = buff;
|
|
||||||
DWORD csize;
|
|
||||||
|
|
||||||
if( drv )
|
|
||||||
{
|
|
||||||
return RES_PARERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( Stat & STA_NOINIT )
|
|
||||||
{
|
|
||||||
return RES_NOTRDY;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = RES_ERROR;
|
|
||||||
switch( ctrl )
|
|
||||||
{
|
|
||||||
case CTRL_SYNC: /* Flush dirty buffer if present */
|
|
||||||
if( select() )
|
|
||||||
{
|
|
||||||
res = RES_OK;
|
|
||||||
deselect();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GET_SECTOR_COUNT: /* Get number of sectors on the disk (WORD) */
|
|
||||||
if( (send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16) )
|
|
||||||
{
|
|
||||||
if( (csd[0] >> 6) == 1 )
|
|
||||||
{ /* SDv2? */
|
|
||||||
csize = csd[9] + ( (WORD) csd[8] << 8 ) + 1;
|
|
||||||
*( DWORD * ) buff = ( DWORD ) csize << 10;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ /* SDv1 or MMCv2 */
|
|
||||||
n = ( csd[5] & 15 ) + ( (csd[10] & 128) >> 7 ) + ( (csd[9] & 3) << 1 ) + 2;
|
|
||||||
csize = ( csd[8] >> 6 ) + ( (WORD) csd[7] << 2 ) + ( (WORD) (csd[6] & 3) << 10 ) + 1;
|
|
||||||
*( DWORD * ) buff = ( DWORD ) csize << ( n - 9 );
|
|
||||||
}
|
|
||||||
|
|
||||||
res = RES_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GET_SECTOR_SIZE: /* Get sectors on the disk (WORD) */
|
|
||||||
* ( WORD * ) buff = 512;
|
|
||||||
res = RES_OK;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GET_BLOCK_SIZE: /* Get erase block size in unit of sectors (DWORD) */
|
|
||||||
if( CardType & CT_SD2 )
|
|
||||||
{ /* SDv2? */
|
|
||||||
if( send_cmd(ACMD13, 0) == 0 )
|
|
||||||
{ /* Read SD status */
|
|
||||||
rcvr_spi();
|
|
||||||
if( rcvr_datablock(csd, 16) )
|
|
||||||
{ /* Read partial block */
|
|
||||||
for( n = 64 - 16; n; n-- )
|
|
||||||
{
|
|
||||||
rcvr_spi(); /* Purge trailing data */
|
|
||||||
}
|
|
||||||
|
|
||||||
* ( DWORD * ) buff = 16UL << ( csd[10] >> 4 );
|
|
||||||
res = RES_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ /* SDv1 or MMCv3 */
|
|
||||||
if( (send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16) )
|
|
||||||
{ /* Read CSD */
|
|
||||||
if( CardType & CT_SD1 )
|
|
||||||
{ /* SDv1 */
|
|
||||||
*( DWORD * ) buff = ( ((csd[10] & 63) << 1) + ((WORD) (csd[11] & 128) >> 7) + 1 ) << ( (csd[13] >> 6) - 1 );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ /* MMCv3 */
|
|
||||||
*( DWORD * ) buff = ( (WORD) ((csd[10] & 124) >> 2) + 1 ) * ( ((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
res = RES_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MMC_GET_TYPE: /* Get card type flags (1 byte) */
|
|
||||||
*ptr = CardType;
|
|
||||||
res = RES_OK;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MMC_GET_CSD: /* Receive CSD as a data block (16 bytes) */
|
|
||||||
if( (send_cmd(CMD9, 0) == 0) /* READ_CSD */ && rcvr_datablock(buff, 16) )
|
|
||||||
{
|
|
||||||
res = RES_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MMC_GET_CID: /* Receive CID as a data block (16 bytes) */
|
|
||||||
if( (send_cmd(CMD10, 0) == 0) /* READ_CID */ && rcvr_datablock(buff, 16) )
|
|
||||||
{
|
|
||||||
res = RES_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MMC_GET_OCR: /* Receive OCR as an R3 resp (4 bytes) */
|
|
||||||
if( send_cmd(CMD58, 0) == 0 )
|
|
||||||
{ /* READ_OCR */
|
|
||||||
for( n = 0; n < 4; n++ )
|
|
||||||
{
|
|
||||||
*( ( BYTE * ) buff + n ) = rcvr_spi();
|
|
||||||
}
|
|
||||||
|
|
||||||
res = RES_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MMC_GET_SDSTAT: /* Receive SD statsu as a data block (64 bytes) */
|
|
||||||
if( send_cmd(ACMD13, 0) == 0 )
|
|
||||||
{ /* SD_STATUS */
|
|
||||||
rcvr_spi();
|
|
||||||
if( rcvr_datablock(buff, 64) )
|
|
||||||
{
|
|
||||||
res = RES_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
res = RES_PARERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
deselect();
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* Device Timer Interrupt Procedure (Platform dependent) */
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* This function must be called in period of 1ms */
|
|
||||||
void disk_timerproc( void )
|
|
||||||
{
|
|
||||||
static unsigned long pv;
|
|
||||||
unsigned long p;
|
|
||||||
BYTE s;
|
|
||||||
UINT n;
|
|
||||||
|
|
||||||
n = Timer1; /* 1000Hz decrement timer */
|
|
||||||
if( n )
|
|
||||||
{
|
|
||||||
Timer1 = --n;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = Timer2;
|
|
||||||
if( n )
|
|
||||||
{
|
|
||||||
Timer2 = --n;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = pv;
|
|
||||||
pv = SOCKPORT & ( SOCKWP | SOCKINS ); /* Sample socket switch */
|
|
||||||
|
|
||||||
if( p == pv )
|
|
||||||
{ /* Have contacts stabled? */
|
|
||||||
s = Stat;
|
|
||||||
|
|
||||||
if( p & SOCKWP )
|
|
||||||
{ /* WP is H (write protected) */
|
|
||||||
s |= STA_PROTECT;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ /* WP is L (write enabled) */
|
|
||||||
s &= ~STA_PROTECT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( p & SOCKINS )
|
|
||||||
{ /* INS = H (Socket empty) */
|
|
||||||
s |= ( STA_NODISK | STA_NOINIT );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ /* INS = L (Card inserted) */
|
|
||||||
s &= ~STA_NODISK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Stat = s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD get_fattime( void )
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void disk_init_spi( void )
|
|
||||||
{
|
|
||||||
volatile unsigned long ulDummy;
|
|
||||||
|
|
||||||
/* The SD card is connected using SPI0. Start by enabling power to the
|
|
||||||
SPI peripheral. */
|
|
||||||
SC->PCONP |= PCONP_PCSPI;
|
|
||||||
|
|
||||||
/* Also enable the clock to the peripheral. */
|
|
||||||
SC->PCLKSEL0 &= ~( 0x03 << 16 );
|
|
||||||
SC->PCLKSEL0 |= ( 0x01 << 16 );
|
|
||||||
|
|
||||||
/* Configure P0.15 as the clock. */
|
|
||||||
PINCON->PINSEL0 |= ( 0x03 << 30 );
|
|
||||||
|
|
||||||
/* Configure P0.16 as SSEL. */
|
|
||||||
GPIO0->FIODIR |= ( 0x01 << 16 );
|
|
||||||
PINCON->PINSEL1 &= ~( 0x03 );
|
|
||||||
|
|
||||||
/* Configure P0.17 as MISO. */
|
|
||||||
PINCON->PINSEL1 |= ( 0x03 << 2 );
|
|
||||||
|
|
||||||
/* Configure P0.18 as MOSI. */
|
|
||||||
PINCON->PINSEL1 |= ( 0x03 << 4 );
|
|
||||||
|
|
||||||
/* Configure P4.29 as (presumably) the card detect input. */
|
|
||||||
GPIO4->FIODIR &= ~( 1 << 29 );
|
|
||||||
|
|
||||||
/* Set outputs to outputs... */
|
|
||||||
GPIO0->FIODIR |= ( (1 << 15) | (1 << 16) | (1 << 18) );
|
|
||||||
|
|
||||||
/* ... and inputs to inputs. */
|
|
||||||
GPIO0->FIODIR &= ~( 1 << 17 );
|
|
||||||
|
|
||||||
/* Ensure SSEL is high. */
|
|
||||||
CS_HIGH();
|
|
||||||
|
|
||||||
/* Set SPI to master mode. */
|
|
||||||
SPI->SPCR |= ( 1 << 5 );
|
|
||||||
|
|
||||||
/* Clear all status bits. */
|
|
||||||
ulDummy = SPI->SPSR;
|
|
||||||
|
|
||||||
/* Set the serial clock frequency. 100MHz / 250 = 400KHz. */
|
|
||||||
SPI->SPCCR = configCPU_CLOCK_HZ / 250;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
|||||||
/*-----------------------------------------------------------------------
|
|
||||||
/ Low level disk interface modlue include file R0.07 (C)ChaN, 2009
|
|
||||||
/-----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef _DISKIO
|
|
||||||
|
|
||||||
#define _READONLY 0 /* 1: Read-only mode */
|
|
||||||
#define _USE_IOCTL 1
|
|
||||||
|
|
||||||
#include "fat_integer.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* Status of Disk Functions */
|
|
||||||
typedef BYTE DSTATUS;
|
|
||||||
|
|
||||||
/* Results of Disk Functions */
|
|
||||||
typedef enum {
|
|
||||||
RES_OK = 0, /* 0: Successful */
|
|
||||||
RES_ERROR, /* 1: R/W Error */
|
|
||||||
RES_WRPRT, /* 2: Write Protected */
|
|
||||||
RES_NOTRDY, /* 3: Not Ready */
|
|
||||||
RES_PARERR /* 4: Invalid Parameter */
|
|
||||||
} DRESULT;
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------*/
|
|
||||||
/* Prototypes for disk control functions */
|
|
||||||
|
|
||||||
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
|
|
@ -1,166 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------/
|
|
||||||
/ FatFs - FAT file system module configuration file R0.07e (C)ChaN, 2009
|
|
||||||
/----------------------------------------------------------------------------/
|
|
||||||
/
|
|
||||||
/ CAUTION! Do not forget to make clean the project after any changes to
|
|
||||||
/ the configuration options.
|
|
||||||
/
|
|
||||||
/----------------------------------------------------------------------------*/
|
|
||||||
#ifndef _FFCONFIG
|
|
||||||
#define _FFCONFIG 0x007E
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------/
|
|
||||||
/ Function and Buffer Configurations
|
|
||||||
/----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#define _FS_TINY 0 /* 0 or 1 */
|
|
||||||
/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system
|
|
||||||
/ object instead of the sector buffer in the individual file object for file
|
|
||||||
/ data transfer. This reduces memory consumption 512 bytes each file object. */
|
|
||||||
|
|
||||||
|
|
||||||
#define _FS_READONLY 0 /* 0 or 1 */
|
|
||||||
/* Setting _FS_READONLY to 1 defines read only configuration. This removes
|
|
||||||
/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
|
|
||||||
/ f_truncate and useless f_getfree. */
|
|
||||||
|
|
||||||
|
|
||||||
#define _FS_MINIMIZE 0 /* 0, 1, 2 or 3 */
|
|
||||||
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
|
|
||||||
/
|
|
||||||
/ 0: Full function.
|
|
||||||
/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename
|
|
||||||
/ are removed.
|
|
||||||
/ 2: f_opendir and f_readdir are removed in addition to level 1.
|
|
||||||
/ 3: f_lseek is removed in addition to level 2. */
|
|
||||||
|
|
||||||
|
|
||||||
#define _USE_STRFUNC 0 /* 0, 1 or 2 */
|
|
||||||
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
|
|
||||||
|
|
||||||
|
|
||||||
#define _USE_MKFS 0 /* 0 or 1 */
|
|
||||||
/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
|
|
||||||
|
|
||||||
|
|
||||||
#define _USE_FORWARD 0 /* 0 or 1 */
|
|
||||||
/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------/
|
|
||||||
/ Locale and Namespace Configurations
|
|
||||||
/----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#define _CODE_PAGE 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 */
|
|
@ -1,165 +0,0 @@
|
|||||||
/*
|
|
||||||
FreeRTOS V6.0.2 - Copyright (C) 2010 Real Time Engineers Ltd.
|
|
||||||
|
|
||||||
***************************************************************************
|
|
||||||
* *
|
|
||||||
* If you are: *
|
|
||||||
* *
|
|
||||||
* + New to FreeRTOS, *
|
|
||||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
|
||||||
* + Looking for basic training, *
|
|
||||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
|
||||||
* *
|
|
||||||
* then take a look at the FreeRTOS eBook *
|
|
||||||
* *
|
|
||||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
|
||||||
* http://www.FreeRTOS.org/Documentation *
|
|
||||||
* *
|
|
||||||
* A pdf reference manual is also available. Both are usually delivered *
|
|
||||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
|
||||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
|
||||||
* exceptional circumstances). Thank you for your support! *
|
|
||||||
* *
|
|
||||||
***************************************************************************
|
|
||||||
|
|
||||||
This file is part of the FreeRTOS distribution.
|
|
||||||
|
|
||||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
|
||||||
the terms of the GNU General Public License (version 2) as published by the
|
|
||||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
|
||||||
***NOTE*** The exception to the GPL is included to allow you to distribute
|
|
||||||
a combined work that includes FreeRTOS without being obliged to provide the
|
|
||||||
source code for proprietary components outside of the FreeRTOS kernel.
|
|
||||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
more details. You should have received a copy of the GNU General Public
|
|
||||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
|
||||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
|
||||||
by writing to Richard Barry, contact details for whom are available on the
|
|
||||||
FreeRTOS WEB site.
|
|
||||||
|
|
||||||
1 tab == 4 spaces!
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
|
||||||
contact details.
|
|
||||||
|
|
||||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
|
||||||
critical systems.
|
|
||||||
|
|
||||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
|
||||||
licensing and training services.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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 */
|
|
@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
FreeRTOS V6.0.2 - Copyright (C) 2010 Real Time Engineers Ltd.
|
|
||||||
|
|
||||||
***************************************************************************
|
|
||||||
* *
|
|
||||||
* If you are: *
|
|
||||||
* *
|
|
||||||
* + New to FreeRTOS, *
|
|
||||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
|
||||||
* + Looking for basic training, *
|
|
||||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
|
||||||
* *
|
|
||||||
* then take a look at the FreeRTOS eBook *
|
|
||||||
* *
|
|
||||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
|
||||||
* http://www.FreeRTOS.org/Documentation *
|
|
||||||
* *
|
|
||||||
* A pdf reference manual is also available. Both are usually delivered *
|
|
||||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
|
||||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
|
||||||
* exceptional circumstances). Thank you for your support! *
|
|
||||||
* *
|
|
||||||
***************************************************************************
|
|
||||||
|
|
||||||
This file is part of the FreeRTOS distribution.
|
|
||||||
|
|
||||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
|
||||||
the terms of the GNU General Public License (version 2) as published by the
|
|
||||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
|
||||||
***NOTE*** The exception to the GPL is included to allow you to distribute
|
|
||||||
a combined work that includes FreeRTOS without being obliged to provide the
|
|
||||||
source code for proprietary components outside of the FreeRTOS kernel.
|
|
||||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
more details. You should have received a copy of the GNU General Public
|
|
||||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
|
||||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
|
||||||
by writing to Richard Barry, contact details for whom are available on the
|
|
||||||
FreeRTOS WEB site.
|
|
||||||
|
|
||||||
1 tab == 4 spaces!
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
|
||||||
contact details.
|
|
||||||
|
|
||||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
|
||||||
critical systems.
|
|
||||||
|
|
||||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
|
||||||
licensing and training services.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LED_HH
|
|
||||||
#define LED_HH
|
|
||||||
|
|
||||||
void vToggleLED( unsigned long ulLED );
|
|
||||||
void vSetLEDState( unsigned long ulLED, long lState );
|
|
||||||
long lGetLEDState( unsigned long ulLED );
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,364 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* 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
@ -1,460 +0,0 @@
|
|||||||
/*
|
|
||||||
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 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* 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__ */
|
|
@ -1,118 +0,0 @@
|
|||||||
/*
|
|
||||||
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);
|
|
@ -1,247 +0,0 @@
|
|||||||
/*
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
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
|
|
||||||
|
|
@ -1,521 +0,0 @@
|
|||||||
/*
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
@ -1,149 +0,0 @@
|
|||||||
/*
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
@ -1,431 +0,0 @@
|
|||||||
/*
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
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_ */
|
|
||||||
|
|
@ -1,159 +0,0 @@
|
|||||||
/*
|
|
||||||
FreeRTOS V6.0.2 - Copyright (C) 2010 Real Time Engineers Ltd.
|
|
||||||
|
|
||||||
***************************************************************************
|
|
||||||
* *
|
|
||||||
* If you are: *
|
|
||||||
* *
|
|
||||||
* + New to FreeRTOS, *
|
|
||||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
|
||||||
* + Looking for basic training, *
|
|
||||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
|
||||||
* *
|
|
||||||
* then take a look at the FreeRTOS eBook *
|
|
||||||
* *
|
|
||||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
|
||||||
* http://www.FreeRTOS.org/Documentation *
|
|
||||||
* *
|
|
||||||
* A pdf reference manual is also available. Both are usually delivered *
|
|
||||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
|
||||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
|
||||||
* exceptional circumstances). Thank you for your support! *
|
|
||||||
* *
|
|
||||||
***************************************************************************
|
|
||||||
|
|
||||||
This file is part of the FreeRTOS distribution.
|
|
||||||
|
|
||||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
|
||||||
the terms of the GNU General Public License (version 2) as published by the
|
|
||||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
|
||||||
***NOTE*** The exception to the GPL is included to allow you to distribute
|
|
||||||
a combined work that includes FreeRTOS without being obliged to provide the
|
|
||||||
source code for proprietary components outside of the FreeRTOS kernel.
|
|
||||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
more details. You should have received a copy of the GNU General Public
|
|
||||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
|
||||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
|
||||||
by writing to Richard Barry, contact details for whom are available on the
|
|
||||||
FreeRTOS WEB site.
|
|
||||||
|
|
||||||
1 tab == 4 spaces!
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
|
||||||
contact details.
|
|
||||||
|
|
||||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
|
||||||
critical systems.
|
|
||||||
|
|
||||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
|
||||||
licensing and training services.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* FreeRTOS.org includes. */
|
|
||||||
#include "FreeRTOS.h"
|
|
||||||
|
|
||||||
/* Demo application includes. */
|
|
||||||
#include "partest.h"
|
|
||||||
|
|
||||||
#define partstFIRST_IO ( ( unsigned long ) 0x04 )
|
|
||||||
#define partstFIO2_BITS ( ( unsigned long ) 0x0000007C )
|
|
||||||
#define partstFIO1_BITS ( ( unsigned long ) 0xB0000000 )
|
|
||||||
#define partstNUM_LEDS ( 5 )
|
|
||||||
#define partstALL_OUTPUTS_OFF ( ( unsigned long ) 0xff )
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------
|
|
||||||
* Simple parallel port IO routines.
|
|
||||||
*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
void vParTestInitialise( void )
|
|
||||||
{
|
|
||||||
/* LEDs on ports 1 and 2 to output. */
|
|
||||||
GPIO2->FIODIR = partstFIO2_BITS;
|
|
||||||
GPIO1->FIODIR = partstFIO1_BITS;
|
|
||||||
|
|
||||||
/* Start will all LEDs off. */
|
|
||||||
GPIO2->FIOCLR = partstFIO2_BITS;
|
|
||||||
GPIO1->FIOCLR = partstFIO1_BITS;
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
void vParTestSetLED( unsigned long ulLEDIn, signed long xValue )
|
|
||||||
{
|
|
||||||
unsigned long ulLED = partstFIRST_IO;
|
|
||||||
|
|
||||||
/* Used to set and clear LEDs on FIO2. */
|
|
||||||
|
|
||||||
if( ulLEDIn < partstNUM_LEDS )
|
|
||||||
{
|
|
||||||
/* Rotate to the wanted bit of port */
|
|
||||||
ulLED <<= ( unsigned long ) ulLEDIn;
|
|
||||||
|
|
||||||
/* Set of clear the output. */
|
|
||||||
if( xValue )
|
|
||||||
{
|
|
||||||
GPIO2->FIOCLR = ulLED;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GPIO2->FIOSET = ulLED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
void vParTestToggleLED( unsigned long ulLEDIn )
|
|
||||||
{
|
|
||||||
unsigned long ulLED = partstFIRST_IO, ulCurrentState;
|
|
||||||
|
|
||||||
/* Used to toggle LEDs on FIO2. */
|
|
||||||
|
|
||||||
if( ulLEDIn < partstNUM_LEDS )
|
|
||||||
{
|
|
||||||
/* Rotate to the wanted bit of port 0. Only P10 to P13 have an LED
|
|
||||||
attached. */
|
|
||||||
ulLED <<= ( unsigned long ) ulLEDIn;
|
|
||||||
|
|
||||||
/* If this bit is already set, clear it, and visa versa. */
|
|
||||||
ulCurrentState = GPIO2->FIOPIN;
|
|
||||||
if( ulCurrentState & ulLED )
|
|
||||||
{
|
|
||||||
GPIO2->FIOCLR = ulLED;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GPIO2->FIOSET = ulLED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
long lParTestGetLEDState( void )
|
|
||||||
{
|
|
||||||
/* Returns the state of the LEDs on FIO1. */
|
|
||||||
if( ( GPIO1->FIOPIN & partstFIO1_BITS ) != 0 )
|
|
||||||
{
|
|
||||||
return pdFALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return pdTRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
void vParTestSetLEDState( long lState )
|
|
||||||
{
|
|
||||||
/* Used to set and clear the LEDs on FIO1. */
|
|
||||||
if( lState != pdFALSE )
|
|
||||||
{
|
|
||||||
GPIO1->FIOSET = partstFIO1_BITS;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GPIO1->FIOCLR = partstFIO1_BITS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
|||||||
<!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 "load(\"$(TargetsDir)/LPC1000/LPC1000_LinkPatch.js\");patch(\"$(TargetPath)\");"" 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>
|
|
@ -1,68 +0,0 @@
|
|||||||
<!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
@ -1,37 +0,0 @@
|
|||||||
<!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>
|
|
@ -1,319 +0,0 @@
|
|||||||
/*
|
|
||||||
FreeRTOS V6.0.2 - Copyright (C) 2010 Real Time Engineers Ltd.
|
|
||||||
|
|
||||||
***************************************************************************
|
|
||||||
* *
|
|
||||||
* If you are: *
|
|
||||||
* *
|
|
||||||
* + New to FreeRTOS, *
|
|
||||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
|
||||||
* + Looking for basic training, *
|
|
||||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
|
||||||
* *
|
|
||||||
* then take a look at the FreeRTOS eBook *
|
|
||||||
* *
|
|
||||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
|
||||||
* http://www.FreeRTOS.org/Documentation *
|
|
||||||
* *
|
|
||||||
* A pdf reference manual is also available. Both are usually delivered *
|
|
||||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
|
||||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
|
||||||
* exceptional circumstances). Thank you for your support! *
|
|
||||||
* *
|
|
||||||
***************************************************************************
|
|
||||||
|
|
||||||
This file is part of the FreeRTOS distribution.
|
|
||||||
|
|
||||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
|
||||||
the terms of the GNU General Public License (version 2) as published by the
|
|
||||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
|
||||||
***NOTE*** The exception to the GPL is included to allow you to distribute
|
|
||||||
a combined work that includes FreeRTOS without being obliged to provide the
|
|
||||||
source code for proprietary components outside of the FreeRTOS kernel.
|
|
||||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
more details. You should have received a copy of the GNU General Public
|
|
||||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
|
||||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
|
||||||
by writing to Richard Barry, contact details for whom are available on the
|
|
||||||
FreeRTOS WEB site.
|
|
||||||
|
|
||||||
1 tab == 4 spaces!
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
|
||||||
contact details.
|
|
||||||
|
|
||||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
|
||||||
critical systems.
|
|
||||||
|
|
||||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
|
||||||
licensing and training services.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Creates all the demo application tasks, then starts the scheduler. The WEB
|
|
||||||
* documentation provides more details of the standard demo application tasks
|
|
||||||
* (which just exist to test the kernel port and provide an example of how to use
|
|
||||||
* each FreeRTOS API function).
|
|
||||||
*
|
|
||||||
* In addition to the standard demo tasks, the following tasks and tests are
|
|
||||||
* defined and/or created within this file:
|
|
||||||
*
|
|
||||||
* "Check" hook - This only executes fully every five seconds from the tick
|
|
||||||
* hook. Its main function is to check that all the standard demo tasks are
|
|
||||||
* still operational. The status can be viewed using on the Task Stats page
|
|
||||||
* served by the WEB server.
|
|
||||||
*
|
|
||||||
* "uIP" task - This is the task that handles the uIP stack. All TCP/IP
|
|
||||||
* processing is performed in this task.
|
|
||||||
*
|
|
||||||
* "USB" task - Enumerates the USB device as a CDC class, then echoes back all
|
|
||||||
* received characters with a configurable offset (for example, if the offset
|
|
||||||
* is 1 and 'A' is received then 'B' will be sent back). A dumb terminal such
|
|
||||||
* as Hyperterminal can be used to talk to the USB task.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Scheduler includes. */
|
|
||||||
#include "FreeRTOS.h"
|
|
||||||
#include "task.h"
|
|
||||||
|
|
||||||
/* Demo app includes. */
|
|
||||||
#include "BlockQ.h"
|
|
||||||
#include "integer.h"
|
|
||||||
#include "blocktim.h"
|
|
||||||
#include "flash.h"
|
|
||||||
#include "partest.h"
|
|
||||||
#include "semtest.h"
|
|
||||||
#include "PollQ.h"
|
|
||||||
#include "GenQTest.h"
|
|
||||||
#include "QPeek.h"
|
|
||||||
#include "recmutex.h"
|
|
||||||
|
|
||||||
/* File system includes. */
|
|
||||||
#include "diskio.h"
|
|
||||||
#include "ff.h"
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* The time between cycles of the 'check' functionality (defined within the
|
|
||||||
tick hook). */
|
|
||||||
#define mainCHECK_DELAY ( ( portTickType ) 5000 / portTICK_RATE_MS )
|
|
||||||
|
|
||||||
/* Task priorities. */
|
|
||||||
#define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
|
||||||
#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
|
||||||
#define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
|
||||||
#define mainUIP_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
|
|
||||||
#define mainINTEGER_TASK_PRIORITY ( tskIDLE_PRIORITY )
|
|
||||||
#define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY )
|
|
||||||
#define mainFLASH_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
|
||||||
|
|
||||||
/* The WEB server has a larger stack as it utilises stack hungry string
|
|
||||||
handling library calls. */
|
|
||||||
#define mainBASIC_WEB_STACK_SIZE ( configMINIMAL_STACK_SIZE * 4 )
|
|
||||||
|
|
||||||
/* The message displayed by the WEB server when all tasks are executing
|
|
||||||
without an error being reported. */
|
|
||||||
#define mainPASS_STATUS_MESSAGE "All tasks are executing without error."
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Configure the hardware for the demo.
|
|
||||||
*/
|
|
||||||
static void prvSetupHardware( void );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The task that handles the uIP stack. All TCP/IP processing is performed in
|
|
||||||
* this task.
|
|
||||||
*/
|
|
||||||
extern void vuIP_Task( void *pvParameters );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The task that handles the USB stack.
|
|
||||||
*/
|
|
||||||
extern void vUSBTask( void *pvParameters );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Simply returns the current status message for display on served WEB pages.
|
|
||||||
*/
|
|
||||||
char *pcGetTaskStatusMessage( void );
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* Holds the status message displayed by the WEB server. */
|
|
||||||
static char *pcStatusMessage = mainPASS_STATUS_MESSAGE;
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
int main( void )
|
|
||||||
{
|
|
||||||
/* Configure the hardware for use by this demo. */
|
|
||||||
prvSetupHardware();
|
|
||||||
|
|
||||||
/* Start the standard demo tasks. These are just here to exercise the
|
|
||||||
kernel port and provide examples of how the FreeRTOS API can be used. */
|
|
||||||
vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );
|
|
||||||
vCreateBlockTimeTasks();
|
|
||||||
vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );
|
|
||||||
vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );
|
|
||||||
vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY );
|
|
||||||
vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY );
|
|
||||||
vStartQueuePeekTasks();
|
|
||||||
vStartRecursiveMutexTasks();
|
|
||||||
vStartLEDFlashTasks( mainFLASH_TASK_PRIORITY );
|
|
||||||
|
|
||||||
/* Create the USB task. */
|
|
||||||
xTaskCreate( vUSBTask, ( signed char * ) "USB", configMINIMAL_STACK_SIZE, ( void * ) NULL, tskIDLE_PRIORITY, NULL );
|
|
||||||
|
|
||||||
/* Create the uIP task. The WEB server runs in this task. */
|
|
||||||
xTaskCreate( vuIP_Task, ( signed char * ) "uIP", mainBASIC_WEB_STACK_SIZE, ( void * ) NULL, mainUIP_TASK_PRIORITY, NULL );
|
|
||||||
|
|
||||||
/* Start the scheduler. */
|
|
||||||
vTaskStartScheduler();
|
|
||||||
|
|
||||||
/* Will only get here if there was insufficient memory to create the idle
|
|
||||||
task. The idle task is created within vTaskStartScheduler(). */
|
|
||||||
for( ;; );
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
void vApplicationTickHook( void )
|
|
||||||
{
|
|
||||||
static unsigned long ulTicksSinceLastDisplay = 0;
|
|
||||||
|
|
||||||
/* Called from every tick interrupt as described in the comments at the top
|
|
||||||
of this file.
|
|
||||||
|
|
||||||
Have enough ticks passed to make it time to perform our health status
|
|
||||||
check again? */
|
|
||||||
ulTicksSinceLastDisplay++;
|
|
||||||
if( ulTicksSinceLastDisplay >= mainCHECK_DELAY )
|
|
||||||
{
|
|
||||||
/* Reset the counter so these checks run again in mainCHECK_DELAY
|
|
||||||
ticks time. */
|
|
||||||
ulTicksSinceLastDisplay = 0;
|
|
||||||
|
|
||||||
/* Has an error been found in any task? */
|
|
||||||
if( xAreGenericQueueTasksStillRunning() != pdTRUE )
|
|
||||||
{
|
|
||||||
pcStatusMessage = "An error has been detected in the Generic Queue test/demo.";
|
|
||||||
}
|
|
||||||
else if( xAreQueuePeekTasksStillRunning() != pdTRUE )
|
|
||||||
{
|
|
||||||
pcStatusMessage = "An error has been detected in the Peek Queue test/demo.";
|
|
||||||
}
|
|
||||||
else if( xAreBlockingQueuesStillRunning() != pdTRUE )
|
|
||||||
{
|
|
||||||
pcStatusMessage = "An error has been detected in the Block Queue test/demo.";
|
|
||||||
}
|
|
||||||
else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )
|
|
||||||
{
|
|
||||||
pcStatusMessage = "An error has been detected in the Block Time test/demo.";
|
|
||||||
}
|
|
||||||
else if( xAreSemaphoreTasksStillRunning() != pdTRUE )
|
|
||||||
{
|
|
||||||
pcStatusMessage = "An error has been detected in the Semaphore test/demo.";
|
|
||||||
}
|
|
||||||
else if( xArePollingQueuesStillRunning() != pdTRUE )
|
|
||||||
{
|
|
||||||
pcStatusMessage = "An error has been detected in the Poll Queue test/demo.";
|
|
||||||
}
|
|
||||||
else if( xAreIntegerMathsTaskStillRunning() != pdTRUE )
|
|
||||||
{
|
|
||||||
pcStatusMessage = "An error has been detected in the Int Math test/demo.";
|
|
||||||
}
|
|
||||||
else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )
|
|
||||||
{
|
|
||||||
pcStatusMessage = "An error has been detected in the Mutex test/demo.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
disk_timerproc();
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
char *pcGetTaskStatusMessage( void )
|
|
||||||
{
|
|
||||||
/* Not bothered about a critical section here. */
|
|
||||||
return pcStatusMessage;
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
void prvSetupHardware( void )
|
|
||||||
{
|
|
||||||
/* Disable peripherals power. */
|
|
||||||
SC->PCONP = 0;
|
|
||||||
|
|
||||||
/* Enable GPIO power. */
|
|
||||||
SC->PCONP = PCONP_PCGPIO;
|
|
||||||
|
|
||||||
/* Disable TPIU. */
|
|
||||||
PINCON->PINSEL10 = 0;
|
|
||||||
|
|
||||||
/* Setup the peripheral bus to be the same as the PLL output (64 MHz). */
|
|
||||||
SC->PCLKSEL0 = 0x05555555;
|
|
||||||
|
|
||||||
/* Configure the LEDs. */
|
|
||||||
vParTestInitialise();
|
|
||||||
|
|
||||||
/* Configure the SPI for communicating with the SD card. */
|
|
||||||
disk_init_spi();
|
|
||||||
|
|
||||||
{
|
|
||||||
FATFS fs;
|
|
||||||
FIL f;
|
|
||||||
static char c[ 2048 ];
|
|
||||||
UINT BytesRead;
|
|
||||||
|
|
||||||
f_mount( 0, &fs );
|
|
||||||
f_open( &f, "/test.htm", FA_READ );
|
|
||||||
f_read( &f, c, 2048, &BytesRead );
|
|
||||||
__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;
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
@ -1,293 +0,0 @@
|
|||||||
/*
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* @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
|
|
@ -1,45 +0,0 @@
|
|||||||
[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"
|
|
@ -1,111 +0,0 @@
|
|||||||
/*
|
|
||||||
* @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
|
|
@ -1,331 +0,0 @@
|
|||||||
/*
|
|
||||||
* @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
|
|
||||||
*---------------------------------------------------------------------------*/
|
|
@ -1,604 +0,0 @@
|
|||||||
/*
|
|
||||||
FreeRTOS V6.0.2 - Copyright (C) 2010 Real Time Engineers Ltd.
|
|
||||||
|
|
||||||
***************************************************************************
|
|
||||||
* *
|
|
||||||
* If you are: *
|
|
||||||
* *
|
|
||||||
* + New to FreeRTOS, *
|
|
||||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
|
||||||
* + Looking for basic training, *
|
|
||||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
|
||||||
* *
|
|
||||||
* then take a look at the FreeRTOS eBook *
|
|
||||||
* *
|
|
||||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
|
||||||
* http://www.FreeRTOS.org/Documentation *
|
|
||||||
* *
|
|
||||||
* A pdf reference manual is also available. Both are usually delivered *
|
|
||||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
|
||||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
|
||||||
* exceptional circumstances). Thank you for your support! *
|
|
||||||
* *
|
|
||||||
***************************************************************************
|
|
||||||
|
|
||||||
This file is part of the FreeRTOS distribution.
|
|
||||||
|
|
||||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
|
||||||
the terms of the GNU General Public License (version 2) as published by the
|
|
||||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
|
||||||
***NOTE*** The exception to the GPL is included to allow you to distribute
|
|
||||||
a combined work that includes FreeRTOS without being obliged to provide the
|
|
||||||
source code for proprietary components outside of the FreeRTOS kernel.
|
|
||||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
more details. You should have received a copy of the GNU General Public
|
|
||||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
|
||||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
|
||||||
by writing to Richard Barry, contact details for whom are available on the
|
|
||||||
FreeRTOS WEB site.
|
|
||||||
|
|
||||||
1 tab == 4 spaces!
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
|
||||||
contact details.
|
|
||||||
|
|
||||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
|
||||||
critical systems.
|
|
||||||
|
|
||||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
|
||||||
licensing and training services.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* 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 );
|
|
||||||
}
|
|
Loading…
Reference in New Issue