potatotron
Well-known member
Not sure where you got this but we definitely had it working at least up to 60Mhz for SPI.
My mistake. Thanks for the clarification.
Not sure where you got this but we definitely had it working at least up to 60Mhz for SPI.
But I think you SPI markings for 38-41 got shifted a couple pins should be on 36-39?
Hmmm, you have the flash/psram pads underneath the Teensy 4.1 as being alternates for SPI2 (i.e. MISO2, MOSI2, SCLK2) which is the SPI bus used for the micro-SD card. Does this mean that if you were to want to have a sketch that reads from both the SD card and the attached QSPI memory that you would have to keep switching the pins between the two?Hi @Paul,
I am going through and doing a quick review of your card versus my card/tables...
Found I had issues with my PWM markings, which I correct on mine.
But I think you SPI markings for 38-41 got shifted a couple pins should be on 36-39?
That is I believe 39 is alternate to MISO1 not 41
Does this mean that if you were to want to have a sketch that reads from both the SD card and the attached QSPI memory that you would have to keep switching the pins between the two?
The QSPI memory accessed with FlexSPI2, which is completely different and separate from all 3 of the normal SPI ports. It's also separate from FlexSPI1 which is used for the main program memory. The FlexSPI ports are designed to map memory chips directly into the ARM's address space. They are very fast and feature another layer of caching between the processor's L1 cache and the actual QSPI memory. FlexSPI is a completely different type of peripheral than the regular SPI ports.
Nope, there's no conflict here.
The SD card is accessed using SDIO (native 4 bit data + cmd). SPI2 isn't used for the SD card. But if no SD card is present, those pins can be used as GPIO or SPI2 or Serial5... that is, if you're able to solder tiny wires to the exposed parts of those SMT pads on the SD socket.
SPI2 isn't used for the QSPI chips either (even though those pins could be used for SPI2 if memory chips aren't installed). The QSPI memory accessed with FlexSPI2, which is completely different and separate from all 3 of the normal SPI ports. It's also separate from FlexSPI1 which is used for the main program memory. The FlexSPI ports are designed to map memory chips directly into the ARM's address space. FlexSPI is much faster than regular SPI. It's triggered automatically by when the processor uses its bus to access memory to fill or flush 32-byte L1 cache lines. The FlexSPI ports also feature another layer of caching between the processor's L1 cache and the actual QSPI memory, so the bus isn't tied up while the QSPI memory transfer happens. FlexSPI is a completely different type of peripheral than the regular SPI ports.
This chip is loaded with so much incredibly powerful hardware that it's hard to keep track of so much capability....
And I suspect we will find subtle caching bugs in the future as more people use the memories.
Does this mean, one can access the additional RAM chip directly via memory access?
Yes you can.Does this mean, one can access the additional RAM chip directly via memory access?
Tested with 8 and 32 bit mem pointer access to write and verify with read of a value '24'. That was interleaved with full pass of the value '42' to verify the 8 MB RAM was fully read and written. And the test starts on odd byte boundary and there was no crash on any boundary with 4 byte access:Does this mean, one can access the additional RAM chip directly via memory access?
[B][COLOR="#FF0000"]uint32_t *ptrERAM_32 = (uint32_t *)0x70000001l;[/COLOR] // Set to ERAM
const uint32_t [B][COLOR="#FF0000"]sizeofERAM_32[/COLOR][/B] = 0x7FFFFF / sizeof( ptrERAM_32 ); // sizeof free RAM in uint32_t units.
[/B]
void check24() {
uint32_t ii;
uint32_t jj = 0, kk = 0;
Serial.print("\n ERAM ========== memory map ===== array* ======== check24() : WRITE !!!!\n");
Serial.printf("\t\tERAM length 0x%X element size of %d\n", sizeofERAM_32, sizeof( ptrERAM_32[0] ));
my_us = 0;
[B] for ( ii = 0; ii < sizeofERAM_32; ii++ ) {
[COLOR="#FF0000"]ptrERAM_32[ii] = 24;[/COLOR]
[/B] }
Serial.printf( "\t took %lu elapsed us\n", (uint32_t)my_us );
Serial.print(" ERAM ============================ check24() : COMPARE !!!!\n");
my_us = 0;
for ( ii = 0; ii < sizeofERAM_32; ii++ ) {
[B] [COLOR="#FF0000"]if ( 24 != ptrERAM_32[ii] )[/COLOR] {
[/B] if ( kk != 0 ) {
Serial.printf( "\t+++ Good Run of %u {bad @ %u}\n", kk, ii );
kk = 0;
}
if ( jj < 100 )
Serial.printf( "%3u=%8u\n", ii, ptrERAM_32[ii] );
jj++;
}
else {
kk++;
}
}
Serial.printf( "\t took %lu elapsed us\n", (uint32_t)my_us );
if ( 0 == jj )
Serial.printf( "Good, " );
else
Serial.printf( "Failed to find 24 in ERAM %d Times", jj );
Serial.printf( "\tFound 24 in ERAM %X Times\n", sizeofERAM_32 - jj );
}
ERAM ========== memory map ================== check24() : WRITE !!!!
ERAM length 0x1FFFFF element size of 4
took 226904 elapsed us
ERAM ============================ check24() : COMPARE !!!!
took 207897 elapsed us
Good, Found 24 in ERAM 1FFFFF Times
Great, Now I only need to receive my T4.1 beta, which seems still in transit.Yes. If you solder the PSRAM chip to the bottom side and run the init code (which will soon become part of the core library's startup code), you get 8 megabytes of memory at 0x70000000 to 0x707FFFFF.
As Paul notes there will be a malloc_extmem() added - but first testing direct access for first pass testing looked like the following: github.com/PaulStoffregen/teensy41_extram/blob/master/extRAM_t4/examples/flashtest4/flashtest4.ino#L431
Tested with 8 and 32 bit mem pointer access to write and verify with read of a value '24'. That was interleaved with full pass of the value '42' to verify the 8 MB RAM was fully read and written. And the test starts on odd byte boundary and there was no crash on any boundary with 4 byte access:
Code:….
@mjs513 has just made the github code cleaner and that current code isn't yet here - but the full run of 8 MB was fast.
Here is one set of results from earlier time - for 2M uint32_t write and reads:
[COLOR="#FF0000"]#if 0
uint32_t *ptrERAM_32 = (uint32_t *)0x70000001l; // Set to ERAM
const uint32_t sizeofERAM_32 = 0x7FFFFF / sizeof( ptrERAM_32 ); // sizeof free RAM in uint32_t units.
#else
uint8_t *ptrERAM_32 = (uint8_t *)0x70000001l; // Set to ERAM
const uint32_t sizeofERAM_32 = 0x7FFFFE / sizeof( ptrERAM_32[0] ); // sizeof free RAM in uint32_t units.
#endif[/COLOR]
void check24() {
uint32_t ii;
uint32_t jj = 0, kk = 0;
Serial.print("\n ERAM ========== memory map ===== array* ======== check24() : WRITE !!!!\n");
Serial.printf("\t\tERAM length 0x%X element size of %d\n", sizeofERAM_32, sizeof( ptrERAM_32[0] ));
my_us = 0;
for ( ii = 0; ii < sizeofERAM_32; ii++ ) {
ptrERAM_32[ii] = 24;
}
Serial.printf( "\t took %lu elapsed us\n", (uint32_t)my_us );
Serial.print(" ERAM ============================ check24() : COMPARE !!!!\n");
my_us = 0;
for ( ii = 0; ii < sizeofERAM_32; ii++ ) {
if ( 24 != ptrERAM_32[ii] ) {
if ( kk != 0 ) {
Serial.printf( "\t+++ Good Run of %u {bad @ %u}\n", kk, ii );
kk = 0;
}
if ( jj < 100 )
Serial.printf( "%3u=%8u\n", ii, ptrERAM_32[ii] );
jj++;
}
else {
kk++;
}
}
Serial.printf( "\t took %lu elapsed us\n", (uint32_t)my_us );
if ( 0 == jj )
Serial.printf( "Good, " );
else
Serial.printf( "Failed to find 24 in ERAM %d Times", jj );
Serial.printf( "\tFound 24 in ERAM %X Times\n", sizeofERAM_32 - jj );
}
The function @defraster is reference has been incorporated into flashtest6.ino in the extRAM_t4 library examples directory:
Just change the if 0 to if 1 to test for uint32'sCode:...
@defragster - how does EXTMEM access compare to normal or DMAMEM access in terms of speed?
from DTCM 15 us
from OCRAM 55 us
from PROGMEM 558 us
from 0x70000000 ERAM 1115 us @49.5MHz 780 us @133MHz EXTMEM
from 0x71000000 EFLASH 1905 us @49.5MHz 780 us @133MHz
You will have to initialize it when you first run it unless Paul incorporates that into the auto-detect routine. The library is set up so you can do an it.For the volatile memory, is it cleared before the sketch starts, or would we need to clear it?
Since we didn't have that macro available we set up the examples in the lib so you can use spiffs on the either or both of the chips. Or direct memory write to volatite memory, also setup functions that you write structured data like the FRAM-i2c library. So you have a few choices.I suspect it is best used as normal RAM memory, hence using the EXTMEM macro to control static allocation.
You know I never really tried it that way but you would think. Will have to try it.There are two flash pads, one of which is large enough for my W25Q128JVSIQ chips and is between pins 35-37 and 30-28. Given this is flash memory, it should persist between reboots.
So to be sure I understand things.
There are two flash pads, one of which is large enough for my W25Q128JVSIQ chips and is between pins 35-37 and 30-28. Given this is flash memory, it should persist between reboots. Is this correct? One way to use this seems to be with a SPIFFS filesystem mounted on that memory. I imagine using with a file system container abstraction is the best way to use this memory, rather than just an 8MB area of persistent memory (though I could imagine use cases as RAW memory).