Serial RAM (SPI SRAM) library 23K256, 23LC1024 (Microchip) see: http://mbed.org/users/okini3939/notebook/extend-memory/
Dependents: SPIRAM_23LC1024_FIFO
SerRAM.cpp
- Committer:
- okini3939
- Date:
- 2013-03-08
- Revision:
- 1:5a261b6a88af
- Parent:
- 0:69ea2af1d9af
File content as of revision 1:5a261b6a88af:
/* * Serial RAM (SPI SRAM) library * Copyright (c) 2013 Hiroshi Suga * Released under the MIT License: http://mbed.org/license/mit */ /** @file * @brief Serial RAM (SPI SRAM) library * 23K256, 23LC1024 (Microchip) * support FIFO * support DMA need http://mbed.org/users/AjK/code/MODDMA/ */ #include "mbed.h" #include "SerRAM.h" #define DBG(...) //#define DBG(...) printf("" __VA_ARGS__) #define CMD_READ 0x03 #define CMD_WRITE 0x02 #define CMD_RDMR 0x05 #define CMD_WRMR 0x01 #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 = LPC_SSP1; // ??? dmacon0 = MODDMA::SSP1_Tx; dmacon1 = MODDMA::SSP1_Rx; dmabusy = false; #endif #ifdef RAM_USE_FIFO fifo_num = 0; #endif } SerRAM::SerRAM (PinName mosi, PinName miso, PinName sck, PinName cs, int size) : _spi(mosi, miso, sck), _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; if (mosi == p5) { _ssp = LPC_SSP1; dmacon0 = MODDMA::SSP1_Tx; dmacon1 = MODDMA::SSP1_Rx; } else if (mosi == p11) { _ssp = LPC_SSP0; dmacon0 = MODDMA::SSP0_Tx; dmacon1 = MODDMA::SSP0_Rx; } dmabusy = false; #endif #ifdef RAM_USE_FIFO fifo_num = 0; #endif } int SerRAM::write (int addr, int dat) { #ifdef RAM_USE_DMA while (dmabusy); #endif _cs = 0; _spi.write(CMD_WRITE); if (_size > 512) { _spi.write((addr >> 16) & 0xff); } _spi.write((addr >> 8) & 0xff); _spi.write(addr & 0xff); _spi.write(dat); _cs = 1; return 0; } 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("write %04x %d\r\n", addr, len); #ifdef RAM_USE_DMA while (dmabusy); #endif _cs = 0; _spi.write(CMD_WRITE); if (_size > 512) { _spi.write((addr >> 16) & 0xff); } _spi.write((addr >> 8) & 0xff); _spi.write(addr & 0xff); #ifdef RAM_USE_DMA if (len > RAM_DMA_SIZE) len = RAM_DMA_SIZE; dmacfg0 ->channelNum ( MODDMA::Channel_0 ) ->srcMemAddr ( (uint32_t)buf ) ->dstMemAddr ( dmacon0 ) ->transferSize ( len ) ->transferType ( MODDMA::m2p ) ->dstConn ( dmacon0 ) ->attach_tc ( this, &SerRAM::tc0_callback ) ->attach_err ( this, &SerRAM::err_callback ) ; // config end dmacfg1 ->channelNum ( MODDMA::Channel_1 ) ->srcMemAddr ( dmacon1 ) ->dstMemAddr ( (uint32_t)dummy ) ->transferSize ( len ) ->transferType ( MODDMA::p2m ) ->srcConn ( dmacon1 ) ->attach_tc ( this, &SerRAM::tc1_callback ) ->attach_err ( this, &SerRAM::err_callback ) ; // config end dmabusy = true; if (dma.Setup( dmacfg0 ) && dma.Setup( dmacfg1 )) { DBG("DMA setup\r\n"); _ssp->DMACR = (1<<1)|(1<<0); // TX,RXDMAE dma.Enable( dmacfg0 ); dma.Enable( dmacfg1 ); DBG("DMA enable\r\n"); i = 0; } else { DBG("DMA error\r\n"); i = -1; } if (async == false) { while (dmabusy); DBG("DMA done\r\n"); } #else for (i = 0; i < len; i ++) { _spi.write(buf[i]); } _cs = 1; #endif return i; } int SerRAM::read (int addr) { int dat; #ifdef RAM_USE_DMA while (dmabusy); #endif _cs = 0; _spi.write(CMD_READ); if (_size > 512) { _spi.write((addr >> 16) & 0xff); } _spi.write((addr >> 8) & 0xff); _spi.write(addr & 0xff); dat = _spi.write(0); _cs = 1; return dat; } int SerRAM::read (int addr, char *buf, int len, bool async) { int i; DBG("read %04x %d\r\n", addr, len); #ifdef RAM_USE_DMA while (dmabusy); #endif _cs = 0; _spi.write(CMD_READ); if (_size > 512) { _spi.write((addr >> 16) & 0xff); } _spi.write((addr >> 8) & 0xff); _spi.write(addr & 0xff); #ifdef RAM_USE_DMA dmacfg0 ->channelNum ( MODDMA::Channel_0 ) ->srcMemAddr ( (uint32_t)buf ) ->dstMemAddr ( dmacon0 ) ->transferSize ( len ) ->transferType ( MODDMA::m2p ) ->dstConn ( dmacon0 ) ->attach_tc ( this, &SerRAM::tc0_callback ) ->attach_err ( this, &SerRAM::err_callback ) ; // config end dmacfg1 ->channelNum ( MODDMA::Channel_1 ) ->srcMemAddr ( dmacon1 ) ->dstMemAddr ( (uint32_t)buf ) ->transferSize ( len ) ->transferType ( MODDMA::p2m ) ->srcConn ( dmacon1 ) ->attach_tc ( this, &SerRAM::tc1_callback ) ->attach_err ( this, &SerRAM::err_callback ) ; // config end dmabusy = true; if (dma.Setup( dmacfg0 ) && dma.Setup( dmacfg1 )) { _ssp->DMACR = (1<<1)|(1<<0); // TX,RXDMAE dma.Enable( dmacfg0 ); dma.Enable( dmacfg1 ); i = 0; } else { DBG("DMA error\r\n"); i = -1; } if (async == false) { while (dmabusy); } #else for (i = 0; i < len; i ++) { buf[i] = _spi.write(0); } _cs = 1; #endif return i; } int SerRAM::setStatus (int status) { #ifdef RAM_USE_DMA while (dmabusy); #endif _cs = 0; _spi.write(CMD_WRMR); _spi.write(status); _cs = 1; return 0; } int SerRAM::getStatus () { int r; #ifdef RAM_USE_DMA while (dmabusy); #endif _cs = 0; _spi.write(CMD_RDMR); r = _spi.write(0); _cs = 1; return r; } #ifdef RAM_USE_DMA void SerRAM::tc0_callback () { 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(); DBG("tc0_callback\r\n"); } void SerRAM::tc1_callback () { dmabusy = false; _cs = 1; _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(); DBG("tc1_callback\r\n"); } void SerRAM::err_callback () { dmabusy = false; _cs = 1; DBG("err_callback\r\n"); } #endif