From: richardbarry Date: Sun, 24 Jan 2010 21:00:36 +0000 (+0000) Subject: Start of new demo added. Still a long way to go. X-Git-Tag: V6.0.3~19 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=014b26830fcacf2258765108dfa23972898032bb;p=freertos Start of new demo added. Still a long way to go. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@967 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/FatFs-port-files/diskio.c b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/FatFs-port-files/diskio.c new file mode 100644 index 000000000..6234a170b --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/FatFs-port-files/diskio.c @@ -0,0 +1,772 @@ +/* Based on MMCv3/SDv1/SDv2 (in SPI mode) control module (C)ChaN, 2009 +Modifications (C) 2010 Real Time Engineers ltd. */ + +#include "FreeRTOS.h" +#include "diskio.h" + +void disk_init_spi( void ); + +/* Definitions for MMC/SDC command */ +#define CMD0 ( 0x40 + 0 ) /* GO_IDLE_STATE */ +#define CMD1 ( 0x40 + 1 ) /* SEND_OP_COND (MMC) */ +#define ACMD41 ( 0xC0 + 41 ) /* SEND_OP_COND (SDC) */ +#define CMD8 ( 0x40 + 8 ) /* SEND_IF_COND */ +#define CMD9 ( 0x40 + 9 ) /* SEND_CSD */ +#define CMD10 ( 0x40 + 10 ) /* SEND_CID */ +#define CMD12 ( 0x40 + 12 ) /* STOP_TRANSMISSION */ +#define ACMD13 ( 0xC0 + 13 ) /* SD_STATUS (SDC) */ +#define CMD16 ( 0x40 + 16 ) /* SET_BLOCKLEN */ +#define CMD17 ( 0x40 + 17 ) /* READ_SINGLE_BLOCK */ +#define CMD18 ( 0x40 + 18 ) /* READ_MULTIPLE_BLOCK */ +#define CMD23 ( 0x40 + 23 ) /* SET_BLOCK_COUNT (MMC) */ +#define ACMD23 ( 0xC0 + 23 ) /* SET_WR_BLK_ERASE_COUNT (SDC) */ +#define CMD24 ( 0x40 + 24 ) /* WRITE_BLOCK */ +#define CMD25 ( 0x40 + 25 ) /* WRITE_MULTIPLE_BLOCK */ +#define CMD55 ( 0x40 + 55 ) /* APP_CMD */ +#define CMD58 ( 0x40 + 58 ) /* READ_OCR */ + +/* Port Controls (Platform dependent) */ +#define CS_LOW() GPIO0->FIOCLR = ( 1 << 16 ) /* MMC CS = L */ +#define CS_HIGH() GPIO0->FIOSET = ( 1 << 16 ) /* MMC CS = H */ + +#define SOCKWP ( 0 ) /* Write protect switch. */ +#define SOCKINS ( 1 << 29 ) /* Card detect switch. */ +#define SOCKPORT ( GPIO4->FIOPIN ) +#define FCLK_SLOW() /* Set slow clock (100k-400k) */ +#define FCLK_FAST() /* Set fast clock (depends on the CSD) */ + +#define xmit_spi( dat ) xchg_spi( dat ) +#define rcvr_spi() xchg_spi( 0xFF ) +#define rcvr_spi_m( p ) \ + SPI->SPDR = 0xFF; \ + while( !( SPI->SPSR & ( 1 << 7 ) ) ); /* Check SPIF bit. */ \ + *( p ) = ( BYTE ) SPI->SPDR; + +/*-------------------------------------------------------------------------- */ + +static volatile DSTATUS Stat = STA_NOINIT; /* Disk status */ +static volatile UINT Timer1, Timer2; /* 1000Hz decrement timer */ +static UINT CardType; + +static BYTE xchg_spi( BYTE dat ) +{ + SPI->SPDR = dat; + while( !( SPI->SPSR & ( 1 << 7 ) ) ); /* Check SPIF bit. */ + return( BYTE ) SPI->SPDR; +} + +/*-----------------------------------------------------------------------*/ + +/* Wait for card ready */ + +/*-----------------------------------------------------------------------*/ +static BYTE wait_ready( void ) +{ + BYTE res; + + Timer2 = 500; /* Wait for ready in timeout of 500ms */ + rcvr_spi(); + do + { + res = rcvr_spi(); + } while( (res != 0xFF) && Timer2 ); + + return res; +} + +/*-----------------------------------------------------------------------*/ + +/* Deselect the card and release SPI bus */ + +/*-----------------------------------------------------------------------*/ +static void deselect( void ) +{ + CS_HIGH(); + rcvr_spi(); +} + +/*-----------------------------------------------------------------------*/ + +/* Select the card and wait ready */ + +/*-----------------------------------------------------------------------*/ +static BOOL select( void ) /* TRUE:Successful, FALSE:Timeout */ +{ + CS_LOW(); + if( wait_ready() != 0xFF ) + { + deselect(); + return FALSE; + } + + return TRUE; +} + +/*-----------------------------------------------------------------------*/ + +/* Power Control (Platform dependent) */ + +/*-----------------------------------------------------------------------*/ + +/* When the target system does not support socket power control, there */ + +/* is nothing to do in these functions and chk_power always returns 1. */ +static void power_on( void ) +{ +#if 0 + /* Enable SPI1 */ + SPI1CON1 = 0x013B; + SPI1CON2 = 0x0000; + _SPIEN = 1; +#endif +} + +static void power_off( void ) +{ +#if 0 + select(); /* Wait for card ready */ + deselect(); + + _SPIEN = 0; /* Disable SPI1 */ + + Stat |= STA_NOINIT; /* Set STA_NOINIT */ +#endif +} + +/*-----------------------------------------------------------------------*/ + +/* Receive a data packet from MMC */ + +/*-----------------------------------------------------------------------*/ +static BOOL rcvr_datablock( BYTE *buff, /* Data buffer to store received data */ UINT btr /* Byte count (must be multiple of 4) */ ) +{ + BYTE token; + + Timer1 = 100; + do + { /* Wait for data packet in timeout of 100ms */ + token = rcvr_spi(); + } while( (token == 0xFF) && Timer1 ); + + if( token != 0xFE ) + { + return FALSE; /* If not valid data token, retutn with error */ + } + + do + { /* Receive the data block into buffer */ + rcvr_spi_m( buff++ ); + rcvr_spi_m( buff++ ); + rcvr_spi_m( buff++ ); + rcvr_spi_m( buff++ ); + } while( btr -= 4 ); + rcvr_spi(); /* Discard CRC */ + rcvr_spi(); + + return TRUE; /* Return with success */ +} + +/*-----------------------------------------------------------------------*/ + +/* Send a data packet to MMC */ + +/*-----------------------------------------------------------------------*/ +#if _READONLY == 0 +static BOOL xmit_datablock( const BYTE *buff, /* 512 byte data block to be transmitted */ BYTE token /* Data/Stop token */ ) +{ + BYTE resp; + UINT bc = 512; + + if( wait_ready() != 0xFF ) + { + return FALSE; + } + + xmit_spi( token ); /* Xmit data token */ + if( token != 0xFD ) + { /* Is data token */ + do + { /* Xmit the 512 byte data block to MMC */ + xmit_spi( *buff++ ); + xmit_spi( *buff++ ); + } while( bc -= 2 ); + xmit_spi( 0xFF ); /* CRC (Dummy) */ + xmit_spi( 0xFF ); + resp = rcvr_spi(); /* Receive data response */ + if( (resp & 0x1F) != 0x05 ) + { /* If not accepted, return with error */ + return FALSE; + } + } + + return TRUE; +} + +#endif /* _READONLY */ + +/*-----------------------------------------------------------------------*/ + +/* Send a command packet to MMC */ + +/*-----------------------------------------------------------------------*/ +static BYTE send_cmd( BYTE cmd, /* Command byte */ DWORD arg /* Argument */ ) +{ + BYTE n, res; + + if( cmd & 0x80 ) + { /* ACMD is the command sequense of CMD55-CMD */ + 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; +} + + diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/FatFs-port-files/diskio.c.bak b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/FatFs-port-files/diskio.c.bak new file mode 100644 index 000000000..e14e24f88 --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/FatFs-port-files/diskio.c.bak @@ -0,0 +1,772 @@ +/* Based on MMCv3/SDv1/SDv2 (in SPI mode) control module (C)ChaN, 2009 +Modifications (C) 2010 Real Time Engineers ltd. */ + +#include "FreeRTOS.h" +#include "diskio.h" + +void disk_init_spi( void ); + +/* Definitions for MMC/SDC command */ +#define CMD0 ( 0x40 + 0 ) /* GO_IDLE_STATE */ +#define CMD1 ( 0x40 + 1 ) /* SEND_OP_COND (MMC) */ +#define ACMD41 ( 0xC0 + 41 ) /* SEND_OP_COND (SDC) */ +#define CMD8 ( 0x40 + 8 ) /* SEND_IF_COND */ +#define CMD9 ( 0x40 + 9 ) /* SEND_CSD */ +#define CMD10 ( 0x40 + 10 ) /* SEND_CID */ +#define CMD12 ( 0x40 + 12 ) /* STOP_TRANSMISSION */ +#define ACMD13 ( 0xC0 + 13 ) /* SD_STATUS (SDC) */ +#define CMD16 ( 0x40 + 16 ) /* SET_BLOCKLEN */ +#define CMD17 ( 0x40 + 17 ) /* READ_SINGLE_BLOCK */ +#define CMD18 ( 0x40 + 18 ) /* READ_MULTIPLE_BLOCK */ +#define CMD23 ( 0x40 + 23 ) /* SET_BLOCK_COUNT (MMC) */ +#define ACMD23 ( 0xC0 + 23 ) /* SET_WR_BLK_ERASE_COUNT (SDC) */ +#define CMD24 ( 0x40 + 24 ) /* WRITE_BLOCK */ +#define CMD25 ( 0x40 + 25 ) /* WRITE_MULTIPLE_BLOCK */ +#define CMD55 ( 0x40 + 55 ) /* APP_CMD */ +#define CMD58 ( 0x40 + 58 ) /* READ_OCR */ + +/* Port Controls (Platform dependent) */ +#define CS_LOW() GPIO0->FIOCLR = ( 1 << 16 ) /* MMC CS = L */ +#define CS_HIGH() GPIO0->FIOSET = ( 1 << 16 ) /* MMC CS = H */ + +#define SOCKWP ( 0 ) /* Write protect switch. */ +#define SOCKINS ( 1 << 29 ) /* Card detect switch. */ +#define SOCKPORT ( GPIO4->FIOPIN ) +#define FCLK_SLOW() /* Set slow clock (100k-400k) */ +#define FCLK_FAST() /* Set fast clock (depends on the CSD) */ + +#define xmit_spi( dat ) xchg_spi( dat ) +#define rcvr_spi() xchg_spi( 0xFF ) +#define rcvr_spi_m( p ) \ + SPI->SPDR = 0xFF; \ + while( !( SPI->SPSR & ( 1 << 7 ) ) ); /* Check SPIF bit. */ \ + *( p ) = ( BYTE ) SPI->SPDR; + +/*-------------------------------------------------------------------------- */ + +static volatile DSTATUS Stat = STA_NOINIT; /* Disk status */ +static volatile UINT Timer1, Timer2; /* 1000Hz decrement timer */ +static UINT CardType; + +static BYTE xchg_spi( BYTE dat ) +{ + SPI->SPDR = dat; + while( !( SPI->SPSR & ( 1 << 7 ) ) ); /* Check SPIF bit. */ + return( BYTE ) SPI->SPDR; +} + +/*-----------------------------------------------------------------------*/ + +/* Wait for card ready */ + +/*-----------------------------------------------------------------------*/ +static BYTE wait_ready( void ) +{ + BYTE res; + + Timer2 = 500; /* Wait for ready in timeout of 500ms */ + rcvr_spi(); + do + { + res = rcvr_spi(); + } while( (res != 0xFF) && Timer2 ); + + return res; +} + +/*-----------------------------------------------------------------------*/ + +/* Deselect the card and release SPI bus */ + +/*-----------------------------------------------------------------------*/ +static void deselect( void ) +{ + CS_HIGH(); + rcvr_spi(); +} + +/*-----------------------------------------------------------------------*/ + +/* Select the card and wait ready */ + +/*-----------------------------------------------------------------------*/ +static BOOL select( void ) /* TRUE:Successful, FALSE:Timeout */ +{ + CS_LOW(); + if( wait_ready() != 0xFF ) + { + deselect(); + return FALSE; + } + + return TRUE; +} + +/*-----------------------------------------------------------------------*/ + +/* Power Control (Platform dependent) */ + +/*-----------------------------------------------------------------------*/ + +/* When the target system does not support socket power control, there */ + +/* is nothing to do in these functions and chk_power always returns 1. */ +static void power_on( void ) +{ +#if 0 + /* Enable SPI1 */ + SPI1CON1 = 0x013B; + SPI1CON2 = 0x0000; + _SPIEN = 1; +#endif +} + +static void power_off( void ) +{ +#if 0 + select(); /* Wait for card ready */ + deselect(); + + _SPIEN = 0; /* Disable SPI1 */ + + Stat |= STA_NOINIT; /* Set STA_NOINIT */ +#endif +} + +/*-----------------------------------------------------------------------*/ + +/* Receive a data packet from MMC */ + +/*-----------------------------------------------------------------------*/ +static BOOL rcvr_datablock( BYTE *buff, /* Data buffer to store received data */ UINT btr /* Byte count (must be multiple of 4) */ ) +{ + BYTE token; + + Timer1 = 100; + do + { /* Wait for data packet in timeout of 100ms */ + token = rcvr_spi(); + } while( (token == 0xFF) && Timer1 ); + + if( token != 0xFE ) + { + return FALSE; /* If not valid data token, retutn with error */ + } + + do + { /* Receive the data block into buffer */ + rcvr_spi_m( buff++ ); + rcvr_spi_m( buff++ ); + rcvr_spi_m( buff++ ); + rcvr_spi_m( buff++ ); + } while( btr -= 4 ); + rcvr_spi(); /* Discard CRC */ + rcvr_spi(); + + return TRUE; /* Return with success */ +} + +/*-----------------------------------------------------------------------*/ + +/* Send a data packet to MMC */ + +/*-----------------------------------------------------------------------*/ +#if _READONLY == 0 +static BOOL xmit_datablock( const BYTE *buff, /* 512 byte data block to be transmitted */ BYTE token /* Data/Stop token */ ) +{ + BYTE resp; + UINT bc = 512; + + if( wait_ready() != 0xFF ) + { + return FALSE; + } + + xmit_spi( token ); /* Xmit data token */ + if( token != 0xFD ) + { /* Is data token */ + do + { /* Xmit the 512 byte data block to MMC */ + xmit_spi( *buff++ ); + xmit_spi( *buff++ ); + } while( bc -= 2 ); + xmit_spi( 0xFF ); /* CRC (Dummy) */ + xmit_spi( 0xFF ); + resp = rcvr_spi(); /* Receive data response */ + if( (resp & 0x1F) != 0x05 ) + { /* If not accepted, return with error */ + return FALSE; + } + } + + return TRUE; +} + +#endif /* _READONLY */ + +/*-----------------------------------------------------------------------*/ + +/* Send a command packet to MMC */ + +/*-----------------------------------------------------------------------*/ +static BYTE send_cmd( BYTE cmd, /* Command byte */ DWORD arg /* Argument */ ) +{ + BYTE n, res; + + if( cmd & 0x80 ) + { /* ACMD is the command sequense of CMD55-CMD */ + 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; +} + + diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/FatFs-port-files/diskio.h b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/FatFs-port-files/diskio.h new file mode 100644 index 000000000..5c31db02e --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/FatFs-port-files/diskio.h @@ -0,0 +1,78 @@ +/*----------------------------------------------------------------------- +/ Low level disk interface modlue include file R0.07 (C)ChaN, 2009 +/-----------------------------------------------------------------------*/ + +#ifndef _DISKIO + +#define _READONLY 0 /* 1: Read-only mode */ +#define _USE_IOCTL 1 + +#include "fat_integer.h" + + +/* Status of Disk Functions */ +typedef BYTE DSTATUS; + +/* Results of Disk Functions */ +typedef enum { + RES_OK = 0, /* 0: Successful */ + RES_ERROR, /* 1: R/W Error */ + RES_WRPRT, /* 2: Write Protected */ + RES_NOTRDY, /* 3: Not Ready */ + RES_PARERR /* 4: Invalid Parameter */ +} DRESULT; + + +/*---------------------------------------*/ +/* Prototypes for disk control functions */ + +void disk_init_spi( void ); +BOOL assign_drives (int argc, char *argv[]); +DSTATUS disk_initialize (BYTE); +DSTATUS disk_status (BYTE); +DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE); +#if _READONLY == 0 +DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE); +#endif +DRESULT disk_ioctl (BYTE, BYTE, void*); + + + +/* Disk Status Bits (DSTATUS) */ + +#define STA_NOINIT 0x01 /* Drive not initialized */ +#define STA_NODISK 0x02 /* No medium in the drive */ +#define STA_PROTECT 0x04 /* Write protected */ + + +/* Command code for disk_ioctrl() */ + +/* Generic command */ +#define CTRL_SYNC 0 /* Mandatory for write functions */ +#define GET_SECTOR_COUNT 1 /* Mandatory for only f_mkfs() */ +#define GET_SECTOR_SIZE 2 /* Mandatory for multiple sector size cfg */ +#define GET_BLOCK_SIZE 3 /* Mandatory for only f_mkfs() */ +#define CTRL_POWER 4 +#define CTRL_LOCK 5 +#define CTRL_EJECT 6 +/* MMC/SDC command */ +#define MMC_GET_TYPE 10 +#define MMC_GET_CSD 11 +#define MMC_GET_CID 12 +#define MMC_GET_OCR 13 +#define MMC_GET_SDSTAT 14 +/* ATA/CF command */ +#define ATA_GET_REV 20 +#define ATA_GET_MODEL 21 +#define ATA_GET_SN 22 + +/* Card type definitions (CardType) */ + +#define CT_MMC 0x01 +#define CT_SD1 0x02 +#define CT_SD2 0x04 +#define CT_SDC (CT_SD1|CT_SD2) +#define CT_BLOCK 0x08 + +#define _DISKIO +#endif diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/FatFs-port-files/diskio.h.bak b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/FatFs-port-files/diskio.h.bak new file mode 100644 index 000000000..bd22b5d5d --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/FatFs-port-files/diskio.h.bak @@ -0,0 +1,77 @@ +/*----------------------------------------------------------------------- +/ Low level disk interface modlue include file R0.07 (C)ChaN, 2009 +/-----------------------------------------------------------------------*/ + +#ifndef _DISKIO + +#define _READONLY 0 /* 1: Read-only mode */ +#define _USE_IOCTL 1 + +#include "fat_integer.h" + + +/* Status of Disk Functions */ +typedef BYTE DSTATUS; + +/* Results of Disk Functions */ +typedef enum { + RES_OK = 0, /* 0: Successful */ + RES_ERROR, /* 1: R/W Error */ + RES_WRPRT, /* 2: Write Protected */ + RES_NOTRDY, /* 3: Not Ready */ + RES_PARERR /* 4: Invalid Parameter */ +} DRESULT; + + +/*---------------------------------------*/ +/* Prototypes for disk control functions */ + +BOOL assign_drives (int argc, char *argv[]); +DSTATUS disk_initialize (BYTE); +DSTATUS disk_status (BYTE); +DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE); +#if _READONLY == 0 +DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE); +#endif +DRESULT disk_ioctl (BYTE, BYTE, void*); + + + +/* Disk Status Bits (DSTATUS) */ + +#define STA_NOINIT 0x01 /* Drive not initialized */ +#define STA_NODISK 0x02 /* No medium in the drive */ +#define STA_PROTECT 0x04 /* Write protected */ + + +/* Command code for disk_ioctrl() */ + +/* Generic command */ +#define CTRL_SYNC 0 /* Mandatory for write functions */ +#define GET_SECTOR_COUNT 1 /* Mandatory for only f_mkfs() */ +#define GET_SECTOR_SIZE 2 /* Mandatory for multiple sector size cfg */ +#define GET_BLOCK_SIZE 3 /* Mandatory for only f_mkfs() */ +#define CTRL_POWER 4 +#define CTRL_LOCK 5 +#define CTRL_EJECT 6 +/* MMC/SDC command */ +#define MMC_GET_TYPE 10 +#define MMC_GET_CSD 11 +#define MMC_GET_CID 12 +#define MMC_GET_OCR 13 +#define MMC_GET_SDSTAT 14 +/* ATA/CF command */ +#define ATA_GET_REV 20 +#define ATA_GET_MODEL 21 +#define ATA_GET_SN 22 + +/* Card type definitions (CardType) */ + +#define CT_MMC 0x01 +#define CT_SD1 0x02 +#define CT_SD2 0x04 +#define CT_SDC (CT_SD1|CT_SD2) +#define CT_BLOCK 0x08 + +#define _DISKIO +#endif diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/FatFs-port-files/ffconf.h b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/FatFs-port-files/ffconf.h new file mode 100644 index 000000000..dc841272a --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/FatFs-port-files/ffconf.h @@ -0,0 +1,166 @@ +/*---------------------------------------------------------------------------/ +/ FatFs - FAT file system module configuration file R0.07e (C)ChaN, 2009 +/----------------------------------------------------------------------------/ +/ +/ CAUTION! Do not forget to make clean the project after any changes to +/ the configuration options. +/ +/----------------------------------------------------------------------------*/ +#ifndef _FFCONFIG +#define _FFCONFIG 0x007E + + +/*---------------------------------------------------------------------------/ +/ Function and Buffer Configurations +/----------------------------------------------------------------------------*/ + +#define _FS_TINY 0 /* 0 or 1 */ +/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system +/ object instead of the sector buffer in the individual file object for file +/ data transfer. This reduces memory consumption 512 bytes each file object. */ + + +#define _FS_READONLY 0 /* 0 or 1 */ +/* Setting _FS_READONLY to 1 defines read only configuration. This removes +/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename, +/ f_truncate and useless f_getfree. */ + + +#define _FS_MINIMIZE 0 /* 0, 1, 2 or 3 */ +/* The _FS_MINIMIZE option defines minimization level to remove some functions. +/ +/ 0: Full function. +/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename +/ are removed. +/ 2: f_opendir and f_readdir are removed in addition to level 1. +/ 3: f_lseek is removed in addition to level 2. */ + + +#define _USE_STRFUNC 0 /* 0, 1 or 2 */ +/* To enable string functions, set _USE_STRFUNC to 1 or 2. */ + + +#define _USE_MKFS 0 /* 0 or 1 */ +/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */ + + +#define _USE_FORWARD 0 /* 0 or 1 */ +/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */ + + + +/*---------------------------------------------------------------------------/ +/ Locale and Namespace Configurations +/----------------------------------------------------------------------------*/ + +#define _CODE_PAGE 437 +/* The _CODE_PAGE specifies the OEM code page to be used on the target system. +/ Incorrect setting of the code page can cause a file open failure. +/ +/ 932 - Japanese Shift-JIS (DBCS, OEM, Windows) +/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows) +/ 949 - Korean (DBCS, OEM, Windows) +/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows) +/ 1250 - Central Europe (Windows) +/ 1251 - Cyrillic (Windows) +/ 1252 - Latin 1 (Windows) +/ 1253 - Greek (Windows) +/ 1254 - Turkish (Windows) +/ 1255 - Hebrew (Windows) +/ 1256 - Arabic (Windows) +/ 1257 - Baltic (Windows) +/ 1258 - Vietnam (OEM, Windows) +/ 437 - U.S. (OEM) +/ 720 - Arabic (OEM) +/ 737 - Greek (OEM) +/ 775 - Baltic (OEM) +/ 850 - Multilingual Latin 1 (OEM) +/ 858 - Multilingual Latin 1 + Euro (OEM) +/ 852 - Latin 2 (OEM) +/ 855 - Cyrillic (OEM) +/ 866 - Russian (OEM) +/ 857 - Turkish (OEM) +/ 862 - Hebrew (OEM) +/ 874 - Thai (OEM, Windows) +/ 1 - ASCII only (Valid for non LFN cfg.) +*/ + + +#define _USE_LFN 0 /* 0, 1 or 2 */ +#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */ +/* The _USE_LFN option switches the LFN support. +/ +/ 0: Disable LFN. _MAX_LFN and _LFN_UNICODE have no effect. +/ 1: Enable LFN with static working buffer on the bss. NOT REENTRANT. +/ 2: Enable LFN with dynamic working buffer on the STACK. +/ +/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. When enable LFN, +/ two Unicode handling functions ff_convert() and ff_wtoupper() must be added +/ to the project. */ + + +#define _LFN_UNICODE 0 /* 0 or 1 */ +/* To switch the character code set on FatFs API to Unicode, +/ enable LFN feature and set _LFN_UNICODE to 1. +*/ + + +#define _FS_RPATH 0 /* 0 or 1 */ +/* When _FS_RPATH is set to 1, relative path feature is enabled and f_chdir, +/ f_chdrive function are available. +/ Note that output of the f_readdir fnction is affected by this option. */ + + + +/*---------------------------------------------------------------------------/ +/ Physical Drive Configurations +/----------------------------------------------------------------------------*/ + +#define _DRIVES 1 +/* Number of volumes (logical drives) to be used. */ + + +#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */ +/* Maximum sector size to be handled. +/ Always set 512 for memory card and hard disk but a larger value may be +/ required for floppy disk (512/1024) and optical disk (512/2048). +/ When _MAX_SS is larger than 512, GET_SECTOR_SIZE command must be implememted +/ to the disk_ioctl function. */ + + +#define _MULTI_PARTITION 0 /* 0 or 1 */ +/* When _MULTI_PARTITION is set to 0, each volume is bound to the same physical +/ drive number and can mount only first primaly partition. When it is set to 1, +/ each volume is tied to the partitions listed in Drives[]. */ + + + +/*---------------------------------------------------------------------------/ +/ System Configurations +/----------------------------------------------------------------------------*/ + +#define _WORD_ACCESS 0 /* 0 or 1 */ +/* The _WORD_ACCESS option defines which access method is used to the word +/ data on the FAT volume. +/ +/ 0: Byte-by-byte access. Always compatible with all platforms. +/ 1: Word access. Do not choose this unless following condition is met. +/ +/ When the byte order on the memory is big-endian or address miss-aligned +/ word access results incorrect behavior, the _WORD_ACCESS must be set to 0. +/ If it is not the case, the value can also be set to 1 to improve the +/ performance and code size. */ + + +#define _FS_REENTRANT 1 /* 0 or 1 */ +#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */ +#define _SYNC_t void * /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */ +/* The _FS_REENTRANT option switches the reentrancy of the FatFs module. +/ +/ 0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect. +/ 1: Enable reentrancy. Also user provided synchronization handlers, +/ ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj +/ function must be added to the project. */ + + +#endif /* _FFCONFIG */ diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/FatFs-port-files/ffconf.h.bak b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/FatFs-port-files/ffconf.h.bak new file mode 100644 index 000000000..2b7702037 --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/FatFs-port-files/ffconf.h.bak @@ -0,0 +1,166 @@ +/*---------------------------------------------------------------------------/ +/ FatFs - FAT file system module configuration file R0.07e (C)ChaN, 2009 +/----------------------------------------------------------------------------/ +/ +/ CAUTION! Do not forget to make clean the project after any changes to +/ the configuration options. +/ +/----------------------------------------------------------------------------*/ +#ifndef _FFCONFIG +#define _FFCONFIG 0x007E + + +/*---------------------------------------------------------------------------/ +/ Function and Buffer Configurations +/----------------------------------------------------------------------------*/ + +#define _FS_TINY 0 /* 0 or 1 */ +/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system +/ object instead of the sector buffer in the individual file object for file +/ data transfer. This reduces memory consumption 512 bytes each file object. */ + + +#define _FS_READONLY 0 /* 0 or 1 */ +/* Setting _FS_READONLY to 1 defines read only configuration. This removes +/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename, +/ f_truncate and useless f_getfree. */ + + +#define _FS_MINIMIZE 0 /* 0, 1, 2 or 3 */ +/* The _FS_MINIMIZE option defines minimization level to remove some functions. +/ +/ 0: Full function. +/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename +/ are removed. +/ 2: f_opendir and f_readdir are removed in addition to level 1. +/ 3: f_lseek is removed in addition to level 2. */ + + +#define _USE_STRFUNC 0 /* 0, 1 or 2 */ +/* To enable string functions, set _USE_STRFUNC to 1 or 2. */ + + +#define _USE_MKFS 0 /* 0 or 1 */ +/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */ + + +#define _USE_FORWARD 0 /* 0 or 1 */ +/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */ + + + +/*---------------------------------------------------------------------------/ +/ Locale and Namespace Configurations +/----------------------------------------------------------------------------*/ + +#define _CODE_PAGE 1250 +/* The _CODE_PAGE specifies the OEM code page to be used on the target system. +/ Incorrect setting of the code page can cause a file open failure. +/ +/ 932 - Japanese Shift-JIS (DBCS, OEM, Windows) +/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows) +/ 949 - Korean (DBCS, OEM, Windows) +/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows) +/ 1250 - Central Europe (Windows) +/ 1251 - Cyrillic (Windows) +/ 1252 - Latin 1 (Windows) +/ 1253 - Greek (Windows) +/ 1254 - Turkish (Windows) +/ 1255 - Hebrew (Windows) +/ 1256 - Arabic (Windows) +/ 1257 - Baltic (Windows) +/ 1258 - Vietnam (OEM, Windows) +/ 437 - U.S. (OEM) +/ 720 - Arabic (OEM) +/ 737 - Greek (OEM) +/ 775 - Baltic (OEM) +/ 850 - Multilingual Latin 1 (OEM) +/ 858 - Multilingual Latin 1 + Euro (OEM) +/ 852 - Latin 2 (OEM) +/ 855 - Cyrillic (OEM) +/ 866 - Russian (OEM) +/ 857 - Turkish (OEM) +/ 862 - Hebrew (OEM) +/ 874 - Thai (OEM, Windows) +/ 1 - ASCII only (Valid for non LFN cfg.) +*/ + + +#define _USE_LFN 0 /* 0, 1 or 2 */ +#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */ +/* The _USE_LFN option switches the LFN support. +/ +/ 0: Disable LFN. _MAX_LFN and _LFN_UNICODE have no effect. +/ 1: Enable LFN with static working buffer on the bss. NOT REENTRANT. +/ 2: Enable LFN with dynamic working buffer on the STACK. +/ +/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. When enable LFN, +/ two Unicode handling functions ff_convert() and ff_wtoupper() must be added +/ to the project. */ + + +#define _LFN_UNICODE 0 /* 0 or 1 */ +/* To switch the character code set on FatFs API to Unicode, +/ enable LFN feature and set _LFN_UNICODE to 1. +*/ + + +#define _FS_RPATH 0 /* 0 or 1 */ +/* When _FS_RPATH is set to 1, relative path feature is enabled and f_chdir, +/ f_chdrive function are available. +/ Note that output of the f_readdir fnction is affected by this option. */ + + + +/*---------------------------------------------------------------------------/ +/ Physical Drive Configurations +/----------------------------------------------------------------------------*/ + +#define _DRIVES 1 +/* Number of volumes (logical drives) to be used. */ + + +#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */ +/* Maximum sector size to be handled. +/ Always set 512 for memory card and hard disk but a larger value may be +/ required for floppy disk (512/1024) and optical disk (512/2048). +/ When _MAX_SS is larger than 512, GET_SECTOR_SIZE command must be implememted +/ to the disk_ioctl function. */ + + +#define _MULTI_PARTITION 0 /* 0 or 1 */ +/* When _MULTI_PARTITION is set to 0, each volume is bound to the same physical +/ drive number and can mount only first primaly partition. When it is set to 1, +/ each volume is tied to the partitions listed in Drives[]. */ + + + +/*---------------------------------------------------------------------------/ +/ System Configurations +/----------------------------------------------------------------------------*/ + +#define _WORD_ACCESS 0 /* 0 or 1 */ +/* The _WORD_ACCESS option defines which access method is used to the word +/ data on the FAT volume. +/ +/ 0: Byte-by-byte access. Always compatible with all platforms. +/ 1: Word access. Do not choose this unless following condition is met. +/ +/ When the byte order on the memory is big-endian or address miss-aligned +/ word access results incorrect behavior, the _WORD_ACCESS must be set to 0. +/ If it is not the case, the value can also be set to 1 to improve the +/ performance and code size. */ + + +#define _FS_REENTRANT 1 /* 0 or 1 */ +#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */ +#define _SYNC_t void * /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */ +/* The _FS_REENTRANT option switches the reentrancy of the FatFs module. +/ +/ 0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect. +/ 1: Enable reentrancy. Also user provided synchronization handlers, +/ ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj +/ function must be added to the project. */ + + +#endif /* _FFCONFIG */ diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/FreeRTOSConfig.h b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/FreeRTOSConfig.h new file mode 100644 index 000000000..e78cc3ad8 --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/FreeRTOSConfig.h @@ -0,0 +1,165 @@ +/* + FreeRTOS V6.0.2 - Copyright (C) 2010 Real Time Engineers Ltd. + + *************************************************************************** + * * + * If you are: * + * * + * + New to FreeRTOS, * + * + Wanting to learn FreeRTOS or multitasking in general quickly * + * + Looking for basic training, * + * + Wanting to improve your FreeRTOS skills and productivity * + * * + * then take a look at the FreeRTOS eBook * + * * + * "Using the FreeRTOS Real Time Kernel - a Practical Guide" * + * http://www.FreeRTOS.org/Documentation * + * * + * A pdf reference manual is also available. Both are usually delivered * + * to your inbox within 20 minutes to two hours when purchased between 8am * + * and 8pm GMT (although please allow up to 24 hours in case of * + * exceptional circumstances). Thank you for your support! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + ***NOTE*** The exception to the GPL is included to allow you to distribute + a combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#include "LPC17xx.h" + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + *----------------------------------------------------------*/ + +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 0 +#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 ) +#define configUSE_TICK_HOOK 1 +#define configCPU_CLOCK_HZ ( ( unsigned long ) 99000000 ) +#define configTICK_RATE_HZ ( ( portTickType ) 1000 ) +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 80 ) +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 19 * 1024 ) ) +#define configMAX_TASK_NAME_LEN ( 12 ) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 0 +#define configUSE_CO_ROUTINES 0 +#define configUSE_MUTEXES 1 + +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +#define configUSE_COUNTING_SEMAPHORES 0 +#define configUSE_ALTERNATIVE_API 0 +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 10 +#define configGENERATE_RUN_TIME_STATS 1 + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ + +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 + +/*----------------------------------------------------------- + * Ethernet configuration. + *-----------------------------------------------------------*/ + +/* MAC address configuration. */ +#define configMAC_ADDR0 0x00 +#define configMAC_ADDR1 0x12 +#define configMAC_ADDR2 0x13 +#define configMAC_ADDR3 0x10 +#define configMAC_ADDR4 0x15 +#define configMAC_ADDR5 0x11 + +/* IP address configuration. */ +#define configIP_ADDR0 192 +#define configIP_ADDR1 168 +#define configIP_ADDR2 0 +#define configIP_ADDR3 201 + +/* Netmask configuration. */ +#define configNET_MASK0 255 +#define configNET_MASK1 255 +#define configNET_MASK2 255 +#define configNET_MASK3 0 + +/* Use the system definition, if there is one */ +#ifdef __NVIC_PRIO_BITS + #define configPRIO_BITS __NVIC_PRIO_BITS +#else + #define configPRIO_BITS 5 /* 32 priority levels */ +#endif + +/* The lowest priority. */ +#define configKERNEL_INTERRUPT_PRIORITY ( 31 << (8 - configPRIO_BITS) ) +/* Priority 5, or 160 as only the top three bits are implemented. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( 5 << (8 - configPRIO_BITS) ) + +/* Priorities passed to NVIC_SetPriority() do not require shifting as the +function does the shifting itself. Note these priorities need to be equal to +or lower than configMAX_SYSCALL_INTERRUPT_PRIORITY - therefore the numeric +value needs to be equal to or greater than 5 (on the Cortex M3 the lower the +numeric value the higher the interrupt priority). */ +#define configEMAC_INTERRUPT_PRIORITY 5 +#define configUSB_INTERRUPT_PRIORITY 6 + + + +/*----------------------------------------------------------- + * Macros required to setup the timer for the run time stats. + *-----------------------------------------------------------*/ +extern void vConfigureTimerForRunTimeStats( void ); +#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats() +#define portGET_RUN_TIME_COUNTER_VALUE() TIM0->TC + + +/* The structure that is passed on the xLCDQueue. Put here for convenience. */ +typedef struct +{ + char *pcMessage; +} xLCDMessage; + +#endif /* FREERTOS_CONFIG_H */ diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LED.h b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LED.h new file mode 100644 index 000000000..ae3b9eee5 --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LED.h @@ -0,0 +1,61 @@ +/* + FreeRTOS V6.0.2 - Copyright (C) 2010 Real Time Engineers Ltd. + + *************************************************************************** + * * + * If you are: * + * * + * + New to FreeRTOS, * + * + Wanting to learn FreeRTOS or multitasking in general quickly * + * + Looking for basic training, * + * + Wanting to improve your FreeRTOS skills and productivity * + * * + * then take a look at the FreeRTOS eBook * + * * + * "Using the FreeRTOS Real Time Kernel - a Practical Guide" * + * http://www.FreeRTOS.org/Documentation * + * * + * A pdf reference manual is also available. Both are usually delivered * + * to your inbox within 20 minutes to two hours when purchased between 8am * + * and 8pm GMT (although please allow up to 24 hours in case of * + * exceptional circumstances). Thank you for your support! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + ***NOTE*** The exception to the GPL is included to allow you to distribute + a combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef LED_HH +#define LED_HH + +void vToggleLED( unsigned long ulLED ); +void vSetLEDState( unsigned long ulLED, long lState ); +long lGetLEDState( unsigned long ulLED ); + +#endif diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPC1700_Startup.s b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPC1700_Startup.s new file mode 100644 index 000000000..5c7a94ea1 --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPC1700_Startup.s @@ -0,0 +1,364 @@ +/***************************************************************************** + * Copyright (c) 2009 Rowley Associates Limited. * + * * + * This file may be distributed under the terms of the License Agreement * + * provided with this software. * + * * + * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE * + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * + *****************************************************************************/ + +/***************************************************************************** + * Preprocessor Definitions + * ------------------------ + * + * STARTUP_FROM_RESET + * + * If defined, the program will startup from power-on/reset. If not defined + * the program will just loop endlessly from power-on/reset. + * + * This definition is not defined by default on this target because the + * debugger is unable to reset this target and maintain control of it over the + * JTAG interface. The advantage of doing this is that it allows the debugger + * to reset the CPU and run programs from a known reset CPU state on each run. + * It also acts as a safety net if you accidently download a program in FLASH + * that crashes and prevents the debugger from taking control over JTAG + * rendering the target unusable over JTAG. The obvious disadvantage of doing + * this is that your application will not startup without the debugger. + * + * We advise that on this target you keep STARTUP_FROM_RESET undefined whilst + * you are developing and only define STARTUP_FROM_RESET when development is + * complete.A + * + * + * CONFIGURE_USB + * + * If defined, the USB clock will be configured. + * + *****************************************************************************/ + +#include + +#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 */ + diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPC17xx.h b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPC17xx.h new file mode 100644 index 000000000..f2480b138 --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPC17xx.h @@ -0,0 +1,1081 @@ +#ifndef __LPC17xx_H +#define __LPC17xx_H + +/* System Control Block (SCB) includes: + Flash Accelerator Module, Clocking and Power Control, External Interrupts, + Reset, System Control and Status +*/ +#define SCB_BASE_ADDR 0x400FC000 + +#define PCONP_PCTIM0 0x00000002 +#define PCONP_PCTIM1 0x00000004 +#define PCONP_PCUART0 0x00000008 +#define PCONP_PCUART1 0x00000010 +#define PCONP_PCPWM1 0x00000040 +#define PCONP_PCI2C0 0x00000080 +#define PCONP_PCSPI 0x00000100 +#define PCONP_PCRTC 0x00000200 +#define PCONP_PCSSP1 0x00000400 +#define PCONP_PCAD 0x00001000 +#define PCONP_PCCAN1 0x00002000 +#define PCONP_PCCAN2 0x00004000 +#define PCONP_PCGPIO 0x00008000 +#define PCONP_PCRIT 0x00010000 +#define PCONP_PCMCPWM 0x00020000 +#define PCONP_PCQEI 0x00040000 +#define PCONP_PCI2C1 0x00080000 +#define PCONP_PCSSP0 0x00200000 +#define PCONP_PCTIM2 0x00400000 +#define PCONP_PCTIM3 0x00800000 +#define PCONP_PCUART2 0x01000000 +#define PCONP_PCUART3 0x02000000 +#define PCONP_PCI2C2 0x04000000 +#define PCONP_PCI2S 0x08000000 +#define PCONP_PCGPDMA 0x20000000 +#define PCONP_PCENET 0x40000000 +#define PCONP_PCUSB 0x80000000 + +#define PLLCON_PLLE 0x00000001 +#define PLLCON_PLLC 0x00000002 +#define PLLCON_MASK 0x00000003 + +#define PLLCFG_MUL1 0x00000000 +#define PLLCFG_MUL2 0x00000001 +#define PLLCFG_MUL3 0x00000002 +#define PLLCFG_MUL4 0x00000003 +#define PLLCFG_MUL5 0x00000004 +#define PLLCFG_MUL6 0x00000005 +#define PLLCFG_MUL7 0x00000006 +#define PLLCFG_MUL8 0x00000007 +#define PLLCFG_MUL9 0x00000008 +#define PLLCFG_MUL10 0x00000009 +#define PLLCFG_MUL11 0x0000000A +#define PLLCFG_MUL12 0x0000000B +#define PLLCFG_MUL13 0x0000000C +#define PLLCFG_MUL14 0x0000000D +#define PLLCFG_MUL15 0x0000000E +#define PLLCFG_MUL16 0x0000000F +#define PLLCFG_MUL17 0x00000010 +#define PLLCFG_MUL18 0x00000011 +#define PLLCFG_MUL19 0x00000012 +#define PLLCFG_MUL20 0x00000013 +#define PLLCFG_MUL21 0x00000014 +#define PLLCFG_MUL22 0x00000015 +#define PLLCFG_MUL23 0x00000016 +#define PLLCFG_MUL24 0x00000017 +#define PLLCFG_MUL25 0x00000018 +#define PLLCFG_MUL26 0x00000019 +#define PLLCFG_MUL27 0x0000001A +#define PLLCFG_MUL28 0x0000001B +#define PLLCFG_MUL29 0x0000001C +#define PLLCFG_MUL30 0x0000001D +#define PLLCFG_MUL31 0x0000001E +#define PLLCFG_MUL32 0x0000001F +#define PLLCFG_MUL33 0x00000020 +#define PLLCFG_MUL34 0x00000021 +#define PLLCFG_MUL35 0x00000022 +#define PLLCFG_MUL36 0x00000023 + +#define PLLCFG_DIV1 0x00000000 +#define PLLCFG_DIV2 0x00010000 +#define PLLCFG_DIV3 0x00020000 +#define PLLCFG_DIV4 0x00030000 +#define PLLCFG_DIV5 0x00040000 +#define PLLCFG_DIV6 0x00050000 +#define PLLCFG_DIV7 0x00060000 +#define PLLCFG_DIV8 0x00070000 +#define PLLCFG_DIV9 0x00080000 +#define PLLCFG_DIV10 0x00090000 +#define PLLCFG_MASK 0x00FF7FFF + +#define PLLSTAT_MSEL_MASK 0x00007FFF +#define PLLSTAT_NSEL_MASK 0x00FF0000 + +#define PLLSTAT_PLLE (1 << 24) +#define PLLSTAT_PLLC (1 << 25) +#define PLLSTAT_PLOCK (1 << 26) + +#define PLLFEED_FEED1 0x000000AA +#define PLLFEED_FEED2 0x00000055 + +#define NVIC_IRQ_WDT 0u // IRQ0, exception number 16 +#define NVIC_IRQ_TIMER0 1u // IRQ1, exception number 17 +#define NVIC_IRQ_TIMER1 2u // IRQ2, exception number 18 +#define NVIC_IRQ_TIMER2 3u // IRQ3, exception number 19 +#define NVIC_IRQ_TIMER3 4u // IRQ4, exception number 20 +#define NVIC_IRQ_UART0 5u // IRQ5, exception number 21 +#define NVIC_IRQ_UART1 6u // IRQ6, exception number 22 +#define NVIC_IRQ_UART2 7u // IRQ7, exception number 23 +#define NVIC_IRQ_UART3 8u // IRQ8, exception number 24 +#define NVIC_IRQ_PWM1 9u // IRQ9, exception number 25 +#define NVIC_IRQ_I2C0 10u // IRQ10, exception number 26 +#define NVIC_IRQ_I2C1 11u // IRQ11, exception number 27 +#define NVIC_IRQ_I2C2 12u // IRQ12, exception number 28 +#define NVIC_IRQ_SPI 13u // IRQ13, exception number 29 +#define NVIC_IRQ_SSP0 14u // IRQ14, exception number 30 +#define NVIC_IRQ_SSP1 15u // IRQ15, exception number 31 +#define NVIC_IRQ_PLL0 16u // IRQ16, exception number 32 +#define NVIC_IRQ_RTC 17u // IRQ17, exception number 33 +#define NVIC_IRQ_EINT0 18u // IRQ18, exception number 34 +#define NVIC_IRQ_EINT1 19u // IRQ19, exception number 35 +#define NVIC_IRQ_EINT2 20u // IRQ20, exception number 36 +#define NVIC_IRQ_EINT3 21u // IRQ21, exception number 37 +#define NVIC_IRQ_ADC 22u // IRQ22, exception number 38 +#define NVIC_IRQ_BOD 23u // IRQ23, exception number 39 +#define NVIC_IRQ_USB 24u // IRQ24, exception number 40 +#define NVIC_IRQ_CAN 25u // IRQ25, exception number 41 +#define NVIC_IRQ_GPDMA 26u // IRQ26, exception number 42 +#define NVIC_IRQ_I2S 27u // IRQ27, exception number 43 +#define NVIC_IRQ_ETHERNET 28u // IRQ28, exception number 44 +#define NVIC_IRQ_RIT 29u // IRQ29, exception number 45 +#define NVIC_IRQ_MCPWM 30u // IRQ30, exception number 46 +#define NVIC_IRQ_QE 31u // IRQ31, exception number 47 +#define NVIC_IRQ_PLL1 32u // IRQ32, exception number 48 +#define NVIC_IRQ_USB_ACT 33u // IRQ33, exception number 49 +#define NVIC_IRQ_CAN_ACT 34u // IRQ34, exception number 50 + + +#endif // __LPC17xx_H + + +#ifndef CMSIS_17xx_H +#define CMSIS_17xx_H + +/****************************************************************************** + * @file: LPC17xx.h + * @purpose: CMSIS Cortex-M3 Core Peripheral Access Layer Header File for + * NXP LPC17xx Device Series + * @version: V1.1 + * @date: 14th May 2009 + *---------------------------------------------------------------------------- + * + * 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 __LPC17xx_H__ +#define __LPC17xx_H__ + +/* + * ========================================================================== + * ---------- Interrupt Number Definition ----------------------------------- + * ========================================================================== + */ + +typedef enum IRQn +{ +/****** Cortex-M3 Processor Exceptions Numbers ***************************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 Memory Management Interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M3 Bus Fault Interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M3 Usage Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV Call Interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 Debug Monitor Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M3 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M3 System Tick Interrupt */ + +/****** LPC17xx Specific Interrupt Numbers *******************************************************/ + WDT_IRQn = 0, /*!< Watchdog Timer Interrupt */ + TIMER0_IRQn = 1, /*!< Timer0 Interrupt */ + TIMER1_IRQn = 2, /*!< Timer1 Interrupt */ + TIMER2_IRQn = 3, /*!< Timer2 Interrupt */ + TIMER3_IRQn = 4, /*!< Timer3 Interrupt */ + UART0_IRQn = 5, /*!< UART0 Interrupt */ + UART1_IRQn = 6, /*!< UART1 Interrupt */ + UART2_IRQn = 7, /*!< UART2 Interrupt */ + UART3_IRQn = 8, /*!< UART3 Interrupt */ + PWM1_IRQn = 9, /*!< PWM1 Interrupt */ + I2C0_IRQn = 10, /*!< I2C0 Interrupt */ + I2C1_IRQn = 11, /*!< I2C1 Interrupt */ + I2C2_IRQn = 12, /*!< I2C2 Interrupt */ + SPI_IRQn = 13, /*!< SPI Interrupt */ + SSP0_IRQn = 14, /*!< SSP0 Interrupt */ + SSP1_IRQn = 15, /*!< SSP1 Interrupt */ + PLL0_IRQn = 16, /*!< PLL0 Lock (Main PLL) Interrupt */ + RTC_IRQn = 17, /*!< Real Time Clock Interrupt */ + EINT0_IRQn = 18, /*!< External Interrupt 0 Interrupt */ + EINT1_IRQn = 19, /*!< External Interrupt 1 Interrupt */ + EINT2_IRQn = 20, /*!< External Interrupt 2 Interrupt */ + EINT3_IRQn = 21, /*!< External Interrupt 3 Interrupt */ + ADC_IRQn = 22, /*!< A/D Converter Interrupt */ + BOD_IRQn = 23, /*!< Brown-Out Detect Interrupt */ + USB_IRQn = 24, /*!< USB Interrupt */ + CAN_IRQn = 25, /*!< CAN Interrupt */ + DMA_IRQn = 26, /*!< General Purpose DMA Interrupt */ + I2S_IRQn = 27, /*!< I2S Interrupt */ + ENET_IRQn = 28, /*!< Ethernet Interrupt */ + RIT_IRQn = 29, /*!< Repetitive Interrupt Timer Interrupt */ + MCPWM_IRQn = 30, /*!< Motor Control PWM Interrupt */ + QEI_IRQn = 31, /*!< Quadrature Encoder Interface Interrupt */ + PLL1_IRQn = 32, /*!< PLL1 Lock (USB PLL) Interrupt */ +} IRQn_Type; + + +/* + * ========================================================================== + * ----------- Processor and Core Peripheral Section ------------------------ + * ========================================================================== + */ + +/* Configuration of the Cortex-M3 Processor and Core Peripherals */ +#define __MPU_PRESENT 1 /*!< MPU present or not */ +#define __NVIC_PRIO_BITS 5 /*!< Number of Bits used for Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ + + +//#include "..\core_cm3.h" /* Cortex-M3 processor and core peripherals */ +#include "core_cm3.h" +#include "system_LPC17xx.h" /* System Header */ + + + +/** + * Initialize the system clock + * + * @param none + * @return none + * + * @brief Setup the microcontroller system. + * Initialize the System and update the SystemFrequency variable. + */ +extern void SystemInit (void); + + +/******************************************************************************/ +/* Device Specific Peripheral registers structures */ +/******************************************************************************/ + +/*------------- System Control (SC) ------------------------------------------*/ +typedef struct +{ + __IO uint32_t FLASHCFG; /* Flash Accelerator Module */ + uint32_t RESERVED0[31]; + __IO uint32_t PLL0CON; /* Clocking and Power Control */ + __IO uint32_t PLL0CFG; + __I uint32_t PLL0STAT; + __O uint32_t PLL0FEED; + uint32_t RESERVED1[4]; + __IO uint32_t PLL1CON; + __IO uint32_t PLL1CFG; + __I uint32_t PLL1STAT; + __O uint32_t PLL1FEED; + uint32_t RESERVED2[4]; + __IO uint32_t PCON; + __IO uint32_t PCONP; + uint32_t RESERVED3[15]; + __IO uint32_t CCLKCFG; + __IO uint32_t USBCLKCFG; + __IO uint32_t CLKSRCSEL; + uint32_t RESERVED4[12]; + __IO uint32_t EXTINT; /* External Interrupts */ + uint32_t RESERVED5; + __IO uint32_t EXTMODE; + __IO uint32_t EXTPOLAR; + uint32_t RESERVED6[12]; + __IO uint32_t RSID; /* Reset */ + uint32_t RESERVED7[7]; + __IO uint32_t SCS; /* Syscon Miscellaneous Registers */ + __IO uint32_t IRCTRIM; /* Clock Dividers */ + __IO uint32_t PCLKSEL0; + __IO uint32_t PCLKSEL1; + uint32_t RESERVED8[4]; + __IO uint32_t USBIntSt; /* USB Device/OTG Interrupt Register */ + uint32_t RESERVED9; + __IO uint32_t CLKOUTCFG; /* Clock Output Configuration */ + } SC_TypeDef; + +/*------------- Pin Connect Block (PINCON) -----------------------------------*/ +typedef struct +{ + __IO uint32_t PINSEL0; + __IO uint32_t PINSEL1; + __IO uint32_t PINSEL2; + __IO uint32_t PINSEL3; + __IO uint32_t PINSEL4; + __IO uint32_t PINSEL5; + __IO uint32_t PINSEL6; + __IO uint32_t PINSEL7; + __IO uint32_t PINSEL8; + __IO uint32_t PINSEL9; + __IO uint32_t PINSEL10; + uint32_t RESERVED0[5]; + __IO uint32_t PINMODE0; + __IO uint32_t PINMODE1; + __IO uint32_t PINMODE2; + __IO uint32_t PINMODE3; + __IO uint32_t PINMODE4; + __IO uint32_t PINMODE5; + __IO uint32_t PINMODE6; + __IO uint32_t PINMODE7; + __IO uint32_t PINMODE8; + __IO uint32_t PINMODE9; + __IO uint32_t PINMODE_OD0; + __IO uint32_t PINMODE_OD1; + __IO uint32_t PINMODE_OD2; + __IO uint32_t PINMODE_OD3; + __IO uint32_t PINMODE_OD4; +} PINCON_TypeDef; + +/*------------- General Purpose Input/Output (GPIO) --------------------------*/ +typedef struct +{ + __IO uint32_t FIODIR; + uint32_t RESERVED0[3]; + __IO uint32_t FIOMASK; + __IO uint32_t FIOPIN; + __IO uint32_t FIOSET; + __O uint32_t FIOCLR; +} GPIO_TypeDef; + +typedef struct +{ + __I uint32_t IntStatus; + __I uint32_t IO0IntStatR; + __I uint32_t IO0IntStatF; + __O uint32_t IO0IntClr; + __IO uint32_t IO0IntEnR; + __IO uint32_t IO0IntEnF; + uint32_t RESERVED0[3]; + __I uint32_t IO2IntStatR; + __I uint32_t IO2IntStatF; + __O uint32_t IO2IntClr; + __IO uint32_t IO2IntEnR; + __IO uint32_t IO2IntEnF; +} GPIOINT_TypeDef; + +/*------------- Timer (TIM) --------------------------------------------------*/ +typedef struct +{ + __IO uint32_t IR; + __IO uint32_t TCR; + __IO uint32_t TC; + __IO uint32_t PR; + __IO uint32_t PC; + __IO uint32_t MCR; + __IO uint32_t MR0; + __IO uint32_t MR1; + __IO uint32_t MR2; + __IO uint32_t MR3; + __IO uint32_t CCR; + __I uint32_t CR0; + __I uint32_t CR1; + uint32_t RESERVED0[2]; + __IO uint32_t EMR; + uint32_t RESERVED1[24]; + __IO uint32_t CTCR; +} TIM_TypeDef; + +/*------------- Pulse-Width Modulation (PWM) ---------------------------------*/ +typedef struct +{ + __IO uint32_t IR; + __IO uint32_t TCR; + __IO uint32_t TC; + __IO uint32_t PR; + __IO uint32_t PC; + __IO uint32_t MCR; + __IO uint32_t MR0; + __IO uint32_t MR1; + __IO uint32_t MR2; + __IO uint32_t MR3; + __IO uint32_t CCR; + __I uint32_t CR0; + __I uint32_t CR1; + __I uint32_t CR2; + __I uint32_t CR3; + __IO uint32_t MR4; + __IO uint32_t MR5; + __IO uint32_t MR6; + __IO uint32_t PCR; + __IO uint32_t LER; + uint32_t RESERVED0[7]; + __IO uint32_t CTCR; +} PWM_TypeDef; + +/*------------- Universal Asynchronous Receiver Transmitter (UART) -----------*/ +typedef struct +{ + union { + __I uint8_t RBR; + __O uint8_t THR; + __IO uint8_t DLL; + uint32_t RESERVED0; + }; + union { + __IO uint8_t DLM; + __IO uint32_t IER; + }; + union { + __I uint32_t IIR; + __O uint8_t FCR; + }; + __IO uint8_t LCR; + uint8_t RESERVED1[7]; + __IO uint8_t LSR; + uint8_t RESERVED2[7]; + __IO uint8_t SCR; + uint8_t RESERVED3[3]; + __IO uint32_t ACR; + __IO uint8_t ICR; + uint8_t RESERVED4[3]; + __IO uint8_t FDR; + uint8_t RESERVED5[7]; + __IO uint8_t TER; + uint8_t RESERVED6[27]; + __IO uint8_t RS485CTRL; + uint8_t RESERVED7[3]; + __IO uint8_t ADRMATCH; +} UART_TypeDef; + +typedef struct +{ + union { + __I uint8_t RBR; + __O uint8_t THR; + __IO uint8_t DLL; + uint32_t RESERVED0; + }; + union { + __IO uint8_t DLM; + __IO uint32_t IER; + }; + union { + __I uint32_t IIR; + __O uint8_t FCR; + }; + __IO uint8_t LCR; + uint8_t RESERVED1[3]; + __IO uint8_t MCR; + uint8_t RESERVED2[3]; + __IO uint8_t LSR; + uint8_t RESERVED3[3]; + __IO uint8_t MSR; + uint8_t RESERVED4[3]; + __IO uint8_t SCR; + uint8_t RESERVED5[3]; + __IO uint32_t ACR; + uint32_t RESERVED6; + __IO uint32_t FDR; + uint32_t RESERVED7; + __IO uint8_t TER; + uint8_t RESERVED8[27]; + __IO uint8_t RS485CTRL; + uint8_t RESERVED9[3]; + __IO uint8_t ADRMATCH; + uint8_t RESERVED10[3]; + __IO uint8_t RS485DLY; +} UART1_TypeDef; + +/*------------- Serial Peripheral Interface (SPI) ----------------------------*/ +typedef struct +{ + __IO uint32_t SPCR; + __I uint32_t SPSR; + __IO uint32_t SPDR; + __IO uint32_t SPCCR; + uint32_t RESERVED0[3]; + __IO uint32_t SPINT; +} SPI_TypeDef; + +/*------------- Synchronous Serial Communication (SSP) -----------------------*/ +typedef struct +{ + __IO uint32_t CR0; + __IO uint32_t CR1; + __IO uint32_t DR; + __I uint32_t SR; + __IO uint32_t CPSR; + __IO uint32_t IMSC; + __IO uint32_t RIS; + __IO uint32_t MIS; + __IO uint32_t ICR; + __IO uint32_t DMACR; +} SSP_TypeDef; + +/*------------- Inter-Integrated Circuit (I2C) -------------------------------*/ +typedef struct +{ + __IO uint32_t I2CONSET; + __I uint32_t I2STAT; + __IO uint32_t I2DAT; + __IO uint32_t I2ADR0; + __IO uint32_t I2SCLH; + __IO uint32_t I2SCLL; + __O uint32_t I2CONCLR; + __IO uint32_t MMCTRL; + __IO uint32_t I2ADR1; + __IO uint32_t I2ADR2; + __IO uint32_t I2ADR3; + __I uint32_t I2DATA_BUFFER; + __IO uint32_t I2MASK0; + __IO uint32_t I2MASK1; + __IO uint32_t I2MASK2; + __IO uint32_t I2MASK3; +} I2C_TypeDef; + +/*------------- Inter IC Sound (I2S) -----------------------------------------*/ +typedef struct +{ + __IO uint32_t I2SDAO; + __IO uint32_t I2SDAI; + __O uint32_t I2STXFIFO; + __I uint32_t I2SRXFIFO; + __I uint32_t I2SSTATE; + __IO uint32_t I2SDMA1; + __IO uint32_t I2SDMA2; + __IO uint32_t I2SIRQ; + __IO uint32_t I2STXRATE; + __IO uint32_t I2SRXRATE; + __IO uint32_t I2STXBITRATE; + __IO uint32_t I2SRXBITRATE; + __IO uint32_t I2STXMODE; + __IO uint32_t I2SRXMODE; +} I2S_TypeDef; + +/*------------- Repetitive Interrupt Timer (RIT) -----------------------------*/ +typedef struct +{ + __IO uint32_t RICOMPVAL; + __IO uint32_t RIMASK; + __IO uint8_t RICTRL; + uint8_t RESERVED0[3]; + __IO uint32_t RICOUNTER; +} RIT_TypeDef; + +/*------------- Real-Time Clock (RTC) ----------------------------------------*/ +typedef struct +{ + __IO uint8_t ILR; + uint8_t RESERVED0[3]; + __IO uint8_t CCR; + uint8_t RESERVED1[3]; + __IO uint8_t CIIR; + uint8_t RESERVED2[3]; + __IO uint8_t AMR; + uint8_t RESERVED3[3]; + __I uint32_t CTIME0; + __I uint32_t CTIME1; + __I uint32_t CTIME2; + __IO uint8_t SEC; + uint8_t RESERVED4[3]; + __IO uint8_t MIN; + uint8_t RESERVED5[3]; + __IO uint8_t HOUR; + uint8_t RESERVED6[3]; + __IO uint8_t DOM; + uint8_t RESERVED7[3]; + __IO uint8_t DOW; + uint8_t RESERVED8[3]; + __IO uint16_t DOY; + uint16_t RESERVED9; + __IO uint8_t MONTH; + uint8_t RESERVED10[3]; + __IO uint16_t YEAR; + uint16_t RESERVED11; + __IO uint32_t CALIBRATION; + __IO uint32_t GPREG0; + __IO uint32_t GPREG1; + __IO uint32_t GPREG2; + __IO uint32_t GPREG3; + __IO uint32_t GPREG4; + __IO uint8_t WAKEUPDIS; + uint8_t RESERVED12[3]; + __IO uint8_t PWRCTRL; + uint8_t RESERVED13[3]; + __IO uint8_t ALSEC; + uint8_t RESERVED14[3]; + __IO uint8_t ALMIN; + uint8_t RESERVED15[3]; + __IO uint8_t ALHOUR; + uint8_t RESERVED16[3]; + __IO uint8_t ALDOM; + uint8_t RESERVED17[3]; + __IO uint8_t ALDOW; + uint8_t RESERVED18[3]; + __IO uint16_t ALDOY; + uint16_t RESERVED19; + __IO uint8_t ALMON; + uint8_t RESERVED20[3]; + __IO uint16_t ALYEAR; + uint16_t RESERVED21; +} RTC_TypeDef; + +/*------------- Watchdog Timer (WDT) -----------------------------------------*/ +typedef struct +{ + __IO uint8_t WDMOD; + uint8_t RESERVED0[3]; + __IO uint32_t WDTC; + __O uint8_t WDFEED; + uint8_t RESERVED1[3]; + __I uint32_t WDTV; + __IO uint32_t WDCLKSEL; +} WDT_TypeDef; + +/*------------- Analog-to-Digital Converter (ADC) ----------------------------*/ +typedef struct +{ + __IO uint32_t ADCR; + __IO uint32_t ADGDR; + uint32_t RESERVED0; + __IO uint32_t ADINTEN; + __I uint32_t ADDR0; + __I uint32_t ADDR1; + __I uint32_t ADDR2; + __I uint32_t ADDR3; + __I uint32_t ADDR4; + __I uint32_t ADDR5; + __I uint32_t ADDR6; + __I uint32_t ADDR7; + __I uint32_t ADSTAT; + __IO uint32_t ADTRM; +} ADC_TypeDef; + +/*------------- Digital-to-Analog Converter (DAC) ----------------------------*/ +typedef struct +{ + __IO uint32_t DACR; + __IO uint32_t DACCTRL; + __IO uint16_t DACCNTVAL; +} DAC_TypeDef; + +/*------------- Motor Control Pulse-Width Modulation (MCPWM) -----------------*/ +typedef struct +{ + __I uint32_t MCCON; + __O uint32_t MCCON_SET; + __O uint32_t MCCON_CLR; + __I uint32_t MCCAPCON; + __O uint32_t MCCAPCON_SET; + __O uint32_t MCCAPCON_CLR; + __IO uint32_t MCTIM0; + __IO uint32_t MCTIM1; + __IO uint32_t MCTIM2; + __IO uint32_t MCPER0; + __IO uint32_t MCPER1; + __IO uint32_t MCPER2; + __IO uint32_t MCPW0; + __IO uint32_t MCPW1; + __IO uint32_t MCPW2; + __IO uint32_t MCDEADTIME; + __IO uint32_t MCCCP; + __IO uint32_t MCCR0; + __IO uint32_t MCCR1; + __IO uint32_t MCCR2; + __I uint32_t MCINTEN; + __O uint32_t MCINTEN_SET; + __O uint32_t MCINTEN_CLR; + __I uint32_t MCCNTCON; + __O uint32_t MCCNTCON_SET; + __O uint32_t MCCNTCON_CLR; + __I uint32_t MCINTFLAG; + __O uint32_t MCINTFLAG_SET; + __O uint32_t MCINTFLAG_CLR; + __O uint32_t MCCAP_CLR; +} MCPWM_TypeDef; + +/*------------- Quadrature Encoder Interface (QEI) ---------------------------*/ +typedef struct +{ + __O uint32_t QEICON; + __I uint32_t QEISTAT; + __IO uint32_t QEICONF; + __I uint32_t QEIPOS; + __IO uint32_t QEIMAXPOS; + __IO uint32_t CMPOS0; + __IO uint32_t CMPOS1; + __IO uint32_t CMPOS2; + __I uint32_t INXCNT; + __IO uint32_t INXCMP; + __IO uint32_t QEILOAD; + __I uint32_t QEITIME; + __I uint32_t QEIVEL; + __I uint32_t QEICAP; + __IO uint32_t VELCOMP; + __IO uint32_t FILTER; + uint32_t RESERVED0[998]; + __O uint32_t QEIIEC; + __O uint32_t QEIIES; + __I uint32_t QEIINTSTAT; + __I uint32_t QEIIE; + __O uint32_t QEICLR; + __O uint32_t QEISET; +} QEI_TypeDef; + +/*------------- Controller Area Network (CAN) --------------------------------*/ +typedef struct +{ + __IO uint32_t mask[512]; /* ID Masks */ +} CANAF_RAM_TypeDef; + +typedef struct /* Acceptance Filter Registers */ +{ + __IO uint32_t AFMR; + __IO uint32_t SFF_sa; + __IO uint32_t SFF_GRP_sa; + __IO uint32_t EFF_sa; + __IO uint32_t EFF_GRP_sa; + __IO uint32_t ENDofTable; + __I uint32_t LUTerrAd; + __I uint32_t LUTerr; +} CANAF_TypeDef; + +typedef struct /* Central Registers */ +{ + __I uint32_t CANTxSR; + __I uint32_t CANRxSR; + __I uint32_t CANMSR; +} CANCR_TypeDef; + +typedef struct /* Controller Registers */ +{ + __IO uint32_t MOD; + __O uint32_t CMR; + __IO uint32_t GSR; + __I uint32_t ICR; + __IO uint32_t IER; + __IO uint32_t BTR; + __IO uint32_t EWL; + __I uint32_t SR; + __IO uint32_t RFS; + __IO uint32_t RID; + __IO uint32_t RDA; + __IO uint32_t RDB; + __IO uint32_t TFI1; + __IO uint32_t TID1; + __IO uint32_t TDA1; + __IO uint32_t TDB1; + __IO uint32_t TFI2; + __IO uint32_t TID2; + __IO uint32_t TDA2; + __IO uint32_t TDB2; + __IO uint32_t TFI3; + __IO uint32_t TID3; + __IO uint32_t TDA3; + __IO uint32_t TDB3; +} CAN_TypeDef; + +/*------------- General Purpose Direct Memory Access (GPDMA) -----------------*/ +typedef struct /* Common Registers */ +{ + __I uint32_t DMACIntStat; + __I uint32_t DMACIntTCStat; + __O uint32_t DMACIntTCClear; + __I uint32_t DMACIntErrStat; + __O uint32_t DMACIntErrClr; + __I uint32_t DMACRawIntTCStat; + __I uint32_t DMACRawIntErrStat; + __I uint32_t DMACEnbldChns; + __IO uint32_t DMACSoftBReq; + __IO uint32_t DMACSoftSReq; + __IO uint32_t DMACSoftLBReq; + __IO uint32_t DMACSoftLSReq; + __IO uint32_t DMACConfig; + __IO uint32_t DMACSync; +} GPDMA_TypeDef; + +typedef struct /* Channel Registers */ +{ + __IO uint32_t DMACCSrcAddr; + __IO uint32_t DMACCDestAddr; + __IO uint32_t DMACCLLI; + __IO uint32_t DMACCControl; + __IO uint32_t DMACCConfig; +} GPDMACH_TypeDef; + +/*------------- Universal Serial Bus (USB) -----------------------------------*/ +typedef struct +{ + __I uint32_t HcRevision; /* USB Host Registers */ + __IO uint32_t HcControl; + __IO uint32_t HcCommandStatus; + __IO uint32_t HcInterruptStatus; + __IO uint32_t HcInterruptEnable; + __IO uint32_t HcInterruptDisable; + __IO uint32_t HcHCCA; + __I uint32_t HcPeriodCurrentED; + __IO uint32_t HcControlHeadED; + __IO uint32_t HcControlCurrentED; + __IO uint32_t HcBulkHeadED; + __IO uint32_t HcBulkCurrentED; + __I uint32_t HcDoneHead; + __IO uint32_t HcFmInterval; + __I uint32_t HcFmRemaining; + __I uint32_t HcFmNumber; + __IO uint32_t HcPeriodicStart; + __IO uint32_t HcLSTreshold; + __IO uint32_t HcRhDescriptorA; + __IO uint32_t HcRhDescriptorB; + __IO uint32_t HcRhStatus; + __IO uint32_t HcRhPortStatus1; + __IO uint32_t HcRhPortStatus2; + uint32_t RESERVED0[40]; + __I uint32_t Module_ID; + + __I uint32_t OTGIntSt; /* USB On-The-Go Registers */ + __IO uint32_t OTGIntEn; + __O uint32_t OTGIntSet; + __O uint32_t OTGIntClr; + __IO uint32_t OTGStCtrl; + __IO uint32_t OTGTmr; + uint32_t RESERVED1[58]; + + __I uint32_t USBDevIntSt; /* USB Device Interrupt Registers */ + __IO uint32_t USBDevIntEn; + __O uint32_t USBDevIntClr; + __O uint32_t USBDevIntSet; + + __O uint32_t USBCmdCode; /* USB Device SIE Command Registers */ + __I uint32_t USBCmdData; + + __I uint32_t USBRxData; /* USB Device Transfer Registers */ + __O uint32_t USBTxData; + __I uint32_t USBRxPLen; + __O uint32_t USBTxPLen; + __IO uint32_t USBCtrl; + __O uint32_t USBDevIntPri; + + __I uint32_t USBEpIntSt; /* USB Device Endpoint Interrupt Regs */ + __IO uint32_t USBEpIntEn; + __O uint32_t USBEpIntClr; + __O uint32_t USBEpIntSet; + __O uint32_t USBEpIntPri; + + __IO uint32_t USBReEp; /* USB Device Endpoint Realization Reg*/ + __O uint32_t USBEpInd; + __IO uint32_t USBMaxPSize; + + __I uint32_t USBDMARSt; /* USB Device DMA Registers */ + __O uint32_t USBDMARClr; + __O uint32_t USBDMARSet; + uint32_t RESERVED2[9]; + __IO uint32_t USBUDCAH; + __I uint32_t USBEpDMASt; + __O uint32_t USBEpDMAEn; + __O uint32_t USBEpDMADis; + __I uint32_t USBDMAIntSt; + __IO uint32_t USBDMAIntEn; + uint32_t RESERVED3[2]; + __I uint32_t USBEoTIntSt; + __O uint32_t USBEoTIntClr; + __O uint32_t USBEoTIntSet; + __I uint32_t USBNDDRIntSt; + __O uint32_t USBNDDRIntClr; + __O uint32_t USBNDDRIntSet; + __I uint32_t USBSysErrIntSt; + __O uint32_t USBSysErrIntClr; + __O uint32_t USBSysErrIntSet; + uint32_t RESERVED4[15]; + + __I uint32_t I2C_RX; /* USB OTG I2C Registers */ + __O uint32_t I2C_WO; + __I uint32_t I2C_STS; + __IO uint32_t I2C_CTL; + __IO uint32_t I2C_CLKHI; + __O uint32_t I2C_CLKLO; + uint32_t RESERVED5[823]; + + union { + __IO uint32_t USBClkCtrl; /* USB Clock Control Registers */ + __IO uint32_t OTGClkCtrl; + } ; + union { + __I uint32_t USBClkSt; + __I uint32_t OTGClkSt; + }; +} USB_TypeDef; + +/*------------- Ethernet Media Access Controller (EMAC) ----------------------*/ +typedef struct +{ + __IO uint32_t MAC1; /* MAC Registers */ + __IO uint32_t MAC2; + __IO uint32_t IPGT; + __IO uint32_t IPGR; + __IO uint32_t CLRT; + __IO uint32_t MAXF; + __IO uint32_t SUPP; + __IO uint32_t TEST; + __IO uint32_t MCFG; + __IO uint32_t MCMD; + __IO uint32_t MADR; + __O uint32_t MWTD; + __I uint32_t MRDD; + __I uint32_t MIND; + uint32_t RESERVED0[2]; + __IO uint32_t SA0; + __IO uint32_t SA1; + __IO uint32_t SA2; + uint32_t RESERVED1[45]; + __IO uint32_t Command; /* Control Registers */ + __I uint32_t Status; + __IO uint32_t RxDescriptor; + __IO uint32_t RxStatus; + __IO uint32_t RxDescriptorNumber; + __I uint32_t RxProduceIndex; + __IO uint32_t RxConsumeIndex; + __IO uint32_t TxDescriptor; + __IO uint32_t TxStatus; + __IO uint32_t TxDescriptorNumber; + __IO uint32_t TxProduceIndex; + __I uint32_t TxConsumeIndex; + uint32_t RESERVED2[10]; + __I uint32_t TSV0; + __I uint32_t TSV1; + __I uint32_t RSV; + uint32_t RESERVED3[3]; + __IO uint32_t FlowControlCounter; + __I uint32_t FlowControlStatus; + uint32_t RESERVED4[34]; + __IO uint32_t RxFilterCtrl; /* Rx Filter Registers */ + __IO uint32_t RxFilterWoLStatus; + __IO uint32_t RxFilterWoLClear; + uint32_t RESERVED5; + __IO uint32_t HashFilterL; + __IO uint32_t HashFilterH; + uint32_t RESERVED6[882]; + __I uint32_t IntStatus; /* Module Control Registers */ + __IO uint32_t IntEnable; + __O uint32_t IntClear; + __O uint32_t IntSet; + uint32_t RESERVED7; + __IO uint32_t PowerDown; + uint32_t RESERVED8; + __IO uint32_t Module_ID; +} EMAC_TypeDef; + + +/******************************************************************************/ +/* Peripheral memory map */ +/******************************************************************************/ +/* Base addresses */ +#define FLASH_BASE (0x00000000UL) +#define RAM_BASE (0x10000000UL) +#define GPIO_BASE (0x2009C000UL) +#define APB0_BASE (0x40000000UL) +#define APB1_BASE (0x40080000UL) +#define AHB_BASE (0x50000000UL) +#define CM3_BASE (0xE0000000UL) + +/* APB0 peripherals */ +#define WDT_BASE (APB0_BASE + 0x00000) +#define TIM0_BASE (APB0_BASE + 0x04000) +#define TIM1_BASE (APB0_BASE + 0x08000) +#define UART0_BASE (APB0_BASE + 0x0C000) +#define UART1_BASE (APB0_BASE + 0x10000) +#define PWM1_BASE (APB0_BASE + 0x18000) +#define I2C0_BASE (APB0_BASE + 0x1C000) +#define SPI_BASE (APB0_BASE + 0x20000) +#define RTC_BASE (APB0_BASE + 0x24000) +#define GPIOINT_BASE (APB0_BASE + 0x28080) +#define PINCON_BASE (APB0_BASE + 0x2C000) +#define SSP1_BASE (APB0_BASE + 0x30000) +#define ADC_BASE (APB0_BASE + 0x34000) +#define CANAF_RAM_BASE (APB0_BASE + 0x38000) +#define CANAF_BASE (APB0_BASE + 0x3C000) +#define CANCR_BASE (APB0_BASE + 0x40000) +#define CAN1_BASE (APB0_BASE + 0x44000) +#define CAN2_BASE (APB0_BASE + 0x48000) +#define I2C1_BASE (APB0_BASE + 0x5C000) + +/* APB1 peripherals */ +#define SSP0_BASE (APB1_BASE + 0x08000) +#define DAC_BASE (APB1_BASE + 0x0C000) +#define TIM2_BASE (APB1_BASE + 0x10000) +#define TIM3_BASE (APB1_BASE + 0x14000) +#define UART2_BASE (APB1_BASE + 0x18000) +#define UART3_BASE (APB1_BASE + 0x1C000) +#define I2C2_BASE (APB1_BASE + 0x20000) +#define I2S_BASE (APB1_BASE + 0x28000) +#define RIT_BASE (APB1_BASE + 0x30000) +#define MCPWM_BASE (APB1_BASE + 0x38000) +#define QEI_BASE (APB1_BASE + 0x3C000) +#define SC_BASE (APB1_BASE + 0x7C000) + +/* AHB peripherals */ +#define EMAC_BASE (AHB_BASE + 0x00000) +#define GPDMA_BASE (AHB_BASE + 0x04000) +#define GPDMACH0_BASE (AHB_BASE + 0x04100) +#define GPDMACH1_BASE (AHB_BASE + 0x04120) +#define GPDMACH2_BASE (AHB_BASE + 0x04140) +#define GPDMACH3_BASE (AHB_BASE + 0x04160) +#define GPDMACH4_BASE (AHB_BASE + 0x04180) +#define GPDMACH5_BASE (AHB_BASE + 0x041A0) +#define GPDMACH6_BASE (AHB_BASE + 0x041C0) +#define GPDMACH7_BASE (AHB_BASE + 0x041E0) +#define USB_BASE (AHB_BASE + 0x0C000) + +/* GPIOs */ +#define GPIO0_BASE (GPIO_BASE + 0x00000) +#define GPIO1_BASE (GPIO_BASE + 0x00020) +#define GPIO2_BASE (GPIO_BASE + 0x00040) +#define GPIO3_BASE (GPIO_BASE + 0x00060) +#define GPIO4_BASE (GPIO_BASE + 0x00080) + + +/******************************************************************************/ +/* Peripheral declaration */ +/******************************************************************************/ +#define SC (( SC_TypeDef *) SC_BASE) +#define GPIO0 (( GPIO_TypeDef *) GPIO0_BASE) +#define GPIO1 (( GPIO_TypeDef *) GPIO1_BASE) +#define GPIO2 (( GPIO_TypeDef *) GPIO2_BASE) +#define GPIO3 (( GPIO_TypeDef *) GPIO3_BASE) +#define GPIO4 (( GPIO_TypeDef *) GPIO4_BASE) +#define WDT (( WDT_TypeDef *) WDT_BASE) +#define TIM0 (( TIM_TypeDef *) TIM0_BASE) +#define TIM1 (( TIM_TypeDef *) TIM1_BASE) +#define TIM2 (( TIM_TypeDef *) TIM2_BASE) +#define TIM3 (( TIM_TypeDef *) TIM3_BASE) +#define RIT (( RIT_TypeDef *) RIT_BASE) +#define UART0 (( UART_TypeDef *) UART0_BASE) +#define UART1 (( UART1_TypeDef *) UART1_BASE) +#define UART2 (( UART_TypeDef *) UART2_BASE) +#define UART3 (( UART_TypeDef *) UART3_BASE) +#define PWM1 (( PWM_TypeDef *) PWM1_BASE) +#define I2C0 (( I2C_TypeDef *) I2C0_BASE) +#define I2C1 (( I2C_TypeDef *) I2C1_BASE) +#define I2C2 (( I2C_TypeDef *) I2C2_BASE) +#define I2S (( I2S_TypeDef *) I2S_BASE) +#define SPI (( SPI_TypeDef *) SPI_BASE) +#define RTC (( RTC_TypeDef *) RTC_BASE) +#define GPIOINT (( GPIOINT_TypeDef *) GPIOINT_BASE) +#define PINCON (( PINCON_TypeDef *) PINCON_BASE) +#define SSP0 (( SSP_TypeDef *) SSP0_BASE) +#define SSP1 (( SSP_TypeDef *) SSP1_BASE) +#define ADC (( ADC_TypeDef *) ADC_BASE) +#define DAC (( DAC_TypeDef *) DAC_BASE) +#define CANAF_RAM ((CANAF_RAM_TypeDef *) CANAF_RAM_BASE) +#define CANAF (( CANAF_TypeDef *) CANAF_BASE) +#define CANCR (( CANCR_TypeDef *) CANCR_BASE) +#define CAN1 (( CAN_TypeDef *) CAN1_BASE) +#define CAN2 (( CAN_TypeDef *) CAN2_BASE) +#define MCPWM (( MCPWM_TypeDef *) MCPWM_BASE) +#define QEI (( QEI_TypeDef *) QEI_BASE) +#define EMAC (( EMAC_TypeDef *) EMAC_BASE) +#define GPDMA (( GPDMA_TypeDef *) GPDMA_BASE) +#define GPDMACH0 (( GPDMACH_TypeDef *) GPDMACH0_BASE) +#define GPDMACH1 (( GPDMACH_TypeDef *) GPDMACH1_BASE) +#define GPDMACH2 (( GPDMACH_TypeDef *) GPDMACH2_BASE) +#define GPDMACH3 (( GPDMACH_TypeDef *) GPDMACH3_BASE) +#define GPDMACH4 (( GPDMACH_TypeDef *) GPDMACH4_BASE) +#define GPDMACH5 (( GPDMACH_TypeDef *) GPDMACH5_BASE) +#define GPDMACH6 (( GPDMACH_TypeDef *) GPDMACH6_BASE) +#define GPDMACH7 (( GPDMACH_TypeDef *) GPDMACH7_BASE) +#define USB (( USB_TypeDef *) USB_BASE) + +#endif // __LPC17xx_H__ + + +#endif diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/USB_CDC.c b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/USB_CDC.c new file mode 100644 index 000000000..adc955ee4 --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/USB_CDC.c @@ -0,0 +1,460 @@ +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + Minimal implementation of a USB serial port, using the CDC class. + This example application simply echoes everything it receives right back + to the host. + + Windows: + Extract the usbser.sys file from .cab file in C:\WINDOWS\Driver Cache\i386 + and store it somewhere (C:\temp is a good place) along with the usbser.inf + file. Then plug in the LPC176x and direct windows to the usbser driver. + Windows then creates an extra COMx port that you can open in a terminal + program, like hyperterminal. [Note for FreeRTOS users - the required .inf + file is included in the project directory.] + + Linux: + The device should be recognised automatically by the cdc_acm driver, + which creates a /dev/ttyACMx device file that acts just like a regular + serial port. + +*/ + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +#include +#include + +#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 ); + } + } +} + diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/type.h b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/type.h new file mode 100644 index 000000000..89d36850a --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/type.h @@ -0,0 +1,38 @@ +/***************************************************************************** + * type.h: Type definition Header file for NXP LPC17xx Family + * Microprocessors + * + * Copyright(C) 2008, NXP Semiconductor + * All rights reserved. + * + * History + * 2008.08.21 ver 1.00 Prelimnary version, first Release + * +******************************************************************************/ +#ifndef __TYPE_H__ +#define __TYPE_H__ + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (1) +#endif + +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; +typedef unsigned int BOOL; + +typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus; +typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; + +/* Pointer to Function returning Void (any number of parameters) */ +typedef void (*PFV)(); + +#endif /* __TYPE_H__ */ diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbapi.h b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbapi.h new file mode 100644 index 000000000..050f0d95b --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbapi.h @@ -0,0 +1,118 @@ +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + @file +*/ + +#include "usbstruct.h" // for TSetupPacket + +/************************************************************************* + USB configuration +**************************************************************************/ + +#define MAX_PACKET_SIZE0 64 /**< maximum packet size for EP 0 */ + +/************************************************************************* + USB hardware interface +**************************************************************************/ + +// endpoint status sent through callback +#define EP_STATUS_DATA (1<<0) /**< EP has data */ +#define EP_STATUS_STALLED (1<<1) /**< EP is stalled */ +#define EP_STATUS_SETUP (1<<2) /**< EP received setup packet */ +#define EP_STATUS_ERROR (1<<3) /**< EP data was overwritten by setup packet */ +#define EP_STATUS_NACKED (1<<4) /**< EP sent NAK */ + +// device status sent through callback +#define DEV_STATUS_CONNECT (1<<0) /**< device just got connected */ +#define DEV_STATUS_SUSPEND (1<<2) /**< device entered suspend state */ +#define DEV_STATUS_RESET (1<<4) /**< device just got reset */ + +// interrupt bits for NACK events in USBHwNakIntEnable +// (these bits conveniently coincide with the LPC176x USB controller bit) +#define INACK_CI (1<<1) /**< interrupt on NACK for control in */ +#define INACK_CO (1<<2) /**< interrupt on NACK for control out */ +#define INACK_II (1<<3) /**< interrupt on NACK for interrupt in */ +#define INACK_IO (1<<4) /**< interrupt on NACK for interrupt out */ +#define INACK_BI (1<<5) /**< interrupt on NACK for bulk in */ +#define INACK_BO (1<<6) /**< interrupt on NACK for bulk out */ + +BOOL USBHwInit (void); +void USBHwISR (void); + +void USBHwNakIntEnable (unsigned char bIntBits); + +void USBHwConnect (BOOL fConnect); + +void USBHwSetAddress (unsigned char bAddr); +void USBHwConfigDevice (BOOL fConfigured); + +// endpoint operations +void USBHwEPConfig (unsigned char bEP, unsigned short wMaxPacketSize); +int USBHwEPRead (unsigned char bEP, unsigned char *pbBuf, int iMaxLen); +int USBHwEPWrite (unsigned char bEP, unsigned char *pbBuf, int iLen); +void USBHwEPStall (unsigned char bEP, BOOL fStall); +unsigned char USBHwEPGetStatus (unsigned char bEP); + +/** Endpoint interrupt handler callback */ +typedef void (TFnEPIntHandler) (unsigned char bEP, unsigned char bEPStatus); +void USBHwRegisterEPIntHandler (unsigned char bEP, TFnEPIntHandler *pfnHandler); + +/** Device status handler callback */ +typedef void (TFnDevIntHandler) (unsigned char bDevStatus); +void USBHwRegisterDevIntHandler (TFnDevIntHandler *pfnHandler); + +/** Frame event handler callback */ +typedef void (TFnFrameHandler)(unsigned short wFrame); +void USBHwRegisterFrameHandler(TFnFrameHandler *pfnHandler); + + +/************************************************************************* + USB application interface +**************************************************************************/ + +// initialise the complete stack, including HW +BOOL USBInit(void); + +/** Request handler callback (standard, vendor, class) */ +typedef BOOL (TFnHandleRequest)(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData); +void USBRegisterRequestHandler(int iType, TFnHandleRequest *pfnHandler, unsigned char *pbDataStore); +void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler); + +/** Descriptor handler callback */ +typedef BOOL (TFnGetDescriptor)(unsigned short wTypeIndex, unsigned short wLangID, int *piLen, unsigned char **ppbData); + +/** Default standard request handler */ +BOOL USBHandleStandardRequest(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData); + +/** Default EP0 handler */ +void USBHandleControlTransfer(unsigned char bEP, unsigned char bEPStat); + +/** Descriptor handling */ +void USBRegisterDescriptors(const unsigned char *pabDescriptors); +BOOL USBGetDescriptor(unsigned short wTypeIndex, unsigned short wLangID, int *piLen, unsigned char **ppbData); diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbcontrol.c b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbcontrol.c new file mode 100644 index 000000000..6dd022c58 --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbcontrol.c @@ -0,0 +1,247 @@ +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +/** @file + Control transfer handler. + + This module handles control transfers and is normally installed on the + endpoint 0 callback. + + Control transfers can be of the following type: + 0 Standard; + 1 Class; + 2 Vendor; + 3 Reserved. + + A callback can be installed for each of these control transfers using + USBRegisterRequestHandler. + When an OUT request arrives, data is collected in the data store provided + with the USBRegisterRequestHandler call. When the transfer is done, the + callback is called. + When an IN request arrives, the callback is called immediately to either + put the control transfer data in the data store, or to get a pointer to + control transfer data. The data is then packetised and sent to the host. +*/ + +#include "usbdebug.h" + +#include "usbstruct.h" +#include "usbapi.h" + + + +#define MAX_CONTROL_SIZE 128 /**< maximum total size of control transfer data */ +#define MAX_REQ_HANDLERS 4 /**< standard, class, vendor, reserved */ + +static TSetupPacket Setup; /**< setup packet */ + +static unsigned char *pbData; /**< pointer to data buffer */ +static int iResidue; /**< remaining bytes in buffer */ +static int iLen; /**< total length of control transfer */ + +/** Array of installed request handler callbacks */ +static TFnHandleRequest *apfnReqHandlers[4] = {NULL, NULL, NULL, NULL}; +/** Array of installed request data pointers */ +static unsigned char *apbDataStore[4] = {NULL, NULL, NULL, NULL}; + +/** + Local function to handle a request by calling one of the installed + request handlers. + + In case of data going from host to device, the data is at *ppbData. + In case of data going from device to host, the handler can either + choose to write its data at *ppbData or update the data pointer. + + @param [in] pSetup The setup packet + @param [in,out] *piLen Pointer to data length + @param [in,out] ppbData Data buffer. + + @return TRUE if the request was handles successfully + */ +static BOOL _HandleRequest(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData) +{ + TFnHandleRequest *pfnHandler; + int iType; + + iType = REQTYPE_GET_TYPE(pSetup->bmRequestType); + pfnHandler = apfnReqHandlers[iType]; + if (pfnHandler == NULL) { + DBG("No handler for reqtype %d\n", iType); + return FALSE; + } + + return pfnHandler(pSetup, piLen, ppbData); +} + + +/** + Local function to stall the control endpoint + + @param [in] bEPStat Endpoint status + */ +static void StallControlPipe(unsigned char bEPStat) +{ + unsigned char *pb; + int i; + + ( void ) bEPStat; + USBHwEPStall(0x80, TRUE); + +// dump setup packet + DBG("STALL on ["); + pb = (unsigned char *)&Setup; + for (i = 0; i < 8; i++) { + DBG(" %02x", *pb++); + } + DBG("] stat=%x\n", bEPStat); +} + + +/** + Sends next chunk of data (possibly 0 bytes) to host + */ +static void DataIn(void) +{ + int iChunk; + + if( MAX_PACKET_SIZE0 < iResidue ) + { + iChunk = MAX_PACKET_SIZE0; + } + else + { + iChunk = iResidue; + } + + USBHwEPWrite(0x80, pbData, iChunk); + pbData += iChunk; + iResidue -= iChunk; +} + + +/** + * Handles IN/OUT transfers on EP0 + * + * @param [in] bEP Endpoint address + * @param [in] bEPStat Endpoint status + */ +void USBHandleControlTransfer(unsigned char bEP, unsigned char bEPStat) +{ + int iChunk, iType; + + if (bEP == 0x00) { + // OUT transfer + if (bEPStat & EP_STATUS_SETUP) { + // setup packet, reset request message state machine + USBHwEPRead(0x00, (unsigned char *)&Setup, sizeof(Setup)); + DBG("S%x", Setup.bRequest); + + // defaults for data pointer and residue + iType = REQTYPE_GET_TYPE(Setup.bmRequestType); + pbData = apbDataStore[iType]; + iResidue = Setup.wLength; + iLen = Setup.wLength; + + if ((Setup.wLength == 0) || + (REQTYPE_GET_DIR(Setup.bmRequestType) == REQTYPE_DIR_TO_HOST)) { + // ask installed handler to process request + if (!_HandleRequest(&Setup, &iLen, &pbData)) { + DBG("_HandleRequest1 failed\n"); + StallControlPipe(bEPStat); + return; + } + // send smallest of requested and offered length + if( iLen < Setup.wLength ) + { + iResidue = iLen; + } + else + { + iResidue = Setup.wLength; + } + + // send first part (possibly a zero-length status message) + DataIn(); + } + } + else { + if (iResidue > 0) { + // store data + iChunk = USBHwEPRead(0x00, pbData, iResidue); + if (iChunk < 0) { + StallControlPipe(bEPStat); + return; + } + pbData += iChunk; + iResidue -= iChunk; + if (iResidue == 0) { + // received all, send data to handler + iType = REQTYPE_GET_TYPE(Setup.bmRequestType); + pbData = apbDataStore[iType]; + if (!_HandleRequest(&Setup, &iLen, &pbData)) { + DBG("_HandleRequest2 failed\n"); + StallControlPipe(bEPStat); + return; + } + // send status to host + DataIn(); + } + } + else { + // absorb zero-length status message + iChunk = USBHwEPRead(0x00, NULL, 0); + DBG(iChunk > 0 ? "?" : ""); + } + } + } + else if (bEP == 0x80) { + // IN transfer + // send more data if available (possibly a 0-length packet) + DataIn(); + } + else { + ASSERT(FALSE); + } +} + + +/** + Registers a callback for handling requests + + @param [in] iType Type of request, e.g. REQTYPE_TYPE_STANDARD + @param [in] *pfnHandler Callback function pointer + @param [in] *pbDataStore Data storage area for this type of request + */ +void USBRegisterRequestHandler(int iType, TFnHandleRequest *pfnHandler, unsigned char *pbDataStore) +{ + ASSERT(iType >= 0); + ASSERT(iType < 4); + apfnReqHandlers[iType] = pfnHandler; + apbDataStore[iType] = pbDataStore; +} + diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbdebug.h b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbdebug.h new file mode 100644 index 000000000..4a14862e6 --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbdebug.h @@ -0,0 +1,41 @@ +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +// CodeRed - comment out this printf, as will use real one from stdio.h +// to implement output via semihosting + +//int printf(const char *format, ...); +# include + +#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 + diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbhw_lpc.c b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbhw_lpc.c new file mode 100644 index 000000000..e9bd46015 --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbhw_lpc.c @@ -0,0 +1,521 @@ +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +/** @file + USB hardware layer + */ + + +#include "usbdebug.h" +#include "usbhw_lpc.h" +#include "usbapi.h" + +/** Installed device interrupt handler */ +static TFnDevIntHandler *_pfnDevIntHandler = NULL; +/** Installed endpoint interrupt handlers */ +static TFnEPIntHandler *_apfnEPIntHandlers[16]; +/** Installed frame interrupt handlers */ +static TFnFrameHandler *_pfnFrameHandler = NULL; + +/** convert from endpoint address to endpoint index */ +#define EP2IDX(bEP) ((((bEP)&0xF)<<1)|(((bEP)&0x80)>>7)) +/** convert from endpoint index to endpoint address */ +#define IDX2EP(idx) ((((idx)<<7)&0x80)|(((idx)>>1)&0xF)) + + + +/** + Local function to wait for a device interrupt (and clear it) + + @param [in] dwIntr Bitmask of interrupts to wait for + */ +static void Wait4DevInt(unsigned long dwIntr) +{ + // wait for specific interrupt + while ((USB->USBDevIntSt & dwIntr) != dwIntr); + // clear the interrupt bits + USB->USBDevIntClr = dwIntr; +} + + +/** + Local function to send a command to the USB protocol engine + + @param [in] bCmd Command to send + */ +static void USBHwCmd(unsigned char bCmd) +{ + // clear CDFULL/CCEMTY + USB->USBDevIntClr = CDFULL | CCEMTY; + // write command code + USB->USBCmdCode = 0x00000500 | (bCmd << 16); + Wait4DevInt(CCEMTY); +} + + +/** + Local function to send a command + data to the USB protocol engine + + @param [in] bCmd Command to send + @param [in] bData Data to send + */ +static void USBHwCmdWrite(unsigned char bCmd, unsigned short bData) +{ + // write command code + USBHwCmd(bCmd); + + // write command data + USB->USBCmdCode = 0x00000100 | (bData << 16); + Wait4DevInt(CCEMTY); +} + + +/** + Local function to send a command to the USB protocol engine and read data + + @param [in] bCmd Command to send + + @return the data + */ +static unsigned char USBHwCmdRead(unsigned char bCmd) +{ + // write command code + USBHwCmd(bCmd); + + // get data + USB->USBCmdCode = 0x00000200 | (bCmd << 16); + Wait4DevInt(CDFULL); + return USB->USBCmdData; +} + + +/** + 'Realizes' an endpoint, meaning that buffer space is reserved for + it. An endpoint needs to be realised before it can be used. + + From experiments, it appears that a USB reset causes USBReEP to + re-initialise to 3 (= just the control endpoints). + However, a USB bus reset does not disturb the USBMaxPSize settings. + + @param [in] idx Endpoint index + @param [in] wMaxPSize Maximum packet size for this endpoint + */ +static void USBHwEPRealize(int idx, unsigned short wMaxPSize) +{ + USB->USBReEP |= (1 << idx); + USB->USBEpInd = idx; + USB->USBMaxPSize = wMaxPSize; + Wait4DevInt(EP_RLZED); +} + + +/** + Enables or disables an endpoint + + @param [in] idx Endpoint index + @param [in] fEnable TRUE to enable, FALSE to disable + */ +static void USBHwEPEnable(int idx, BOOL fEnable) +{ + USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fEnable ? 0 : EP_DA); +} + + +/** + Configures an endpoint and enables it + + @param [in] bEP Endpoint number + @param [in] wMaxPacketSize Maximum packet size for this EP + */ +void USBHwEPConfig(unsigned char bEP, unsigned short wMaxPacketSize) +{ + int idx; + + idx = EP2IDX(bEP); + + // realise EP + USBHwEPRealize(idx, wMaxPacketSize); + + // enable EP + USBHwEPEnable(idx, TRUE); +} + + +/** + Registers an endpoint event callback + + @param [in] bEP Endpoint number + @param [in] pfnHandler Callback function + */ +void USBHwRegisterEPIntHandler(unsigned char bEP, TFnEPIntHandler *pfnHandler) +{ + int idx; + + idx = EP2IDX(bEP); + + ASSERT(idx<32); + + /* add handler to list of EP handlers */ + _apfnEPIntHandlers[idx / 2] = pfnHandler; + + /* enable EP interrupt */ + USB->USBEpIntEn |= (1 << idx); + USB->USBDevIntEn |= EP_SLOW; + + DBG("Registered handler for EP 0x%x\n", bEP); +} + + +/** + Registers an device status callback + + @param [in] pfnHandler Callback function + */ +void USBHwRegisterDevIntHandler(TFnDevIntHandler *pfnHandler) +{ + _pfnDevIntHandler = pfnHandler; + + // enable device interrupt + USB->USBDevIntEn |= DEV_STAT; + + DBG("Registered handler for device status\n"); +} + + +/** + Registers the frame callback + + @param [in] pfnHandler Callback function + */ +void USBHwRegisterFrameHandler(TFnFrameHandler *pfnHandler) +{ + _pfnFrameHandler = pfnHandler; + + // enable device interrupt + USB->USBDevIntEn |= FRAME; + + DBG("Registered handler for frame\n"); +} + + +/** + Sets the USB address. + + @param [in] bAddr Device address to set + */ +void USBHwSetAddress(unsigned char bAddr) +{ + USBHwCmdWrite(CMD_DEV_SET_ADDRESS, DEV_EN | bAddr); +} + + +/** + Connects or disconnects from the USB bus + + @param [in] fConnect If TRUE, connect, otherwise disconnect + */ +void USBHwConnect(BOOL fConnect) +{ + USBHwCmdWrite(CMD_DEV_STATUS, fConnect ? CON : 0); +} + + +/** + Enables interrupt on NAK condition + + For IN endpoints a NAK is generated when the host wants to read data + from the device, but none is available in the endpoint buffer. + For OUT endpoints a NAK is generated when the host wants to write data + to the device, but the endpoint buffer is still full. + + The endpoint interrupt handlers can distinguish regular (ACK) interrupts + from NAK interrupt by checking the bits in their bEPStatus argument. + + @param [in] bIntBits Bitmap indicating which NAK interrupts to enable + */ +void USBHwNakIntEnable(unsigned char bIntBits) +{ + USBHwCmdWrite(CMD_DEV_SET_MODE, bIntBits); +} + + +/** + Gets the status from a specific endpoint. + + @param [in] bEP Endpoint number + @return Endpoint status byte (containing EP_STATUS_xxx bits) + */ +unsigned char USBHwEPGetStatus(unsigned char bEP) +{ + int idx = EP2IDX(bEP); + + return USBHwCmdRead(CMD_EP_SELECT | idx); +} + + +/** + Sets the stalled property of an endpoint + + @param [in] bEP Endpoint number + @param [in] fStall TRUE to stall, FALSE to unstall + */ +void USBHwEPStall(unsigned char bEP, BOOL fStall) +{ + int idx = EP2IDX(bEP); + + USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fStall ? EP_ST : 0); +} + + +/** + Writes data to an endpoint buffer + + @param [in] bEP Endpoint number + @param [in] pbBuf Endpoint data + @param [in] iLen Number of bytes to write + + @return TRUE if the data was successfully written or <0 in case of error. +*/ +int USBHwEPWrite(unsigned char bEP, unsigned char *pbBuf, int iLen) +{ + int idx; + + idx = EP2IDX(bEP); + + // set write enable for specific endpoint + USB->USBCtrl = WR_EN | ((bEP & 0xF) << 2); + + // set packet length + USB->USBTxPLen = iLen; + + // write data + while (USB->USBCtrl & WR_EN) { + USB->USBTxData = (pbBuf[3] << 24) | (pbBuf[2] << 16) | (pbBuf[1] << 8) | pbBuf[0]; + pbBuf += 4; + } + + // select endpoint and validate buffer + USBHwCmd(CMD_EP_SELECT | idx); + USBHwCmd(CMD_EP_VALIDATE_BUFFER); + + return iLen; +} + + +/** + Reads data from an endpoint buffer + + @param [in] bEP Endpoint number + @param [in] pbBuf Endpoint data + @param [in] iMaxLen Maximum number of bytes to read + + @return the number of bytes available in the EP (possibly more than iMaxLen), + or <0 in case of error. + */ +int USBHwEPRead(unsigned char bEP, unsigned char *pbBuf, int iMaxLen) +{ + unsigned int i, idx; + unsigned long dwData, dwLen; + + idx = EP2IDX(bEP); + + // set read enable bit for specific endpoint + USB->USBCtrl = RD_EN | ((bEP & 0xF) << 2); + + // wait for PKT_RDY + do { + dwLen = USB->USBRxPLen; + } while ((dwLen & PKT_RDY) == 0); + + // packet valid? + if ((dwLen & DV) == 0) { + return -1; + } + + // get length + dwLen &= PKT_LNGTH_MASK; + + // get data + dwData = 0; + for (i = 0; i < dwLen; i++) { + if ((i % 4) == 0) { + dwData = USB->USBRxData; + } + if ((pbBuf != NULL) && ((int)i < iMaxLen)) { + pbBuf[i] = dwData & 0xFF; + } + dwData >>= 8; + } + + // make sure RD_EN is clear + USB->USBCtrl = 0; + + // select endpoint and clear buffer + USBHwCmd(CMD_EP_SELECT | idx); + USBHwCmd(CMD_EP_CLEAR_BUFFER); + + return dwLen; +} + + +/** + Sets the 'configured' state. + + All registered endpoints are 'realised' and enabled, and the + 'configured' bit is set in the device status register. + + @param [in] fConfigured If TRUE, configure device, else unconfigure + */ +void USBHwConfigDevice(BOOL fConfigured) +{ + // set configured bit + USBHwCmdWrite(CMD_DEV_CONFIG, fConfigured ? CONF_DEVICE : 0); +} + + +/** + USB interrupt handler + + @todo Get all 11 bits of frame number instead of just 8 + + Endpoint interrupts are mapped to the slow interrupt + */ +void USBHwISR(void) +{ + unsigned long dwStatus; + unsigned long dwIntBit; + unsigned char bEPStat, bDevStat, bStat; + int i; + unsigned short wFrame; + + // handle device interrupts + dwStatus = USB->USBDevIntSt; + + // frame interrupt + if (dwStatus & FRAME) { + // clear int + USB->USBDevIntClr = FRAME; + // call handler + if (_pfnFrameHandler != NULL) { + wFrame = USBHwCmdRead(CMD_DEV_READ_CUR_FRAME_NR); + _pfnFrameHandler(wFrame); + } + } + + // device status interrupt + if (dwStatus & DEV_STAT) { + /* Clear DEV_STAT interrupt before reading DEV_STAT register. + This prevents corrupted device status reads, see + LPC2148 User manual revision 2, 25 july 2006. + */ + USB->USBDevIntClr = DEV_STAT; + bDevStat = USBHwCmdRead(CMD_DEV_STATUS); + if (bDevStat & (CON_CH | SUS_CH | RST)) { + // convert device status into something HW independent + bStat = ((bDevStat & CON) ? DEV_STATUS_CONNECT : 0) | + ((bDevStat & SUS) ? DEV_STATUS_SUSPEND : 0) | + ((bDevStat & RST) ? DEV_STATUS_RESET : 0); + // call handler + if (_pfnDevIntHandler != NULL) { + _pfnDevIntHandler(bStat); + } + } + } + + // endpoint interrupt + if (dwStatus & EP_SLOW) { + // clear EP_SLOW + USB->USBDevIntClr = EP_SLOW; + // check all endpoints + for (i = 0; i < 32; i++) { + dwIntBit = (1 << i); + if (USB->USBEpIntSt & dwIntBit) { + // clear int (and retrieve status) + USB->USBEpIntClr = dwIntBit; + Wait4DevInt(CDFULL); + bEPStat = USB->USBCmdData; + // convert EP pipe stat into something HW independent + bStat = ((bEPStat & EPSTAT_FE) ? EP_STATUS_DATA : 0) | + ((bEPStat & EPSTAT_ST) ? EP_STATUS_STALLED : 0) | + ((bEPStat & EPSTAT_STP) ? EP_STATUS_SETUP : 0) | + ((bEPStat & EPSTAT_EPN) ? EP_STATUS_NACKED : 0) | + ((bEPStat & EPSTAT_PO) ? EP_STATUS_ERROR : 0); + // call handler + if (_apfnEPIntHandlers[i / 2] != NULL) { + _apfnEPIntHandlers[i / 2](IDX2EP(i), bStat); + } + } + } + } +} + + + +/** + Initialises the USB hardware + + + @return TRUE if the hardware was successfully initialised + */ +BOOL USBHwInit(void) +{ + // P2.9 -> USB_CONNECT + PINCON->PINSEL4 &= ~0x000C0000; + PINCON->PINSEL4 |= 0x00040000; + + // P1.18 -> USB_UP_LED + // P1.30 -> VBUS + PINCON->PINSEL3 &= ~0x30000030; + PINCON->PINSEL3 |= 0x20000010; + + // P0.29 -> USB_D+ + // P0.30 -> USB_D- + PINCON->PINSEL1 &= ~0x3C000000; + PINCON->PINSEL1 |= 0x14000000; + + // enable PUSB + SC->PCONP |= (1 << 31); + + USB->OTGClkCtrl = 0x12; /* Dev clock, AHB clock enable */ + while ((USB->OTGClkSt & 0x12) != 0x12); + + // disable/clear all interrupts for now + USB->USBDevIntEn = 0; + USB->USBDevIntClr = 0xFFFFFFFF; + USB->USBDevIntPri = 0; + + USB->USBEpIntEn = 0; + USB->USBEpIntClr = 0xFFFFFFFF; + USB->USBEpIntPri = 0; + + // by default, only ACKs generate interrupts + USBHwNakIntEnable(0); + + return TRUE; +} + diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbhw_lpc.h b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbhw_lpc.h new file mode 100644 index 000000000..2a4de7949 --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbhw_lpc.h @@ -0,0 +1,149 @@ +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +/** + Hardware definitions for the LPC176x USB controller + + These are private to the usbhw module +*/ + +// CodeRed - pull in defines from NXP header file +//#include "NXP\LPC17xx\LPC17xx.h" +#include "LPC17xx.h" + + +// CodeRed - these registers have been renamed on LPC176x +#define USBReEP USBReEp +#define OTG_CLK_CTRL USBClkCtrl +#define OTG_CLK_STAT USBClkSt + +/* USBIntSt bits */ +#define USB_INT_REQ_LP (1<<0) +#define USB_INT_REQ_HP (1<<1) +#define USB_INT_REQ_DMA (1<<2) +#define USB_need_clock (1<<8) +#define EN_USB_BITS (1<<31) + +/* USBDevInt... bits */ +#define FRAME (1<<0) +#define EP_FAST (1<<1) +#define EP_SLOW (1<<2) +#define DEV_STAT (1<<3) +#define CCEMTY (1<<4) +#define CDFULL (1<<5) +#define RxENDPKT (1<<6) +#define TxENDPKT (1<<7) +#define EP_RLZED (1<<8) +#define ERR_INT (1<<9) + +/* USBRxPLen bits */ +#define PKT_LNGTH (1<<0) +#define PKT_LNGTH_MASK 0x3FF +#define DV (1<<10) +#define PKT_RDY (1<<11) + +/* USBCtrl bits */ +#define RD_EN (1<<0) +#define WR_EN (1<<1) +#define LOG_ENDPOINT (1<<2) + +/* protocol engine command codes */ + /* device commands */ +#define CMD_DEV_SET_ADDRESS 0xD0 +#define CMD_DEV_CONFIG 0xD8 +#define CMD_DEV_SET_MODE 0xF3 +#define CMD_DEV_READ_CUR_FRAME_NR 0xF5 +#define CMD_DEV_READ_TEST_REG 0xFD +#define CMD_DEV_STATUS 0xFE /* read/write */ +#define CMD_DEV_GET_ERROR_CODE 0xFF +#define CMD_DEV_READ_ERROR_STATUS 0xFB + /* endpoint commands */ +#define CMD_EP_SELECT 0x00 +#define CMD_EP_SELECT_CLEAR 0x40 +#define CMD_EP_SET_STATUS 0x40 +#define CMD_EP_CLEAR_BUFFER 0xF2 +#define CMD_EP_VALIDATE_BUFFER 0xFA + +/* set address command */ +#define DEV_ADDR (1<<0) +#define DEV_EN (1<<7) + +/* configure device command */ +#define CONF_DEVICE (1<<0) + +/* set mode command */ +#define AP_CLK (1<<0) +#define INAK_CI (1<<1) +#define INAK_CO (1<<2) +#define INAK_II (1<<3) +#define INAK_IO (1<<4) +#define INAK_BI (1<<5) +#define INAK_BO (1<<6) + +/* set get device status command */ +#define CON (1<<0) +#define CON_CH (1<<1) +#define SUS (1<<2) +#define SUS_CH (1<<3) +#define RST (1<<4) + +/* get error code command */ +// ... + +/* Select Endpoint command read bits */ +#define EPSTAT_FE (1<<0) +#define EPSTAT_ST (1<<1) +#define EPSTAT_STP (1<<2) +#define EPSTAT_PO (1<<3) +#define EPSTAT_EPN (1<<4) +#define EPSTAT_B1FULL (1<<5) +#define EPSTAT_B2FULL (1<<6) + +/* CMD_EP_SET_STATUS command */ +#define EP_ST (1<<0) +#define EP_DA (1<<5) +#define EP_RF_MO (1<<6) +#define EP_CND_ST (1<<7) + +/* read error status command */ +#define PID_ERR (1<<0) +#define UEPKT (1<<1) +#define DCRC (1<<2) +#define TIMEOUT (1<<3) +#define EOP (1<<4) +#define B_OVRN (1<<5) +#define BTSTF (1<<6) +#define TGL_ERR (1<<7) + + + + + + + + diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbinit.c b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbinit.c new file mode 100644 index 000000000..8bb718317 --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbinit.c @@ -0,0 +1,82 @@ +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +/** @file + USB stack initialisation + */ + + +#include "usbdebug.h" +#include "usbapi.h" + + +/** data storage area for standard requests */ +static unsigned char abStdReqData[8]; + + +/** + USB reset handler + + @param [in] bDevStatus Device status + */ +static void HandleUsbReset(unsigned char bDevStatus) +{ + if (bDevStatus & DEV_STATUS_RESET) { + DBG("\n!"); + } +} + + +/** + Initialises the USB hardware and sets up the USB stack by + installing default callbacks. + + @return TRUE if initialisation was successful + */ +BOOL USBInit(void) +{ + // init hardware + USBHwInit(); + + // register bus reset handler + USBHwRegisterDevIntHandler(HandleUsbReset); + + // register control transfer handler on EP0 + USBHwRegisterEPIntHandler(0x00, USBHandleControlTransfer); + USBHwRegisterEPIntHandler(0x80, USBHandleControlTransfer); + + // setup control endpoints + USBHwEPConfig(0x00, MAX_PACKET_SIZE0); + USBHwEPConfig(0x80, MAX_PACKET_SIZE0); + + // register standard request handler + USBRegisterRequestHandler(REQTYPE_TYPE_STANDARD, USBHandleStandardRequest, abStdReqData); + + return TRUE; +} + diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbstdreq.c b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbstdreq.c new file mode 100644 index 000000000..cb2f55a09 --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbstdreq.c @@ -0,0 +1,431 @@ +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +/** @file + Standard request handler. + + This modules handles the 'chapter 9' processing, specifically the + standard device requests in table 9-3 from the universal serial bus + specification revision 2.0 + + Specific types of devices may specify additional requests (for example + HID devices add a GET_DESCRIPTOR request for interfaces), but they + will not be part of this module. + + @todo some requests have to return a request error if device not configured: + @todo GET_INTERFACE, GET_STATUS, SET_INTERFACE, SYNCH_FRAME + @todo this applies to the following if endpoint != 0: + @todo SET_FEATURE, GET_FEATURE +*/ + +#include "usbdebug.h" +#include "usbstruct.h" +#include "usbapi.h" + +#define MAX_DESC_HANDLERS 4 /**< device, interface, endpoint, other */ + + +/* general descriptor field offsets */ +#define DESC_bLength 0 /**< length offset */ +#define DESC_bDescriptorType 1 /**< descriptor type offset */ + +/* config descriptor field offsets */ +#define CONF_DESC_wTotalLength 2 /**< total length offset */ +#define CONF_DESC_bConfigurationValue 5 /**< configuration value offset */ +#define CONF_DESC_bmAttributes 7 /**< configuration characteristics */ + +/* interface descriptor field offsets */ +#define INTF_DESC_bAlternateSetting 3 /**< alternate setting offset */ + +/* endpoint descriptor field offsets */ +#define ENDP_DESC_bEndpointAddress 2 /**< endpoint address offset */ +#define ENDP_DESC_wMaxPacketSize 4 /**< maximum packet size offset */ + + +/** Currently selected configuration */ +static unsigned char bConfiguration = 0; +/** Installed custom request handler */ +static TFnHandleRequest *pfnHandleCustomReq = NULL; +/** Pointer to registered descriptors */ +static const unsigned char *pabDescrip = NULL; + + +/** + Registers a pointer to a descriptor block containing all descriptors + for the device. + + @param [in] pabDescriptors The descriptor byte array + */ +void USBRegisterDescriptors(const unsigned char *pabDescriptors) +{ + pabDescrip = pabDescriptors; +} + + +/** + Parses the list of installed USB descriptors and attempts to find + the specified USB descriptor. + + @param [in] wTypeIndex Type and index of the descriptor + @param [in] wLangID Language ID of the descriptor (currently unused) + @param [out] *piLen Descriptor length + @param [out] *ppbData Descriptor data + + @return TRUE if the descriptor was found, FALSE otherwise + */ +BOOL USBGetDescriptor(unsigned short wTypeIndex, unsigned short wLangID, int *piLen, unsigned char **ppbData) +{ + unsigned char bType, bIndex; + unsigned char *pab; + int iCurIndex; + + ( void ) wLangID; + ASSERT(pabDescrip != NULL); + + bType = GET_DESC_TYPE(wTypeIndex); + bIndex = GET_DESC_INDEX(wTypeIndex); + + pab = (unsigned char *)pabDescrip; + iCurIndex = 0; + + while (pab[DESC_bLength] != 0) { + if (pab[DESC_bDescriptorType] == bType) { + if (iCurIndex == bIndex) { + // set data pointer + *ppbData = pab; + // get length from structure + if (bType == DESC_CONFIGURATION) { + // configuration descriptor is an exception, length is at offset 2 and 3 + *piLen = (pab[CONF_DESC_wTotalLength]) | + (pab[CONF_DESC_wTotalLength + 1] << 8); + } + else { + // normally length is at offset 0 + *piLen = pab[DESC_bLength]; + } + return TRUE; + } + iCurIndex++; + } + // skip to next descriptor + pab += pab[DESC_bLength]; + } + // nothing found + DBG("Desc %x not found!\n", wTypeIndex); + return FALSE; +} + + +/** + Configures the device according to the specified configuration index and + alternate setting by parsing the installed USB descriptor list. + A configuration index of 0 unconfigures the device. + + @param [in] bConfigIndex Configuration index + @param [in] bAltSetting Alternate setting number + + @todo function always returns TRUE, add stricter checking? + + @return TRUE if successfully configured, FALSE otherwise + */ +static BOOL USBSetConfiguration(unsigned char bConfigIndex, unsigned char bAltSetting) +{ + unsigned char *pab; + unsigned char bCurConfig, bCurAltSetting; + unsigned char bEP; + unsigned short wMaxPktSize; + + ASSERT(pabDescrip != NULL); + + if (bConfigIndex == 0) { + // unconfigure device + USBHwConfigDevice(FALSE); + } + else { + // configure endpoints for this configuration/altsetting + pab = (unsigned char *)pabDescrip; + bCurConfig = 0xFF; + bCurAltSetting = 0xFF; + + while (pab[DESC_bLength] != 0) { + + switch (pab[DESC_bDescriptorType]) { + + case DESC_CONFIGURATION: + // remember current configuration index + bCurConfig = pab[CONF_DESC_bConfigurationValue]; + break; + + case DESC_INTERFACE: + // remember current alternate setting + bCurAltSetting = pab[INTF_DESC_bAlternateSetting]; + break; + + case DESC_ENDPOINT: + if ((bCurConfig == bConfigIndex) && + (bCurAltSetting == bAltSetting)) { + // endpoint found for desired config and alternate setting + bEP = pab[ENDP_DESC_bEndpointAddress]; + wMaxPktSize = (pab[ENDP_DESC_wMaxPacketSize]) | + (pab[ENDP_DESC_wMaxPacketSize + 1] << 8); + // configure endpoint + USBHwEPConfig(bEP, wMaxPktSize); + } + break; + + default: + break; + } + // skip to next descriptor + pab += pab[DESC_bLength]; + } + + // configure device + USBHwConfigDevice(TRUE); + } + + return TRUE; +} + + +/** + Local function to handle a standard device request + + @param [in] pSetup The setup packet + @param [in,out] *piLen Pointer to data length + @param [in,out] ppbData Data buffer. + + @return TRUE if the request was handled successfully + */ +static BOOL HandleStdDeviceReq(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData) +{ + unsigned char *pbData = *ppbData; + + switch (pSetup->bRequest) { + + case REQ_GET_STATUS: + // bit 0: self-powered + // bit 1: remote wakeup = not supported + pbData[0] = 0; + pbData[1] = 0; + *piLen = 2; + break; + + case REQ_SET_ADDRESS: + USBHwSetAddress(pSetup->wValue); + break; + + case REQ_GET_DESCRIPTOR: + DBG("D%x", pSetup->wValue); + return USBGetDescriptor(pSetup->wValue, pSetup->wIndex, piLen, ppbData); + + case REQ_GET_CONFIGURATION: + // indicate if we are configured + pbData[0] = bConfiguration; + *piLen = 1; + break; + + case REQ_SET_CONFIGURATION: + if (!USBSetConfiguration(pSetup->wValue & 0xFF, 0)) { + DBG("USBSetConfiguration failed!\n"); + return FALSE; + } + // configuration successful, update current configuration + bConfiguration = pSetup->wValue & 0xFF; + break; + + case REQ_CLEAR_FEATURE: + case REQ_SET_FEATURE: + if (pSetup->wValue == FEA_REMOTE_WAKEUP) { + // put DEVICE_REMOTE_WAKEUP code here + } + if (pSetup->wValue == FEA_TEST_MODE) { + // put TEST_MODE code here + } + return FALSE; + + case REQ_SET_DESCRIPTOR: + DBG("Device req %d not implemented\n", pSetup->bRequest); + return FALSE; + + default: + DBG("Illegal device req %d\n", pSetup->bRequest); + return FALSE; + } + + return TRUE; +} + + +/** + Local function to handle a standard interface request + + @param [in] pSetup The setup packet + @param [in,out] *piLen Pointer to data length + @param [in] ppbData Data buffer. + + @return TRUE if the request was handled successfully + */ +static BOOL HandleStdInterfaceReq(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData) +{ + unsigned char *pbData = *ppbData; + + switch (pSetup->bRequest) { + + case REQ_GET_STATUS: + // no bits specified + pbData[0] = 0; + pbData[1] = 0; + *piLen = 2; + break; + + case REQ_CLEAR_FEATURE: + case REQ_SET_FEATURE: + // not defined for interface + return FALSE; + + case REQ_GET_INTERFACE: // TODO use bNumInterfaces + // there is only one interface, return n-1 (= 0) + pbData[0] = 0; + *piLen = 1; + break; + + case REQ_SET_INTERFACE: // TODO use bNumInterfaces + // there is only one interface (= 0) + if (pSetup->wValue != 0) { + return FALSE; + } + *piLen = 0; + break; + + default: + DBG("Illegal interface req %d\n", pSetup->bRequest); + return FALSE; + } + + return TRUE; +} + + +/** + Local function to handle a standard endpoint request + + @param [in] pSetup The setup packet + @param [in,out] *piLen Pointer to data length + @param [in] ppbData Data buffer. + + @return TRUE if the request was handled successfully + */ +static BOOL HandleStdEndPointReq(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData) +{ + unsigned char *pbData = *ppbData; + + switch (pSetup->bRequest) { + case REQ_GET_STATUS: + // bit 0 = endpointed halted or not + pbData[0] = (USBHwEPGetStatus(pSetup->wIndex) & EP_STATUS_STALLED) ? 1 : 0; + pbData[1] = 0; + *piLen = 2; + break; + + case REQ_CLEAR_FEATURE: + if (pSetup->wValue == FEA_ENDPOINT_HALT) { + // clear HALT by unstalling + USBHwEPStall(pSetup->wIndex, FALSE); + break; + } + // only ENDPOINT_HALT defined for endpoints + return FALSE; + + case REQ_SET_FEATURE: + if (pSetup->wValue == FEA_ENDPOINT_HALT) { + // set HALT by stalling + USBHwEPStall(pSetup->wIndex, TRUE); + break; + } + // only ENDPOINT_HALT defined for endpoints + return FALSE; + + case REQ_SYNCH_FRAME: + DBG("EP req %d not implemented\n", pSetup->bRequest); + return FALSE; + + default: + DBG("Illegal EP req %d\n", pSetup->bRequest); + return FALSE; + } + + return TRUE; +} + + +/** + Default handler for standard ('chapter 9') requests + + If a custom request handler was installed, this handler is called first. + + @param [in] pSetup The setup packet + @param [in,out] *piLen Pointer to data length + @param [in] ppbData Data buffer. + + @return TRUE if the request was handled successfully + */ +BOOL USBHandleStandardRequest(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData) +{ + // try the custom request handler first + if ((pfnHandleCustomReq != NULL) && pfnHandleCustomReq(pSetup, piLen, ppbData)) { + return TRUE; + } + + switch (REQTYPE_GET_RECIP(pSetup->bmRequestType)) { + case REQTYPE_RECIP_DEVICE: return HandleStdDeviceReq(pSetup, piLen, ppbData); + case REQTYPE_RECIP_INTERFACE: return HandleStdInterfaceReq(pSetup, piLen, ppbData); + case REQTYPE_RECIP_ENDPOINT: return HandleStdEndPointReq(pSetup, piLen, ppbData); + default: return FALSE; + } +} + + +/** + Registers a callback for custom device requests + + In USBHandleStandardRequest, the custom request handler gets a first + chance at handling the request before it is handed over to the 'chapter 9' + request handler. + + This can be used for example in HID devices, where a REQ_GET_DESCRIPTOR + request is sent to an interface, which is not covered by the 'chapter 9' + specification. + + @param [in] pfnHandler Callback function pointer + */ +void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler) +{ + pfnHandleCustomReq = pfnHandler; +} + diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbstruct.h b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbstruct.h new file mode 100644 index 000000000..113e2fef4 --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/LPCUSB/usbstruct.h @@ -0,0 +1,119 @@ +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +/** + Definitions of structures of standard USB packets +*/ + +#ifndef _USBSTRUCT_H_ +#define _USBSTRUCT_H_ + +// CodeRed - include the LPCUSB type.h file rather than NXP one directly +#include "type.h" + +/** setup packet definitions */ +typedef struct { + unsigned char bmRequestType; /**< characteristics of the specific request */ + unsigned char bRequest; /**< specific request */ + unsigned short wValue; /**< request specific parameter */ + unsigned short wIndex; /**< request specific parameter */ + unsigned short wLength; /**< length of data transfered in data phase */ +} TSetupPacket; + + +#define REQTYPE_GET_DIR(x) (((x)>>7)&0x01) +#define REQTYPE_GET_TYPE(x) (((x)>>5)&0x03) +#define REQTYPE_GET_RECIP(x) ((x)&0x1F) + +#define REQTYPE_DIR_TO_DEVICE 0 +#define REQTYPE_DIR_TO_HOST 1 + +#define REQTYPE_TYPE_STANDARD 0 +#define REQTYPE_TYPE_CLASS 1 +#define REQTYPE_TYPE_VENDOR 2 +#define REQTYPE_TYPE_RESERVED 3 + +#define REQTYPE_RECIP_DEVICE 0 +#define REQTYPE_RECIP_INTERFACE 1 +#define REQTYPE_RECIP_ENDPOINT 2 +#define REQTYPE_RECIP_OTHER 3 + +/* standard requests */ +#define REQ_GET_STATUS 0x00 +#define REQ_CLEAR_FEATURE 0x01 +#define REQ_SET_FEATURE 0x03 +#define REQ_SET_ADDRESS 0x05 +#define REQ_GET_DESCRIPTOR 0x06 +#define REQ_SET_DESCRIPTOR 0x07 +#define REQ_GET_CONFIGURATION 0x08 +#define REQ_SET_CONFIGURATION 0x09 +#define REQ_GET_INTERFACE 0x0A +#define REQ_SET_INTERFACE 0x0B +#define REQ_SYNCH_FRAME 0x0C + +/* class requests HID */ +#define HID_GET_REPORT 0x01 +#define HID_GET_IDLE 0x02 +#define HID_GET_PROTOCOL 0x03 +#define HID_SET_REPORT 0x09 +#define HID_SET_IDLE 0x0A +#define HID_SET_PROTOCOL 0x0B + +/* feature selectors */ +#define FEA_ENDPOINT_HALT 0x00 +#define FEA_REMOTE_WAKEUP 0x01 +#define FEA_TEST_MODE 0x02 + +/* + USB descriptors +*/ + +/** USB descriptor header */ +typedef struct { + unsigned char bLength; /**< descriptor length */ + unsigned char bDescriptorType; /**< descriptor type */ +} TUSBDescHeader; + +#define DESC_DEVICE 1 +#define DESC_CONFIGURATION 2 +#define DESC_STRING 3 +#define DESC_INTERFACE 4 +#define DESC_ENDPOINT 5 +#define DESC_DEVICE_QUALIFIER 6 +#define DESC_OTHER_SPEED 7 +#define DESC_INTERFACE_POWER 8 + +#define DESC_HID_HID 0x21 +#define DESC_HID_REPORT 0x22 +#define DESC_HID_PHYSICAL 0x23 + +#define GET_DESC_TYPE(x) (((x)>>8)&0xFF) +#define GET_DESC_INDEX(x) ((x)&0xFF) + +#endif /* _USBSTRUCT_H_ */ + diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/ParTest.c b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/ParTest.c new file mode 100644 index 000000000..01675bdc1 --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/ParTest.c @@ -0,0 +1,159 @@ +/* + FreeRTOS V6.0.2 - Copyright (C) 2010 Real Time Engineers Ltd. + + *************************************************************************** + * * + * If you are: * + * * + * + New to FreeRTOS, * + * + Wanting to learn FreeRTOS or multitasking in general quickly * + * + Looking for basic training, * + * + Wanting to improve your FreeRTOS skills and productivity * + * * + * then take a look at the FreeRTOS eBook * + * * + * "Using the FreeRTOS Real Time Kernel - a Practical Guide" * + * http://www.FreeRTOS.org/Documentation * + * * + * A pdf reference manual is also available. Both are usually delivered * + * to your inbox within 20 minutes to two hours when purchased between 8am * + * and 8pm GMT (although please allow up to 24 hours in case of * + * exceptional circumstances). Thank you for your support! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + ***NOTE*** The exception to the GPL is included to allow you to distribute + a combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* FreeRTOS.org includes. */ +#include "FreeRTOS.h" + +/* Demo application includes. */ +#include "partest.h" + +#define partstFIRST_IO ( ( unsigned long ) 0x04 ) +#define partstFIO2_BITS ( ( unsigned long ) 0x0000007C ) +#define partstFIO1_BITS ( ( unsigned long ) 0xB0000000 ) +#define partstNUM_LEDS ( 5 ) +#define partstALL_OUTPUTS_OFF ( ( unsigned long ) 0xff ) + +/*----------------------------------------------------------- + * Simple parallel port IO routines. + *-----------------------------------------------------------*/ + +void vParTestInitialise( void ) +{ + /* LEDs on ports 1 and 2 to output. */ + GPIO2->FIODIR = partstFIO2_BITS; + GPIO1->FIODIR = partstFIO1_BITS; + + /* Start will all LEDs off. */ + GPIO2->FIOCLR = partstFIO2_BITS; + GPIO1->FIOCLR = partstFIO1_BITS; +} +/*-----------------------------------------------------------*/ + +void vParTestSetLED( unsigned long ulLEDIn, signed long xValue ) +{ +unsigned long ulLED = partstFIRST_IO; + + /* Used to set and clear LEDs on FIO2. */ + + if( ulLEDIn < partstNUM_LEDS ) + { + /* Rotate to the wanted bit of port */ + ulLED <<= ( unsigned long ) ulLEDIn; + + /* Set of clear the output. */ + if( xValue ) + { + GPIO2->FIOCLR = ulLED; + } + else + { + GPIO2->FIOSET = ulLED; + } + } +} +/*-----------------------------------------------------------*/ + +void vParTestToggleLED( unsigned long ulLEDIn ) +{ +unsigned long ulLED = partstFIRST_IO, ulCurrentState; + + /* Used to toggle LEDs on FIO2. */ + + if( ulLEDIn < partstNUM_LEDS ) + { + /* Rotate to the wanted bit of port 0. Only P10 to P13 have an LED + attached. */ + ulLED <<= ( unsigned long ) ulLEDIn; + + /* If this bit is already set, clear it, and visa versa. */ + ulCurrentState = GPIO2->FIOPIN; + if( ulCurrentState & ulLED ) + { + GPIO2->FIOCLR = ulLED; + } + else + { + GPIO2->FIOSET = ulLED; + } + } +} +/*-----------------------------------------------------------*/ + +long lParTestGetLEDState( void ) +{ + /* Returns the state of the LEDs on FIO1. */ + if( ( GPIO1->FIOPIN & partstFIO1_BITS ) != 0 ) + { + return pdFALSE; + } + else + { + return pdTRUE; + } +} +/*-----------------------------------------------------------*/ + +void vParTestSetLEDState( long lState ) +{ + /* Used to set and clear the LEDs on FIO1. */ + if( lState != pdFALSE ) + { + GPIO1->FIOSET = partstFIO1_BITS; + } + else + { + GPIO1->FIOCLR = partstFIO1_BITS; + } +} +/*-----------------------------------------------------------*/ + diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/ParTest.c.bak b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/ParTest.c.bak new file mode 100644 index 000000000..8e16f87ca --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/ParTest.c.bak @@ -0,0 +1,159 @@ +/* + FreeRTOS V6.0.2 - Copyright (C) 2010 Real Time Engineers Ltd. + + *************************************************************************** + * * + * If you are: * + * * + * + New to FreeRTOS, * + * + Wanting to learn FreeRTOS or multitasking in general quickly * + * + Looking for basic training, * + * + Wanting to improve your FreeRTOS skills and productivity * + * * + * then take a look at the FreeRTOS eBook * + * * + * "Using the FreeRTOS Real Time Kernel - a Practical Guide" * + * http://www.FreeRTOS.org/Documentation * + * * + * A pdf reference manual is also available. Both are usually delivered * + * to your inbox within 20 minutes to two hours when purchased between 8am * + * and 8pm GMT (although please allow up to 24 hours in case of * + * exceptional circumstances). Thank you for your support! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + ***NOTE*** The exception to the GPL is included to allow you to distribute + a combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* FreeRTOS.org includes. */ +#include "FreeRTOS.h" + +/* Demo application includes. */ +#include "partest.h" + +#define partstFIRST_IO ( ( unsigned long ) 0x04 ) +#define partstFIO2_BITS ( ( unsigned long ) 0x0000007C ) +#define partstFIO1_BITS ( ( unsigned long ) 0xB0000000 ) +#define partstNUM_LEDS ( 5 ) +#define partstALL_OUTPUTS_OFF ( ( unsigned long ) 0xff ) + +/*----------------------------------------------------------- + * Simple parallel port IO routines. + *-----------------------------------------------------------*/ + +void vParTestInitialise( void ) +{ + /* LEDs on ports 1 and 2 to output. */ + GPIO2->FIODIR = partstFIO2_BITS; + GPIO1->FIODIR = partstFIO1_BITS; + + /* Start will all LEDs off. */ + GPIO2->FIOCLR = partstFIO2_BITS; + GPIO1->FIOCLR = partstFIO1_BITS; +} +/*-----------------------------------------------------------*/ + +void vParTestSetLED( unsigned long ulLEDIn, signed long xValue ) +{ +unsigned long ulLED = partstFIRST_IO; + + /* Used to set and clear LEDs on FIO2. */ + + if( ulLEDIn < partstNUM_LEDS ) + { + /* Rotate to the wanted bit of port */ + ulLED <<= ( unsigned long ) ulLEDIn; + + /* Set of clear the output. */ + if( xValue ) + { + GPIO2->FIOCLR = ulLED; + } + else + { + GPIO2->FIOSET = ulLED; + } + } +} +/*-----------------------------------------------------------*/ + +void vParTestToggleLED( unsigned long ulLEDIn ) +{ +unsigned long ulLED = partstFIRST_IO, ulCurrentState; + + /* Used to toggle LEDs on FIO2. */ + + if( ulLEDIn < partstNUM_LEDS ) + { + /* Rotate to the wanted bit of port 0. Only P10 to P13 have an LED + attached. */ + ulLED <<= ( unsigned long ) ulLEDIn; + + /* If this bit is already set, clear it, and visa versa. */ + ulCurrentState = GPIO2->FIOPIN; + if( ulCurrentState & ulLED ) + { + GPIO2->FIOCLR = ulLED; + } + else + { + GPIO2->FIOSET = ulLED; + } + } +} +/*-----------------------------------------------------------*/ + +long lParTestGetLEDState( void ) +{ + /* Returns the state of the LEDs on FIO1. */ + if( ( GPIO1->FIOPIN & partstFIO1_BITS ) != 0 ) + { + return pdFALSE; + } + else + { + return pdTRUE; + } +} +/*-----------------------------------------------------------*/ + +void vParTestSetLEDState( long lState ) +{ + /* Used to set and clear the LEDs on FIO1. */ + if( lState != pdFALSE ) + { + GPIO1->FIOSET = partstFIO1_BITS; + } + else + { + GPIO1->FIOCLR = partstFIO1_BITS; + } +} +/*-----------------------------------------------------------*/ + diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/RTOSDemo.hzp b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/RTOSDemo.hzp new file mode 100644 index 000000000..10626a174 --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/RTOSDemo.hzp @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/RTOSDemo.hzs b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/RTOSDemo.hzs new file mode 100644 index 000000000..a3d8e1f7d --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/RTOSDemo.hzs @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/core_cm3.h b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/core_cm3.h new file mode 100644 index 000000000..b6f9696bf --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/core_cm3.h @@ -0,0 +1,1367 @@ +/****************************************************************************** + * @file: core_cm3.h + * @purpose: CMSIS Cortex-M3 Core Peripheral Access Layer Header File + * @version: V1.20 + * @date: 22. May 2009 + *---------------------------------------------------------------------------- + * + * Copyright (C) 2009 ARM Limited. All rights reserved. + * + * ARM Limited (ARM) is supplying this software for use with Cortex-Mx + * 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 __CM3_CORE_H__ +#define __CM3_CORE_H__ + +#ifdef __cplusplus + extern "C" { +#endif + +#define __CM3_CMSIS_VERSION_MAIN (0x01) /*!< [31:16] CMSIS HAL main version */ +#define __CM3_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */ +#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16) | __CM3_CMSIS_VERSION_SUB) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x03) /*!< Cortex core */ + +/** + * Lint configuration \n + * ----------------------- \n + * + * The following Lint messages will be suppressed and not shown: \n + * \n + * --- Error 10: --- \n + * register uint32_t __regBasePri __asm("basepri"); \n + * Error 10: Expecting ';' \n + * \n + * --- Error 530: --- \n + * return(__regBasePri); \n + * Warning 530: Symbol '__regBasePri' (line 264) not initialized \n + * \n + * --- Error 550: --- \n + * __regBasePri = (basePri & 0x1ff); \n + * } \n + * Warning 550: Symbol '__regBasePri' (line 271) not accessed \n + * \n + * --- Error 754: --- \n + * uint32_t RESERVED0[24]; \n + * Info 754: local structure member '' (line 109, file ./cm3_core.h) not referenced \n + * \n + * --- Error 750: --- \n + * #define __CM3_CORE_H__ \n + * Info 750: local macro '__CM3_CORE_H__' (line 43, file./cm3_core.h) not referenced \n + * \n + * --- Error 528: --- \n + * static __INLINE void NVIC_DisableIRQ(uint32_t IRQn) \n + * Warning 528: Symbol 'NVIC_DisableIRQ(unsigned int)' (line 419, file ./cm3_core.h) not referenced \n + * \n + * --- Error 751: --- \n + * } InterruptType_Type; \n + * Info 751: local typedef 'InterruptType_Type' (line 170, file ./cm3_core.h) not referenced \n + * \n + * \n + * Note: To re-enable a Message, insert a space before 'lint' * \n + * + */ + +/*lint -save */ +/*lint -e10 */ +/*lint -e530 */ +/*lint -e550 */ +/*lint -e754 */ +/*lint -e750 */ +/*lint -e528 */ +/*lint -e751 */ + + +#include /* Include standard types */ + +#if defined (__ICCARM__) + #include /* IAR Intrinsics */ +#endif + + +#ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4 /*!< standard definition for NVIC Priority Bits */ +#endif + + + + +/** + * IO definitions + * + * define access restrictions to peripheral registers + */ + +#ifdef __cplusplus +#define __I volatile /*!< defines 'read only' permissions */ +#else +#define __I volatile const /*!< defines 'read only' permissions */ +#endif +#define __O volatile /*!< defines 'write only' permissions */ +#define __IO volatile /*!< defines 'read / write' permissions */ + + + +/******************************************************************************* + * Register Abstraction + ******************************************************************************/ + + +/* System Reset */ +#define NVIC_VECTRESET 0 /*!< Vector Reset Bit */ +#define NVIC_SYSRESETREQ 2 /*!< System Reset Request */ +#define NVIC_AIRCR_VECTKEY (0x5FA << 16) /*!< AIRCR Key for write access */ +#define NVIC_AIRCR_ENDIANESS 15 /*!< Endianess */ + +/* Core Debug */ +#define CoreDebug_DEMCR_TRCENA (1 << 24) /*!< DEMCR TRCENA enable */ +#define ITM_TCR_ITMENA 1 /*!< ITM enable */ + + + + +/* memory mapping struct for Nested Vectored Interrupt Controller (NVIC) */ +typedef struct +{ + __IO uint32_t ISER[8]; /*!< Interrupt Set Enable Register */ + uint32_t RESERVED0[24]; + __IO uint32_t ICER[8]; /*!< Interrupt Clear Enable Register */ + uint32_t RSERVED1[24]; + __IO uint32_t ISPR[8]; /*!< Interrupt Set Pending Register */ + uint32_t RESERVED2[24]; + __IO uint32_t ICPR[8]; /*!< Interrupt Clear Pending Register */ + uint32_t RESERVED3[24]; + __IO uint32_t IABR[8]; /*!< Interrupt Active bit Register */ + uint32_t RESERVED4[56]; + __IO uint8_t IP[240]; /*!< Interrupt Priority Register, 8Bit wide */ + uint32_t RESERVED5[644]; + __O uint32_t STIR; /*!< Software Trigger Interrupt Register */ +} NVIC_Type; + + +/* memory mapping struct for System Control Block */ +typedef struct +{ + __I uint32_t CPUID; /*!< CPU ID Base Register */ + __IO uint32_t ICSR; /*!< Interrupt Control State Register */ + __IO uint32_t VTOR; /*!< Vector Table Offset Register */ + __IO uint32_t AIRCR; /*!< Application Interrupt / Reset Control Register */ + __IO uint32_t SCR; /*!< System Control Register */ + __IO uint32_t CCR; /*!< Configuration Control Register */ + __IO uint8_t SHP[12]; /*!< System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IO uint32_t SHCSR; /*!< System Handler Control and State Register */ + __IO uint32_t CFSR; /*!< Configurable Fault Status Register */ + __IO uint32_t HFSR; /*!< Hard Fault Status Register */ + __IO uint32_t DFSR; /*!< Debug Fault Status Register */ + __IO uint32_t MMFAR; /*!< Mem Manage Address Register */ + __IO uint32_t BFAR; /*!< Bus Fault Address Register */ + __IO uint32_t AFSR; /*!< Auxiliary Fault Status Register */ + __I uint32_t PFR[2]; /*!< Processor Feature Register */ + __I uint32_t DFR; /*!< Debug Feature Register */ + __I uint32_t ADR; /*!< Auxiliary Feature Register */ + __I uint32_t MMFR[4]; /*!< Memory Model Feature Register */ + __I uint32_t ISAR[5]; /*!< ISA Feature Register */ +} SCB_Type; + + +/* memory mapping struct for SysTick */ +typedef struct +{ + __IO uint32_t CTRL; /*!< SysTick Control and Status Register */ + __IO uint32_t LOAD; /*!< SysTick Reload Value Register */ + __IO uint32_t VAL; /*!< SysTick Current Value Register */ + __I uint32_t CALIB; /*!< SysTick Calibration Register */ +} SysTick_Type; + + +/* memory mapping structur for ITM */ +typedef struct +{ + __O union + { + __O uint8_t u8; /*!< ITM Stimulus Port 8-bit */ + __O uint16_t u16; /*!< ITM Stimulus Port 16-bit */ + __O uint32_t u32; /*!< ITM Stimulus Port 32-bit */ + } PORT [32]; /*!< ITM Stimulus Port Registers */ + uint32_t RESERVED0[864]; + __IO uint32_t TER; /*!< ITM Trace Enable Register */ + uint32_t RESERVED1[15]; + __IO uint32_t TPR; /*!< ITM Trace Privilege Register */ + uint32_t RESERVED2[15]; + __IO uint32_t TCR; /*!< ITM Trace Control Register */ + uint32_t RESERVED3[29]; + __IO uint32_t IWR; /*!< ITM Integration Write Register */ + __IO uint32_t IRR; /*!< ITM Integration Read Register */ + __IO uint32_t IMCR; /*!< ITM Integration Mode Control Register */ + uint32_t RESERVED4[43]; + __IO uint32_t LAR; /*!< ITM Lock Access Register */ + __IO uint32_t LSR; /*!< ITM Lock Status Register */ + uint32_t RESERVED5[6]; + __I uint32_t PID4; /*!< ITM Product ID Registers */ + __I uint32_t PID5; + __I uint32_t PID6; + __I uint32_t PID7; + __I uint32_t PID0; + __I uint32_t PID1; + __I uint32_t PID2; + __I uint32_t PID3; + __I uint32_t CID0; + __I uint32_t CID1; + __I uint32_t CID2; + __I uint32_t CID3; +} ITM_Type; + + +/* memory mapped struct for Interrupt Type */ +typedef struct +{ + uint32_t RESERVED0; + __I uint32_t ICTR; /*!< Interrupt Control Type Register */ +#if ((defined __CM3_REV) && (__CM3_REV >= 0x200)) + __IO uint32_t ACTLR; /*!< Auxiliary Control Register */ +#else + uint32_t RESERVED1; +#endif +} InterruptType_Type; + + +/* Memory Protection Unit */ +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1) +typedef struct +{ + __I uint32_t TYPE; /*!< MPU Type Register */ + __IO uint32_t CTRL; /*!< MPU Control Register */ + __IO uint32_t RNR; /*!< MPU Region RNRber Register */ + __IO uint32_t RBAR; /*!< MPU Region Base Address Register */ + __IO uint32_t RASR; /*!< MPU Region Attribute and Size Register */ + __IO uint32_t RBAR_A1; /*!< MPU Alias 1 Region Base Address Register */ + __IO uint32_t RASR_A1; /*!< MPU Alias 1 Region Attribute and Size Register */ + __IO uint32_t RBAR_A2; /*!< MPU Alias 2 Region Base Address Register */ + __IO uint32_t RASR_A2; /*!< MPU Alias 2 Region Attribute and Size Register */ + __IO uint32_t RBAR_A3; /*!< MPU Alias 3 Region Base Address Register */ + __IO uint32_t RASR_A3; /*!< MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; +#endif + + +/* Core Debug Register */ +typedef struct +{ + __IO uint32_t DHCSR; /*!< Debug Halting Control and Status Register */ + __O uint32_t DCRSR; /*!< Debug Core Register Selector Register */ + __IO uint32_t DCRDR; /*!< Debug Core Register Data Register */ + __IO uint32_t DEMCR; /*!< Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + + +/* Memory mapping of Cortex-M3 Hardware */ +#define SCS_BASE (0xE000E000) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000) /*!< ITM Base Address */ +#define CoreDebug_BASE (0xE000EDF0) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00) /*!< System Control Block Base Address */ + +#define InterruptType ((InterruptType_Type *) SCS_BASE) /*!< Interrupt Type Register */ +#define SCB ((SCB_Type *) SCB_BASE) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE) /*!< ITM configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1) + #define MPU_BASE (SCS_BASE + 0x0D90) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type*) MPU_BASE) /*!< Memory Protection Unit */ +#endif + + + +/******************************************************************************* + * Hardware Abstraction Layer + ******************************************************************************/ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */ + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + +#endif + + +/* ################### Compiler specific Intrinsics ########################### */ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#define __enable_fault_irq __enable_fiq +#define __disable_fault_irq __disable_fiq + +#define __NOP __nop +#define __WFI __wfi +#define __WFE __wfe +#define __SEV __sev +#define __ISB() __isb(0) +#define __DSB() __dsb(0) +#define __DMB() __dmb(0) +#define __REV __rev +#define __RBIT __rbit +#define __LDREXB(ptr) ((unsigned char ) __ldrex(ptr)) +#define __LDREXH(ptr) ((unsigned short) __ldrex(ptr)) +#define __LDREXW(ptr) ((unsigned int ) __ldrex(ptr)) +#define __STREXB(value, ptr) __strex(value, ptr) +#define __STREXH(value, ptr) __strex(value, ptr) +#define __STREXW(value, ptr) __strex(value, ptr) + + +/* intrinsic unsigned long long __ldrexd(volatile void *ptr) */ +/* intrinsic int __strexd(unsigned long long val, volatile void *ptr) */ +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + + +/** + * @brief Return the Process Stack Pointer + * + * @param none + * @return uint32_t ProcessStackPointer + * + * Return the actual process stack pointer + */ +extern uint32_t __get_PSP(void); + +/** + * @brief Set the Process Stack Pointer + * + * @param uint32_t Process Stack Pointer + * @return none + * + * Assign the value ProcessStackPointer to the MSP + * (process stack pointer) Cortex processor register + */ +extern void __set_PSP(uint32_t topOfProcStack); + +/** + * @brief Return the Main Stack Pointer + * + * @param none + * @return uint32_t Main Stack Pointer + * + * Return the current value of the MSP (main stack pointer) + * Cortex processor register + */ +extern uint32_t __get_MSP(void); + +/** + * @brief Set the Main Stack Pointer + * + * @param uint32_t Main Stack Pointer + * @return none + * + * Assign the value mainStackPointer to the MSP + * (main stack pointer) Cortex processor register + */ +extern void __set_MSP(uint32_t topOfMainStack); + +/** + * @brief Reverse byte order in unsigned short value + * + * @param uint16_t value to reverse + * @return uint32_t reversed value + * + * Reverse byte order in unsigned short value + */ +extern uint32_t __REV16(uint16_t value); + +/* + * @brief Reverse byte order in signed short value with sign extension to integer + * + * @param int16_t value to reverse + * @return int32_t reversed value + * + * Reverse byte order in signed short value with sign extension to integer + */ +extern int32_t __REVSH(int16_t value); + + +#if (__ARMCC_VERSION < 400000) + +/** + * @brief Remove the exclusive lock created by ldrex + * + * @param none + * @return none + * + * Removes the exclusive lock which is created by ldrex. + */ +extern void __CLREX(void); + +/** + * @brief Return the Base Priority value + * + * @param none + * @return uint32_t BasePriority + * + * Return the content of the base priority register + */ +extern uint32_t __get_BASEPRI(void); + +/** + * @brief Set the Base Priority value + * + * @param uint32_t BasePriority + * @return none + * + * Set the base priority register + */ +extern void __set_BASEPRI(uint32_t basePri); + +/** + * @brief Return the Priority Mask value + * + * @param none + * @return uint32_t PriMask + * + * Return the state of the priority mask bit from the priority mask + * register + */ +extern uint32_t __get_PRIMASK(void); + +/** + * @brief Set the Priority Mask value + * + * @param uint32_t PriMask + * @return none + * + * Set the priority mask bit in the priority mask register + */ +extern void __set_PRIMASK(uint32_t priMask); + +/** + * @brief Return the Fault Mask value + * + * @param none + * @return uint32_t FaultMask + * + * Return the content of the fault mask register + */ +extern uint32_t __get_FAULTMASK(void); + +/** + * @brief Set the Fault Mask value + * + * @param uint32_t faultMask value + * @return none + * + * Set the fault mask register + */ +extern void __set_FAULTMASK(uint32_t faultMask); + +/** + * @brief Return the Control Register value + * + * @param none + * @return uint32_t Control value + * + * Return the content of the control register + */ +extern uint32_t __get_CONTROL(void); + +/** + * @brief Set the Control Register value + * + * @param uint32_t Control value + * @return none + * + * Set the control register + */ +extern void __set_CONTROL(uint32_t control); + +#else /* (__ARMCC_VERSION >= 400000) */ + + +/** + * @brief Remove the exclusive lock created by ldrex + * + * @param none + * @return none + * + * Removes the exclusive lock which is created by ldrex. + */ +#define __CLREX __clrex + +/** + * @brief Return the Base Priority value + * + * @param none + * @return uint32_t BasePriority + * + * Return the content of the base priority register + */ +static __INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + +/** + * @brief Set the Base Priority value + * + * @param uint32_t BasePriority + * @return none + * + * Set the base priority register + */ +static __INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0x1ff); +} + +/** + * @brief Return the Priority Mask value + * + * @param none + * @return uint32_t PriMask + * + * Return the state of the priority mask bit from the priority mask + * register + */ +static __INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + +/** + * @brief Set the Priority Mask value + * + * @param uint32_t PriMask + * @return none + * + * Set the priority mask bit in the priority mask register + */ +static __INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + +/** + * @brief Return the Fault Mask value + * + * @param none + * @return uint32_t FaultMask + * + * Return the content of the fault mask register + */ +static __INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + +/** + * @brief Set the Fault Mask value + * + * @param uint32_t faultMask value + * @return none + * + * Set the fault mask register + */ +static __INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & 1); +} + +/** + * @brief Return the Control Register value + * + * @param none + * @return uint32_t Control value + * + * Return the content of the control register + */ +static __INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + +/** + * @brief Set the Control Register value + * + * @param uint32_t Control value + * @return none + * + * Set the control register + */ +static __INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + +#endif /* __ARMCC_VERSION */ + + + +#elif (defined (__ICCARM__)) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#define __enable_irq __enable_interrupt /*!< global Interrupt enable */ +#define __disable_irq __disable_interrupt /*!< global Interrupt disable */ + +static __INLINE void __enable_fault_irq() { __ASM ("cpsie f"); } +static __INLINE void __disable_fault_irq() { __ASM ("cpsid f"); } + +#define __NOP __no_operation() /*!< no operation intrinsic in IAR Compiler */ +static __INLINE void __WFI() { __ASM ("wfi"); } +static __INLINE void __WFE() { __ASM ("wfe"); } +static __INLINE void __SEV() { __ASM ("sev"); } +static __INLINE void __CLREX() { __ASM ("clrex"); } + +/* intrinsic void __ISB(void) */ +/* intrinsic void __DSB(void) */ +/* intrinsic void __DMB(void) */ +/* intrinsic void __set_PRIMASK(); */ +/* intrinsic void __get_PRIMASK(); */ +/* intrinsic void __set_FAULTMASK(); */ +/* intrinsic void __get_FAULTMASK(); */ +/* intrinsic uint32_t __REV(uint32_t value); */ +/* intrinsic uint32_t __REVSH(uint32_t value); */ +/* intrinsic unsigned long __STREX(unsigned long, unsigned long); */ +/* intrinsic unsigned long __LDREX(unsigned long *); */ + + +/** + * @brief Return the Process Stack Pointer + * + * @param none + * @return uint32_t ProcessStackPointer + * + * Return the actual process stack pointer + */ +extern uint32_t __get_PSP(void); + +/** + * @brief Set the Process Stack Pointer + * + * @param uint32_t Process Stack Pointer + * @return none + * + * Assign the value ProcessStackPointer to the MSP + * (process stack pointer) Cortex processor register + */ +extern void __set_PSP(uint32_t topOfProcStack); + +/** + * @brief Return the Main Stack Pointer + * + * @param none + * @return uint32_t Main Stack Pointer + * + * Return the current value of the MSP (main stack pointer) + * Cortex processor register + */ +extern uint32_t __get_MSP(void); + +/** + * @brief Set the Main Stack Pointer + * + * @param uint32_t Main Stack Pointer + * @return none + * + * Assign the value mainStackPointer to the MSP + * (main stack pointer) Cortex processor register + */ +extern void __set_MSP(uint32_t topOfMainStack); + +/** + * @brief Reverse byte order in unsigned short value + * + * @param uint16_t value to reverse + * @return uint32_t reversed value + * + * Reverse byte order in unsigned short value + */ +extern uint32_t __REV16(uint16_t value); + +/** + * @brief Reverse bit order of value + * + * @param uint32_t value to reverse + * @return uint32_t reversed value + * + * Reverse bit order of value + */ +extern uint32_t __RBIT(uint32_t value); + +/** + * @brief LDR Exclusive + * + * @param uint8_t* address + * @return uint8_t value of (*address) + * + * Exclusive LDR command + */ +extern uint8_t __LDREXB(uint8_t *addr); + +/** + * @brief LDR Exclusive + * + * @param uint16_t* address + * @return uint16_t value of (*address) + * + * Exclusive LDR command + */ +extern uint16_t __LDREXH(uint16_t *addr); + +/** + * @brief LDR Exclusive + * + * @param uint32_t* address + * @return uint32_t value of (*address) + * + * Exclusive LDR command + */ +extern uint32_t __LDREXW(uint32_t *addr); + +/** + * @brief STR Exclusive + * + * @param uint8_t *address + * @param uint8_t value to store + * @return uint32_t successful / failed + * + * Exclusive STR command + */ +extern uint32_t __STREXB(uint8_t value, uint8_t *addr); + +/** + * @brief STR Exclusive + * + * @param uint16_t *address + * @param uint16_t value to store + * @return uint32_t successful / failed + * + * Exclusive STR command + */ +extern uint32_t __STREXH(uint16_t value, uint16_t *addr); + +/** + * @brief STR Exclusive + * + * @param uint32_t *address + * @param uint32_t value to store + * @return uint32_t successful / failed + * + * Exclusive STR command + */ +extern uint32_t __STREXW(uint32_t value, uint32_t *addr); + + + +#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +static __INLINE void __enable_irq() { __ASM volatile ("cpsie i"); } +static __INLINE void __disable_irq() { __ASM volatile ("cpsid i"); } + +static __INLINE void __enable_fault_irq() { __ASM volatile ("cpsie f"); } +static __INLINE void __disable_fault_irq() { __ASM volatile ("cpsid f"); } + +static __INLINE void __NOP() { __ASM volatile ("nop"); } +static __INLINE void __WFI() { __ASM volatile ("wfi"); } +static __INLINE void __WFE() { __ASM volatile ("wfe"); } +static __INLINE void __SEV() { __ASM volatile ("sev"); } +static __INLINE void __ISB() { __ASM volatile ("isb"); } +static __INLINE void __DSB() { __ASM volatile ("dsb"); } +static __INLINE void __DMB() { __ASM volatile ("dmb"); } +static __INLINE void __CLREX() { __ASM volatile ("clrex"); } + + +/** + * @brief Return the Process Stack Pointer + * + * @param none + * @return uint32_t ProcessStackPointer + * + * Return the actual process stack pointer + */ +extern uint32_t __get_PSP(void); + +/** + * @brief Set the Process Stack Pointer + * + * @param uint32_t Process Stack Pointer + * @return none + * + * Assign the value ProcessStackPointer to the MSP + * (process stack pointer) Cortex processor register + */ +extern void __set_PSP(uint32_t topOfProcStack); + +/** + * @brief Return the Main Stack Pointer + * + * @param none + * @return uint32_t Main Stack Pointer + * + * Return the current value of the MSP (main stack pointer) + * Cortex processor register + */ +extern uint32_t __get_MSP(void); + +/** + * @brief Set the Main Stack Pointer + * + * @param uint32_t Main Stack Pointer + * @return none + * + * Assign the value mainStackPointer to the MSP + * (main stack pointer) Cortex processor register + */ +extern void __set_MSP(uint32_t topOfMainStack); + +/** + * @brief Return the Base Priority value + * + * @param none + * @return uint32_t BasePriority + * + * Return the content of the base priority register + */ +extern uint32_t __get_BASEPRI(void); + +/** + * @brief Set the Base Priority value + * + * @param uint32_t BasePriority + * @return none + * + * Set the base priority register + */ +extern void __set_BASEPRI(uint32_t basePri); + +/** + * @brief Return the Priority Mask value + * + * @param none + * @return uint32_t PriMask + * + * Return the state of the priority mask bit from the priority mask + * register + */ +extern uint32_t __get_PRIMASK(void); + +/** + * @brief Set the Priority Mask value + * + * @param uint32_t PriMask + * @return none + * + * Set the priority mask bit in the priority mask register + */ +extern void __set_PRIMASK(uint32_t priMask); + +/** + * @brief Return the Fault Mask value + * + * @param none + * @return uint32_t FaultMask + * + * Return the content of the fault mask register + */ +extern uint32_t __get_FAULTMASK(void); + +/** + * @brief Set the Fault Mask value + * + * @param uint32_t faultMask value + * @return none + * + * Set the fault mask register + */ +extern void __set_FAULTMASK(uint32_t faultMask); + +/** + * @brief Return the Control Register value +* +* @param none +* @return uint32_t Control value + * + * Return the content of the control register + */ +extern uint32_t __get_CONTROL(void); + +/** + * @brief Set the Control Register value + * + * @param uint32_t Control value + * @return none + * + * Set the control register + */ +extern void __set_CONTROL(uint32_t control); + +/** + * @brief Reverse byte order in integer value + * + * @param uint32_t value to reverse + * @return uint32_t reversed value + * + * Reverse byte order in integer value + */ +extern uint32_t __REV(uint32_t value); + +/** + * @brief Reverse byte order in unsigned short value + * + * @param uint16_t value to reverse + * @return uint32_t reversed value + * + * Reverse byte order in unsigned short value + */ +extern uint32_t __REV16(uint16_t value); + +/* + * Reverse byte order in signed short value with sign extension to integer + * + * @param int16_t value to reverse + * @return int32_t reversed value + * + * @brief Reverse byte order in signed short value with sign extension to integer + */ +extern int32_t __REVSH(int16_t value); + +/** + * @brief Reverse bit order of value + * + * @param uint32_t value to reverse + * @return uint32_t reversed value + * + * Reverse bit order of value + */ +extern uint32_t __RBIT(uint32_t value); + +/** + * @brief LDR Exclusive + * + * @param uint8_t* address + * @return uint8_t value of (*address) + * + * Exclusive LDR command + */ +extern uint8_t __LDREXB(uint8_t *addr); + +/** + * @brief LDR Exclusive + * + * @param uint16_t* address + * @return uint16_t value of (*address) + * + * Exclusive LDR command + */ +extern uint16_t __LDREXH(uint16_t *addr); + +/** + * @brief LDR Exclusive + * + * @param uint32_t* address + * @return uint32_t value of (*address) + * + * Exclusive LDR command + */ +extern uint32_t __LDREXW(uint32_t *addr); + +/** + * @brief STR Exclusive + * + * @param uint8_t *address + * @param uint8_t value to store + * @return uint32_t successful / failed + * + * Exclusive STR command + */ +extern uint32_t __STREXB(uint8_t value, uint8_t *addr); + +/** + * @brief STR Exclusive + * + * @param uint16_t *address + * @param uint16_t value to store + * @return uint32_t successful / failed + * + * Exclusive STR command + */ +extern uint32_t __STREXH(uint16_t value, uint16_t *addr); + +/** + * @brief STR Exclusive + * + * @param uint32_t *address + * @param uint32_t value to store + * @return uint32_t successful / failed + * + * Exclusive STR command + */ +extern uint32_t __STREXW(uint32_t value, uint32_t *addr); + + +#elif (defined (__TASKING__)) /*------------------ TASKING Compiler ---------------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all instrinsics, + * Including the CMSIS ones. + */ + +#endif + + + +/* ########################## NVIC functions #################################### */ + + +/** + * @brief Set the Priority Grouping in NVIC Interrupt Controller + * + * @param uint32_t priority_grouping is priority grouping field + * @return none + * + * Set the priority grouping field using the required unlock sequence. + * The parameter priority_grouping is assigned to the field + * SCB->AIRCR [10:8] PRIGROUP field. Only values from 0..7 are used. + * In case of a conflict between priority grouping and available + * priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + */ +static __INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((0xFFFFU << 16) | (0x0F << 8)); /* clear bits to change */ + reg_value = ((reg_value | NVIC_AIRCR_VECTKEY | (PriorityGroupTmp << 8))); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + +/** + * @brief Get the Priority Grouping from NVIC Interrupt Controller + * + * @param none + * @return uint32_t priority grouping field + * + * Get the priority grouping from NVIC Interrupt Controller. + * priority grouping is SCB->AIRCR [10:8] PRIGROUP field. + */ +static __INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((SCB->AIRCR >> 8) & 0x07); /* read priority grouping field */ +} + +/** + * @brief Enable Interrupt in NVIC Interrupt Controller + * + * @param IRQn_Type IRQn specifies the interrupt number + * @return none + * + * Enable a device specific interupt in the NVIC interrupt controller. + * The interrupt number cannot be a negative value. + */ +static __INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* enable interrupt */ +} + +/** + * @brief Disable the interrupt line for external interrupt specified + * + * @param IRQn_Type IRQn is the positive number of the external interrupt + * @return none + * + * Disable a device specific interupt in the NVIC interrupt controller. + * The interrupt number cannot be a negative value. + */ +static __INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* disable interrupt */ +} + +/** + * @brief Read the interrupt pending bit for a device specific interrupt source + * + * @param IRQn_Type IRQn is the number of the device specifc interrupt + * @return uint32_t 1 if pending interrupt else 0 + * + * Read the pending register in NVIC and return 1 if its status is pending, + * otherwise it returns 0 + */ +static __INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->ISPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if pending else 0 */ +} + +/** + * @brief Set the pending bit for an external interrupt + * + * @param IRQn_Type IRQn is the Number of the interrupt + * @return none + * + * Set the pending bit for the specified interrupt. + * The interrupt number cannot be a negative value. + */ +static __INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */ +} + +/** + * @brief Clear the pending bit for an external interrupt + * + * @param IRQn_Type IRQn is the Number of the interrupt + * @return none + * + * Clear the pending bit for the specified interrupt. + * The interrupt number cannot be a negative value. + */ +static __INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ +} + +/** + * @brief Read the active bit for an external interrupt + * + * @param IRQn_Type IRQn is the Number of the interrupt + * @return uint32_t 1 if active else 0 + * + * Read the active register in NVIC and returns 1 if its status is active, + * otherwise it returns 0. + */ +static __INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)((NVIC->IABR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if active else 0 */ +} + +/** + * @brief Set the priority for an interrupt + * + * @param IRQn_Type IRQn is the Number of the interrupt + * @param priority is the priority for the interrupt + * @return none + * + * Set the priority for the specified interrupt. The interrupt + * number can be positive to specify an external (device specific) + * interrupt, or negative to specify an internal (core) interrupt. \n + * + * Note: The priority cannot be set for every core interrupt. + */ +static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if(IRQn < 0) { + SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M3 System Interrupts */ + else { + NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for device specific Interrupts */ +} + +/** + * @brief Read the priority for an interrupt + * + * @param IRQn_Type IRQn is the Number of the interrupt + * @return uint32_t priority is the priority for the interrupt + * + * Read the priority for the specified interrupt. The interrupt + * number can be positive to specify an external (device specific) + * interrupt, or negative to specify an internal (core) interrupt. + * + * The returned priority value is automatically aligned to the implemented + * priority bits of the microcontroller. + * + * Note: The priority cannot be set for every core interrupt. + */ +static __INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if(IRQn < 0) { + return((uint32_t)(SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M3 system interrupts */ + else { + return((uint32_t)(NVIC->IP[(uint32_t)(IRQn)] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */ +} + + +/** + * @brief Encode the priority for an interrupt + * + * @param uint32_t PriorityGroup is the used priority group + * @param uint32_t PreemptPriority is the preemptive priority value (starting from 0) + * @param uint32_t SubPriority is the sub priority value (starting from 0) + * @return uint32_t the priority for the interrupt + * + * Encode the priority for an interrupt with the given priority group, + * preemptive priority value and sub priority value. + * In case of a conflict between priority grouping and available + * priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set. + * + * The returned priority value can be used for NVIC_SetPriority(...) function + */ +static __INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + return ( + ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) | + ((SubPriority & ((1 << (SubPriorityBits )) - 1))) + ); +} + + +/** + * @brief Decode the priority of an interrupt + * + * @param uint32_t Priority the priority for the interrupt + * @param uint32_t PrioGroup is the used priority group + * @param uint32_t* pPreemptPrio is the preemptive priority value (starting from 0) + * @param uint32_t* pSubPrio is the sub priority value (starting from 0) + * @return none + * + * Decode an interrupt priority value with the given priority group to + * preemptive priority value and sub priority value. + * In case of a conflict between priority grouping and available + * priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set. + * + * The priority value can be retrieved with NVIC_GetPriority(...) function + */ +static __INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + *pPreemptPriority = (Priority >> SubPriorityBits) & ((1 << (PreemptPriorityBits)) - 1); + *pSubPriority = (Priority ) & ((1 << (SubPriorityBits )) - 1); +} + + + +/* ################################## SysTick function ############################################ */ + +#if (!defined (__Vendor_SysTickConfig)) || (__Vendor_SysTickConfig == 0) + +/* SysTick constants */ +#define SYSTICK_ENABLE 0 /* Config-Bit to start or stop the SysTick Timer */ +#define SYSTICK_TICKINT 1 /* Config-Bit to enable or disable the SysTick interrupt */ +#define SYSTICK_CLKSOURCE 2 /* Clocksource has the offset 2 in SysTick Control and Status Register */ +#define SYSTICK_MAXCOUNT ((1<<24) -1) /* SysTick MaxCount */ + +/** + * @brief Initialize and start the SysTick counter and its interrupt. + * + * @param uint32_t ticks is the number of ticks between two interrupts + * @return none + * + * Initialise the system tick timer and its interrupt and start the + * system tick timer / counter in free running mode to generate + * periodical interrupts. + */ +static __INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if (ticks > SYSTICK_MAXCOUNT) return (1); /* Reload value impossible */ + + SysTick->LOAD = (ticks & SYSTICK_MAXCOUNT) - 1; /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */ + SysTick->VAL = (0x00); /* Load the SysTick Counter Value */ + SysTick->CTRL = (1 << SYSTICK_CLKSOURCE) | (1<AIRCR = (NVIC_AIRCR_VECTKEY | (SCB->AIRCR & (0x700)) | (1<DEMCR & CoreDebug_DEMCR_TRCENA) && + (ITM->TCR & ITM_TCR_ITMENA) && + (ITM->TER & (1UL << 0)) ) + { + while (ITM->PORT[0].u32 == 0); + ITM->PORT[0].u8 = (uint8_t) ch; + } + return (ch); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __CM3_CORE_H__ */ + +/*lint -restore */ diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/flash_placement.xml b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/flash_placement.xml new file mode 100644 index 000000000..95fef0a7f --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/flash_placement.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/main.c b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/main.c new file mode 100644 index 000000000..4ec9660fa --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/main.c @@ -0,0 +1,319 @@ +/* + FreeRTOS V6.0.2 - Copyright (C) 2010 Real Time Engineers Ltd. + + *************************************************************************** + * * + * If you are: * + * * + * + New to FreeRTOS, * + * + Wanting to learn FreeRTOS or multitasking in general quickly * + * + Looking for basic training, * + * + Wanting to improve your FreeRTOS skills and productivity * + * * + * then take a look at the FreeRTOS eBook * + * * + * "Using the FreeRTOS Real Time Kernel - a Practical Guide" * + * http://www.FreeRTOS.org/Documentation * + * * + * A pdf reference manual is also available. Both are usually delivered * + * to your inbox within 20 minutes to two hours when purchased between 8am * + * and 8pm GMT (although please allow up to 24 hours in case of * + * exceptional circumstances). Thank you for your support! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + ***NOTE*** The exception to the GPL is included to allow you to distribute + a combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +/* + * Creates all the demo application tasks, then starts the scheduler. The WEB + * documentation provides more details of the standard demo application tasks + * (which just exist to test the kernel port and provide an example of how to use + * each FreeRTOS API function). + * + * In addition to the standard demo tasks, the following tasks and tests are + * defined and/or created within this file: + * + * "Check" hook - This only executes fully every five seconds from the tick + * hook. Its main function is to check that all the standard demo tasks are + * still operational. The status can be viewed using on the Task Stats page + * served by the WEB server. + * + * "uIP" task - This is the task that handles the uIP stack. All TCP/IP + * processing is performed in this task. + * + * "USB" task - Enumerates the USB device as a CDC class, then echoes back all + * received characters with a configurable offset (for example, if the offset + * is 1 and 'A' is received then 'B' will be sent back). A dumb terminal such + * as Hyperterminal can be used to talk to the USB task. + */ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Demo app includes. */ +#include "BlockQ.h" +#include "integer.h" +#include "blocktim.h" +#include "flash.h" +#include "partest.h" +#include "semtest.h" +#include "PollQ.h" +#include "GenQTest.h" +#include "QPeek.h" +#include "recmutex.h" + +/* File system includes. */ +#include "diskio.h" +#include "ff.h" + +/*-----------------------------------------------------------*/ + +/* The time between cycles of the 'check' functionality (defined within the +tick hook). */ +#define mainCHECK_DELAY ( ( portTickType ) 5000 / portTICK_RATE_MS ) + +/* Task priorities. */ +#define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 ) +#define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#define mainUIP_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 ) +#define mainINTEGER_TASK_PRIORITY ( tskIDLE_PRIORITY ) +#define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY ) +#define mainFLASH_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) + +/* The WEB server has a larger stack as it utilises stack hungry string +handling library calls. */ +#define mainBASIC_WEB_STACK_SIZE ( configMINIMAL_STACK_SIZE * 4 ) + +/* The message displayed by the WEB server when all tasks are executing +without an error being reported. */ +#define mainPASS_STATUS_MESSAGE "All tasks are executing without error." + +/*-----------------------------------------------------------*/ + +/* + * Configure the hardware for the demo. + */ +static void prvSetupHardware( void ); + +/* + * The task that handles the uIP stack. All TCP/IP processing is performed in + * this task. + */ +extern void vuIP_Task( void *pvParameters ); + +/* + * The task that handles the USB stack. + */ +extern void vUSBTask( void *pvParameters ); + +/* + * Simply returns the current status message for display on served WEB pages. + */ +char *pcGetTaskStatusMessage( void ); + +/*-----------------------------------------------------------*/ + +/* Holds the status message displayed by the WEB server. */ +static char *pcStatusMessage = mainPASS_STATUS_MESSAGE; + +/*-----------------------------------------------------------*/ + +int main( void ) +{ + /* Configure the hardware for use by this demo. */ + prvSetupHardware(); + + /* Start the standard demo tasks. These are just here to exercise the + kernel port and provide examples of how the FreeRTOS API can be used. */ + vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY ); + vCreateBlockTimeTasks(); + vStartSemaphoreTasks( mainSEM_TEST_PRIORITY ); + vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY ); + vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY ); + vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY ); + vStartQueuePeekTasks(); + vStartRecursiveMutexTasks(); + vStartLEDFlashTasks( mainFLASH_TASK_PRIORITY ); + + /* Create the USB task. */ + xTaskCreate( vUSBTask, ( signed char * ) "USB", configMINIMAL_STACK_SIZE, ( void * ) NULL, tskIDLE_PRIORITY, NULL ); + + /* Create the uIP task. The WEB server runs in this task. */ + xTaskCreate( vuIP_Task, ( signed char * ) "uIP", mainBASIC_WEB_STACK_SIZE, ( void * ) NULL, mainUIP_TASK_PRIORITY, NULL ); + + /* Start the scheduler. */ + vTaskStartScheduler(); + + /* Will only get here if there was insufficient memory to create the idle + task. The idle task is created within vTaskStartScheduler(). */ + for( ;; ); +} +/*-----------------------------------------------------------*/ + +void vApplicationTickHook( void ) +{ +static unsigned long ulTicksSinceLastDisplay = 0; + + /* Called from every tick interrupt as described in the comments at the top + of this file. + + Have enough ticks passed to make it time to perform our health status + check again? */ + ulTicksSinceLastDisplay++; + if( ulTicksSinceLastDisplay >= mainCHECK_DELAY ) + { + /* Reset the counter so these checks run again in mainCHECK_DELAY + ticks time. */ + ulTicksSinceLastDisplay = 0; + + /* Has an error been found in any task? */ + if( xAreGenericQueueTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "An error has been detected in the Generic Queue test/demo."; + } + else if( xAreQueuePeekTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "An error has been detected in the Peek Queue test/demo."; + } + else if( xAreBlockingQueuesStillRunning() != pdTRUE ) + { + pcStatusMessage = "An error has been detected in the Block Queue test/demo."; + } + else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "An error has been detected in the Block Time test/demo."; + } + else if( xAreSemaphoreTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "An error has been detected in the Semaphore test/demo."; + } + else if( xArePollingQueuesStillRunning() != pdTRUE ) + { + pcStatusMessage = "An error has been detected in the Poll Queue test/demo."; + } + else if( xAreIntegerMathsTaskStillRunning() != pdTRUE ) + { + pcStatusMessage = "An error has been detected in the Int Math test/demo."; + } + else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "An error has been detected in the Mutex test/demo."; + } + } + + disk_timerproc(); +} +/*-----------------------------------------------------------*/ + +char *pcGetTaskStatusMessage( void ) +{ + /* Not bothered about a critical section here. */ + return pcStatusMessage; +} +/*-----------------------------------------------------------*/ + +void prvSetupHardware( void ) +{ + /* Disable peripherals power. */ + SC->PCONP = 0; + + /* Enable GPIO power. */ + SC->PCONP = PCONP_PCGPIO; + + /* Disable TPIU. */ + PINCON->PINSEL10 = 0; + + /* Setup the peripheral bus to be the same as the PLL output (64 MHz). */ + SC->PCLKSEL0 = 0x05555555; + + /* Configure the LEDs. */ + vParTestInitialise(); + + /* Configure the SPI for communicating with the SD card. */ + disk_init_spi(); + +{ +FATFS fs; +FIL f; +static char c[ 2048 ]; +UINT BytesRead; + + f_mount( 0, &fs ); + f_open( &f, "/test.htm", FA_READ ); + f_read( &f, c, 2048, &BytesRead ); + __asm volatile( "NOP" ); +} + +} +/*-----------------------------------------------------------*/ + +void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName ) +{ + /* This function will get called if a task overflows its stack. */ + + ( void ) pxTask; + ( void ) pcTaskName; + + for( ;; ); +} +/*-----------------------------------------------------------*/ + +void vConfigureTimerForRunTimeStats( void ) +{ +const unsigned long TCR_COUNT_RESET = 2, CTCR_CTM_TIMER = 0x00, TCR_COUNT_ENABLE = 0x01; + + /* This function configures a timer that is used as the time base when + collecting run time statistical information - basically the percentage + of CPU time that each task is utilising. It is called automatically when + the scheduler is started (assuming configGENERATE_RUN_TIME_STATS is set + to 1). */ + + /* Power up and feed the timer. */ + SC->PCONP |= 0x02UL; + SC->PCLKSEL0 = (SC->PCLKSEL0 & (~(0x3<<2))) | (0x01 << 2); + + /* Reset Timer 0 */ + TIM0->TCR = TCR_COUNT_RESET; + + /* Just count up. */ + TIM0->CTCR = CTCR_CTM_TIMER; + + /* Prescale to a frequency that is good enough to get a decent resolution, + but not too fast so as to overflow all the time. */ + TIM0->PR = ( configCPU_CLOCK_HZ / 10000UL ) - 1UL; + + /* Start the counter. */ + TIM0->TCR = TCR_COUNT_ENABLE; +} +/*-----------------------------------------------------------*/ + diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/main.c.bak b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/main.c.bak new file mode 100644 index 000000000..291d8d000 --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/main.c.bak @@ -0,0 +1,318 @@ +/* + FreeRTOS V6.0.2 - Copyright (C) 2010 Real Time Engineers Ltd. + + *************************************************************************** + * * + * If you are: * + * * + * + New to FreeRTOS, * + * + Wanting to learn FreeRTOS or multitasking in general quickly * + * + Looking for basic training, * + * + Wanting to improve your FreeRTOS skills and productivity * + * * + * then take a look at the FreeRTOS eBook * + * * + * "Using the FreeRTOS Real Time Kernel - a Practical Guide" * + * http://www.FreeRTOS.org/Documentation * + * * + * A pdf reference manual is also available. Both are usually delivered * + * to your inbox within 20 minutes to two hours when purchased between 8am * + * and 8pm GMT (although please allow up to 24 hours in case of * + * exceptional circumstances). Thank you for your support! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + ***NOTE*** The exception to the GPL is included to allow you to distribute + a combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +/* + * Creates all the demo application tasks, then starts the scheduler. The WEB + * documentation provides more details of the standard demo application tasks + * (which just exist to test the kernel port and provide an example of how to use + * each FreeRTOS API function). + * + * In addition to the standard demo tasks, the following tasks and tests are + * defined and/or created within this file: + * + * "Check" hook - This only executes fully every five seconds from the tick + * hook. Its main function is to check that all the standard demo tasks are + * still operational. The status can be viewed using on the Task Stats page + * served by the WEB server. + * + * "uIP" task - This is the task that handles the uIP stack. All TCP/IP + * processing is performed in this task. + * + * "USB" task - Enumerates the USB device as a CDC class, then echoes back all + * received characters with a configurable offset (for example, if the offset + * is 1 and 'A' is received then 'B' will be sent back). A dumb terminal such + * as Hyperterminal can be used to talk to the USB task. + */ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Demo app includes. */ +#include "BlockQ.h" +#include "integer.h" +#include "blocktim.h" +#include "flash.h" +#include "partest.h" +#include "semtest.h" +#include "PollQ.h" +#include "GenQTest.h" +#include "QPeek.h" +#include "recmutex.h" + +/* File system includes. */ +#include "diskio.h" +#include "ff.h" + +/*-----------------------------------------------------------*/ + +/* The time between cycles of the 'check' functionality (defined within the +tick hook). */ +#define mainCHECK_DELAY ( ( portTickType ) 5000 / portTICK_RATE_MS ) + +/* Task priorities. */ +#define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 ) +#define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#define mainUIP_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 ) +#define mainINTEGER_TASK_PRIORITY ( tskIDLE_PRIORITY ) +#define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY ) +#define mainFLASH_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) + +/* The WEB server has a larger stack as it utilises stack hungry string +handling library calls. */ +#define mainBASIC_WEB_STACK_SIZE ( configMINIMAL_STACK_SIZE * 4 ) + +/* The message displayed by the WEB server when all tasks are executing +without an error being reported. */ +#define mainPASS_STATUS_MESSAGE "All tasks are executing without error." + +/*-----------------------------------------------------------*/ + +/* + * Configure the hardware for the demo. + */ +static void prvSetupHardware( void ); + +/* + * The task that handles the uIP stack. All TCP/IP processing is performed in + * this task. + */ +extern void vuIP_Task( void *pvParameters ); + +/* + * The task that handles the USB stack. + */ +extern void vUSBTask( void *pvParameters ); + +/* + * Simply returns the current status message for display on served WEB pages. + */ +char *pcGetTaskStatusMessage( void ); + +/*-----------------------------------------------------------*/ + +/* Holds the status message displayed by the WEB server. */ +static char *pcStatusMessage = mainPASS_STATUS_MESSAGE; + +/*-----------------------------------------------------------*/ + +int main( void ) +{ + /* Configure the hardware for use by this demo. */ + prvSetupHardware(); + + /* Start the standard demo tasks. These are just here to exercise the + kernel port and provide examples of how the FreeRTOS API can be used. */ + vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY ); + vCreateBlockTimeTasks(); + vStartSemaphoreTasks( mainSEM_TEST_PRIORITY ); + vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY ); + vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY ); + vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY ); + vStartQueuePeekTasks(); + vStartRecursiveMutexTasks(); + vStartLEDFlashTasks( mainFLASH_TASK_PRIORITY ); + + /* Create the USB task. */ + xTaskCreate( vUSBTask, ( signed char * ) "USB", configMINIMAL_STACK_SIZE, ( void * ) NULL, tskIDLE_PRIORITY, NULL ); + + /* Create the uIP task. The WEB server runs in this task. */ + xTaskCreate( vuIP_Task, ( signed char * ) "uIP", mainBASIC_WEB_STACK_SIZE, ( void * ) NULL, mainUIP_TASK_PRIORITY, NULL ); + + /* Start the scheduler. */ + vTaskStartScheduler(); + + /* Will only get here if there was insufficient memory to create the idle + task. The idle task is created within vTaskStartScheduler(). */ + for( ;; ); +} +/*-----------------------------------------------------------*/ + +void vApplicationTickHook( void ) +{ +static unsigned long ulTicksSinceLastDisplay = 0; + + /* Called from every tick interrupt as described in the comments at the top + of this file. + + Have enough ticks passed to make it time to perform our health status + check again? */ + ulTicksSinceLastDisplay++; + if( ulTicksSinceLastDisplay >= mainCHECK_DELAY ) + { + /* Reset the counter so these checks run again in mainCHECK_DELAY + ticks time. */ + ulTicksSinceLastDisplay = 0; + + /* Has an error been found in any task? */ + if( xAreGenericQueueTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "An error has been detected in the Generic Queue test/demo."; + } + else if( xAreQueuePeekTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "An error has been detected in the Peek Queue test/demo."; + } + else if( xAreBlockingQueuesStillRunning() != pdTRUE ) + { + pcStatusMessage = "An error has been detected in the Block Queue test/demo."; + } + else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "An error has been detected in the Block Time test/demo."; + } + else if( xAreSemaphoreTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "An error has been detected in the Semaphore test/demo."; + } + else if( xArePollingQueuesStillRunning() != pdTRUE ) + { + pcStatusMessage = "An error has been detected in the Poll Queue test/demo."; + } + else if( xAreIntegerMathsTaskStillRunning() != pdTRUE ) + { + pcStatusMessage = "An error has been detected in the Int Math test/demo."; + } + else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "An error has been detected in the Mutex test/demo."; + } + } + + disk_timerproc(); +} +/*-----------------------------------------------------------*/ + +char *pcGetTaskStatusMessage( void ) +{ + /* Not bothered about a critical section here. */ + return pcStatusMessage; +} +/*-----------------------------------------------------------*/ + +void prvSetupHardware( void ) +{ + /* Disable peripherals power. */ + SC->PCONP = 0; + + /* Enable GPIO power. */ + SC->PCONP = PCONP_PCGPIO; + + /* Disable TPIU. */ + PINCON->PINSEL10 = 0; + + /* Setup the peripheral bus to be the same as the PLL output (64 MHz). */ + SC->PCLKSEL0 = 0x05555555; + + /* Configure the LEDs. */ + vParTestInitialise(); + + /* Configure the SPI for communicating with the SD card. */ + disk_init_spi(); + +{ +FATFS fs; +FIL f; +static char c[ 2048 ]; +UINT BytesRead; + + f_mount( 0, &fs ); + f_open( &f, "/test.htm", FA_READ ); + f_read( &f, c, 2048, &BytesRead ); +} + +} +/*-----------------------------------------------------------*/ + +void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName ) +{ + /* This function will get called if a task overflows its stack. */ + + ( void ) pxTask; + ( void ) pcTaskName; + + for( ;; ); +} +/*-----------------------------------------------------------*/ + +void vConfigureTimerForRunTimeStats( void ) +{ +const unsigned long TCR_COUNT_RESET = 2, CTCR_CTM_TIMER = 0x00, TCR_COUNT_ENABLE = 0x01; + + /* This function configures a timer that is used as the time base when + collecting run time statistical information - basically the percentage + of CPU time that each task is utilising. It is called automatically when + the scheduler is started (assuming configGENERATE_RUN_TIME_STATS is set + to 1). */ + + /* Power up and feed the timer. */ + SC->PCONP |= 0x02UL; + SC->PCLKSEL0 = (SC->PCLKSEL0 & (~(0x3<<2))) | (0x01 << 2); + + /* Reset Timer 0 */ + TIM0->TCR = TCR_COUNT_RESET; + + /* Just count up. */ + TIM0->CTCR = CTCR_CTM_TIMER; + + /* Prescale to a frequency that is good enough to get a decent resolution, + but not too fast so as to overflow all the time. */ + TIM0->PR = ( configCPU_CLOCK_HZ / 10000UL ) - 1UL; + + /* Start the counter. */ + TIM0->TCR = TCR_COUNT_ENABLE; +} +/*-----------------------------------------------------------*/ + diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/printf-stdarg.c b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/printf-stdarg.c new file mode 100644 index 000000000..b5ac41be7 --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/printf-stdarg.c @@ -0,0 +1,293 @@ +/* + Copyright 2001, 2002 Georges Menie (www.menie.org) + stdarg version contributed by Christian Ettinger + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + putchar is the only external dependency for this file, + if you have a working putchar, leave it commented out. + If not, uncomment the define below and + replace outbyte(c) by your own function call. + +*/ + +#define putchar(c) c + +#include + +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; +} + diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/system_LPC17xx.h b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/system_LPC17xx.h new file mode 100644 index 000000000..a5c9727d4 --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/system_LPC17xx.h @@ -0,0 +1,40 @@ +/****************************************************************************** + * @file: system_LPC17xx.h + * @purpose: CMSIS Cortex-M3 Device Peripheral Access Layer Header File + * for the NXP LPC17xx Device Series + * @version: V1.0 + * @date: 25. Nov. 2008 + *---------------------------------------------------------------------------- + * + * Copyright (C) 2008 ARM Limited. All rights reserved. + * + * ARM Limited (ARM) is supplying this software for use with Cortex-M3 + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + + +#ifndef __SYSTEM_LPC17xx_H +#define __SYSTEM_LPC17xx_H + +extern uint32_t SystemFrequency; /*!< System Clock Frequency (Core Clock) */ + + +/** + * Initialize the system + * + * @param none + * @return none + * + * @brief Setup the microcontroller system. + * Initialize the System and update the SystemFrequency variable. + */ +extern void SystemInit (void); +#endif diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/usbser.inf b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/usbser.inf new file mode 100644 index 000000000..607fc9e6d --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/usbser.inf @@ -0,0 +1,45 @@ +[Version] +Signature="$Windows NT$" +Class=Ports +ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} +Provider=%LINUX% +DriverVer=08/17/2004,0.0.2.0 +; Copyright (C) 2004 Al Borchers (alborchers@steinerpoint.com) +; released under GNU General Public License + +[Manufacturer] +%LINUX%=GSerialDeviceList + +[GSerialDeviceList] +%GSERIAL%=GSerialInstall, USB\VID_FFFF&PID_0005 + +[DestinationDirs] +DefaultDestDir=10,System32\Drivers + +[GSerialInstall] +CopyFiles=GSerialCopyFiles +AddReg=GSerialAddReg + +[GSerialCopyFiles] +usbser.sys + +[GSerialAddReg] +HKR,,DevLoader,,*ntkern +HKR,,NTMPDriver,,usbser.sys +HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" + +[GSerialInstall.Services] +AddService = usbser,0x0002,GSerialService + +[GSerialService] +DisplayName = %GSERIAL_DISPLAY_NAME% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 1 ; SERVICE_ERROR_NORMAL +ServiceBinary = %10%\System32\Drivers\usbser.sys +LoadOrderGroup = Base + +[Strings] +LINUX = "Linux" +GSERIAL = "USB CDC serial port emulation" +GSERIAL_DISPLAY_NAME = "USB CDC serial port emulation" \ No newline at end of file diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/webserver/EthDev.h b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/webserver/EthDev.h new file mode 100644 index 000000000..f67789f44 --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/webserver/EthDev.h @@ -0,0 +1,111 @@ +/* + * @file: EthDev.h + * @purpose: Ethernet Device Definitions + * @version: V1.10 + * @date: 24. Feb. 2009 + *---------------------------------------------------------------------------- + * + * Copyright (C) 2009 ARM Limited. All rights reserved. + * + * ARM Limited (ARM) is supplying this software for use with Cortex-M3 + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + */ + +#ifndef _ETHDEV__H +#define _ETHDEV__H + +#ifndef NULL + #define NULL 0 +#endif + +/*---------------------------------------------------------------------------- + Ethernet Device Defines + *----------------------------------------------------------------------------*/ +#define EthDev_ADDR_SIZE 6 /*!< Ethernet Address size in bytes */ +#define EthDev_MTU_SIZE 1514 /*!< Maximum Transmission Unit */ + + +/*---------------------------------------------------------------------------- + Ethernet Device Configuration and Control Command Defines + *----------------------------------------------------------------------------*/ +typedef enum { + EthDev_LINK_DOWN = 0, /*!< Ethernet link not established */ + EthDev_LINK_UP = 1, /*!< Ethernet link established */ +} EthDev_LINK; + +typedef enum { + EthDev_SPEED_10M = 0, /*!< 10.0 Mbps link speed */ + EthDev_SPEED_100M = 1, /*!< 100.0 Mbps link speed */ + EthDev_SPEED_1000M = 2, /*!< 1.0 Gbps link speed */ +} EthDev_SPEED; + +typedef enum { + EthDev_DUPLEX_HALF = 0, /*!< Link half duplex */ + EthDev_DUPLEX_FULL = 1, /*!< Link full duplex */ +} EthDev_DUPLEX; + +typedef enum { + EthDev_MODE_AUTO = 0, + EthDev_MODE_10M_FULL = 1, + EthDev_MODE_10M_HALF = 2, + EthDev_MODE_100M_FULL = 3, + EthDev_MODE_100M_HALF = 4, + EthDev_MODE_1000M_FULL = 5, + EthDev_MODE_1000M_HALF = 6, +} EthDev_MODE; + +typedef struct { + EthDev_LINK Link : 1; + EthDev_DUPLEX Duplex : 1; + EthDev_SPEED Speed : 2; +} EthDev_STATUS; + + +/*---------------------------------------------------------------------------- + Ethernet Device IO Block Structure + *----------------------------------------------------------------------------*/ +typedef struct { + + /* Initialized by the user application before call to Init. */ + EthDev_MODE Mode; + unsigned char HwAddr[EthDev_ADDR_SIZE]; + void *(*RxFrame) (int size); + void (*RxFrameReady) (int size); + + /* Initialized by Ethernet driver. */ + int (*Init) (void); + int (*UnInit) (void); + int (*SetMCFilter)(int NumHwAddr, unsigned char *pHwAddr); + int (*TxFrame) (void *pData, int size); + void (*Lock) (void); + void (*UnLock) (void); + EthDev_STATUS (*LinkChk) (void); +} EthDev_IOB; + + +/* + * Look for received data. If data is found then uip_buf is assigned to the + * new data and the length of the data is returned. If no data is found then + * uip_buf is not updated and 0 is returned. + */ +unsigned long ulGetEMACRxData( void ); + +/* + * Send usTxDataLen bytes from uip_buf. + */ +void vSendEMACTxData( unsigned short usTxDataLen ); + +/* + * Prepare the Ethernet hardware ready for TCP/IP comms. + */ +long lEMACInit(void); + +#endif diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/webserver/EthDev_LPC17xx.h b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/webserver/EthDev_LPC17xx.h new file mode 100644 index 000000000..93134430f --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/webserver/EthDev_LPC17xx.h @@ -0,0 +1,331 @@ +/* + * @file: EthDev_LPC17xx.h + * @purpose: Ethernet Device Definitions for NXP LPC17xx + * @version: V0.01 + * @date: 14. May 2009 + *---------------------------------------------------------------------------- + * + * Copyright (C) 2009 ARM Limited. All rights reserved. + * + * ARM Limited (ARM) is supplying this software for use with Cortex-M3 + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + */ + +#ifndef __ETHDEV_LPC17XX_H +#define __ETHDEV_LPC17XX_H + +#include + +/* 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 + *---------------------------------------------------------------------------*/ diff --git a/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/webserver/emac.c b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/webserver/emac.c new file mode 100644 index 000000000..46c0688b8 --- /dev/null +++ b/Demo/CORTEX_LPC17xx_Rowley_lwIP_FatFs_USB/webserver/emac.c @@ -0,0 +1,604 @@ +/* + FreeRTOS V6.0.2 - Copyright (C) 2010 Real Time Engineers Ltd. + + *************************************************************************** + * * + * If you are: * + * * + * + New to FreeRTOS, * + * + Wanting to learn FreeRTOS or multitasking in general quickly * + * + Looking for basic training, * + * + Wanting to improve your FreeRTOS skills and productivity * + * * + * then take a look at the FreeRTOS eBook * + * * + * "Using the FreeRTOS Real Time Kernel - a Practical Guide" * + * http://www.FreeRTOS.org/Documentation * + * * + * A pdf reference manual is also available. Both are usually delivered * + * to your inbox within 20 minutes to two hours when purchased between 8am * + * and 8pm GMT (although please allow up to 24 hours in case of * + * exceptional circumstances). Thank you for your support! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + ***NOTE*** The exception to the GPL is included to allow you to distribute + a combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* Originally adapted from file written by Andreas Dannenberg. Supplied with permission. */ + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* Hardware specific includes. */ +#include "EthDev_LPC17xx.h" + +/* Time to wait between each inspection of the link status. */ +#define emacWAIT_FOR_LINK_TO_ESTABLISH ( 500 / portTICK_RATE_MS ) + +/* Short delay used in several places during the initialisation process. */ +#define emacSHORT_DELAY ( 2 ) + +/* Hardware specific bit definitions. */ +#define emacLINK_ESTABLISHED ( 0x0001 ) +#define emacFULL_DUPLEX_ENABLED ( 0x0004 ) +#define emac10BASE_T_MODE ( 0x0002 ) +#define emacPINSEL2_VALUE ( 0x50150105 ) + +/* If no buffers are available, then wait this long before looking again.... */ +#define emacBUFFER_WAIT_DELAY ( 3 / portTICK_RATE_MS ) + +/* ...and don't look more than this many times. */ +#define emacBUFFER_WAIT_ATTEMPTS ( 30 ) + +/* Index to the Tx descriptor that is always used first for every Tx. The second +descriptor is then used to re-send in order to speed up the uIP Tx process. */ +#define emacTX_DESC_INDEX ( 0 ) + +/*-----------------------------------------------------------*/ + +/* + * Configure both the Rx and Tx descriptors during the init process. + */ +static void prvInitDescriptors( void ); + +/* + * Setup the IO and peripherals required for Ethernet communication. + */ +static void prvSetupEMACHardware( void ); + +/* + * Control the auto negotiate process. + */ +static void prvConfigurePHY( void ); + +/* + * Wait for a link to be established, then setup the PHY according to the link + * parameters. + */ +static long prvSetupLinkStatus( void ); + +/* + * Search the pool of buffers to find one that is free. If a buffer is found + * mark it as in use before returning its address. + */ +static unsigned char *prvGetNextBuffer( void ); + +/* + * Return an allocated buffer to the pool of free buffers. + */ +static void prvReturnBuffer( unsigned char *pucBuffer ); + +/* + * Send lValue to the lPhyReg within the PHY. + */ +static long prvWritePHY( long lPhyReg, long lValue ); + +/* + * Read a value from ucPhyReg within the PHY. *plStatus will be set to + * pdFALSE if there is an error. + */ +static unsigned short prvReadPHY( unsigned char ucPhyReg, long *plStatus ); + +/*-----------------------------------------------------------*/ + +/* The semaphore used to wake the uIP task when data arrives. */ +extern xSemaphoreHandle xEMACSemaphore; + +/* Each ucBufferInUse index corresponds to a position in the pool of buffers. +If the index contains a 1 then the buffer within pool is in use, if it +contains a 0 then the buffer is free. */ +static unsigned char ucBufferInUse[ ETH_NUM_BUFFERS ] = { pdFALSE }; + +/* The uip_buffer is not a fixed array, but instead gets pointed to the buffers +allocated within this file. */ +unsigned char * uip_buf; + +/* Store the length of the data being sent so the data can be sent twice. The +value will be set back to 0 once the data has been sent twice. */ +static unsigned short usSendLen = 0; + +/*-----------------------------------------------------------*/ + +long lEMACInit( void ) +{ +long lReturn = pdPASS; +unsigned long ulID1, ulID2; + + /* Reset peripherals, configure port pins and registers. */ + prvSetupEMACHardware(); + + /* Check the PHY part number is as expected. */ + ulID1 = prvReadPHY( PHY_REG_IDR1, &lReturn ); + ulID2 = prvReadPHY( PHY_REG_IDR2, &lReturn ); + if( ( (ulID1 << 16UL ) | ( ulID2 & 0xFFF0UL ) ) == DP83848C_ID ) + { + /* Set the Ethernet MAC Address registers */ + EMAC->SA0 = ( configMAC_ADDR0 << 8 ) | configMAC_ADDR1; + EMAC->SA1 = ( configMAC_ADDR2 << 8 ) | configMAC_ADDR3; + EMAC->SA2 = ( configMAC_ADDR4 << 8 ) | configMAC_ADDR5; + + /* Initialize Tx and Rx DMA Descriptors */ + prvInitDescriptors(); + + /* Receive broadcast and perfect match packets */ + EMAC->RxFilterCtrl = RFC_UCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN; + + /* Setup the PHY. */ + prvConfigurePHY(); + } + else + { + lReturn = pdFAIL; + } + + /* Check the link status. */ + if( lReturn == pdPASS ) + { + lReturn = prvSetupLinkStatus(); + } + + if( lReturn == pdPASS ) + { + /* Initialise uip_buf to ensure it points somewhere valid. */ + uip_buf = prvGetNextBuffer(); + + /* Reset all interrupts */ + EMAC->IntClear = ( INT_RX_OVERRUN | INT_RX_ERR | INT_RX_FIN | INT_RX_DONE | INT_TX_UNDERRUN | INT_TX_ERR | INT_TX_FIN | INT_TX_DONE | INT_SOFT_INT | INT_WAKEUP ); + + /* Enable receive and transmit mode of MAC Ethernet core */ + EMAC->Command |= ( CR_RX_EN | CR_TX_EN ); + EMAC->MAC1 |= MAC1_REC_EN; + } + + return lReturn; +} +/*-----------------------------------------------------------*/ + +static unsigned char *prvGetNextBuffer( void ) +{ +long x; +unsigned char *pucReturn = NULL; +unsigned long ulAttempts = 0; + + while( pucReturn == NULL ) + { + /* Look through the buffers to find one that is not in use by + anything else. */ + for( x = 0; x < ETH_NUM_BUFFERS; x++ ) + { + if( ucBufferInUse[ x ] == pdFALSE ) + { + ucBufferInUse[ x ] = pdTRUE; + pucReturn = ( unsigned char * ) ETH_BUF( x ); + break; + } + } + + /* Was a buffer found? */ + if( pucReturn == NULL ) + { + ulAttempts++; + + if( ulAttempts >= emacBUFFER_WAIT_ATTEMPTS ) + { + break; + } + + /* Wait then look again. */ + vTaskDelay( emacBUFFER_WAIT_DELAY ); + } + } + + return pucReturn; +} +/*-----------------------------------------------------------*/ + +static void prvInitDescriptors( void ) +{ +long x, lNextBuffer = 0; + + for( x = 0; x < NUM_RX_FRAG; x++ ) + { + /* Allocate the next Ethernet buffer to this descriptor. */ + RX_DESC_PACKET( x ) = ETH_BUF( lNextBuffer ); + RX_DESC_CTRL( x ) = RCTRL_INT | ( ETH_FRAG_SIZE - 1 ); + RX_STAT_INFO( x ) = 0; + RX_STAT_HASHCRC( x ) = 0; + + /* The Ethernet buffer is now in use. */ + ucBufferInUse[ lNextBuffer ] = pdTRUE; + lNextBuffer++; + } + + /* Set EMAC Receive Descriptor Registers. */ + EMAC->RxDescriptor = RX_DESC_BASE; + EMAC->RxStatus = RX_STAT_BASE; + EMAC->RxDescriptorNumber = NUM_RX_FRAG - 1; + + /* Rx Descriptors Point to 0 */ + EMAC->RxConsumeIndex = 0; + + /* A buffer is not allocated to the Tx descriptors until they are actually + used. */ + for( x = 0; x < NUM_TX_FRAG; x++ ) + { + TX_DESC_PACKET( x ) = ( unsigned long ) NULL; + TX_DESC_CTRL( x ) = 0; + TX_STAT_INFO( x ) = 0; + } + + /* Set EMAC Transmit Descriptor Registers. */ + EMAC->TxDescriptor = TX_DESC_BASE; + EMAC->TxStatus = TX_STAT_BASE; + EMAC->TxDescriptorNumber = NUM_TX_FRAG - 1; + + /* Tx Descriptors Point to 0 */ + EMAC->TxProduceIndex = 0; +} +/*-----------------------------------------------------------*/ + +static void prvSetupEMACHardware( void ) +{ +unsigned short us; +long x, lDummy; + + /* Enable P1 Ethernet Pins. */ + PINCON->PINSEL2 = emacPINSEL2_VALUE; + PINCON->PINSEL3 = ( PINCON->PINSEL3 & ~0x0000000F ) | 0x00000005; + + /* Power Up the EMAC controller. */ + SC->PCONP |= PCONP_PCENET; + vTaskDelay( emacSHORT_DELAY ); + + /* Reset all EMAC internal modules. */ + EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES; + EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM; + + /* A short delay after reset. */ + vTaskDelay( emacSHORT_DELAY ); + + /* Initialize MAC control registers. */ + EMAC->MAC1 = MAC1_PASS_ALL; + EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN; + EMAC->MAXF = ETH_MAX_FLEN; + EMAC->CLRT = CLRT_DEF; + EMAC->IPGR = IPGR_DEF; + + /* Enable Reduced MII interface. */ + EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM; + + /* Reset Reduced MII Logic. */ + EMAC->SUPP = SUPP_RES_RMII; + vTaskDelay( emacSHORT_DELAY ); + EMAC->SUPP = 0; + + /* Put the PHY in reset mode */ + prvWritePHY( PHY_REG_BMCR, MCFG_RES_MII ); + prvWritePHY( PHY_REG_BMCR, MCFG_RES_MII ); + + /* Wait for hardware reset to end. */ + for( x = 0; x < 100; x++ ) + { + vTaskDelay( emacSHORT_DELAY * 5 ); + us = prvReadPHY( PHY_REG_BMCR, &lDummy ); + if( !( us & MCFG_RES_MII ) ) + { + /* Reset complete */ + break; + } + } +} +/*-----------------------------------------------------------*/ + +static void prvConfigurePHY( void ) +{ +unsigned short us; +long x, lDummy; + + /* Auto negotiate the configuration. */ + if( prvWritePHY( PHY_REG_BMCR, PHY_AUTO_NEG ) ) + { + vTaskDelay( emacSHORT_DELAY * 5 ); + + for( x = 0; x < 10; x++ ) + { + us = prvReadPHY( PHY_REG_BMSR, &lDummy ); + + if( us & PHY_AUTO_NEG_COMPLETE ) + { + break; + } + + vTaskDelay( emacWAIT_FOR_LINK_TO_ESTABLISH ); + } + } +} +/*-----------------------------------------------------------*/ + +static long prvSetupLinkStatus( void ) +{ +long lReturn = pdFAIL, x; +unsigned short usLinkStatus; + + /* Wait with timeout for the link to be established. */ + for( x = 0; x < 10; x++ ) + { + usLinkStatus = prvReadPHY( PHY_REG_STS, &lReturn ); + if( usLinkStatus & emacLINK_ESTABLISHED ) + { + /* Link is established. */ + lReturn = pdPASS; + break; + } + + vTaskDelay( emacWAIT_FOR_LINK_TO_ESTABLISH ); + } + + if( lReturn == pdPASS ) + { + /* Configure Full/Half Duplex mode. */ + if( usLinkStatus & emacFULL_DUPLEX_ENABLED ) + { + /* Full duplex is enabled. */ + EMAC->MAC2 |= MAC2_FULL_DUP; + EMAC->Command |= CR_FULL_DUP; + EMAC->IPGT = IPGT_FULL_DUP; + } + else + { + /* Half duplex mode. */ + EMAC->IPGT = IPGT_HALF_DUP; + } + + /* Configure 100MBit/10MBit mode. */ + if( usLinkStatus & emac10BASE_T_MODE ) + { + /* 10MBit mode. */ + EMAC->SUPP = 0; + } + else + { + /* 100MBit mode. */ + EMAC->SUPP = SUPP_SPEED; + } + } + + return lReturn; +} +/*-----------------------------------------------------------*/ + +static void prvReturnBuffer( unsigned char *pucBuffer ) +{ +unsigned long ul; + + /* Return a buffer to the pool of free buffers. */ + for( ul = 0; ul < ETH_NUM_BUFFERS; ul++ ) + { + if( ETH_BUF( ul ) == ( unsigned long ) pucBuffer ) + { + ucBufferInUse[ ul ] = pdFALSE; + break; + } + } +} +/*-----------------------------------------------------------*/ + +unsigned long ulGetEMACRxData( void ) +{ +unsigned long ulLen = 0; +long lIndex; + + if( EMAC->RxProduceIndex != EMAC->RxConsumeIndex ) + { + /* Mark the current buffer as free as uip_buf is going to be set to + the buffer that contains the received data. */ + prvReturnBuffer( uip_buf ); + + ulLen = ( RX_STAT_INFO( EMAC->RxConsumeIndex ) & RINFO_SIZE ) - 3; + uip_buf = ( unsigned char * ) RX_DESC_PACKET( EMAC->RxConsumeIndex ); + + /* Allocate a new buffer to the descriptor. */ + RX_DESC_PACKET( EMAC->RxConsumeIndex ) = ( unsigned long ) prvGetNextBuffer(); + + /* Move the consume index onto the next position, ensuring it wraps to + the beginning at the appropriate place. */ + lIndex = EMAC->RxConsumeIndex; + + lIndex++; + if( lIndex >= NUM_RX_FRAG ) + { + lIndex = 0; + } + + EMAC->RxConsumeIndex = lIndex; + } + + return ulLen; +} +/*-----------------------------------------------------------*/ + +void vSendEMACTxData( unsigned short usTxDataLen ) +{ +unsigned long ulAttempts = 0UL; + + /* Check to see if the Tx descriptor is free, indicated by its buffer being + NULL. */ + while( TX_DESC_PACKET( emacTX_DESC_INDEX ) != ( unsigned long ) NULL ) + { + /* Wait for the Tx descriptor to become available. */ + vTaskDelay( emacBUFFER_WAIT_DELAY ); + + ulAttempts++; + if( ulAttempts > emacBUFFER_WAIT_ATTEMPTS ) + { + /* Something has gone wrong as the Tx descriptor is still in use. + Clear it down manually, the data it was sending will probably be + lost. */ + prvReturnBuffer( ( unsigned char * ) TX_DESC_PACKET( emacTX_DESC_INDEX ) ); + break; + } + } + + /* Setup the Tx descriptor for transmission. Remember the length of the + data being sent so the second descriptor can be used to send it again from + within the ISR. */ + usSendLen = usTxDataLen; + TX_DESC_PACKET( emacTX_DESC_INDEX ) = ( unsigned long ) uip_buf; + TX_DESC_CTRL( emacTX_DESC_INDEX ) = ( usTxDataLen | TCTRL_LAST | TCTRL_INT ); + EMAC->TxProduceIndex = ( emacTX_DESC_INDEX + 1 ); + + /* uip_buf is being sent by the Tx descriptor. Allocate a new buffer. */ + uip_buf = prvGetNextBuffer(); +} +/*-----------------------------------------------------------*/ + +static long prvWritePHY( long lPhyReg, long lValue ) +{ +const long lMaxTime = 10; +long x; + + EMAC->MADR = DP83848C_DEF_ADR | lPhyReg; + EMAC->MWTD = lValue; + + x = 0; + for( x = 0; x < lMaxTime; x++ ) + { + if( ( EMAC->MIND & MIND_BUSY ) == 0 ) + { + /* Operation has finished. */ + break; + } + + vTaskDelay( emacSHORT_DELAY ); + } + + if( x < lMaxTime ) + { + return pdPASS; + } + else + { + return pdFAIL; + } +} +/*-----------------------------------------------------------*/ + +static unsigned short prvReadPHY( unsigned char ucPhyReg, long *plStatus ) +{ +long x; +const long lMaxTime = 10; + + EMAC->MADR = DP83848C_DEF_ADR | ucPhyReg; + EMAC->MCMD = MCMD_READ; + + for( x = 0; x < lMaxTime; x++ ) + { + /* Operation has finished. */ + if( ( EMAC->MIND & MIND_BUSY ) == 0 ) + { + break; + } + + vTaskDelay( emacSHORT_DELAY ); + } + + EMAC->MCMD = 0; + + if( x >= lMaxTime ) + { + *plStatus = pdFAIL; + } + + return( EMAC->MRDD ); +} +/*-----------------------------------------------------------*/ + +void vEMAC_ISR( void ) +{ +unsigned long ulStatus; +long lHigherPriorityTaskWoken = pdFALSE; + + ulStatus = EMAC->IntStatus; + + /* Clear the interrupt. */ + EMAC->IntClear = ulStatus; + + if( ulStatus & INT_RX_DONE ) + { + /* Ensure the uIP task is not blocked as data has arrived. */ + xSemaphoreGiveFromISR( xEMACSemaphore, &lHigherPriorityTaskWoken ); + } + + if( ulStatus & INT_TX_DONE ) + { + if( usSendLen > 0 ) + { + /* Send the data again, using the second descriptor. As there are + only two descriptors the index is set back to 0. */ + TX_DESC_PACKET( ( emacTX_DESC_INDEX + 1 ) ) = TX_DESC_PACKET( emacTX_DESC_INDEX ); + TX_DESC_CTRL( ( emacTX_DESC_INDEX + 1 ) ) = ( usSendLen | TCTRL_LAST | TCTRL_INT ); + EMAC->TxProduceIndex = ( emacTX_DESC_INDEX ); + + /* This is the second Tx so set usSendLen to 0 to indicate that the + Tx descriptors will be free again. */ + usSendLen = 0UL; + } + else + { + /* The Tx buffer is no longer required. */ + prvReturnBuffer( ( unsigned char * ) TX_DESC_PACKET( emacTX_DESC_INDEX ) ); + TX_DESC_PACKET( emacTX_DESC_INDEX ) = ( unsigned long ) NULL; + } + } + + portEND_SWITCHING_ISR( lHigherPriorityTaskWoken ); +}