diff --git a/demos/ARM7-LPC214x-GCC/main.c b/demos/ARM7-LPC214x-GCC/main.c index 9e0a4222c..614020271 100644 --- a/demos/ARM7-LPC214x-GCC/main.c +++ b/demos/ARM7-LPC214x-GCC/main.c @@ -21,7 +21,6 @@ #include "lpc214x.h" #include "lpc214x_serial.h" -//#include "lpc214x_ssp.h" #include "mmcsd.h" #include "buzzer.h" #include "evtimer.h" @@ -56,8 +55,9 @@ static t_msg Thread2(void *arg) { return 0; } +static BYTE8 rwbuf[512]; + static void TimerHandler(t_eventid id) { -// static BYTE8 sspbuf[16]; t_msg TestThread(void *p); if (!(IO0PIN & 0x00018000)) { // Both buttons @@ -68,16 +68,21 @@ static void TimerHandler(t_eventid id) { if (!(IO0PIN & 0x00008000)) // Button 1 PlaySound(1000, 100); if (!(IO0PIN & 0x00010000)) { // Button 2 -// sspRW(sspbuf, (BYTE8 *)"Hello World!\r\n", 14); -// chFDDWrite(&COM1, sspbuf, 14); + MMCCSD data; + chFDDWrite(&COM1, (BYTE8 *)"Hello World!\r\n", 14); - if (!mmcInit()) - PlaySound(2000, 500); + if (mmcInit()) + return; + if (mmcGetSize(&data)) + return; + if (mmcBlockRead(0x200000, rwbuf)) + return; + PlaySound(2000, 100); } } } -static BYTE8 waThread3[UserStackSize(64)]; +static BYTE8 waThread3[UserStackSize(128)]; static EvTimer evt; static t_evhandler evhndl[1] = { TimerHandler diff --git a/demos/ARM7-LPC214x-GCC/mmcsd.c b/demos/ARM7-LPC214x-GCC/mmcsd.c index 1c0d5c7d8..7867782c9 100644 --- a/demos/ARM7-LPC214x-GCC/mmcsd.c +++ b/demos/ARM7-LPC214x-GCC/mmcsd.c @@ -26,11 +26,64 @@ static EventSource MMCInsertEventSource; +/* + * Subsystem initialization. + */ void InitMMC(void) { chEvtInit(&MMCInsertEventSource); } +static void sendhdr(BYTE8 cmd, ULONG32 arg) { + BYTE8 buf[6]; + + /* + * Wait for the bus to become idle if a write operation was in progress. + */ + while (TRUE) { + sspRW(buf, NULL, 1); + if (buf[0] == 0xFF) + break; +#ifdef NICE_WAITING + chThdSleep(1); /* Trying to be nice with the other threads.*/ +#endif + } + + buf[0] = 0x40 | cmd; + buf[1] = arg >> 24; + buf[2] = arg >> 16; + buf[3] = arg >> 8; + buf[4] = arg; + buf[5] = 0x95; /* Valid for CMD0 ingnored by other commands. */ + sspRW(NULL, buf, 6); +} + +static BYTE8 recvr1(void) { + int i; + BYTE8 r1[1]; + + for (i = 0; i < 9; i++) { + sspRW(r1, NULL, 1); + if (r1[0] != 0xFF) + return r1[0]; + } + return 0xFF; /* Timeout.*/ +} + +static BOOL getdata(BYTE8 *buf, ULONG32 n) { + int i; + + for (i = 0; i < MMC_WAIT_DATA; i++) { + sspRW(buf, NULL, 1); + if (buf[0] == 0xFE) { + sspRW(buf, NULL, n); + sspRW(NULL, NULL, 2); /* CRC ignored.*/ + return FALSE; + } + } + return TRUE; /* Timeout.*/ +} + /* * Initializes a card after the power up by selecting the SPI mode. */ @@ -47,7 +100,7 @@ BOOL mmcInit(void) { sspRW(NULL, NULL, 16); /* 128 clock pulses without ~CS asserted. */ int i = 0; while (TRUE) { - if (mmcSendCommand(0, 0) == 0x01) + if (mmcSendCommand(CMDGOIDLE, 0) == 0x01) break; if (++i >= CMD0_RETRY) return TRUE; @@ -59,7 +112,7 @@ BOOL mmcInit(void) { */ i = 0; while (TRUE) { - BYTE8 b = mmcSendCommand(1, 0); + BYTE8 b = mmcSendCommand(CMDINIT, 0); if (b == 0x00) break; if (b != 0x01) @@ -76,32 +129,6 @@ BOOL mmcInit(void) { return FALSE; } -static void sendhdr(BYTE8 cmd, ULONG32 arg) { - BYTE8 buf[8]; - - buf[0] = 0xFF; - buf[1] = 0x40 | cmd; - buf[2] = arg >> 24; - buf[3] = arg >> 16; - buf[4] = arg >> 8; - buf[5] = arg; - buf[6] = 0x95; /* Valid for CMD0 ingnored by other commands. */ - buf[7] = 0xFF; - sspRW(NULL, buf, 8); -} - -static BYTE8 recvr1(void) { - int i; - BYTE8 r1[1]; - - for (i = 0; i < 8; i++) { - sspRW(r1, NULL, 1); - if (r1[0] != 0xFF) - return r1[0]; - } - return 0xFF; -} - /* * Sends a simple command and returns a R1-type response. */ @@ -114,3 +141,100 @@ BYTE8 mmcSendCommand(BYTE8 cmd, ULONG32 arg) { sspReleaseBus(); return r1; } + +/* + * Reads the card info record. + * @param data the pointer to a \p MMCCSD structure + * @return \p TRUE if an error happened + */ +BOOL mmcGetSize(MMCCSD *data) { + BYTE8 buf[16]; + + sspAcquireBus(); + sendhdr(CMDREADCSD, 0); + if (recvr1() != 0x00) { + sspReleaseBus(); + return TRUE; + } + if (getdata(buf, 16)) { + sspReleaseBus(); + return TRUE; + } + sspReleaseBus(); + + /* csize * multiplier */ + data->csize = (((buf[6] & 3) << 10) | (buf[7] << 2) | (buf[8] >> 6)) * + (1 << (2 + (((buf[9] & 3) << 1) | (buf[10] >> 7)))); + data->rdblklen = 1 << (buf[5] & 15); + return FALSE; +} + +/* + * Reads a block. + * @param blknum the block number + * @param buf the pointer to the read buffer + * @return \p TRUE if an error happened + */ +BOOL mmcBlockRead(ULONG32 blknum, BYTE8 *buf) { + + sspAcquireBus(); + sendhdr(CMDREAD, blknum << 8); + if (recvr1() != 0x00) { + sspReleaseBus(); + return TRUE; + } + if (getdata(buf, 512)) { + sspReleaseBus(); + return TRUE; + } + sspReleaseBus(); + return FALSE; +} + +/* + * Writes a block. + * @param blknum the block number + * @param buf the pointer to the write buffer + * @return \p TRUE if an error happened + * @note The function DOES NOT wait for the SPI bus to become free after + * sending the data, the bus check is done before sending commands to + * the card, this allows to not make useless busy waiting. The invoking + * thread can do other things while the data is being written. + */ +BOOL mmcBlockWrite(ULONG32 blknum, BYTE8 *buf) { + static BYTE8 start[] = {0xFF, 0xFE}; + BYTE8 b[4]; + + sspAcquireBus(); + sendhdr(CMDWRITE, blknum << 8); + if (recvr1() != 0x00) { + sspReleaseBus(); + return TRUE; + } + sspRW(NULL, start, 2); /* Data prologue.*/ + sspRW(NULL, buf, 512); /* Data.*/ + sspRW(NULL, NULL, 2); /* CRC ignored in this version.*/ + sspRW(b, NULL, 1); + sspReleaseBus(); + if ((b[0] & 0x1E) != 0x05) + return TRUE; + return FALSE; +} + +/* + * Makes sure that pending operations are completed before returning. + */ +void mmcSynch(void) { + BYTE8 buf[4]; + + sspAcquireBus(); + while (TRUE) { + sspRW(buf, NULL, 1); + if (buf[0] == 0xFF) + break; +#ifdef NICE_WAITING + chThdSleep(1); /* Trying to be nice with the other threads.*/ +#endif + } + sspReleaseBus(); +} diff --git a/demos/ARM7-LPC214x-GCC/mmcsd.h b/demos/ARM7-LPC214x-GCC/mmcsd.h index 4c9f1d643..047fd0fb2 100644 --- a/demos/ARM7-LPC214x-GCC/mmcsd.h +++ b/demos/ARM7-LPC214x-GCC/mmcsd.h @@ -20,12 +20,33 @@ #ifndef _MMCSD_H_ #define _MMCSD_H_ +#define NICE_WAITING + +/* Following times are 10mS units.*/ #define CMD0_RETRY 10 #define CMD1_RETRY 100 +/* Byte transfer time units.*/ +#define MMC_WAIT_DATA 10000 + +#define CMDGOIDLE 0 +#define CMDINIT 1 +#define CMDREADCSD 9 +#define CMDREAD 17 +#define CMDWRITE 24 + +typedef struct { + ULONG32 csize; + ULONG32 rdblklen; +} MMCCSD; + void InitMMC(void); BOOL mmcInit(void); BYTE8 mmcSendCommand(BYTE8 cmd, ULONG32 arg); +BOOL mmcGetSize(MMCCSD *data); +BOOL mmcBlockRead(ULONG32 blknum, BYTE8 *buf); +BOOL mmcBlockWrite(ULONG32 blknum, BYTE8 *buf); +void mmcSynch(void); #endif /* _MMCSD_H_*/ diff --git a/ports/ARM7-LPC214x/GCC/lpc214x.h b/ports/ARM7-LPC214x/GCC/lpc214x.h index ba9ce4c29..af6262eda 100644 --- a/ports/ARM7-LPC214x/GCC/lpc214x.h +++ b/ports/ARM7-LPC214x/GCC/lpc214x.h @@ -60,6 +60,29 @@ typedef volatile unsigned int IOREG32; PCPWM0 | PCI2C0 | PCSPI0 | PCRTC | PCSPI1 | \ PCAD0 | PCI2C1 | PCAD1 | PCUSB) +#define EINT0 1 +#define EINT1 2 +#define EINT2 4 +#define EINT3 8 + +#define EXTWAKE0 1 +#define EXTWAKE1 2 +#define EXTWAKE2 4 +#define EXTWAKE3 8 +#define USBWAKE 0x20 +#define BODWAKE 0x4000 +#define RTCWAKE 0x8000 + +#define EXTMODE0 1 +#define EXTMODE1 2 +#define EXTMODE2 4 +#define EXTMODE3 8 + +#define EXTPOLAR0 1 +#define EXTPOLAR1 2 +#define EXTPOLAR2 4 +#define EXTPOLAR3 8 + typedef struct { IOREG32 PLL0_CON; IOREG32 PLL0_CFG; diff --git a/readme.txt b/readme.txt index dbfaaa0c7..966e3c405 100644 --- a/readme.txt +++ b/readme.txt @@ -39,10 +39,10 @@ AVR-AT90CANx-GCC - Port on AVR AT90CAN128, not complete yet. ***************************************************************************** *** 0.3.6 *** -- Added SSP (SPI1) definitions to the lpc214x.h file. +- Added SSP (SPI1) and ext.interrupts definitions to the lpc214x.h file. - Added SSP driver for the LPC2148. -- Added MMC/SD block driver to the LPC2148 demo in order to support file - systems in future releases. +- Added experimental MMC/SD block driver to the LPC2148 demo in order to + support file systems. - Added missing chThdSuspend() declararion in threads.h. *** 0.3.5 ***