My question is around latency limitations of the PSRAM on the Teensy 4.1 in regards to random access.
I was hoping to achieve worst case sub-microsecond tiny random access reads (reading a single byte) from the PSRAM. The majority of the time, I experience sub-microsecond reads (well below that limit) but I do experience the occasional read that takes particularly long. My understanding from reading the datasheets and startup.c is that there is some caching/prefetching/other complicating factors that make it non-trivial to immediately tell how long worst case random access read should take.
My question (for someone who understands this far deeper than I do) is two-fold:
1. Are worst case sub-microsecond tiny random access reads from PSRAM feasible?
2. If so, any suggestions on how one might achieve this? I'm guessing it would require a rewrite of the FlexSPI configuration to optimize short, random reads?
I wrote a little script to get basic timing data on sequential vs random access reads. Hopefully it's helpful to understand the types of reads I'm talking about. You can see that, on average, the random access reads are well below a microsecond but there are outliers in there that are causing issues for my use case (interfacing with an externally clocked system). You can also see that sequential access is an order of magnitude faster than random access on the PSRAM.
I'm a software dev with little hardware experience so sorry if I'm missing something obvious. Happy to provide any additional details that might be helpful. Thanks!
I was hoping to achieve worst case sub-microsecond tiny random access reads (reading a single byte) from the PSRAM. The majority of the time, I experience sub-microsecond reads (well below that limit) but I do experience the occasional read that takes particularly long. My understanding from reading the datasheets and startup.c is that there is some caching/prefetching/other complicating factors that make it non-trivial to immediately tell how long worst case random access read should take.
My question (for someone who understands this far deeper than I do) is two-fold:
1. Are worst case sub-microsecond tiny random access reads from PSRAM feasible?
2. If so, any suggestions on how one might achieve this? I'm guessing it would require a rewrite of the FlexSPI configuration to optimize short, random reads?
I wrote a little script to get basic timing data on sequential vs random access reads. Hopefully it's helpful to understand the types of reads I'm talking about. You can see that, on average, the random access reads are well below a microsecond but there are outliers in there that are causing issues for my use case (interfacing with an externally clocked system). You can also see that sequential access is an order of magnitude faster than random access on the PSRAM.
I'm a software dev with little hardware experience so sorry if I'm missing something obvious. Happy to provide any additional details that might be helpful. Thanks!
Code:
// Output running locally for 10000 reads:
//Random access
//Fast RAM: 221 us
//PSRAM: 6950 us
//Sequential access
//Fast RAM: 202 us
//PSRAM: 319 us
EXTMEM uint8_t extmem_data[0x10000];
uint8_t data[0x10000];
uint32_t memory_test() {
while (!Serial) ;
uint32_t result[10]; // prevent optimizing the loops away
uint32_t num_samples = 100000;
uint32_t num_iters = 10000;
uint32_t *idxes = malloc(num_samples);
// fill in random indices to access
for (int i = 0; i < num_samples; i++) {
idxes[i] = random(0x10000);
}
Serial.println("Random access");
elapsedMicros took = 0;
for (int i = 0; i < num_iters; i++) {
result[i % 10] = data[idxes[i]];
}
unsigned long res = took;
Serial.printf("Fast RAM: %d\n", res);
took = 0;
for (int i = 0; i < num_iters; i++) {
result[i % 10] = extmem_data[idxes[i]];
}
res = took;
Serial.printf("PSRAM: %d\n", res);
Serial.println("Sequential access");
took = 0;
for (int i = 0; i < num_iters; i++) {
result[i % 10] = data[i];
}
res = took;
Serial.printf("Fast RAM: %d\n", res);
took = 0;
for (int i = 0; i < num_iters; i++) {
result[i % 10] = extmem_data[i];
}
res = took;
Serial.printf("PSRAM: %d\n", res);
return result[5];
}
void setup() {
memory_test();
}
void loop() {
// put your main code here, to run repeatedly:
}