psram_t.cpp
1 /* 2 PSRAM driver for IPS6404 3 */ 4 5 #include "psram_t.h" 6 7 Page PSRAM_T::pages[MAX_PAGES]; 8 uint8_t PSRAM_T::nbPages=0; 9 int8_t PSRAM_T::top=0; 10 int8_t PSRAM_T::last=0; 11 12 13 #ifdef HAS_PSRAM 14 15 #include <SPI.h> 16 #include <DMAChannel.h> 17 18 #define SPI SPI2 19 20 //#define SPICLOCK 104000000 21 #define SPICLOCK 70000000 22 //#define SPICLOCK 144e6 //Just a number..max speed 23 #define SPI_MODE SPI_MODE0 24 25 #define RAM_READ 0xB 26 //#define RAM_READ 0x3 27 #define RAM_WRITE 0x2 28 29 30 uint8_t PSRAM_T::_cs, PSRAM_T::_miso, PSRAM_T::_mosi, PSRAM_T::_sclk; 31 32 33 PSRAM_T::PSRAM_T(uint8_t cs, uint8_t mosi, uint8_t sclk, uint8_t miso) 34 { 35 _cs = cs; 36 _mosi = mosi; 37 _sclk = sclk; 38 _miso = miso; 39 pinMode(_cs, OUTPUT); 40 digitalWrite(_cs, 1); 41 } 42 43 44 void PSRAM_T::begin(void) 45 { 46 SPI.setMOSI(_mosi); 47 SPI.setMISO(_miso); 48 SPI.setSCK(_sclk); 49 SPI.begin(); 50 51 delay(1); 52 53 digitalWrite(_cs, 0); 54 SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE)); 55 SPI.transfer(0x66); 56 digitalWrite(_cs, 1); 57 SPI.endTransaction(); 58 SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE)); 59 digitalWrite(_cs, 0); 60 SPI.transfer(0x99); 61 SPI.endTransaction(); 62 digitalWrite(_cs, 1); 63 delayMicroseconds(20); 64 } 65 66 67 68 uint8_t PSRAM_T::psram_read(uint32_t addr) 69 { 70 uint8_t val=0; 71 72 digitalWrite(_cs, 0); 73 SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE)); 74 SPI.transfer(RAM_READ); 75 SPI.transfer((addr>>16)&0xff); 76 SPI.transfer((addr>>8)&0xff); 77 SPI.transfer(addr&0xff); 78 #if RAM_READ == 0xB 79 SPI.transfer(0xFF); 80 #endif 81 val = SPI.transfer(0xFF); 82 SPI.endTransaction(); 83 digitalWrite(_cs, 1); 84 return val; 85 } 86 87 88 void PSRAM_T::psram_read_n(uint32_t addr, uint8_t * val, int n) 89 { 90 digitalWrite(_cs, 0); 91 SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE)); 92 SPI.transfer(RAM_READ); 93 SPI.transfer((addr>>16)&0xff); 94 SPI.transfer((addr>>8)&0xff); 95 SPI.transfer(addr&0xff); 96 #if RAM_READ == 0xB 97 SPI.transfer(0xFF); 98 #endif 99 /* 100 while (n > 0) { 101 *val++ = SPI.transfer(0xFF); 102 n--; 103 } 104 */ 105 SPI.transfer(val,n); 106 SPI.endTransaction(); 107 digitalWrite(_cs, 1); 108 } 109 110 111 void PSRAM_T::psram_write(uint32_t addr, uint8_t val) 112 { 113 digitalWrite(_cs, 0); 114 SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE)); 115 SPI.transfer(RAM_WRITE); 116 SPI.transfer((addr>>16)&0xff); 117 SPI.transfer((addr>>8)&0xff); 118 SPI.transfer(addr&0xff); 119 SPI.transfer(val); 120 SPI.endTransaction(); 121 digitalWrite(_cs, 1); 122 } 123 124 static uint8_t resp[PAGE_SIZE]; 125 126 127 void PSRAM_T::psram_write_n(uint32_t addr, uint8_t * val, int n) 128 { 129 digitalWrite(_cs, 0); 130 SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE)); 131 SPI.transfer(RAM_WRITE); 132 SPI.transfer((addr>>16)&0xff); 133 SPI.transfer((addr>>8)&0xff); 134 SPI.transfer(addr&0xff); 135 /* 136 while (n > 0) { 137 SPI.transfer(*val++); 138 n--; 139 } 140 */ 141 SPI.transfer(val,&resp[0],n); 142 SPI.endTransaction(); 143 digitalWrite(_cs, 1); 144 } 145 146 147 #ifdef DMATRY 148 #include <DMAChannel.h> 149 150 DMAMEM static uint8_t src[PAGE_SIZE+4]; 151 DMAMEM static uint8_t dst[PAGE_SIZE+4]; 152 static DMASetting dmasettings[8]; 153 static DMAChannel dmatx; 154 static volatile uint8_t rstop = 0; 155 156 #define DMASPI_PRINT(x) do {Serial.printf(x) ; Serial.flush();} while (0); 157 158 static void dmaInterrupt() 159 { 160 dmatx.clearInterrupt(); 161 rstop = 1; 162 //DMASPI_PRINT("irq"); 163 } 164 165 void PSRAM_T::psram_write_n_dma(uint32_t addr, uint8_t * val, int n) { 166 uint8_t * dstPt = &dst[0]; 167 //*dstPt++ = RAM_WRITE; 168 //*dstPt++ = (addr>>16)&0xff; 169 //*dstPt++ = (addr>>8)&0xff; 170 //*dstPt++ = addr&0xff; 171 int cnt = n; 172 while (cnt > 0) { 173 *dstPt++ = *val++; 174 cnt--; 175 } 176 arm_dcache_flush(&dst[0], n); 177 rstop = 0; 178 dmatx.disable(); 179 dmatx.attachInterrupt(dmaInterrupt); 180 181 dmasettings[0].sourceBuffer(&dst[0], n); 182 //dmasettings[0].destination((uint8_t &) LPSPI4_TDR); 183 dmasettings[0].destination((uint8_t &) IMXRT_LPSPI1_S.TDR); 184 dmasettings[0].TCD->ATTR_DST = 1; 185 dmasettings[0].interruptAtCompletion(); 186 187 Serial.printf("A") ; Serial.flush(); 188 189 digitalWrite(_cs, HIGH); 190 // SPI.begin(); 191 SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE)); 192 193 digitalWrite(_cs, 0); 194 SPI.transfer(RAM_WRITE); 195 SPI.transfer((addr>>16)&0xff); 196 SPI.transfer((addr>>8)&0xff); 197 SPI.transfer(addr&0xff); 198 //SPI.transfer(0); 199 //SPI.transfer(1); 200 Serial.printf("B") ; Serial.flush(); 201 202 #ifdef XXX 203 LPSPI4_CR &= ~LPSPI_CR_MEN;//disable LPSPI: 204 LPSPI4_CFGR1 |= LPSPI_CFGR1_NOSTALL; //prevent stall from RX 205 //LPSPI4_TCR = 15; // Framesize 16 Bits 206 IMXRT_LPSPI4_S.TCR = (IMXRT_LPSPI4_S.TCR & ~(LPSPI_TCR_FRAMESZ(31))) | LPSPI_TCR_FRAMESZ(7); 207 LPSPI4_DER = LPSPI_DER_TDDE; //TX DMA Request Enable 208 // IMXRT_LPSPI4_S.DER = LPSPI_DER_TDDE; // | LPSPI_DER_RDDE; //enable DMA on both TX and RX 209 LPSPI4_CR |= LPSPI_CR_MEN; //enable LPSPI: 210 //IMXRT_LPSPI4_S.TCR = (IMXRT_LPSPI4_S.TCR & ~(LPSPI_TCR_FRAMESZ(31))) | LPSPI_TCR_FRAMESZ(7); 211 // IMXRT_LPSPI4_S.FCR = 0; 212 // Lets try to output the first byte to make sure that we are in 8 bit mode... 213 // IMXRT_LPSPI4_S.SR = 0x3f00; // clear out all of the other status... 214 215 dmatx.triggerAtHardwareEvent( DMAMUX_SOURCE_LPSPI4_TX ); 216 #endif 217 IMXRT_LPSPI1_S.CR &= ~LPSPI_CR_MEN;//disable LPSPI: 218 IMXRT_LPSPI1_S.CFGR1 |= LPSPI_CFGR1_NOSTALL; //prevent stall from RX 219 IMXRT_LPSPI1_S.TCR = (IMXRT_LPSPI4_S.TCR & ~(LPSPI_TCR_FRAMESZ(31))) | LPSPI_TCR_FRAMESZ(7); 220 IMXRT_LPSPI1_S.DER = LPSPI_DER_TDDE; //TX DMA Request Enable 221 IMXRT_LPSPI1_S.CR |= LPSPI_CR_MEN; //enable LPSPI: 222 dmatx.triggerAtHardwareEvent( DMAMUX_SOURCE_LPSPI1_TX ); 223 Serial.printf("C") ; Serial.flush(); 224 // SPI.initDMAChannels(); 225 dmatx = dmasettings[0]; 226 227 dmatx.enable(); 228 Serial.printf("D") ; Serial.flush(); 229 while (rstop == 0) {}; 230 231 Serial.printf("E") ; Serial.flush(); 232 digitalWrite(_cs, 1); 233 } 234 #endif 235 236 237 238 #else 239 240 241 #include "emuapi.h" 242 243 244 PSRAM_T::PSRAM_T(uint8_t cs, uint8_t mosi, uint8_t sclk, uint8_t miso) 245 { 246 } 247 248 void PSRAM_T::begin(void) 249 { 250 emu_FileTempInit(); 251 } 252 253 void PSRAM_T::psram_read_n(uint32_t addr, uint8_t * val, int n) 254 { 255 emu_FileTempRead(addr,val,n); 256 } 257 258 259 void PSRAM_T::psram_write(uint32_t addr, uint8_t val) 260 { 261 emu_FileTempWrite(addr,val); 262 } 263 264 #endif 265 266 267 268 void PSRAM_T::pswrite(uint32_t addr, uint8_t val) 269 { 270 psram_write(addr, val); 271 //return; 272 uint32_t curPage=addr&(~(PAGE_SIZE-1)); 273 for (int i=0; i<nbPages; i++) { 274 if (pages[i].pageid == curPage) { 275 pages[i].page[addr&(PAGE_SIZE-1)] = val; 276 break; 277 } 278 } 279 } 280 281 282 283 284 uint8_t PSRAM_T::psread(uint32_t addr) 285 { 286 //uint8_t val = psram_read(addr); 287 //return val; 288 uint32_t curPage=addr&(~(PAGE_SIZE-1)); 289 uint32_t offs = addr&(PAGE_SIZE-1); 290 291 for (int i=0; i<nbPages; i++) { 292 if (pages[i].pageid == curPage) { 293 if ( (pages[i].prev != i) && (pages[i].next != i) ) { 294 pages[pages[i].prev].next = pages[i].next; 295 pages[pages[i].next].prev = pages[i].prev; 296 } 297 else if (pages[i].next != i) { 298 pages[pages[i].next].prev = i; 299 } 300 else if (pages[i].prev != i) { 301 pages[pages[i].prev].next = pages[i].prev; 302 last = pages[i].prev; 303 } 304 // last page accessed to top 305 pages[i].prev = i; //-1; 306 pages[i].next = top; 307 pages[top].prev = i; 308 top = i; 309 return pages[top].page[offs]; 310 } 311 } 312 if (nbPages<MAX_PAGES) 313 { 314 // add at top 315 pages[nbPages].pageid = curPage; 316 pages[nbPages].prev = nbPages; //-1; 317 pages[nbPages].next = top; 318 pages[top].prev = nbPages; 319 top = nbPages; 320 nbPages++; 321 } 322 else { 323 // replace last and move to top 324 int n = pages[last].prev; 325 pages[n].next = n; //-1; 326 pages[last].pageid = curPage; 327 pages[last].prev = last; //-1; 328 pages[last].next = top; 329 pages[top].prev = last; 330 top = last; 331 last = n; 332 } 333 //emu_printi(curPage); 334 psram_read_n(curPage,&(pages[top].page[0]),PAGE_SIZE); 335 return pages[top].page[offs]; 336 } 337 338 uint16_t PSRAM_T::psread_w(uint32_t addr) 339 { 340 uint32_t curPage=addr&(~(PAGE_SIZE-1)); 341 uint32_t offs = addr&(PAGE_SIZE-1); 342 343 for (int i=0; i<nbPages; i++) { 344 if (pages[i].pageid == curPage) { 345 if ( (pages[i].prev != i) && (pages[i].next != i) ) { 346 pages[pages[i].prev].next = pages[i].next; 347 pages[pages[i].next].prev = pages[i].prev; 348 } 349 else if (pages[i].next != i) { 350 pages[pages[i].next].prev = i; 351 } 352 else if (pages[i].prev != i) { 353 pages[pages[i].prev].next = pages[i].prev; 354 last = pages[i].prev; 355 } 356 // last page accessed to top 357 pages[i].prev = i; //-1; 358 pages[i].next = top; 359 pages[top].prev = i; 360 top = i; 361 return (pages[top].page[offs+1]<<8) + pages[top].page[offs]; 362 } 363 } 364 if (nbPages<MAX_PAGES) 365 { 366 // add at top 367 pages[nbPages].pageid = curPage; 368 pages[nbPages].prev = nbPages; //-1; 369 pages[nbPages].next = top; 370 pages[top].prev = nbPages; 371 top = nbPages; 372 nbPages++; 373 } 374 else { 375 // replace last and move to top 376 int n = pages[last].prev; 377 pages[n].next = n; //-1; 378 pages[last].pageid = curPage; 379 pages[last].prev = last; //-1; 380 pages[last].next = top; 381 pages[top].prev = last; 382 top = last; 383 last = n; 384 } 385 //emu_printi(curPage); 386 psram_read_n(curPage,&(pages[top].page[0]),PAGE_SIZE); 387 return (pages[top].page[offs+1]<<8) + pages[top].page[offs]; 388 } 389 390