Call to arms | Teensy + SDRAM = true

@PaulStoffregen - @defragster
Scanner012 test:
Code:
Teensy 4.0 Scanner 012
Scanning...
Wire  Device found at address 0x29  (TSL2561,VL6180,TSL2561,TSL2591,BNO055,CAP1188)
Wire  Device found at address 0x3C  (SSD1306,DigisparkOLED)
Wire1 Device found at address 0x4B  (ADS1115,TMP102,BNO080)
Wire1 Device found at address 0x50  (EEPROM,FRAM)
Wire  Device found at address 0x62  (LidarLite,MCP4725,AtlasEzoORP)
Wire1 Device found at address 0x68  (DS1307,DS3231,MPU6050,MPU9050,MPU9250,ITG3200,ITG3701,LSM9DS0,L3G4200D)
Wire1 Device found at address 0x7C  (FRAM_x)
done

Teensy 4.1 Scanner 012
Hangs sketch - goes offline - have to do 15sec restore or press program button
9 red flashes

Not sure why Teensy 4 works but not Teens4.1? Didnt bother testing Micromod - figured that would work.

SPI - GraphicsTest.ino from ILI9341 library
Teensy 4.1 - works
Teensy 4.0 - works
 
@PaulStoffregen
Decided to put pack in 0.59.4 core with the recommended SCB changes.

Tested I2C on the T4.1 and no issues (non-malloc version)
Code:
I2C Wire Scanner
Scanning...
Wire  Device found at address 0x29  (TSL2561,VL6180,TSL2561,TSL2591,BNO055,CAP1188)
Wire  Device found at address 0x3C  (SSD1306,DigisparkOLED)
Wire1 Device found at address 0x4B  (ADS1115,TMP102,BNO080)
Wire1 Device found at address 0x50  (EEPROM,FRAM)
Wire  Device found at address 0x62  (LidarLite,MCP4725,AtlasEzoORP)
Wire1 Device found at address 0x68  (DS1307,DS3231,MPU6050,MPU9050,MPU9250,ITG3200,ITG3701,LSM9DS0,L3G4200D)
Wire1 Device found at address 0x7C  (FRAM_x)
done

and it works on the TMM with the Dev Board with SDRAM
Code:
I2C Wire Scanner
Scanning...
Wire  Device found at address 0x29  (TSL2561,VL6180,TSL2561,TSL2591,BNO055,CAP1188)
Wire  Device found at address 0x3C  (SSD1306,DigisparkOLED)
Wire1 Device found at address 0x4B  (ADS1115,TMP102,BNO080)
Wire1 Device found at address 0x50  (EEPROM,FRAM)
Wire  Device found at address 0x62  (LidarLite,MCP4725,AtlasEzoORP)
Wire1 Device found at address 0x68  (DS1307,DS3231,MPU6050,MPU9050,MPU9250,ITG3200,ITG3701,LSM9DS0,L3G4200D)
Wire1 Device found at address 0x7C  (FRAM_x)
done


Also if I activate SDRAM using the SDRAM_t4 library (yes just moded it for 0x90000000) I2C still works.

As for graphicstest.ino
Teensy Micromod SDRAM Board - works
Teensy 4.1 - works

Now to go back and try and sort out why its not working when I implement the smalloc version. But at this point the Library seems to be working with address 0x90000000 addr.

but think will have to do that with a clear head in the morning here its late :)
 
Thanks @mjs513 WORKING T_4.1 BLINK and UART!
> All 5 UARTS working at 5Mbaud
Not sure what happened - or what got fixed but I can build now for a working T_4.1 from IDE 18.19! Also T_MM/DevBoard and T_4.0!

Did a fresh Beta 4 install and copied: PJRC updated IMXRT.h and the CORES files from mallocSDRAM
> Interesting: the sdram_malloc if defaulting to malloc() on the T_4.0 and T_4.1 even though I forgot to edit the #defines. Suppose that is by GOOD design?

>> And working with CrashReport removed again
>> AND edit SDRAM_t4's 0x8 to 0x9 and the early first hardcoded UART 2 Serial example works!
 
Last edited:
@defragster - @PaulStoffregen

Ok got things sorted out before I crashed looks like both mallocSDRAM and SDRAM lib is now working with the new address. Found what I forgot.

All changes pushed to the repo as of about 10 minutes ago

Tested I2C with the I2C test board using a T4.1 and the SDRAM Dev board, BOTH WORKED

Ran graphicstest on both boards as well and SPI worked as well.
 
Last updates are marked 2 hours ago (?) - and with those all is well per p#278

Three boards pictured in earlier post here happily/annoyingly blinking at 8.5-9 Hz.

Just put i2c SSD1306 Adafruit snowflake demo running on pictured boards: T_4.0, T_4.1 and DevBoard/T_MM
 
Something ODD
Reading to RED LINE BELOW will explain why: UART_extmem_ARR.ino sketch failing after power OFF until running : sdram.init()

> with i2c Wired to the DevBoard/T_MM it cannot run the : UART_extmem_ARR.ino

It was running that sketch after it previously failed {and many hassles to get it to run again}
> Unplugged the T_MMdb board
> SSD1306 was wired up
> Plugged in and it would just restart - no prints and CrashReport disabled in loaded code
> Uploaded the prior UART_extmem.ino [uses direct 0x90000000 addressing into SDRAM and only 2 UARTS]
> that ran before and again after then: Verify build and upload the UART_extmem_ARR.ino sketch to work.

As noted this was after it failed before: following p#280 running the AdaF SSD1306 sketch
> Attempt to upload and run UART_extmem_ARR.ino would not work using sdram_malloc() version
> Rebuild with DMAMEM using malloc() version and it ran fine, but still would not properly run the sdram_malloc() version?
> did a 15s Restore and that did not help - upload still if anything was just scrolling meaningless SPEW.
> unplugged the WIRE i2C SSD1306 from p#' 18&19 - ran the prior Direct Address version.
>> Seems the SDRAM_t4 .init() was accomplishing something the inbuilt sdram_malloc() version does not.
>> And once done the hardware remembers that setting?

> Just did a 15 sec Restore and that then allowed upload to run - as it was running before - so that did not UNDO anything.
> UNPOWERED THE T_MMdb and repowered and it is just RESTARTING!
> rebuild that to run DMAMEM and it works
> rebuild to sdram_malloc version and just restarts
> CrashReport and no prints from that - but the SPEW starts with some semblance of expected SPEW suggested formatting - but all garbage
>Power off and on and it just restarts as it CrashReport - but no output.
>> This may be what I was seeing in earlier posts that appeared to clear after BETA 0.59.4 reinstall
>> SOLUTION: put #include "SDRAM_t4.h" into the UART_extmem_ARR.ino sketch
> @mjs513 did not post his fixed version but local edits to 0x90000000 in library here working to init SDRAM
 
NOTE: Had NOT been checking for '0' return from sdram_malloc() - added that for the 17 alloc on 5 UART usage.
>> Checking these values and stopping does not get that far - if they are failing?

CONFIRM T_MMdb Powered OFF and restarted prior running code resolves to RESTARTING without explicit sdram.init().

Uploaded code with while(1) when any sdram_malloc() return ZERO and print was not shown - it just Restarts.

Enabled CrashReport and this does display, So setup() is entered and working - LED#13 on first then CrashReport, next instructions are sdram_malloc. This seems to be an error where 'addr2line' isn't expected to help?
CrashReport:
A problem occurred at (system time) 0:0:0
Code was executing from address 0x401A
CFSR: 400
(IMPRECISERR) Data bus error but address not related to instruction
Temperature inside the chip was 44.50 °C
Startup CPU clock speed is 600MHz
Reboot was caused by auto reboot after fault or bad interrupt detected
Restoring SDRAM_t4 and sdram.init() to the program returns to working as needed after loss of power.
So it seems whatever sdram.init() does that is static until power loss works, but is not being working with the EXTMEM::sdram_malloc code.
 
@mjs513: Confirm these changes: https://github.com/Defragster/EVKB_1060/tree/main/mallocSDRAM/Core files

@mjs513 this didnt get changed from '8' in extsdram.c ???
// Teensy Micromod external RAM address range is 0x80000000 to 0x8FFFFFFF
#define HAS_SDRAM
#define IS_SDRAM(addr) (((uint32_t)addr >> 28) == 9)
#endif
It didn't fix or change my problem.

THIS DID:: In SDRAM.c these address space numbers: SendIPCommand(0x80000000 ...
// send IP commands to initialize SDRAM chip:
// precharge all
// auto refresh (NXP SDK sends this twice, why?)
// mode set
bool result_cmd = SendIPCommand(0x90000000, 0x0f, 0, NULL); //Prechargeall
if (result_cmd != true)
{
return result_cmd;
}
result_cmd = SendIPCommand(0x90000000, 0x0c, 0, NULL); //AutoRefresh
if (result_cmd != true)
{
return result_cmd;
}
result_cmd = SendIPCommand(0x90000000, 0x0c, 0, NULL); //AutoRefresh
if (result_cmd != true)
{
return result_cmd;
}
/* Mode setting value. */
uint16_t mode = (uint16_t)3| (uint16_t)(3 << 4);
result_cmd = SendIPCommand(0x90000000, 0x0a, mode, NULL); //Modeset
 
Tim
Think it was too late - made the changes in github desktop but forgot to pull the trigger - just pushed the changes up.

Now back to bed

That included changes to the library version for the address change but think I forgot to change the addresses in the ip command
 
,,, thought it was missing before ... still not seeing all unless my chages mathed your

should have looked before all those recent posts ,,, arrrgh
 
Ok Tim - attached is the zip file with all the changes - they should be on the repo as well - the changes that is
 

Attachments

  • mallocSDRAM.zip
    19.2 KB · Views: 92
Found an old datalogger sketch that uses a buffer to write to an sd card, https://forum.pjrc.com/index.php?threads/generic-data-logger-object.60809/, with timings so ran it with RAM1, DMAMEM and SDRAM:

Rich (BB code):
Data Logger Timing Example   Compiled on Jan  4 2024 08:14:41
Card Type is exFAT
File system initialization done.
RTC has set the system time
Buffer initialization complete.
buffer at: 0x20003010 with length 128000   //ram
chunk size is 12800   or 800 data records
Starting Logger.
File name is:  <LOG_0800.bin>
Opening FIle  LOG_0800.bin
File Opened
Pre-allocating 1GB file space
Allocation succeeded.
Opened  File LOG_0800.bin
 File Open

   4.920,   Records:   48800   Overflows:    0
   9.880,   Records:   98400   Overflows:    0
  14.920,   Records:  148800   Overflows:    0
  19.880,   Records:  198400   Overflows:    0
  24.920,   Records:  248800   Overflows:    0
  29.880,   Records:  298400   Overflows:    0
Stopping Logger.

Logger Status:
MBytes Written:     4.68
Collection time: 31 seconds
Max Collection delay: 0 microseconds
Average Write Time:  7.231 milliseconds
Maximum Write Time: 42.844 milliseconds
========================================

Data Logger Timing Example   Compiled on Jan  4 2024 08:16:20
Card Type is exFAT
File system initialization done.
RTC has set the system time
Buffer initialization complete.
buffer at: 0x20200000 with length 128000   //DMAMEM
chunk size is 12800   or 800 data records
Starting Logger.
File name is:  <LOG_0800.bin>
Opening FIle  LOG_0800.bin
File Opened
Pre-allocating 1GB file space
Allocation succeeded.
Opened  File LOG_0800.bin
 File Open

   4.920,   Records:   48800   Overflows:    0
   9.880,   Records:   98400   Overflows:    0
  14.920,   Records:  148800   Overflows:    0
  19.880,   Records:  198400   Overflows:    0
  24.920,   Records:  248800   Overflows:    0
  29.880,   Records:  298400   Overflows:    0
Stopping Logger.

Logger Status:
MBytes Written:     4.99
Collection time: 32 seconds
Max Collection delay: 0 microseconds
Average Write Time:  7.195 milliseconds
Maximum Write Time: 12.660 milliseconds

========================================================
Data Logger Timing Example   Compiled on Jan  4 2024 08:18:58
Card Type is exFAT
File system initialization done.
RTC has set the system time
Buffer initialization complete.
buffer at: 0x90000000 with length 128000 //SDRAM
chunk size is 12800   or 800 data records
Starting Logger.
File name is:  <LOG_0800.bin>
Opening FIle  LOG_0800.bin
File Opened
Pre-allocating 1GB file space
Allocation succeeded.
Opened  File LOG_0800.bin
 File Open

   4.920,   Records:   48800   Overflows:    0
   9.880,   Records:   98400   Overflows:    0
  14.920,   Records:  148800   Overflows:    0
  19.880,   Records:  198400   Overflows:    0
  24.920,   Records:  248800   Overflows:    0
  29.880,   Records:  298400   Overflows:    0
Stopping Logger.

Logger Status:
MBytes Written:     5.30
Collection time: 35 seconds
Max Collection delay: 1 microseconds
Average Write Time:  7.207 milliseconds
Maximum Write Time:  9.707 milliseconds
 
Just ran the same sketch on the Teensy 4.1 :
Code:
Data Logger Timing Example   Compiled on Jan  4 2024 10:03:37
Card Type is exFAT
File system initialization done.
RTC has set the system time
Buffer initialization complete.
buffer at: 0x20003014 with length 128000
chunk size is 12800   or 800 data records
Starting Logger.
File name is:  <LOG_0000.bin>
Opening FIle  LOG_0000.bin
File Opened
Pre-allocating 1GB file space
Allocation succeeded.
Opened  File LOG_0000.bin
 File Open

   4.920,   Records:   48800   Overflows:    0
   9.880,   Records:   98400   Overflows:    0
  14.920,   Records:  148800   Overflows:    0
  19.880,   Records:  198400   Overflows:    0
  24.920,   Records:  248800   Overflows:    0
  29.880,   Records:  298400   Overflows:    0
Stopping Logger.

Logger Status:
MBytes Written:     4.75
Collection time: 31 seconds
Max Collection delay: 0 microseconds
Average Write Time:  7.142 milliseconds
Maximum Write Time:  9.791 milliseconds



Data Logger Timing Example   Compiled on Jan  4 2024 10:06:40
Card Type is exFAT
File system initialization done.
RTC has set the system time
Buffer initialization complete.
buffer at: 0x70000000 with length 128000
chunk size is 12800   or 800 data records
Starting Logger.
File name is:  <LOG_1000.bin>
Opening FIle  LOG_1000.bin
File Opened
Pre-allocating 1GB file space
Allocation succeeded.
Opened  File LOG_1000.bin
 File Open

   4.920,   Records:   48800   Overflows:    0
   9.880,   Records:   98400   Overflows:    0
  14.920,   Records:  148800   Overflows:    0
  19.880,   Records:  198400   Overflows:    0
  24.920,   Records:  248800   Overflows:    0
  29.880,   Records:  298400   Overflows:    0
Stopping Logger.

Logger Status:
MBytes Written:     4.76
Collection time: 31 seconds
Max Collection delay: 1 microseconds
Average Write Time:  7.568 milliseconds
Maximum Write Time: 48.327 milliseconds
 
Was interesting to see "IMPRECISERR" - likely trying SDRAM access when the chip was not commanded to be ready and RAM I/O failed?
Ok Tim - attached is the zip file with all the changes - they should be on the repo as well - the changes that is
Caught up now - p#280 didn't see new files - No Diffs pulled so my edits of 8 to 9 must have matched - except one comment so my push won.

The Array of 5 UARTS running with No Errors after 7.8 hours.
 
Pulled them and review looks good. WIll integrate and test after lunch.

More testing - seems to work. I was looking to put the SSD1306 as an option in the UART Array test to update with run stats just to see i2c Working since it runs on all 1062's involved will make sure nothing is broken.

Not sure of another test. The UART pounds nothing but interrupts for the 1.7MB/sec data transfer with all memory 17*24KB from either SDRAM or DMAMEM. Compared to possible data rates that is a trickle - even for PSRAM - though could alter to test on that to see if it keeps up when a T_4.1 has that.

Prior test is just continued pounding on SDRAM for various patterm or 'random' writes - I could modify that to use the sdram_malloc() instead of manual addressing.

There are also SPI tests ... not sure what else could conflict or show erroneous or problematic issues in SDRAM access.
 
Got the SSD1306 displaying during the UART test just fine. Once each second or each loop showing some feedback.

Opps ... Discovered he memcmp was testing received length not the sent test packet length. Some packets coming in short - always on the last UART in the list. As last to send the others got a head start and caused an interrupt storm slowing things down going and coming for that port. Expected any sent chars to come in and if short the one round then it would be long and miscompare the next time - and that never happened.

Started looking for .available arriving late before next send and found a rabbit hole. Those 'short' characters may be 'lost' due to FIFO overflow when the interrupt storm overwhelms response time with 5 active Tx lines and 5 active Rx lines active at the same time. And if they share a multiplexed interrupt the last on the chain could easily get short changed?

Running 5 UARTS at 2Mbaud instead of 5 Mbaud isn't showing those errors - throughput drops from 1.7MB/sec to 900KB/sec.

Quick test with DMAMEM versus SDRAM and DMAMEM showed those errors faster with 5 UARTS at 5 MBaud.
 
Not sure of another test.

Maybe add usage of a DMA-based display library, like Kurt's ILI9341_t3n, of course with the display's buffer allocated in SDRAM. Hopefully you can have the display doing large area fills with different colors or copying images while the rest of the code runs doing serial communication.

Suggesting this because, at least as I understand, the most likely reason people will go to the trouble and huge pin usage of SDRAM is for large display buffers.
 
Maybe add usage of a DMA-based display library, like Kurt's ILI9341_t3n,
I would suggest more the ILI9488_t3 library. It probably would need some editing, but on T4.1 with EXTMEM, it can be setup to use a Frame buffer where each pixel is 32 bits of memory (only 24 used) and 320*480*4 bytes....
 
I would suggest more the ILI9488_t3 library. It probably would need some editing, but on T4.1 with EXTMEM, it can be setup to use a Frame buffer where each pixel is 32 bits of memory (only 24 used) and 320*480*4 bytes....
Probably a good idea will take a look at later - kind of got stuck in the middle of something else right now
 
Suggesting this because, at least as I understand, the most likely reason people will go to the trouble and huge pin usage of SDRAM is for large display buffers.
My guess is that they may also be likely to expose the pins for CSI and/or eLCDIF - maybe make something similar to the
Arduino GIGA R1 and GIGA Display Shield. Which could be fun! But would require additional software... And probably none of it applicable to any of the existing Teensy boards. But maybe a 4.2 or ??? 😉
 
@KurtE we did expose all the eLCDIF pins 😎
One of the reasons for the SDRAM is the dual buffers capacity and the speed vs PSRAM
 
DMA test would be important - sort of assumed that was part of what @mjs513 might have done already with SPI display - though see that needs work/selection to be done per @KurtE .

UART test with SSD1306 display running 12.82 hours here without error on 5 UARTS at 3 Mbaud - with corrected memcmp() check for proper packet length fully received :( With 5 UARTS (crossed amongst themselves), 20KB packets each out and back (+the ~76 B info header) - passing 12-13 loops/second for up to 1,305,070 B/sec - and the associated millions of interrupts to fill and empty the 10 FIFO's.
 
DMA test would be important - sort of assumed that was part of what @mjs513 might have done already with SPI display - though see that needs work/selection to be done per @KurtE .
It was done using a ILI9341 display which works a bit differently since the display sizes are different (320x240) vs (480x320) and done at 133Mhz on the SDRAM.

Been working on it for awhile using the ILI9488 and just finished it before dinner after discussion with @KurtE. Comments before the results
1. ILI9488_t3 lib had to modified slightly.
2. After extensive testing on both the 9488 and 9341 found that for the framebuffer to work correctly sdram has to operate at 133mhz. At 166mhz you see tearing on the 9341 and on the 9488 framebuffer (updateScreen) has issues where the buffer is displayed incorrectly.
3. Why not sure, could be a bug in updateScreen or timing issues.

But after the lib moded and clock changed to 133Mhz.
Code:
Begin: CS:10, DC:9RST: 8
  Size of RAFB: 4
::begin 20002308 255 255 255
ILI9488_t3::begin - End
Time noFB: 615
Time updateScreen: 642
Time updateScreenAsync: 642
Time noFB: 615
Time updateScreen: 642
Time updateScreenAsync: 642
Time is consistent from run to run.

Note on the ILI9488 the RAFB is 32bits as kurt mentioned earlier.

Now running the same sketch on the T4.1 with DMAMEM with 16bit RAFB

Code:
Begin: CS:10, DC:9RST: 8
  Size of RAFB: 2
::begin 20002488 255 255 255
ILI9488_t3::begin - End
Time noFB: 615
Time updateScreen: 634
Time updateScreenAsync: 634
Time noFB: 615
Time updateScreen: 635
Time updateScreenAsync: 634
Time noFB: 615
Time updateScreen: 635
Time updateScreenAsync: 634

Here is the sketch (thanks @KurtE) my original one was a lot simpler :)
Code:
#include <ILI9488_t3.h>
#include <SPI.h>
#include <Arduino.h>

#define TFT_DC 9  // only CS pin
#define TFT_CS 10  // using standard pin
#define TFT_RST 8
#define ROTATION 3
ILI9488_t3 tft = ILI9488_t3(&SPI, TFT_CS, TFT_DC, TFT_RST);

//#define TRY_EXTMEM

#if !defined(ENABLE_EXT_DMA_UPDATES)
DMAMEM RAFB tft_frame_buffer[ILI9488_TFTWIDTH * ILI9488_TFTHEIGHT];
#endif


#ifdef TRY_EXTMEM
EXTSDMEM RAFB extmem_frame_buffer[ILI9488_TFTWIDTH * ILI9488_TFTHEIGHT];
#endif

void setup() {
  while (!Serial && (millis() < 4000))
    ;
  Serial.begin(115200);
  Serial.printf("Begin: CS:%d, DC:%dRST: %d\n", TFT_CS, TFT_DC, TFT_RST);
  Serial.printf("  Size of RAFB: %d\n", sizeof(RAFB));
  tft.begin(26000000);

#if defined(ENABLE_EXT_DMA_UPDATES)
  tft.setFrameBuffer(extmem_frame_buffer);
#else
  tft.setFrameBuffer(tft_frame_buffer);
#endif

#if defined(ENABLE_EXT_DMA_UPDATES)
  tft.setFrameBuffer(extmem_frame_buffer);
#else
  tft.setFrameBuffer(tft_frame_buffer);
#endif
  tft.setRotation(ROTATION);
  tft.fillScreen(ILI9488_BLACK);
}

void fillScreenTest(void (*cb)()) {
  tft.fillScreen(ILI9488_RED);
  (*cb)();
  tft.fillScreen(ILI9488_GREEN);
  (*cb)();
  tft.fillScreen(ILI9488_WHITE);
  (*cb)();
  tft.fillScreen(ILI9488_BLACK);
  (*cb)();
}

bool wait_for_input = false;
bool delay_between_pages = false;
void check_for_pause_or_delay() {
  int ch = -1;
  if (wait_for_input) {
    Serial.println("Enter something to continue");
    while ((ch = Serial.read()) == -1) {}
  } else {
    if (delay_between_pages) delay(250);
    if (Serial.available()) {
      ch = Serial.read();
    }
  }
  while (Serial.read() != -1) {}
  if (ch == 'w') {
    wait_for_input = !wait_for_input;
    if (wait_for_input) Serial.println("Waiting between pages enabled");
    else Serial.println("Waiting between pages disabled");
  }
  if (ch == 'd') {
    delay_between_pages = !delay_between_pages;
    if (delay_between_pages) Serial.println("delay between pages enabled");
    else Serial.println("delay between pages disabled");
  }

};



void cbUpdateScreen() {
  tft.updateScreen();
  check_for_pause_or_delay();
}

void cbUpdateScreenAsync() {
  tft.updateScreenAsync();
  tft.waitUpdateAsyncComplete();
  check_for_pause_or_delay();
}

void loop() {
  // put your main code here, to run repeatedly:
  tft.useFrameBuffer(0);
  elapsedMillis em = 0;
  tft.useFrameBuffer(0);
  fillScreenTest(&check_for_pause_or_delay);
  Serial.printf("Time noFB: %u\n", (uint32_t)em);
  delay(1000);
  tft.useFrameBuffer(1);
  em = 0;
  fillScreenTest(&cbUpdateScreen);
  Serial.printf("Time updateScreen: %u\n", (uint32_t)em);
  delay(1000);
  em = 0;
  fillScreenTest(&cbUpdateScreenAsync);
  Serial.printf("Time updateScreenAsync: %u\n", (uint32_t)em);
  delay(5000);
}
 
Last edited:
Back
Top