Serial RAM (SPI SRAM) library 23K256, 23LC1024 (Microchip) see: http://mbed.org/users/okini3939/notebook/extend-memory/

Dependents:   SPIRAM_23LC1024_FIFO

Committer:
okini3939
Date:
Fri Mar 08 14:00:38 2013 +0000
Revision:
1:5a261b6a88af
Parent:
0:69ea2af1d9af
add CircBuffer

Who changed what in which revision?

UserRevisionLine numberNew contents of line
okini3939 0:69ea2af1d9af 1 /*
okini3939 0:69ea2af1d9af 2 * Serial RAM (SPI SRAM) library
okini3939 0:69ea2af1d9af 3 * Copyright (c) 2013 Hiroshi Suga
okini3939 0:69ea2af1d9af 4 * Released under the MIT License: http://mbed.org/license/mit
okini3939 0:69ea2af1d9af 5 */
okini3939 0:69ea2af1d9af 6
okini3939 0:69ea2af1d9af 7 /** @file
okini3939 0:69ea2af1d9af 8 * @brief Serial RAM (SPI SRAM) library
okini3939 0:69ea2af1d9af 9 * 23K256, 23LC1024 (Microchip)
okini3939 0:69ea2af1d9af 10 * support FIFO
okini3939 1:5a261b6a88af 11 * support DMA need http://mbed.org/users/AjK/code/MODDMA/
okini3939 0:69ea2af1d9af 12 */
okini3939 0:69ea2af1d9af 13
okini3939 0:69ea2af1d9af 14 #include "mbed.h"
okini3939 0:69ea2af1d9af 15 #include "SerRAM.h"
okini3939 0:69ea2af1d9af 16
okini3939 0:69ea2af1d9af 17 #define DBG(...)
okini3939 0:69ea2af1d9af 18 //#define DBG(...) printf("" __VA_ARGS__)
okini3939 0:69ea2af1d9af 19
okini3939 0:69ea2af1d9af 20 #define CMD_READ 0x03
okini3939 0:69ea2af1d9af 21 #define CMD_WRITE 0x02
okini3939 0:69ea2af1d9af 22 #define CMD_RDMR 0x05
okini3939 0:69ea2af1d9af 23 #define CMD_WRMR 0x01
okini3939 0:69ea2af1d9af 24
okini3939 0:69ea2af1d9af 25 #define MODE_BYTE 0x00
okini3939 0:69ea2af1d9af 26 #define MODE_SEQ 0x40
okini3939 0:69ea2af1d9af 27
okini3939 1:5a261b6a88af 28 SerRAM * SerRAM::_inst;
okini3939 0:69ea2af1d9af 29
okini3939 0:69ea2af1d9af 30 SerRAM::SerRAM (SPI& spi, PinName cs, int size) : _spi(spi), _cs(cs) {
okini3939 0:69ea2af1d9af 31 _spi.frequency(16000000);
okini3939 0:69ea2af1d9af 32 _cs = 1;
okini3939 0:69ea2af1d9af 33 _size = size;
okini3939 0:69ea2af1d9af 34 _alloc = 0;
okini3939 1:5a261b6a88af 35 _inst = this;
okini3939 0:69ea2af1d9af 36
okini3939 0:69ea2af1d9af 37 #ifdef RAM_USE_DMA
okini3939 0:69ea2af1d9af 38 dmacfg0 = new MODDMA_Config;
okini3939 0:69ea2af1d9af 39 dmacfg1 = new MODDMA_Config;
okini3939 1:5a261b6a88af 40 _ssp = LPC_SSP1; // ???
okini3939 0:69ea2af1d9af 41 dmacon0 = MODDMA::SSP1_Tx;
okini3939 0:69ea2af1d9af 42 dmacon1 = MODDMA::SSP1_Rx;
okini3939 1:5a261b6a88af 43 dmabusy = false;
okini3939 0:69ea2af1d9af 44 #endif
okini3939 0:69ea2af1d9af 45
okini3939 0:69ea2af1d9af 46 #ifdef RAM_USE_FIFO
okini3939 0:69ea2af1d9af 47 fifo_num = 0;
okini3939 0:69ea2af1d9af 48 #endif
okini3939 0:69ea2af1d9af 49 }
okini3939 0:69ea2af1d9af 50
okini3939 0:69ea2af1d9af 51 SerRAM::SerRAM (PinName mosi, PinName miso, PinName sck, PinName cs, int size) : _spi(mosi, miso, sck), _cs(cs) {
okini3939 0:69ea2af1d9af 52 _spi.frequency(16000000);
okini3939 0:69ea2af1d9af 53 _cs = 1;
okini3939 0:69ea2af1d9af 54 _size = size;
okini3939 0:69ea2af1d9af 55 _alloc = 0;
okini3939 1:5a261b6a88af 56 _inst = this;
okini3939 0:69ea2af1d9af 57
okini3939 0:69ea2af1d9af 58 #ifdef RAM_USE_DMA
okini3939 0:69ea2af1d9af 59 dmacfg0 = new MODDMA_Config;
okini3939 0:69ea2af1d9af 60 dmacfg1 = new MODDMA_Config;
okini3939 0:69ea2af1d9af 61 if (mosi == p5) {
okini3939 1:5a261b6a88af 62 _ssp = LPC_SSP1;
okini3939 0:69ea2af1d9af 63 dmacon0 = MODDMA::SSP1_Tx;
okini3939 0:69ea2af1d9af 64 dmacon1 = MODDMA::SSP1_Rx;
okini3939 0:69ea2af1d9af 65 } else
okini3939 0:69ea2af1d9af 66 if (mosi == p11) {
okini3939 1:5a261b6a88af 67 _ssp = LPC_SSP0;
okini3939 0:69ea2af1d9af 68 dmacon0 = MODDMA::SSP0_Tx;
okini3939 0:69ea2af1d9af 69 dmacon1 = MODDMA::SSP0_Rx;
okini3939 0:69ea2af1d9af 70 }
okini3939 1:5a261b6a88af 71 dmabusy = false;
okini3939 0:69ea2af1d9af 72 #endif
okini3939 0:69ea2af1d9af 73
okini3939 0:69ea2af1d9af 74 #ifdef RAM_USE_FIFO
okini3939 0:69ea2af1d9af 75 fifo_num = 0;
okini3939 0:69ea2af1d9af 76 #endif
okini3939 0:69ea2af1d9af 77 }
okini3939 0:69ea2af1d9af 78
okini3939 0:69ea2af1d9af 79 int SerRAM::write (int addr, int dat) {
okini3939 0:69ea2af1d9af 80
okini3939 1:5a261b6a88af 81 #ifdef RAM_USE_DMA
okini3939 1:5a261b6a88af 82 while (dmabusy);
okini3939 1:5a261b6a88af 83 #endif
okini3939 0:69ea2af1d9af 84 _cs = 0;
okini3939 0:69ea2af1d9af 85 _spi.write(CMD_WRITE);
okini3939 0:69ea2af1d9af 86 if (_size > 512) {
okini3939 0:69ea2af1d9af 87 _spi.write((addr >> 16) & 0xff);
okini3939 0:69ea2af1d9af 88 }
okini3939 0:69ea2af1d9af 89 _spi.write((addr >> 8) & 0xff);
okini3939 0:69ea2af1d9af 90 _spi.write(addr & 0xff);
okini3939 0:69ea2af1d9af 91 _spi.write(dat);
okini3939 0:69ea2af1d9af 92 _cs = 1;
okini3939 0:69ea2af1d9af 93 return 0;
okini3939 0:69ea2af1d9af 94 }
okini3939 0:69ea2af1d9af 95
okini3939 1:5a261b6a88af 96 int SerRAM::write (int addr, char *buf, int len, bool async) {
okini3939 0:69ea2af1d9af 97 int i;
okini3939 0:69ea2af1d9af 98 #ifdef RAM_USE_DMA
okini3939 0:69ea2af1d9af 99 static char dummy[RAM_DMA_SIZE];
okini3939 0:69ea2af1d9af 100 #endif
okini3939 0:69ea2af1d9af 101
okini3939 1:5a261b6a88af 102 DBG("write %04x %d\r\n", addr, len);
okini3939 0:69ea2af1d9af 103 #ifdef RAM_USE_DMA
okini3939 1:5a261b6a88af 104 while (dmabusy);
okini3939 0:69ea2af1d9af 105 #endif
okini3939 0:69ea2af1d9af 106 _cs = 0;
okini3939 0:69ea2af1d9af 107 _spi.write(CMD_WRITE);
okini3939 0:69ea2af1d9af 108 if (_size > 512) {
okini3939 0:69ea2af1d9af 109 _spi.write((addr >> 16) & 0xff);
okini3939 0:69ea2af1d9af 110 }
okini3939 0:69ea2af1d9af 111 _spi.write((addr >> 8) & 0xff);
okini3939 0:69ea2af1d9af 112 _spi.write(addr & 0xff);
okini3939 0:69ea2af1d9af 113
okini3939 0:69ea2af1d9af 114 #ifdef RAM_USE_DMA
okini3939 0:69ea2af1d9af 115 if (len > RAM_DMA_SIZE) len = RAM_DMA_SIZE;
okini3939 0:69ea2af1d9af 116
okini3939 0:69ea2af1d9af 117 dmacfg0
okini3939 0:69ea2af1d9af 118 ->channelNum ( MODDMA::Channel_0 )
okini3939 0:69ea2af1d9af 119 ->srcMemAddr ( (uint32_t)buf )
okini3939 0:69ea2af1d9af 120 ->dstMemAddr ( dmacon0 )
okini3939 0:69ea2af1d9af 121 ->transferSize ( len )
okini3939 0:69ea2af1d9af 122 ->transferType ( MODDMA::m2p )
okini3939 0:69ea2af1d9af 123 ->dstConn ( dmacon0 )
okini3939 0:69ea2af1d9af 124 ->attach_tc ( this, &SerRAM::tc0_callback )
okini3939 0:69ea2af1d9af 125 ->attach_err ( this, &SerRAM::err_callback )
okini3939 0:69ea2af1d9af 126 ; // config end
okini3939 0:69ea2af1d9af 127
okini3939 0:69ea2af1d9af 128 dmacfg1
okini3939 0:69ea2af1d9af 129 ->channelNum ( MODDMA::Channel_1 )
okini3939 0:69ea2af1d9af 130 ->srcMemAddr ( dmacon1 )
okini3939 0:69ea2af1d9af 131 ->dstMemAddr ( (uint32_t)dummy )
okini3939 0:69ea2af1d9af 132 ->transferSize ( len )
okini3939 0:69ea2af1d9af 133 ->transferType ( MODDMA::p2m )
okini3939 0:69ea2af1d9af 134 ->srcConn ( dmacon1 )
okini3939 0:69ea2af1d9af 135 ->attach_tc ( this, &SerRAM::tc1_callback )
okini3939 0:69ea2af1d9af 136 ->attach_err ( this, &SerRAM::err_callback )
okini3939 0:69ea2af1d9af 137 ; // config end
okini3939 0:69ea2af1d9af 138
okini3939 1:5a261b6a88af 139 dmabusy = true;
okini3939 0:69ea2af1d9af 140 if (dma.Setup( dmacfg0 ) && dma.Setup( dmacfg1 )) {
okini3939 0:69ea2af1d9af 141 DBG("DMA setup\r\n");
okini3939 1:5a261b6a88af 142 _ssp->DMACR = (1<<1)|(1<<0); // TX,RXDMAE
okini3939 0:69ea2af1d9af 143 dma.Enable( dmacfg0 );
okini3939 0:69ea2af1d9af 144 dma.Enable( dmacfg1 );
okini3939 0:69ea2af1d9af 145 DBG("DMA enable\r\n");
okini3939 0:69ea2af1d9af 146 i = 0;
okini3939 0:69ea2af1d9af 147 } else {
okini3939 0:69ea2af1d9af 148 DBG("DMA error\r\n");
okini3939 0:69ea2af1d9af 149 i = -1;
okini3939 0:69ea2af1d9af 150 }
okini3939 0:69ea2af1d9af 151
okini3939 1:5a261b6a88af 152 if (async == false) {
okini3939 1:5a261b6a88af 153 while (dmabusy);
okini3939 0:69ea2af1d9af 154 DBG("DMA done\r\n");
okini3939 0:69ea2af1d9af 155 }
okini3939 0:69ea2af1d9af 156 #else
okini3939 0:69ea2af1d9af 157 for (i = 0; i < len; i ++) {
okini3939 0:69ea2af1d9af 158 _spi.write(buf[i]);
okini3939 0:69ea2af1d9af 159 }
okini3939 0:69ea2af1d9af 160 _cs = 1;
okini3939 0:69ea2af1d9af 161 #endif
okini3939 0:69ea2af1d9af 162 return i;
okini3939 0:69ea2af1d9af 163 }
okini3939 0:69ea2af1d9af 164
okini3939 0:69ea2af1d9af 165 int SerRAM::read (int addr) {
okini3939 0:69ea2af1d9af 166 int dat;
okini3939 0:69ea2af1d9af 167
okini3939 1:5a261b6a88af 168 #ifdef RAM_USE_DMA
okini3939 1:5a261b6a88af 169 while (dmabusy);
okini3939 1:5a261b6a88af 170 #endif
okini3939 0:69ea2af1d9af 171 _cs = 0;
okini3939 0:69ea2af1d9af 172 _spi.write(CMD_READ);
okini3939 0:69ea2af1d9af 173 if (_size > 512) {
okini3939 0:69ea2af1d9af 174 _spi.write((addr >> 16) & 0xff);
okini3939 0:69ea2af1d9af 175 }
okini3939 0:69ea2af1d9af 176 _spi.write((addr >> 8) & 0xff);
okini3939 0:69ea2af1d9af 177 _spi.write(addr & 0xff);
okini3939 0:69ea2af1d9af 178 dat = _spi.write(0);
okini3939 0:69ea2af1d9af 179 _cs = 1;
okini3939 0:69ea2af1d9af 180 return dat;
okini3939 0:69ea2af1d9af 181 }
okini3939 0:69ea2af1d9af 182
okini3939 1:5a261b6a88af 183 int SerRAM::read (int addr, char *buf, int len, bool async) {
okini3939 0:69ea2af1d9af 184 int i;
okini3939 0:69ea2af1d9af 185
okini3939 1:5a261b6a88af 186 DBG("read %04x %d\r\n", addr, len);
okini3939 0:69ea2af1d9af 187 #ifdef RAM_USE_DMA
okini3939 1:5a261b6a88af 188 while (dmabusy);
okini3939 0:69ea2af1d9af 189 #endif
okini3939 0:69ea2af1d9af 190 _cs = 0;
okini3939 0:69ea2af1d9af 191 _spi.write(CMD_READ);
okini3939 0:69ea2af1d9af 192 if (_size > 512) {
okini3939 0:69ea2af1d9af 193 _spi.write((addr >> 16) & 0xff);
okini3939 0:69ea2af1d9af 194 }
okini3939 0:69ea2af1d9af 195 _spi.write((addr >> 8) & 0xff);
okini3939 0:69ea2af1d9af 196 _spi.write(addr & 0xff);
okini3939 0:69ea2af1d9af 197
okini3939 0:69ea2af1d9af 198 #ifdef RAM_USE_DMA
okini3939 0:69ea2af1d9af 199 dmacfg0
okini3939 0:69ea2af1d9af 200 ->channelNum ( MODDMA::Channel_0 )
okini3939 0:69ea2af1d9af 201 ->srcMemAddr ( (uint32_t)buf )
okini3939 0:69ea2af1d9af 202 ->dstMemAddr ( dmacon0 )
okini3939 0:69ea2af1d9af 203 ->transferSize ( len )
okini3939 0:69ea2af1d9af 204 ->transferType ( MODDMA::m2p )
okini3939 0:69ea2af1d9af 205 ->dstConn ( dmacon0 )
okini3939 0:69ea2af1d9af 206 ->attach_tc ( this, &SerRAM::tc0_callback )
okini3939 0:69ea2af1d9af 207 ->attach_err ( this, &SerRAM::err_callback )
okini3939 0:69ea2af1d9af 208 ; // config end
okini3939 0:69ea2af1d9af 209
okini3939 0:69ea2af1d9af 210 dmacfg1
okini3939 0:69ea2af1d9af 211 ->channelNum ( MODDMA::Channel_1 )
okini3939 0:69ea2af1d9af 212 ->srcMemAddr ( dmacon1 )
okini3939 0:69ea2af1d9af 213 ->dstMemAddr ( (uint32_t)buf )
okini3939 0:69ea2af1d9af 214 ->transferSize ( len )
okini3939 0:69ea2af1d9af 215 ->transferType ( MODDMA::p2m )
okini3939 0:69ea2af1d9af 216 ->srcConn ( dmacon1 )
okini3939 0:69ea2af1d9af 217 ->attach_tc ( this, &SerRAM::tc1_callback )
okini3939 0:69ea2af1d9af 218 ->attach_err ( this, &SerRAM::err_callback )
okini3939 0:69ea2af1d9af 219 ; // config end
okini3939 0:69ea2af1d9af 220
okini3939 1:5a261b6a88af 221 dmabusy = true;
okini3939 0:69ea2af1d9af 222 if (dma.Setup( dmacfg0 ) && dma.Setup( dmacfg1 )) {
okini3939 1:5a261b6a88af 223 _ssp->DMACR = (1<<1)|(1<<0); // TX,RXDMAE
okini3939 0:69ea2af1d9af 224 dma.Enable( dmacfg0 );
okini3939 0:69ea2af1d9af 225 dma.Enable( dmacfg1 );
okini3939 0:69ea2af1d9af 226 i = 0;
okini3939 0:69ea2af1d9af 227 } else {
okini3939 0:69ea2af1d9af 228 DBG("DMA error\r\n");
okini3939 0:69ea2af1d9af 229 i = -1;
okini3939 0:69ea2af1d9af 230 }
okini3939 0:69ea2af1d9af 231
okini3939 1:5a261b6a88af 232 if (async == false) {
okini3939 1:5a261b6a88af 233 while (dmabusy);
okini3939 0:69ea2af1d9af 234 }
okini3939 0:69ea2af1d9af 235 #else
okini3939 0:69ea2af1d9af 236 for (i = 0; i < len; i ++) {
okini3939 0:69ea2af1d9af 237 buf[i] = _spi.write(0);
okini3939 0:69ea2af1d9af 238 }
okini3939 0:69ea2af1d9af 239 _cs = 1;
okini3939 0:69ea2af1d9af 240 #endif
okini3939 0:69ea2af1d9af 241 return i;
okini3939 0:69ea2af1d9af 242 }
okini3939 0:69ea2af1d9af 243
okini3939 0:69ea2af1d9af 244 int SerRAM::setStatus (int status) {
okini3939 0:69ea2af1d9af 245
okini3939 1:5a261b6a88af 246 #ifdef RAM_USE_DMA
okini3939 1:5a261b6a88af 247 while (dmabusy);
okini3939 1:5a261b6a88af 248 #endif
okini3939 0:69ea2af1d9af 249 _cs = 0;
okini3939 0:69ea2af1d9af 250 _spi.write(CMD_WRMR);
okini3939 0:69ea2af1d9af 251 _spi.write(status);
okini3939 0:69ea2af1d9af 252 _cs = 1;
okini3939 0:69ea2af1d9af 253 return 0;
okini3939 0:69ea2af1d9af 254 }
okini3939 0:69ea2af1d9af 255
okini3939 0:69ea2af1d9af 256 int SerRAM::getStatus () {
okini3939 0:69ea2af1d9af 257 int r;
okini3939 0:69ea2af1d9af 258
okini3939 1:5a261b6a88af 259 #ifdef RAM_USE_DMA
okini3939 1:5a261b6a88af 260 while (dmabusy);
okini3939 1:5a261b6a88af 261 #endif
okini3939 0:69ea2af1d9af 262 _cs = 0;
okini3939 0:69ea2af1d9af 263 _spi.write(CMD_RDMR);
okini3939 0:69ea2af1d9af 264 r = _spi.write(0);
okini3939 0:69ea2af1d9af 265 _cs = 1;
okini3939 0:69ea2af1d9af 266 return r;
okini3939 0:69ea2af1d9af 267 }
okini3939 0:69ea2af1d9af 268
okini3939 0:69ea2af1d9af 269 #ifdef RAM_USE_DMA
okini3939 0:69ea2af1d9af 270 void SerRAM::tc0_callback () {
okini3939 0:69ea2af1d9af 271
okini3939 0:69ea2af1d9af 272 MODDMA_Config *config = dma.getConfig();
okini3939 0:69ea2af1d9af 273 dma.Disable( (MODDMA::CHANNELS)config->channelNum() );
okini3939 0:69ea2af1d9af 274
okini3939 0:69ea2af1d9af 275 // Clear DMA IRQ flags.
okini3939 0:69ea2af1d9af 276 if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq();
okini3939 0:69ea2af1d9af 277 if (dma.irqType() == MODDMA::ErrIrq) dma.clearErrIrq();
okini3939 0:69ea2af1d9af 278 DBG("tc0_callback\r\n");
okini3939 0:69ea2af1d9af 279 }
okini3939 0:69ea2af1d9af 280
okini3939 0:69ea2af1d9af 281 void SerRAM::tc1_callback () {
okini3939 0:69ea2af1d9af 282
okini3939 1:5a261b6a88af 283 dmabusy = false;
okini3939 0:69ea2af1d9af 284 _cs = 1;
okini3939 1:5a261b6a88af 285 _ssp->DMACR = 0;
okini3939 0:69ea2af1d9af 286
okini3939 0:69ea2af1d9af 287 MODDMA_Config *config = dma.getConfig();
okini3939 0:69ea2af1d9af 288 dma.Disable( (MODDMA::CHANNELS)config->channelNum() );
okini3939 0:69ea2af1d9af 289
okini3939 0:69ea2af1d9af 290 // Clear DMA IRQ flags.
okini3939 1:5a261b6a88af 291 if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq();
okini3939 1:5a261b6a88af 292 if (dma.irqType() == MODDMA::ErrIrq) dma.clearErrIrq();
okini3939 0:69ea2af1d9af 293 DBG("tc1_callback\r\n");
okini3939 0:69ea2af1d9af 294 }
okini3939 0:69ea2af1d9af 295
okini3939 0:69ea2af1d9af 296 void SerRAM::err_callback () {
okini3939 1:5a261b6a88af 297 dmabusy = false;
okini3939 0:69ea2af1d9af 298 _cs = 1;
okini3939 0:69ea2af1d9af 299 DBG("err_callback\r\n");
okini3939 0:69ea2af1d9af 300 }
okini3939 0:69ea2af1d9af 301 #endif