Serial RAM (SPI SRAM) library 23K256, 23LC1024 (Microchip) see: http://mbed.org/users/okini3939/notebook/extend-memory/
Dependents: SPIRAM_23LC1024_FIFO
SerRAM.cpp@0:69ea2af1d9af, 2013-01-07 (annotated)
- Committer:
- okini3939
- Date:
- Mon Jan 07 14:30:06 2013 +0000
- Revision:
- 0:69ea2af1d9af
- Child:
- 1:5a261b6a88af
1st build
Who changed what in which revision?
User | Revision | Line number | New 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 | 0:69ea2af1d9af | 11 | * support DMA 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 | 0:69ea2af1d9af | 28 | |
okini3939 | 0:69ea2af1d9af | 29 | SerRAM::SerRAM (SPI& spi, PinName cs, int size) : _spi(spi), _cs(cs) { |
okini3939 | 0:69ea2af1d9af | 30 | _spi.frequency(16000000); |
okini3939 | 0:69ea2af1d9af | 31 | _cs = 1; |
okini3939 | 0:69ea2af1d9af | 32 | _size = size; |
okini3939 | 0:69ea2af1d9af | 33 | _alloc = 0; |
okini3939 | 0:69ea2af1d9af | 34 | |
okini3939 | 0:69ea2af1d9af | 35 | #ifdef RAM_USE_DMA |
okini3939 | 0:69ea2af1d9af | 36 | dmacfg0 = new MODDMA_Config; |
okini3939 | 0:69ea2af1d9af | 37 | dmacfg1 = new MODDMA_Config; |
okini3939 | 0:69ea2af1d9af | 38 | ssp_dmacr = &LPC_SSP1->DMACR; |
okini3939 | 0:69ea2af1d9af | 39 | dmacon0 = MODDMA::SSP1_Tx; |
okini3939 | 0:69ea2af1d9af | 40 | dmacon1 = MODDMA::SSP1_Rx; |
okini3939 | 0:69ea2af1d9af | 41 | dmaexit = 1; |
okini3939 | 0:69ea2af1d9af | 42 | #endif |
okini3939 | 0:69ea2af1d9af | 43 | |
okini3939 | 0:69ea2af1d9af | 44 | #ifdef RAM_USE_FIFO |
okini3939 | 0:69ea2af1d9af | 45 | fifo_num = 0; |
okini3939 | 0:69ea2af1d9af | 46 | #endif |
okini3939 | 0:69ea2af1d9af | 47 | } |
okini3939 | 0:69ea2af1d9af | 48 | |
okini3939 | 0:69ea2af1d9af | 49 | SerRAM::SerRAM (PinName mosi, PinName miso, PinName sck, PinName cs, int size) : _spi(mosi, miso, sck), _cs(cs) { |
okini3939 | 0:69ea2af1d9af | 50 | _spi.frequency(16000000); |
okini3939 | 0:69ea2af1d9af | 51 | _cs = 1; |
okini3939 | 0:69ea2af1d9af | 52 | _size = size; |
okini3939 | 0:69ea2af1d9af | 53 | _alloc = 0; |
okini3939 | 0:69ea2af1d9af | 54 | |
okini3939 | 0:69ea2af1d9af | 55 | #ifdef RAM_USE_DMA |
okini3939 | 0:69ea2af1d9af | 56 | dmacfg0 = new MODDMA_Config; |
okini3939 | 0:69ea2af1d9af | 57 | dmacfg1 = new MODDMA_Config; |
okini3939 | 0:69ea2af1d9af | 58 | if (mosi == p5) { |
okini3939 | 0:69ea2af1d9af | 59 | ssp_dmacr = &LPC_SSP1->DMACR; |
okini3939 | 0:69ea2af1d9af | 60 | dmacon0 = MODDMA::SSP1_Tx; |
okini3939 | 0:69ea2af1d9af | 61 | dmacon1 = MODDMA::SSP1_Rx; |
okini3939 | 0:69ea2af1d9af | 62 | } else |
okini3939 | 0:69ea2af1d9af | 63 | if (mosi == p11) { |
okini3939 | 0:69ea2af1d9af | 64 | ssp_dmacr = &LPC_SSP0->DMACR; |
okini3939 | 0:69ea2af1d9af | 65 | dmacon0 = MODDMA::SSP0_Tx; |
okini3939 | 0:69ea2af1d9af | 66 | dmacon1 = MODDMA::SSP0_Rx; |
okini3939 | 0:69ea2af1d9af | 67 | } |
okini3939 | 0:69ea2af1d9af | 68 | dmaexit = 1; |
okini3939 | 0:69ea2af1d9af | 69 | #endif |
okini3939 | 0:69ea2af1d9af | 70 | |
okini3939 | 0:69ea2af1d9af | 71 | #ifdef RAM_USE_FIFO |
okini3939 | 0:69ea2af1d9af | 72 | fifo_num = 0; |
okini3939 | 0:69ea2af1d9af | 73 | #endif |
okini3939 | 0:69ea2af1d9af | 74 | } |
okini3939 | 0:69ea2af1d9af | 75 | |
okini3939 | 0:69ea2af1d9af | 76 | int SerRAM::write (int addr, int dat) { |
okini3939 | 0:69ea2af1d9af | 77 | |
okini3939 | 0:69ea2af1d9af | 78 | _cs = 0; |
okini3939 | 0:69ea2af1d9af | 79 | _spi.write(CMD_WRITE); |
okini3939 | 0:69ea2af1d9af | 80 | if (_size > 512) { |
okini3939 | 0:69ea2af1d9af | 81 | _spi.write((addr >> 16) & 0xff); |
okini3939 | 0:69ea2af1d9af | 82 | } |
okini3939 | 0:69ea2af1d9af | 83 | _spi.write((addr >> 8) & 0xff); |
okini3939 | 0:69ea2af1d9af | 84 | _spi.write(addr & 0xff); |
okini3939 | 0:69ea2af1d9af | 85 | _spi.write(dat); |
okini3939 | 0:69ea2af1d9af | 86 | _cs = 1; |
okini3939 | 0:69ea2af1d9af | 87 | return 0; |
okini3939 | 0:69ea2af1d9af | 88 | } |
okini3939 | 0:69ea2af1d9af | 89 | |
okini3939 | 0:69ea2af1d9af | 90 | int SerRAM::write (int addr, char *buf, int len, int async) { |
okini3939 | 0:69ea2af1d9af | 91 | int i; |
okini3939 | 0:69ea2af1d9af | 92 | #ifdef RAM_USE_DMA |
okini3939 | 0:69ea2af1d9af | 93 | static char dummy[RAM_DMA_SIZE]; |
okini3939 | 0:69ea2af1d9af | 94 | #endif |
okini3939 | 0:69ea2af1d9af | 95 | |
okini3939 | 0:69ea2af1d9af | 96 | DBG("DMA write %04x %d\r\n", addr, len); |
okini3939 | 0:69ea2af1d9af | 97 | #ifdef RAM_USE_DMA |
okini3939 | 0:69ea2af1d9af | 98 | while (! dmaexit); |
okini3939 | 0:69ea2af1d9af | 99 | #endif |
okini3939 | 0:69ea2af1d9af | 100 | _cs = 0; |
okini3939 | 0:69ea2af1d9af | 101 | _spi.write(CMD_WRITE); |
okini3939 | 0:69ea2af1d9af | 102 | if (_size > 512) { |
okini3939 | 0:69ea2af1d9af | 103 | _spi.write((addr >> 16) & 0xff); |
okini3939 | 0:69ea2af1d9af | 104 | } |
okini3939 | 0:69ea2af1d9af | 105 | _spi.write((addr >> 8) & 0xff); |
okini3939 | 0:69ea2af1d9af | 106 | _spi.write(addr & 0xff); |
okini3939 | 0:69ea2af1d9af | 107 | |
okini3939 | 0:69ea2af1d9af | 108 | #ifdef RAM_USE_DMA |
okini3939 | 0:69ea2af1d9af | 109 | if (len > RAM_DMA_SIZE) len = RAM_DMA_SIZE; |
okini3939 | 0:69ea2af1d9af | 110 | |
okini3939 | 0:69ea2af1d9af | 111 | dmacfg0 |
okini3939 | 0:69ea2af1d9af | 112 | ->channelNum ( MODDMA::Channel_0 ) |
okini3939 | 0:69ea2af1d9af | 113 | ->srcMemAddr ( (uint32_t)buf ) |
okini3939 | 0:69ea2af1d9af | 114 | ->dstMemAddr ( dmacon0 ) |
okini3939 | 0:69ea2af1d9af | 115 | ->transferSize ( len ) |
okini3939 | 0:69ea2af1d9af | 116 | ->transferType ( MODDMA::m2p ) |
okini3939 | 0:69ea2af1d9af | 117 | ->dstConn ( dmacon0 ) |
okini3939 | 0:69ea2af1d9af | 118 | ->attach_tc ( this, &SerRAM::tc0_callback ) |
okini3939 | 0:69ea2af1d9af | 119 | ->attach_err ( this, &SerRAM::err_callback ) |
okini3939 | 0:69ea2af1d9af | 120 | ; // config end |
okini3939 | 0:69ea2af1d9af | 121 | |
okini3939 | 0:69ea2af1d9af | 122 | dmacfg1 |
okini3939 | 0:69ea2af1d9af | 123 | ->channelNum ( MODDMA::Channel_1 ) |
okini3939 | 0:69ea2af1d9af | 124 | ->srcMemAddr ( dmacon1 ) |
okini3939 | 0:69ea2af1d9af | 125 | ->dstMemAddr ( (uint32_t)dummy ) |
okini3939 | 0:69ea2af1d9af | 126 | ->transferSize ( len ) |
okini3939 | 0:69ea2af1d9af | 127 | ->transferType ( MODDMA::p2m ) |
okini3939 | 0:69ea2af1d9af | 128 | ->srcConn ( dmacon1 ) |
okini3939 | 0:69ea2af1d9af | 129 | ->attach_tc ( this, &SerRAM::tc1_callback ) |
okini3939 | 0:69ea2af1d9af | 130 | ->attach_err ( this, &SerRAM::err_callback ) |
okini3939 | 0:69ea2af1d9af | 131 | ; // config end |
okini3939 | 0:69ea2af1d9af | 132 | |
okini3939 | 0:69ea2af1d9af | 133 | dmaexit = 0; |
okini3939 | 0:69ea2af1d9af | 134 | if (dma.Setup( dmacfg0 ) && dma.Setup( dmacfg1 )) { |
okini3939 | 0:69ea2af1d9af | 135 | DBG("DMA setup\r\n"); |
okini3939 | 0:69ea2af1d9af | 136 | *ssp_dmacr = (1<<1)|(1<<0); // TX,RXDMAE |
okini3939 | 0:69ea2af1d9af | 137 | dma.Enable( dmacfg0 ); |
okini3939 | 0:69ea2af1d9af | 138 | dma.Enable( dmacfg1 ); |
okini3939 | 0:69ea2af1d9af | 139 | DBG("DMA enable\r\n"); |
okini3939 | 0:69ea2af1d9af | 140 | i = 0; |
okini3939 | 0:69ea2af1d9af | 141 | } else { |
okini3939 | 0:69ea2af1d9af | 142 | DBG("DMA error\r\n"); |
okini3939 | 0:69ea2af1d9af | 143 | i = -1; |
okini3939 | 0:69ea2af1d9af | 144 | } |
okini3939 | 0:69ea2af1d9af | 145 | |
okini3939 | 0:69ea2af1d9af | 146 | if (async == 0) { |
okini3939 | 0:69ea2af1d9af | 147 | while (! dmaexit); |
okini3939 | 0:69ea2af1d9af | 148 | DBG("DMA done\r\n"); |
okini3939 | 0:69ea2af1d9af | 149 | } |
okini3939 | 0:69ea2af1d9af | 150 | #else |
okini3939 | 0:69ea2af1d9af | 151 | for (i = 0; i < len; i ++) { |
okini3939 | 0:69ea2af1d9af | 152 | _spi.write(buf[i]); |
okini3939 | 0:69ea2af1d9af | 153 | } |
okini3939 | 0:69ea2af1d9af | 154 | _cs = 1; |
okini3939 | 0:69ea2af1d9af | 155 | #endif |
okini3939 | 0:69ea2af1d9af | 156 | return i; |
okini3939 | 0:69ea2af1d9af | 157 | } |
okini3939 | 0:69ea2af1d9af | 158 | |
okini3939 | 0:69ea2af1d9af | 159 | int SerRAM::read (int addr) { |
okini3939 | 0:69ea2af1d9af | 160 | int dat; |
okini3939 | 0:69ea2af1d9af | 161 | |
okini3939 | 0:69ea2af1d9af | 162 | _cs = 0; |
okini3939 | 0:69ea2af1d9af | 163 | _spi.write(CMD_READ); |
okini3939 | 0:69ea2af1d9af | 164 | if (_size > 512) { |
okini3939 | 0:69ea2af1d9af | 165 | _spi.write((addr >> 16) & 0xff); |
okini3939 | 0:69ea2af1d9af | 166 | } |
okini3939 | 0:69ea2af1d9af | 167 | _spi.write((addr >> 8) & 0xff); |
okini3939 | 0:69ea2af1d9af | 168 | _spi.write(addr & 0xff); |
okini3939 | 0:69ea2af1d9af | 169 | dat = _spi.write(0); |
okini3939 | 0:69ea2af1d9af | 170 | _cs = 1; |
okini3939 | 0:69ea2af1d9af | 171 | return dat; |
okini3939 | 0:69ea2af1d9af | 172 | } |
okini3939 | 0:69ea2af1d9af | 173 | |
okini3939 | 0:69ea2af1d9af | 174 | int SerRAM::read (int addr, char *buf, int len, int async) { |
okini3939 | 0:69ea2af1d9af | 175 | int i; |
okini3939 | 0:69ea2af1d9af | 176 | |
okini3939 | 0:69ea2af1d9af | 177 | DBG("DMA read %04x %d\r\n", addr, len); |
okini3939 | 0:69ea2af1d9af | 178 | #ifdef RAM_USE_DMA |
okini3939 | 0:69ea2af1d9af | 179 | while (! dmaexit); |
okini3939 | 0:69ea2af1d9af | 180 | #endif |
okini3939 | 0:69ea2af1d9af | 181 | _cs = 0; |
okini3939 | 0:69ea2af1d9af | 182 | _spi.write(CMD_READ); |
okini3939 | 0:69ea2af1d9af | 183 | if (_size > 512) { |
okini3939 | 0:69ea2af1d9af | 184 | _spi.write((addr >> 16) & 0xff); |
okini3939 | 0:69ea2af1d9af | 185 | } |
okini3939 | 0:69ea2af1d9af | 186 | _spi.write((addr >> 8) & 0xff); |
okini3939 | 0:69ea2af1d9af | 187 | _spi.write(addr & 0xff); |
okini3939 | 0:69ea2af1d9af | 188 | |
okini3939 | 0:69ea2af1d9af | 189 | #ifdef RAM_USE_DMA |
okini3939 | 0:69ea2af1d9af | 190 | dmacfg0 |
okini3939 | 0:69ea2af1d9af | 191 | ->channelNum ( MODDMA::Channel_0 ) |
okini3939 | 0:69ea2af1d9af | 192 | ->srcMemAddr ( (uint32_t)buf ) |
okini3939 | 0:69ea2af1d9af | 193 | ->dstMemAddr ( dmacon0 ) |
okini3939 | 0:69ea2af1d9af | 194 | ->transferSize ( len ) |
okini3939 | 0:69ea2af1d9af | 195 | ->transferType ( MODDMA::m2p ) |
okini3939 | 0:69ea2af1d9af | 196 | ->dstConn ( dmacon0 ) |
okini3939 | 0:69ea2af1d9af | 197 | ->attach_tc ( this, &SerRAM::tc0_callback ) |
okini3939 | 0:69ea2af1d9af | 198 | ->attach_err ( this, &SerRAM::err_callback ) |
okini3939 | 0:69ea2af1d9af | 199 | ; // config end |
okini3939 | 0:69ea2af1d9af | 200 | |
okini3939 | 0:69ea2af1d9af | 201 | dmacfg1 |
okini3939 | 0:69ea2af1d9af | 202 | ->channelNum ( MODDMA::Channel_1 ) |
okini3939 | 0:69ea2af1d9af | 203 | ->srcMemAddr ( dmacon1 ) |
okini3939 | 0:69ea2af1d9af | 204 | ->dstMemAddr ( (uint32_t)buf ) |
okini3939 | 0:69ea2af1d9af | 205 | ->transferSize ( len ) |
okini3939 | 0:69ea2af1d9af | 206 | ->transferType ( MODDMA::p2m ) |
okini3939 | 0:69ea2af1d9af | 207 | ->srcConn ( dmacon1 ) |
okini3939 | 0:69ea2af1d9af | 208 | ->attach_tc ( this, &SerRAM::tc1_callback ) |
okini3939 | 0:69ea2af1d9af | 209 | ->attach_err ( this, &SerRAM::err_callback ) |
okini3939 | 0:69ea2af1d9af | 210 | ; // config end |
okini3939 | 0:69ea2af1d9af | 211 | |
okini3939 | 0:69ea2af1d9af | 212 | dmaexit = 0; |
okini3939 | 0:69ea2af1d9af | 213 | if (dma.Setup( dmacfg0 ) && dma.Setup( dmacfg1 )) { |
okini3939 | 0:69ea2af1d9af | 214 | *ssp_dmacr = (1<<1)|(1<<0); // TX,RXDMAE |
okini3939 | 0:69ea2af1d9af | 215 | dma.Enable( dmacfg0 ); |
okini3939 | 0:69ea2af1d9af | 216 | dma.Enable( dmacfg1 ); |
okini3939 | 0:69ea2af1d9af | 217 | i = 0; |
okini3939 | 0:69ea2af1d9af | 218 | } else { |
okini3939 | 0:69ea2af1d9af | 219 | DBG("DMA error\r\n"); |
okini3939 | 0:69ea2af1d9af | 220 | i = -1; |
okini3939 | 0:69ea2af1d9af | 221 | } |
okini3939 | 0:69ea2af1d9af | 222 | |
okini3939 | 0:69ea2af1d9af | 223 | if (async == 0) { |
okini3939 | 0:69ea2af1d9af | 224 | while (! dmaexit); |
okini3939 | 0:69ea2af1d9af | 225 | } |
okini3939 | 0:69ea2af1d9af | 226 | #else |
okini3939 | 0:69ea2af1d9af | 227 | for (i = 0; i < len; i ++) { |
okini3939 | 0:69ea2af1d9af | 228 | buf[i] = _spi.write(0); |
okini3939 | 0:69ea2af1d9af | 229 | } |
okini3939 | 0:69ea2af1d9af | 230 | _cs = 1; |
okini3939 | 0:69ea2af1d9af | 231 | #endif |
okini3939 | 0:69ea2af1d9af | 232 | return i; |
okini3939 | 0:69ea2af1d9af | 233 | } |
okini3939 | 0:69ea2af1d9af | 234 | |
okini3939 | 0:69ea2af1d9af | 235 | int SerRAM::setStatus (int status) { |
okini3939 | 0:69ea2af1d9af | 236 | |
okini3939 | 0:69ea2af1d9af | 237 | _cs = 0; |
okini3939 | 0:69ea2af1d9af | 238 | _spi.write(CMD_WRMR); |
okini3939 | 0:69ea2af1d9af | 239 | _spi.write(status); |
okini3939 | 0:69ea2af1d9af | 240 | _cs = 1; |
okini3939 | 0:69ea2af1d9af | 241 | return 0; |
okini3939 | 0:69ea2af1d9af | 242 | } |
okini3939 | 0:69ea2af1d9af | 243 | |
okini3939 | 0:69ea2af1d9af | 244 | int SerRAM::getStatus () { |
okini3939 | 0:69ea2af1d9af | 245 | int r; |
okini3939 | 0:69ea2af1d9af | 246 | |
okini3939 | 0:69ea2af1d9af | 247 | _cs = 0; |
okini3939 | 0:69ea2af1d9af | 248 | _spi.write(CMD_RDMR); |
okini3939 | 0:69ea2af1d9af | 249 | r = _spi.write(0); |
okini3939 | 0:69ea2af1d9af | 250 | _cs = 1; |
okini3939 | 0:69ea2af1d9af | 251 | return r; |
okini3939 | 0:69ea2af1d9af | 252 | } |
okini3939 | 0:69ea2af1d9af | 253 | |
okini3939 | 0:69ea2af1d9af | 254 | #ifdef RAM_USE_DMA |
okini3939 | 0:69ea2af1d9af | 255 | void SerRAM::tc0_callback () { |
okini3939 | 0:69ea2af1d9af | 256 | |
okini3939 | 0:69ea2af1d9af | 257 | MODDMA_Config *config = dma.getConfig(); |
okini3939 | 0:69ea2af1d9af | 258 | dma.Disable( (MODDMA::CHANNELS)config->channelNum() ); |
okini3939 | 0:69ea2af1d9af | 259 | |
okini3939 | 0:69ea2af1d9af | 260 | // Clear DMA IRQ flags. |
okini3939 | 0:69ea2af1d9af | 261 | if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); |
okini3939 | 0:69ea2af1d9af | 262 | if (dma.irqType() == MODDMA::ErrIrq) dma.clearErrIrq(); |
okini3939 | 0:69ea2af1d9af | 263 | DBG("tc0_callback\r\n"); |
okini3939 | 0:69ea2af1d9af | 264 | } |
okini3939 | 0:69ea2af1d9af | 265 | |
okini3939 | 0:69ea2af1d9af | 266 | void SerRAM::tc1_callback () { |
okini3939 | 0:69ea2af1d9af | 267 | |
okini3939 | 0:69ea2af1d9af | 268 | dmaexit = 1; |
okini3939 | 0:69ea2af1d9af | 269 | _cs = 1; |
okini3939 | 0:69ea2af1d9af | 270 | *ssp_dmacr = 0; |
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("tc1_callback\r\n"); |
okini3939 | 0:69ea2af1d9af | 279 | } |
okini3939 | 0:69ea2af1d9af | 280 | |
okini3939 | 0:69ea2af1d9af | 281 | void SerRAM::err_callback () { |
okini3939 | 0:69ea2af1d9af | 282 | dmaexit = -1; |
okini3939 | 0:69ea2af1d9af | 283 | _cs = 1; |
okini3939 | 0:69ea2af1d9af | 284 | DBG("err_callback\r\n"); |
okini3939 | 0:69ea2af1d9af | 285 | } |
okini3939 | 0:69ea2af1d9af | 286 | #endif |
okini3939 | 0:69ea2af1d9af | 287 | |
okini3939 | 0:69ea2af1d9af | 288 | #ifdef RAM_USE_FIFO |
okini3939 | 0:69ea2af1d9af | 289 | int SerRAM::fifoAlloc (int size) { |
okini3939 | 0:69ea2af1d9af | 290 | int n, s; |
okini3939 | 0:69ea2af1d9af | 291 | |
okini3939 | 0:69ea2af1d9af | 292 | s = ((size + 1) / RAM_DMA_SIZE + 1) * RAM_DMA_SIZE; |
okini3939 | 0:69ea2af1d9af | 293 | if (fifo_num >= RAM_FIFO_NUM || (_size * 1024 - _alloc) < s) return -1; |
okini3939 | 0:69ea2af1d9af | 294 | |
okini3939 | 0:69ea2af1d9af | 295 | n = fifo_num; |
okini3939 | 0:69ea2af1d9af | 296 | fifo[n].size = size + 1; |
okini3939 | 0:69ea2af1d9af | 297 | fifo[n].buf_w = new char[RAM_DMA_SIZE]; |
okini3939 | 0:69ea2af1d9af | 298 | fifo[n].buf_r = new char[RAM_DMA_SIZE]; |
okini3939 | 0:69ea2af1d9af | 299 | fifo[n].ram = _alloc; |
okini3939 | 0:69ea2af1d9af | 300 | fifoClear(n); |
okini3939 | 0:69ea2af1d9af | 301 | |
okini3939 | 0:69ea2af1d9af | 302 | fifo_num ++; |
okini3939 | 0:69ea2af1d9af | 303 | _alloc += s; |
okini3939 | 0:69ea2af1d9af | 304 | DBG("alloc %d + %d (%d)\r\n", fifo[n].ram, fifo[n].size, _alloc); |
okini3939 | 0:69ea2af1d9af | 305 | return n; |
okini3939 | 0:69ea2af1d9af | 306 | } |
okini3939 | 0:69ea2af1d9af | 307 | |
okini3939 | 0:69ea2af1d9af | 308 | int SerRAM::fifoPut (int n, char dat) { |
okini3939 | 0:69ea2af1d9af | 309 | int next, next2; |
okini3939 | 0:69ea2af1d9af | 310 | |
okini3939 | 0:69ea2af1d9af | 311 | next = fifo[n].addr_w + 1; |
okini3939 | 0:69ea2af1d9af | 312 | next2 = fifo[n].addr2_w + 1; |
okini3939 | 0:69ea2af1d9af | 313 | if (next >= fifo[n].size) { |
okini3939 | 0:69ea2af1d9af | 314 | // last of fifo |
okini3939 | 0:69ea2af1d9af | 315 | next = 0; |
okini3939 | 0:69ea2af1d9af | 316 | next2 = 0; |
okini3939 | 0:69ea2af1d9af | 317 | } |
okini3939 | 0:69ea2af1d9af | 318 | if (next2 >= RAM_DMA_SIZE) { |
okini3939 | 0:69ea2af1d9af | 319 | // last of buffer |
okini3939 | 0:69ea2af1d9af | 320 | next2 = 0; |
okini3939 | 0:69ea2af1d9af | 321 | } |
okini3939 | 0:69ea2af1d9af | 322 | |
okini3939 | 0:69ea2af1d9af | 323 | if (next == fifo[n].addr_r) { |
okini3939 | 0:69ea2af1d9af | 324 | // no data |
okini3939 | 0:69ea2af1d9af | 325 | return -1; |
okini3939 | 0:69ea2af1d9af | 326 | } |
okini3939 | 0:69ea2af1d9af | 327 | #ifdef RAM_USE_DMA |
okini3939 | 0:69ea2af1d9af | 328 | while (! dmaexit); // busy DMA |
okini3939 | 0:69ea2af1d9af | 329 | #endif |
okini3939 | 0:69ea2af1d9af | 330 | fifo[n].buf_w[fifo[n].addr2_w] = dat; |
okini3939 | 0:69ea2af1d9af | 331 | |
okini3939 | 0:69ea2af1d9af | 332 | if (next2 == 0) { |
okini3939 | 0:69ea2af1d9af | 333 | // ring |
okini3939 | 0:69ea2af1d9af | 334 | write(fifo[n].ram + fifo[n].ram_w, fifo[n].buf_w, RAM_DMA_SIZE, 1); |
okini3939 | 0:69ea2af1d9af | 335 | if (fifo[n].ram_w == fifo[n].ram_r) { |
okini3939 | 0:69ea2af1d9af | 336 | // w = r |
okini3939 | 0:69ea2af1d9af | 337 | memcpy(fifo[n].buf_r, fifo[n].buf_w, RAM_DMA_SIZE); |
okini3939 | 0:69ea2af1d9af | 338 | } |
okini3939 | 0:69ea2af1d9af | 339 | |
okini3939 | 0:69ea2af1d9af | 340 | fifo[n].ram_w += RAM_DMA_SIZE; |
okini3939 | 0:69ea2af1d9af | 341 | if (next == 0) { |
okini3939 | 0:69ea2af1d9af | 342 | fifo[n].ram_w = 0; |
okini3939 | 0:69ea2af1d9af | 343 | } |
okini3939 | 0:69ea2af1d9af | 344 | } |
okini3939 | 0:69ea2af1d9af | 345 | fifo[n].addr_w = next; |
okini3939 | 0:69ea2af1d9af | 346 | fifo[n].addr2_w = next2; |
okini3939 | 0:69ea2af1d9af | 347 | return 0; |
okini3939 | 0:69ea2af1d9af | 348 | } |
okini3939 | 0:69ea2af1d9af | 349 | |
okini3939 | 0:69ea2af1d9af | 350 | int SerRAM::fifoPut (int n, char *buf, int len) { |
okini3939 | 0:69ea2af1d9af | 351 | int i; |
okini3939 | 0:69ea2af1d9af | 352 | |
okini3939 | 0:69ea2af1d9af | 353 | for (i = 0; i < len; i ++) { |
okini3939 | 0:69ea2af1d9af | 354 | if (fifoPut(n, buf[i])) return -1; |
okini3939 | 0:69ea2af1d9af | 355 | } |
okini3939 | 0:69ea2af1d9af | 356 | return 0; |
okini3939 | 0:69ea2af1d9af | 357 | } |
okini3939 | 0:69ea2af1d9af | 358 | |
okini3939 | 0:69ea2af1d9af | 359 | int SerRAM::fifoGet (int n, char *dat) { |
okini3939 | 0:69ea2af1d9af | 360 | |
okini3939 | 0:69ea2af1d9af | 361 | if (fifo[n].addr_r == fifo[n].addr_w) { |
okini3939 | 0:69ea2af1d9af | 362 | // no data |
okini3939 | 0:69ea2af1d9af | 363 | return -1; |
okini3939 | 0:69ea2af1d9af | 364 | } |
okini3939 | 0:69ea2af1d9af | 365 | #ifdef RAM_USE_DMA |
okini3939 | 0:69ea2af1d9af | 366 | while (! dmaexit); // busy DMA |
okini3939 | 0:69ea2af1d9af | 367 | #endif |
okini3939 | 0:69ea2af1d9af | 368 | if (fifo[n].ram_r != fifo[n].ram_w) { |
okini3939 | 0:69ea2af1d9af | 369 | *dat = fifo[n].buf_r[fifo[n].addr2_r]; |
okini3939 | 0:69ea2af1d9af | 370 | } else |
okini3939 | 0:69ea2af1d9af | 371 | if (fifo[n].addr_w < fifo[n].addr_r) { |
okini3939 | 0:69ea2af1d9af | 372 | *dat = fifo[n].buf_r[fifo[n].addr2_r]; |
okini3939 | 0:69ea2af1d9af | 373 | } else { |
okini3939 | 0:69ea2af1d9af | 374 | // w = r and w > r |
okini3939 | 0:69ea2af1d9af | 375 | *dat = fifo[n].buf_w[fifo[n].addr2_r]; |
okini3939 | 0:69ea2af1d9af | 376 | } |
okini3939 | 0:69ea2af1d9af | 377 | |
okini3939 | 0:69ea2af1d9af | 378 | fifo[n].addr_r += 1; |
okini3939 | 0:69ea2af1d9af | 379 | fifo[n].addr2_r += 1; |
okini3939 | 0:69ea2af1d9af | 380 | if (fifo[n].addr_r >= fifo[n].size) { |
okini3939 | 0:69ea2af1d9af | 381 | // last of fifo |
okini3939 | 0:69ea2af1d9af | 382 | fifo[n].addr_r = 0; |
okini3939 | 0:69ea2af1d9af | 383 | fifo[n].addr2_r = 0; |
okini3939 | 0:69ea2af1d9af | 384 | } |
okini3939 | 0:69ea2af1d9af | 385 | if (fifo[n].addr2_r >= RAM_DMA_SIZE) { |
okini3939 | 0:69ea2af1d9af | 386 | // last of buffer |
okini3939 | 0:69ea2af1d9af | 387 | fifo[n].addr2_r = 0; |
okini3939 | 0:69ea2af1d9af | 388 | } |
okini3939 | 0:69ea2af1d9af | 389 | if (fifo[n].addr2_r == 0) { |
okini3939 | 0:69ea2af1d9af | 390 | // ring |
okini3939 | 0:69ea2af1d9af | 391 | fifo[n].ram_r += RAM_DMA_SIZE; |
okini3939 | 0:69ea2af1d9af | 392 | if (fifo[n].addr_r == 0) { |
okini3939 | 0:69ea2af1d9af | 393 | fifo[n].ram_r = 0; |
okini3939 | 0:69ea2af1d9af | 394 | } |
okini3939 | 0:69ea2af1d9af | 395 | read(fifo[n].ram + fifo[n].ram_r, fifo[n].buf_r, RAM_DMA_SIZE); |
okini3939 | 0:69ea2af1d9af | 396 | } |
okini3939 | 0:69ea2af1d9af | 397 | return 0; |
okini3939 | 0:69ea2af1d9af | 398 | } |
okini3939 | 0:69ea2af1d9af | 399 | |
okini3939 | 0:69ea2af1d9af | 400 | int SerRAM::fifoGet (int n, char *buf, int len) { |
okini3939 | 0:69ea2af1d9af | 401 | int i; |
okini3939 | 0:69ea2af1d9af | 402 | |
okini3939 | 0:69ea2af1d9af | 403 | for (i = 0; i < len; i ++) { |
okini3939 | 0:69ea2af1d9af | 404 | if (fifoGet(n, &buf[i])) return -1; |
okini3939 | 0:69ea2af1d9af | 405 | } |
okini3939 | 0:69ea2af1d9af | 406 | return 0; |
okini3939 | 0:69ea2af1d9af | 407 | } |
okini3939 | 0:69ea2af1d9af | 408 | |
okini3939 | 0:69ea2af1d9af | 409 | int SerRAM::fifoAvailable (int n) { |
okini3939 | 0:69ea2af1d9af | 410 | if (fifo[n].addr_w < fifo[n].addr_r) { |
okini3939 | 0:69ea2af1d9af | 411 | return fifo[n].addr_r - fifo[n].addr_w - 1; |
okini3939 | 0:69ea2af1d9af | 412 | } else { |
okini3939 | 0:69ea2af1d9af | 413 | return (fifo[n].size - fifo[n].addr_w) + fifo[n].addr_r - 1; |
okini3939 | 0:69ea2af1d9af | 414 | } |
okini3939 | 0:69ea2af1d9af | 415 | } |
okini3939 | 0:69ea2af1d9af | 416 | |
okini3939 | 0:69ea2af1d9af | 417 | int SerRAM::fifoUse (int n) { |
okini3939 | 0:69ea2af1d9af | 418 | return fifo[n].size - fifoAvailable(n) - 1; |
okini3939 | 0:69ea2af1d9af | 419 | } |
okini3939 | 0:69ea2af1d9af | 420 | |
okini3939 | 0:69ea2af1d9af | 421 | void SerRAM::fifoClear (int n) { |
okini3939 | 0:69ea2af1d9af | 422 | fifo[n].addr_w = 0; |
okini3939 | 0:69ea2af1d9af | 423 | fifo[n].addr_r = 0; |
okini3939 | 0:69ea2af1d9af | 424 | fifo[n].addr2_w = 0; |
okini3939 | 0:69ea2af1d9af | 425 | fifo[n].addr2_r = 0; |
okini3939 | 0:69ea2af1d9af | 426 | fifo[n].ram_w = 0; |
okini3939 | 0:69ea2af1d9af | 427 | fifo[n].ram_r = 0; |
okini3939 | 0:69ea2af1d9af | 428 | |
okini3939 | 0:69ea2af1d9af | 429 | read(fifo[n].ram + fifo[n].ram_r, fifo[n].buf_r, RAM_DMA_SIZE); |
okini3939 | 0:69ea2af1d9af | 430 | } |
okini3939 | 0:69ea2af1d9af | 431 | #endif |