Serial RAM (SPI SRAM) library 23K256, 23LC1024 (Microchip) see: http://mbed.org/users/okini3939/notebook/extend-memory/
Dependents: SPIRAM_23LC1024_FIFO
Revision 1:5a261b6a88af, committed 2013-03-08
- Comitter:
- okini3939
- Date:
- Fri Mar 08 14:00:38 2013 +0000
- Parent:
- 0:69ea2af1d9af
- Commit message:
- add CircBuffer
Changed in this revision
diff -r 69ea2af1d9af -r 5a261b6a88af CBuffer_SRAM.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CBuffer_SRAM.cpp Fri Mar 08 14:00:38 2013 +0000 @@ -0,0 +1,124 @@ +/* Copyright (C) 2012 mbed.org, MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/* + * Modified by 2013 Hiroshi Suga, MIT License + */ + +#include "CBuffer_SRAM.h" + +#define DBG(...) +//#define DBG(...) printf("" __VA_ARGS__) + +CircBuffer::CircBuffer(int length) { + _ram = SerRAM::getInstance(); + write = 0; + read = 0; + ram_addr = xalloc(length + 1); + size = length + 1; +}; + +int CircBuffer::xalloc(int n) { + static uint32_t ram_alloc = 0; + uint32_t a; + + a = ram_alloc; + ram_alloc += (n + WINDOW_SIZE - 1) & ~WINDOW_MASK; + DBG("alloc %x ,next %x\r\n", a, ram_alloc); + return a; +} + +bool CircBuffer::isFull() { + return (((write + 1) % size) == read); +}; + +bool CircBuffer::isEmpty() { + return (read == write); +}; + +bool CircBuffer::queue(char k) { + if (isFull()) { + return false; + } +#ifdef RAM_USE_DMA + while (_ram->isBusy()) DBG("busy\r\n"); +#endif + uint32_t w = write; + buf_w[w & WINDOW_MASK] = k; + w = (w + 1) % size; + if ((w & WINDOW_MASK) == 0) { + _ram->write(ram_addr + (write & ~WINDOW_MASK), buf_w, WINDOW_SIZE, true); + DBG("(W %x)\r\n", ram_addr + (write & ~WINDOW_MASK)); + if ((write & ~WINDOW_MASK) == (read & ~WINDOW_MASK)) { + // w = r + memcpy(buf_r, buf_w, WINDOW_SIZE); + DBG("memcpy\r\n"); + } + } + write = w; + return true; +} + +void CircBuffer::flush() { + _ram->write(ram_addr + (write & ~WINDOW_MASK), buf_w, WINDOW_SIZE, true); + read = 0; + write = 0; +} + +uint32_t CircBuffer::available() { + return (write >= read) ? write - read : size - read + write; +}; + +uint32_t CircBuffer::use() { + return size - available() - 1; +}; + +bool CircBuffer::dequeue(char * c) { + bool empty = isEmpty(); + if (!empty) { +#ifdef RAM_USE_DMA + while (_ram->isBusy()) DBG("busy\r\n"); +#endif + uint32_t w = write, r = read; + if ((w & ~WINDOW_MASK) == (r & ~WINDOW_MASK) && w > r) { + *c = buf_w[r & WINDOW_MASK]; + } else { + *c = buf_r[r & WINDOW_MASK]; + } + r = (r + 1) % size; + if ((r & WINDOW_MASK) == 0) { + _ram->read(ram_addr + (r & ~WINDOW_MASK), buf_r, WINDOW_SIZE, true); + DBG("(R %x)\r\n", (r & ~WINDOW_MASK)); + } + read = r; + } + return (!empty); +}; + +void CircBuffer::dump() { + int i; + printf("buf_w\r\n"); + for (i = 0; i < WINDOW_SIZE; i ++) { + printf(" %02x", buf_w[i]); + if ((i & 0x0f) == 0x0f) printf("\r\n"); + } + printf("buf_r\r\n"); + for (i = 0; i < WINDOW_SIZE; i ++) { + printf(" %02x", buf_r[i]); + if ((i & 0x0f) == 0x0f) printf("\r\n"); + } +}
diff -r 69ea2af1d9af -r 5a261b6a88af CBuffer_SRAM.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CBuffer_SRAM.h Fri Mar 08 14:00:38 2013 +0000 @@ -0,0 +1,65 @@ +/* Copyright (C) 2012 mbed.org, MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/* + * Modified by 2013 Hiroshi Suga, MIT License + */ + +#ifndef CIRCBUFFER_H_ +#define CIRCBUFFER_H_ + +#define WINDOW_SIZE 64 +#define WINDOW_MASK 0x3f + +#include "SerRAM.h" + +class CircBuffer { +public: + CircBuffer(int length); + + bool isFull(); + + bool isEmpty(); + + bool queue(char k); + + void flush(); + + + uint32_t available(); + + uint32_t use(); + + bool dequeue(char * c); + + void dump(); + +private: + volatile uint32_t write; + volatile uint32_t read; + uint32_t size; + char buf_w[WINDOW_SIZE]; + char buf_r[WINDOW_SIZE]; + + SerRAM * _ram; + uint32_t ram_addr; + uint32_t ram_w, ram_r; + + static int xalloc(int size); +}; + +#endif
diff -r 69ea2af1d9af -r 5a261b6a88af SerRAM.cpp --- a/SerRAM.cpp Mon Jan 07 14:30:06 2013 +0000 +++ b/SerRAM.cpp Fri Mar 08 14:00:38 2013 +0000 @@ -8,7 +8,7 @@ * @brief Serial RAM (SPI SRAM) library * 23K256, 23LC1024 (Microchip) * support FIFO - * support DMA http://mbed.org/users/AjK/code/MODDMA/ + * support DMA need http://mbed.org/users/AjK/code/MODDMA/ */ #include "mbed.h" @@ -25,20 +25,22 @@ #define MODE_BYTE 0x00 #define MODE_SEQ 0x40 +SerRAM * SerRAM::_inst; SerRAM::SerRAM (SPI& spi, PinName cs, int size) : _spi(spi), _cs(cs) { _spi.frequency(16000000); _cs = 1; _size = size; _alloc = 0; + _inst = this; #ifdef RAM_USE_DMA dmacfg0 = new MODDMA_Config; dmacfg1 = new MODDMA_Config; - ssp_dmacr = &LPC_SSP1->DMACR; + _ssp = LPC_SSP1; // ??? dmacon0 = MODDMA::SSP1_Tx; dmacon1 = MODDMA::SSP1_Rx; - dmaexit = 1; + dmabusy = false; #endif #ifdef RAM_USE_FIFO @@ -51,21 +53,22 @@ _cs = 1; _size = size; _alloc = 0; + _inst = this; #ifdef RAM_USE_DMA dmacfg0 = new MODDMA_Config; dmacfg1 = new MODDMA_Config; if (mosi == p5) { - ssp_dmacr = &LPC_SSP1->DMACR; + _ssp = LPC_SSP1; dmacon0 = MODDMA::SSP1_Tx; dmacon1 = MODDMA::SSP1_Rx; } else if (mosi == p11) { - ssp_dmacr = &LPC_SSP0->DMACR; + _ssp = LPC_SSP0; dmacon0 = MODDMA::SSP0_Tx; dmacon1 = MODDMA::SSP0_Rx; } - dmaexit = 1; + dmabusy = false; #endif #ifdef RAM_USE_FIFO @@ -75,6 +78,9 @@ int SerRAM::write (int addr, int dat) { +#ifdef RAM_USE_DMA + while (dmabusy); +#endif _cs = 0; _spi.write(CMD_WRITE); if (_size > 512) { @@ -87,15 +93,15 @@ return 0; } -int SerRAM::write (int addr, char *buf, int len, int async) { +int SerRAM::write (int addr, char *buf, int len, bool async) { int i; #ifdef RAM_USE_DMA static char dummy[RAM_DMA_SIZE]; #endif - DBG("DMA write %04x %d\r\n", addr, len); + DBG("write %04x %d\r\n", addr, len); #ifdef RAM_USE_DMA - while (! dmaexit); + while (dmabusy); #endif _cs = 0; _spi.write(CMD_WRITE); @@ -130,10 +136,10 @@ ->attach_err ( this, &SerRAM::err_callback ) ; // config end - dmaexit = 0; + dmabusy = true; if (dma.Setup( dmacfg0 ) && dma.Setup( dmacfg1 )) { DBG("DMA setup\r\n"); - *ssp_dmacr = (1<<1)|(1<<0); // TX,RXDMAE + _ssp->DMACR = (1<<1)|(1<<0); // TX,RXDMAE dma.Enable( dmacfg0 ); dma.Enable( dmacfg1 ); DBG("DMA enable\r\n"); @@ -143,8 +149,8 @@ i = -1; } - if (async == 0) { - while (! dmaexit); + if (async == false) { + while (dmabusy); DBG("DMA done\r\n"); } #else @@ -159,6 +165,9 @@ int SerRAM::read (int addr) { int dat; +#ifdef RAM_USE_DMA + while (dmabusy); +#endif _cs = 0; _spi.write(CMD_READ); if (_size > 512) { @@ -171,12 +180,12 @@ return dat; } -int SerRAM::read (int addr, char *buf, int len, int async) { +int SerRAM::read (int addr, char *buf, int len, bool async) { int i; - DBG("DMA read %04x %d\r\n", addr, len); + DBG("read %04x %d\r\n", addr, len); #ifdef RAM_USE_DMA - while (! dmaexit); + while (dmabusy); #endif _cs = 0; _spi.write(CMD_READ); @@ -209,9 +218,9 @@ ->attach_err ( this, &SerRAM::err_callback ) ; // config end - dmaexit = 0; + dmabusy = true; if (dma.Setup( dmacfg0 ) && dma.Setup( dmacfg1 )) { - *ssp_dmacr = (1<<1)|(1<<0); // TX,RXDMAE + _ssp->DMACR = (1<<1)|(1<<0); // TX,RXDMAE dma.Enable( dmacfg0 ); dma.Enable( dmacfg1 ); i = 0; @@ -220,8 +229,8 @@ i = -1; } - if (async == 0) { - while (! dmaexit); + if (async == false) { + while (dmabusy); } #else for (i = 0; i < len; i ++) { @@ -234,6 +243,9 @@ int SerRAM::setStatus (int status) { +#ifdef RAM_USE_DMA + while (dmabusy); +#endif _cs = 0; _spi.write(CMD_WRMR); _spi.write(status); @@ -244,6 +256,9 @@ int SerRAM::getStatus () { int r; +#ifdef RAM_USE_DMA + while (dmabusy); +#endif _cs = 0; _spi.write(CMD_RDMR); r = _spi.write(0); @@ -265,167 +280,22 @@ void SerRAM::tc1_callback () { - dmaexit = 1; + dmabusy = false; _cs = 1; - *ssp_dmacr = 0; + _ssp->DMACR = 0; MODDMA_Config *config = dma.getConfig(); dma.Disable( (MODDMA::CHANNELS)config->channelNum() ); // Clear DMA IRQ flags. - if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); - if (dma.irqType() == MODDMA::ErrIrq) dma.clearErrIrq(); + if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); + if (dma.irqType() == MODDMA::ErrIrq) dma.clearErrIrq(); DBG("tc1_callback\r\n"); } void SerRAM::err_callback () { - dmaexit = -1; + dmabusy = false; _cs = 1; DBG("err_callback\r\n"); } #endif - -#ifdef RAM_USE_FIFO -int SerRAM::fifoAlloc (int size) { - int n, s; - - s = ((size + 1) / RAM_DMA_SIZE + 1) * RAM_DMA_SIZE; - if (fifo_num >= RAM_FIFO_NUM || (_size * 1024 - _alloc) < s) return -1; - - n = fifo_num; - fifo[n].size = size + 1; - fifo[n].buf_w = new char[RAM_DMA_SIZE]; - fifo[n].buf_r = new char[RAM_DMA_SIZE]; - fifo[n].ram = _alloc; - fifoClear(n); - - fifo_num ++; - _alloc += s; - DBG("alloc %d + %d (%d)\r\n", fifo[n].ram, fifo[n].size, _alloc); - return n; -} - -int SerRAM::fifoPut (int n, char dat) { - int next, next2; - - next = fifo[n].addr_w + 1; - next2 = fifo[n].addr2_w + 1; - if (next >= fifo[n].size) { - // last of fifo - next = 0; - next2 = 0; - } - if (next2 >= RAM_DMA_SIZE) { - // last of buffer - next2 = 0; - } - - if (next == fifo[n].addr_r) { - // no data - return -1; - } -#ifdef RAM_USE_DMA - while (! dmaexit); // busy DMA -#endif - fifo[n].buf_w[fifo[n].addr2_w] = dat; - - if (next2 == 0) { - // ring - write(fifo[n].ram + fifo[n].ram_w, fifo[n].buf_w, RAM_DMA_SIZE, 1); - if (fifo[n].ram_w == fifo[n].ram_r) { - // w = r - memcpy(fifo[n].buf_r, fifo[n].buf_w, RAM_DMA_SIZE); - } - - fifo[n].ram_w += RAM_DMA_SIZE; - if (next == 0) { - fifo[n].ram_w = 0; - } - } - fifo[n].addr_w = next; - fifo[n].addr2_w = next2; - return 0; -} - -int SerRAM::fifoPut (int n, char *buf, int len) { - int i; - - for (i = 0; i < len; i ++) { - if (fifoPut(n, buf[i])) return -1; - } - return 0; -} - -int SerRAM::fifoGet (int n, char *dat) { - - if (fifo[n].addr_r == fifo[n].addr_w) { - // no data - return -1; - } -#ifdef RAM_USE_DMA - while (! dmaexit); // busy DMA -#endif - if (fifo[n].ram_r != fifo[n].ram_w) { - *dat = fifo[n].buf_r[fifo[n].addr2_r]; - } else - if (fifo[n].addr_w < fifo[n].addr_r) { - *dat = fifo[n].buf_r[fifo[n].addr2_r]; - } else { - // w = r and w > r - *dat = fifo[n].buf_w[fifo[n].addr2_r]; - } - - fifo[n].addr_r += 1; - fifo[n].addr2_r += 1; - if (fifo[n].addr_r >= fifo[n].size) { - // last of fifo - fifo[n].addr_r = 0; - fifo[n].addr2_r = 0; - } - if (fifo[n].addr2_r >= RAM_DMA_SIZE) { - // last of buffer - fifo[n].addr2_r = 0; - } - if (fifo[n].addr2_r == 0) { - // ring - fifo[n].ram_r += RAM_DMA_SIZE; - if (fifo[n].addr_r == 0) { - fifo[n].ram_r = 0; - } - read(fifo[n].ram + fifo[n].ram_r, fifo[n].buf_r, RAM_DMA_SIZE); - } - return 0; -} - -int SerRAM::fifoGet (int n, char *buf, int len) { - int i; - - for (i = 0; i < len; i ++) { - if (fifoGet(n, &buf[i])) return -1; - } - return 0; -} - -int SerRAM::fifoAvailable (int n) { - if (fifo[n].addr_w < fifo[n].addr_r) { - return fifo[n].addr_r - fifo[n].addr_w - 1; - } else { - return (fifo[n].size - fifo[n].addr_w) + fifo[n].addr_r - 1; - } -} - -int SerRAM::fifoUse (int n) { - return fifo[n].size - fifoAvailable(n) - 1; -} - -void SerRAM::fifoClear (int n) { - fifo[n].addr_w = 0; - fifo[n].addr_r = 0; - fifo[n].addr2_w = 0; - fifo[n].addr2_r = 0; - fifo[n].ram_w = 0; - fifo[n].ram_r = 0; - - read(fifo[n].ram + fifo[n].ram_r, fifo[n].buf_r, RAM_DMA_SIZE); -} -#endif
diff -r 69ea2af1d9af -r 5a261b6a88af SerRAM.h --- a/SerRAM.h Mon Jan 07 14:30:06 2013 +0000 +++ b/SerRAM.h Fri Mar 08 14:00:38 2013 +0000 @@ -8,20 +8,17 @@ * @brief Serial RAM (SPI SRAM) library * 23K256, 23LC1024 (Microchip) * support FIFO - * support DMA http://mbed.org/users/AjK/code/MODDMA/ + * support DMA need http://mbed.org/users/AjK/code/MODDMA/ */ #ifndef __SerRAM_h__ #define __SerRAM_h__ #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) -//#define RAM_USE_DMA +#define RAM_USE_DMA #define RAM_DMA_SIZE 64 #endif -#define RAM_USE_FIFO -#define RAM_FIFO_NUM 20 - #include "mbed.h" #ifdef RAM_USE_DMA @@ -53,7 +50,7 @@ * @param async block (DMA) * @return >=0:success, -1:failure */ - int write (int addr, char *buf, int len, int async = 0); + int write (int addr, char *buf, int len, bool async = false); /** * @param addr address * @return data @@ -66,20 +63,19 @@ * @param async block (DMA) * @return 0:success, -1:failure */ - int read (int addr, char *buf, int len, int async = 0); + int read (int addr, char *buf, int len, bool async = false); int setStatus (int status); int getStatus (); -#ifdef RAM_USE_FIFO - int fifoAlloc (int size); - int fifoPut (int n, char dat); - int fifoPut (int n, char *buf, int len); - int fifoGet (int n, char *dat); - int fifoGet (int n, char *buf, int len); - int fifoAvailable (int n); - int fifoUse (int n); - void fifoClear (int n); + static SerRAM * getInstance() { + return _inst; + }; + +#ifdef RAM_USE_DMA + bool isBusy () { + return dmabusy; + }; #endif private: @@ -87,29 +83,18 @@ DigitalOut _cs; int _size; int _alloc; + static SerRAM * _inst; #ifdef RAM_USE_DMA void tc0_callback (); void tc1_callback (); void err_callback (); - __IO uint32_t *ssp_dmacr; + LPC_SSP_TypeDef *_ssp; MODDMA dma; MODDMA_Config *dmacfg0, *dmacfg1; MODDMA::GPDMA_CONNECTION dmacon0, dmacon1; - volatile int dmaexit; -#endif - -#ifdef RAM_USE_FIFO - int fifo_num; - struct { - char *buf_w, *buf_r; - int size; - int addr_w, addr_r; - int addr2_w, addr2_r; - int ram; - int ram_w, ram_r; - } fifo[RAM_FIFO_NUM]; + volatile bool dmabusy; #endif };