kopia lustrzana https://github.com/Jean-MarcHarvengt/MCUME
				
				
				
			
		
			
				
	
	
		
			390 wiersze
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			390 wiersze
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C++
		
	
	
| /*
 | |
|   PSRAM driver for IPS6404
 | |
| */
 | |
| 
 | |
| #include "psram_t.h"
 | |
| 
 | |
| Page PSRAM_T::pages[MAX_PAGES];
 | |
| uint8_t PSRAM_T::nbPages=0;
 | |
| int8_t PSRAM_T::top=0;
 | |
| int8_t PSRAM_T::last=0;
 | |
| 
 | |
| 
 | |
| #ifdef HAS_PSRAM
 | |
| 
 | |
| #include <SPI.h>
 | |
| #include <DMAChannel.h>
 | |
| 
 | |
| #define SPI SPI2
 | |
| 
 | |
| //#define SPICLOCK 104000000 
 | |
| #define SPICLOCK 70000000 
 | |
| //#define SPICLOCK 144e6 //Just a number..max speed
 | |
| #define SPI_MODE SPI_MODE0
 | |
| 
 | |
| #define RAM_READ  0xB
 | |
| //#define RAM_READ  0x3
 | |
| #define RAM_WRITE 0x2
 | |
| 
 | |
| 
 | |
| uint8_t PSRAM_T::_cs, PSRAM_T::_miso, PSRAM_T::_mosi, PSRAM_T::_sclk;
 | |
| 
 | |
| 
 | |
| PSRAM_T::PSRAM_T(uint8_t cs, uint8_t mosi, uint8_t sclk, uint8_t miso)
 | |
| {
 | |
|   _cs   = cs;
 | |
|   _mosi = mosi;
 | |
|   _sclk = sclk;
 | |
|   _miso = miso;
 | |
|   pinMode(_cs, OUTPUT); 
 | |
|   digitalWrite(_cs, 1);
 | |
| }
 | |
| 
 | |
| 
 | |
| void PSRAM_T::begin(void)
 | |
| {
 | |
|   SPI.setMOSI(_mosi);
 | |
|   SPI.setMISO(_miso);
 | |
|   SPI.setSCK(_sclk);
 | |
|   SPI.begin();
 | |
| 
 | |
|   delay(1);
 | |
| 
 | |
|   digitalWrite(_cs, 0);
 | |
|   SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 | |
|   SPI.transfer(0x66);
 | |
|   digitalWrite(_cs, 1);
 | |
|   SPI.endTransaction();  
 | |
|   SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 | |
|   digitalWrite(_cs, 0);
 | |
|   SPI.transfer(0x99);
 | |
|   SPI.endTransaction();
 | |
|   digitalWrite(_cs, 1);
 | |
|   delayMicroseconds(20);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| uint8_t PSRAM_T::psram_read(uint32_t addr) 
 | |
| {
 | |
|   uint8_t val=0;
 | |
| 
 | |
|   digitalWrite(_cs, 0);  
 | |
|   SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 | |
|   SPI.transfer(RAM_READ);
 | |
|   SPI.transfer((addr>>16)&0xff);
 | |
|   SPI.transfer((addr>>8)&0xff);
 | |
|   SPI.transfer(addr&0xff);
 | |
| #if RAM_READ == 0xB  
 | |
|   SPI.transfer(0xFF);       
 | |
| #endif
 | |
|   val = SPI.transfer(0xFF);  
 | |
|   SPI.endTransaction();
 | |
|   digitalWrite(_cs, 1);
 | |
|   return val;
 | |
| }
 | |
| 
 | |
| 
 | |
| void PSRAM_T::psram_read_n(uint32_t addr, uint8_t * val, int n) 
 | |
| {
 | |
|   digitalWrite(_cs, 0);
 | |
|   SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 | |
|   SPI.transfer(RAM_READ);
 | |
|   SPI.transfer((addr>>16)&0xff);
 | |
|   SPI.transfer((addr>>8)&0xff);
 | |
|   SPI.transfer(addr&0xff);
 | |
| #if RAM_READ == 0xB  
 | |
|   SPI.transfer(0xFF);       
 | |
| #endif
 | |
|   /*
 | |
|   while (n > 0) {
 | |
|     *val++ = SPI.transfer(0xFF);
 | |
|     n--;       
 | |
|   }    
 | |
|   */
 | |
|   SPI.transfer(val,n);
 | |
|   SPI.endTransaction();
 | |
|   digitalWrite(_cs, 1);
 | |
| }
 | |
| 
 | |
| 
 | |
| void PSRAM_T::psram_write(uint32_t addr, uint8_t val) 
 | |
| {
 | |
|   digitalWrite(_cs, 0);
 | |
|   SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 | |
|   SPI.transfer(RAM_WRITE);
 | |
|   SPI.transfer((addr>>16)&0xff);
 | |
|   SPI.transfer((addr>>8)&0xff);
 | |
|   SPI.transfer(addr&0xff);    
 | |
|   SPI.transfer(val);
 | |
|   SPI.endTransaction();    
 | |
|   digitalWrite(_cs, 1);
 | |
| }
 | |
| 
 | |
| static uint8_t resp[PAGE_SIZE];
 | |
| 
 | |
| 
 | |
| void PSRAM_T::psram_write_n(uint32_t addr, uint8_t * val, int n) 
 | |
| {
 | |
|   digitalWrite(_cs, 0);
 | |
|   SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 | |
|   SPI.transfer(RAM_WRITE);
 | |
|   SPI.transfer((addr>>16)&0xff);
 | |
|   SPI.transfer((addr>>8)&0xff);
 | |
|   SPI.transfer(addr&0xff);
 | |
|   /*
 | |
|   while (n > 0) {
 | |
|     SPI.transfer(*val++);
 | |
|     n--;       
 | |
|   }
 | |
|   */
 | |
|   SPI.transfer(val,&resp[0],n);
 | |
|   SPI.endTransaction();  
 | |
|   digitalWrite(_cs, 1); 
 | |
| }
 | |
| 
 | |
| 
 | |
| #ifdef DMATRY
 | |
| #include <DMAChannel.h>
 | |
| 
 | |
| DMAMEM static uint8_t src[PAGE_SIZE+4]; 
 | |
| DMAMEM static uint8_t dst[PAGE_SIZE+4];
 | |
| static DMASetting dmasettings[8];
 | |
| static DMAChannel dmatx;
 | |
| static volatile uint8_t rstop = 0;
 | |
| 
 | |
| #define DMASPI_PRINT(x) do {Serial.printf(x) ; Serial.flush();} while (0);
 | |
| 
 | |
| static void dmaInterrupt() 
 | |
| {
 | |
|   dmatx.clearInterrupt();
 | |
|   rstop = 1;  
 | |
|   //DMASPI_PRINT("irq");
 | |
| }
 | |
| 
 | |
| void PSRAM_T::psram_write_n_dma(uint32_t addr, uint8_t * val, int n) {
 | |
|   uint8_t * dstPt = &dst[0];
 | |
|   //*dstPt++ = RAM_WRITE;
 | |
|   //*dstPt++ = (addr>>16)&0xff;
 | |
|   //*dstPt++ = (addr>>8)&0xff;
 | |
|   //*dstPt++ = addr&0xff;
 | |
|   int cnt = n;
 | |
|   while (cnt > 0) {
 | |
|     *dstPt++ = *val++;
 | |
|     cnt--;       
 | |
|   }    
 | |
|   arm_dcache_flush(&dst[0], n);
 | |
|   rstop = 0;     
 | |
|   dmatx.disable();
 | |
|   dmatx.attachInterrupt(dmaInterrupt);
 | |
| 
 | |
|   dmasettings[0].sourceBuffer(&dst[0], n);
 | |
|   //dmasettings[0].destination((uint8_t &)  LPSPI4_TDR);
 | |
|   dmasettings[0].destination((uint8_t &)  IMXRT_LPSPI1_S.TDR);
 | |
|   dmasettings[0].TCD->ATTR_DST = 1;
 | |
|   dmasettings[0].interruptAtCompletion();
 | |
| 
 | |
| Serial.printf("A") ; Serial.flush();
 | |
| 
 | |
|   digitalWrite(_cs, HIGH);
 | |
|  // SPI.begin();
 | |
|   SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 | |
| 
 | |
|   digitalWrite(_cs, 0); 
 | |
|   SPI.transfer(RAM_WRITE);
 | |
|   SPI.transfer((addr>>16)&0xff);
 | |
|   SPI.transfer((addr>>8)&0xff);
 | |
|   SPI.transfer(addr&0xff);
 | |
|   //SPI.transfer(0);
 | |
|   //SPI.transfer(1);
 | |
| Serial.printf("B") ; Serial.flush();
 | |
| 
 | |
| #ifdef XXX           
 | |
|   LPSPI4_CR &= ~LPSPI_CR_MEN;//disable LPSPI:
 | |
|   LPSPI4_CFGR1 |= LPSPI_CFGR1_NOSTALL; //prevent stall from RX
 | |
|   //LPSPI4_TCR = 15; // Framesize 16 Bits
 | |
|   IMXRT_LPSPI4_S.TCR = (IMXRT_LPSPI4_S.TCR & ~(LPSPI_TCR_FRAMESZ(31))) | LPSPI_TCR_FRAMESZ(7);  
 | |
|    LPSPI4_DER = LPSPI_DER_TDDE; //TX DMA Request Enable
 | |
|    // IMXRT_LPSPI4_S.DER = LPSPI_DER_TDDE; // | LPSPI_DER_RDDE; //enable DMA on both TX and RX
 | |
|   LPSPI4_CR |= LPSPI_CR_MEN; //enable LPSPI:
 | |
|    //IMXRT_LPSPI4_S.TCR = (IMXRT_LPSPI4_S.TCR & ~(LPSPI_TCR_FRAMESZ(31))) | LPSPI_TCR_FRAMESZ(7);  
 | |
|   //  IMXRT_LPSPI4_S.FCR = 0; 
 | |
|     // Lets try to output the first byte to make sure that we are in 8 bit mode...
 | |
|  //   IMXRT_LPSPI4_S.SR = 0x3f00; // clear out all of the other status...
 | |
|    
 | |
|   dmatx.triggerAtHardwareEvent( DMAMUX_SOURCE_LPSPI4_TX );
 | |
| #endif
 | |
|   IMXRT_LPSPI1_S.CR &= ~LPSPI_CR_MEN;//disable LPSPI:
 | |
|   IMXRT_LPSPI1_S.CFGR1 |= LPSPI_CFGR1_NOSTALL; //prevent stall from RX
 | |
|   IMXRT_LPSPI1_S.TCR = (IMXRT_LPSPI4_S.TCR & ~(LPSPI_TCR_FRAMESZ(31))) | LPSPI_TCR_FRAMESZ(7);  
 | |
|   IMXRT_LPSPI1_S.DER = LPSPI_DER_TDDE; //TX DMA Request Enable
 | |
|   IMXRT_LPSPI1_S.CR |= LPSPI_CR_MEN; //enable LPSPI:
 | |
|   dmatx.triggerAtHardwareEvent( DMAMUX_SOURCE_LPSPI1_TX );
 | |
| Serial.printf("C") ; Serial.flush();
 | |
| //  SPI.initDMAChannels();
 | |
|   dmatx = dmasettings[0];
 | |
|       
 | |
|   dmatx.enable();
 | |
| Serial.printf("D") ; Serial.flush();
 | |
|   while (rstop == 0) {};
 | |
| 
 | |
|  Serial.printf("E") ; Serial.flush();
 | |
|   digitalWrite(_cs, 1);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| 
 | |
| #else
 | |
| 
 | |
| 
 | |
| #include "emuapi.h"
 | |
| 
 | |
| 
 | |
| PSRAM_T::PSRAM_T(uint8_t cs, uint8_t mosi, uint8_t sclk, uint8_t miso)
 | |
| {
 | |
| }
 | |
| 
 | |
| void PSRAM_T::begin(void)
 | |
| {
 | |
|   emu_FileTempInit();
 | |
| }
 | |
| 
 | |
| void PSRAM_T::psram_read_n(uint32_t addr, uint8_t * val, int n) 
 | |
| {
 | |
|   emu_FileTempRead(addr,val,n);    
 | |
| }
 | |
| 
 | |
| 
 | |
| void PSRAM_T::psram_write(uint32_t addr, uint8_t val) 
 | |
| {
 | |
|   emu_FileTempWrite(addr,val);  
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| 
 | |
| 
 | |
| void PSRAM_T::pswrite(uint32_t addr, uint8_t val) 
 | |
| {
 | |
|   psram_write(addr, val);
 | |
|   //return;
 | |
|   uint32_t curPage=addr&(~(PAGE_SIZE-1));
 | |
|   for (int i=0; i<nbPages; i++) {
 | |
|     if (pages[i].pageid == curPage) {
 | |
|       pages[i].page[addr&(PAGE_SIZE-1)] = val;
 | |
|       break;
 | |
|     }
 | |
|   }   
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| uint8_t PSRAM_T::psread(uint32_t addr) 
 | |
| {
 | |
|   //uint8_t val = psram_read(addr);
 | |
|   //return val;
 | |
|   uint32_t curPage=addr&(~(PAGE_SIZE-1));
 | |
|   uint32_t offs = addr&(PAGE_SIZE-1);
 | |
| 
 | |
|   for (int i=0; i<nbPages; i++) {
 | |
|     if (pages[i].pageid == curPage) {
 | |
|       if ( (pages[i].prev != i) && (pages[i].next != i) ) {
 | |
|         pages[pages[i].prev].next =  pages[i].next;
 | |
|         pages[pages[i].next].prev = pages[i].prev;     
 | |
|       }
 | |
|       else if (pages[i].next != i) {
 | |
|         pages[pages[i].next].prev = i;
 | |
|       }
 | |
|       else if (pages[i].prev != i) {
 | |
|         pages[pages[i].prev].next =  pages[i].prev;
 | |
|         last = pages[i].prev;        
 | |
|       }
 | |
|        // last page accessed to top
 | |
|       pages[i].prev = i; //-1;
 | |
|       pages[i].next = top;      
 | |
|       pages[top].prev = i;
 | |
|       top = i;
 | |
|       return pages[top].page[offs];
 | |
|     }
 | |
|   }
 | |
|   if (nbPages<MAX_PAGES) 
 | |
|   {
 | |
|     // add at top
 | |
|     pages[nbPages].pageid = curPage;           
 | |
|     pages[nbPages].prev = nbPages; //-1;
 | |
|     pages[nbPages].next = top;     
 | |
|     pages[top].prev = nbPages;
 | |
|     top = nbPages;
 | |
|     nbPages++;
 | |
|   }
 | |
|   else {
 | |
|       // replace last and move to top
 | |
|       int n = pages[last].prev;
 | |
|       pages[n].next = n; //-1;
 | |
|       pages[last].pageid = curPage;
 | |
|       pages[last].prev = last; //-1;
 | |
|       pages[last].next = top;      
 | |
|       pages[top].prev = last;
 | |
|       top = last;
 | |
|       last = n;
 | |
|   }
 | |
|   //emu_printi(curPage);
 | |
|   psram_read_n(curPage,&(pages[top].page[0]),PAGE_SIZE);   
 | |
|   return pages[top].page[offs];
 | |
| }
 | |
| 
 | |
| uint16_t PSRAM_T::psread_w(uint32_t addr) 
 | |
| {
 | |
|   uint32_t curPage=addr&(~(PAGE_SIZE-1));
 | |
|   uint32_t offs = addr&(PAGE_SIZE-1);
 | |
| 
 | |
|   for (int i=0; i<nbPages; i++) {
 | |
|     if (pages[i].pageid == curPage) {
 | |
|       if ( (pages[i].prev != i) && (pages[i].next != i) ) {
 | |
|         pages[pages[i].prev].next =  pages[i].next;
 | |
|         pages[pages[i].next].prev = pages[i].prev;     
 | |
|       }
 | |
|       else if (pages[i].next != i) {
 | |
|         pages[pages[i].next].prev = i;
 | |
|       }
 | |
|       else if (pages[i].prev != i) {
 | |
|         pages[pages[i].prev].next =  pages[i].prev;
 | |
|         last = pages[i].prev;        
 | |
|       }
 | |
|        // last page accessed to top
 | |
|       pages[i].prev = i; //-1;
 | |
|       pages[i].next = top;      
 | |
|       pages[top].prev = i;
 | |
|       top = i;     
 | |
|       return (pages[top].page[offs+1]<<8) + pages[top].page[offs];
 | |
|     }
 | |
|   }
 | |
|   if (nbPages<MAX_PAGES) 
 | |
|   {
 | |
|     // add at top
 | |
|     pages[nbPages].pageid = curPage;           
 | |
|     pages[nbPages].prev = nbPages; //-1;
 | |
|     pages[nbPages].next = top;     
 | |
|     pages[top].prev = nbPages;
 | |
|     top = nbPages;
 | |
|     nbPages++;
 | |
|   }
 | |
|   else {
 | |
|       // replace last and move to top
 | |
|       int n = pages[last].prev;
 | |
|       pages[n].next = n; //-1;
 | |
|       pages[last].pageid = curPage;
 | |
|       pages[last].prev = last; //-1;
 | |
|       pages[last].next = top;      
 | |
|       pages[top].prev = last;
 | |
|       top = last;
 | |
|       last = n;
 | |
|   }
 | |
|   //emu_printi(curPage);
 | |
|   psram_read_n(curPage,&(pages[top].page[0]),PAGE_SIZE);   
 | |
|   return (pages[top].page[offs+1]<<8) + pages[top].page[offs];
 | |
| }
 | |
| 
 |