Call to arms | Teensy + SDRAM = true

Dogbone06

Well-known member
Hello fellow Teensiers.

First off, this is only for custom boards!

I plan to make the Teensy work with SDRAM. Making custom Teensy boards is something I've done for a while with great success. The forum has been good help and the community we all have here is amazing!

To make sure no mistakes are made I need to confirm the pins for the SDRAM. I'm asking for the community to help out.
Once I have a working board in my hand the next step will be code. Finally when that's working, we will have this thread to lean on as a guide on how to add SDRAM to a custom Teensy. Helpful for anyone out there wanting to add SDRAM to a custom Teensy!

The NXP 1060 EVAL board has SDRAM, I've looked at that schematic and then implemented it into my design. The board is ready to go, I see no problems with the pin mapping but I've been wrong before!

* I've combined my schematic with the EVAL schematic into one PDF to make it easyer to double check. It's attached below.
My schematic is in black. The EVAL schematic is white.
* Attached is also the NXP 1060 EVAL schematic as a PDF.
* SDRAM PDF: https://www.mouser.se/datasheet/2/198/42_45S83200J_16160J-462626.pdf

If you feel that you want to contribute to this little endeavor, feel free to look through the EVAL datasheet (attached below) and confirm these pins.

Thank you all! 😀
 

Attachments

  • Teensy_SDRAM.pdf
    289.4 KB · Views: 212
  • SPF-47858_B1.PDF
    1.6 MB · Views: 184
I looked at your PDF briefly. Seems you copied NXP's eval schematic closely. I don't know why it's not working.
If you say that the pins look good then that's enough safety for me to order the board.
I'll update this thread in 2ish weeks time once the board arrives.
 
I'm pretty sure you created a thread about this earlier, where I mentioned the trace lengths matter. I believe I also gave a link to NXP's hardware guide.
 
I'm pretty sure you created a thread about this earlier, where I mentioned the trace lengths matter. I believe I also gave a link to NXP's hardware guide.
You’re right. I’m sorry if the two threads are confusing. The purpose with this one is to have the community together make SDRAM possible for the Teensy. Just like so many other threads where everyone’s come together to make things happen.

Perhaps the other one can be removed?
 
I'm super interested in this so will definitely make one if you can get the sdram working
With the help of the community we’ll get it working. The PCB is the easy part, atleast for me. Harder part will be the code but I know there’s more than enough knowledge in here! Obviously the final schematic/pin mapping will be shared in this thread as well as the code once we got that. :D

EDIT: Board was ordered today, should arrive in two weeks. Not the prettiest board but it has many pins exposed. All of the FlexIO's and a bunch more. And before anyone asks about the dual USB, it's there for wear and tare. Board also has plenty of 3.3V, 5V and GND. Can never have enough of those!

1700235664225.png
 
Last edited:
With the help of the community we’ll get it working. The PCB is the easy part, atleast for me. Harder part will be the code but I know there’s more than enough knowledge in here! Obviously the final schematic/pin mapping will be shared in this thread as well as the code once we got that. :D

EDIT: Board was ordered today, should arrive in two weeks. Not the prettiest board but it has many pins exposed. All of the FlexIO's and a bunch more. And before anyone asks about the dual USB, it's there for wear and tare. Board also has plenty of 3.3V, 5V and GND. Can never have enough of those!

View attachment 32397
How did you go with your pcb?
 
How did you go with your pcb?
I saw your post yesterday and I did recieve the boards yesterday but haven't had time to test them until now.
The news is good, the board works! This means that it's time to move on to the code side. I do lack the knowledge but I will do my best. I wish there was more interest for this tho, but I'm sure we'll get there eventually!
 
Looking into this with an NXP evaluation board - EVKB 1060 a functional SEMC SDRAM example was found and seen to work. Somehow building the SDK for the newer EVKB board didn't offer an example, Many searches later it said there was one and rebuilding their SDK and searching SEMC to add it was only in the EVK build? With that SDK built - then updated - it was pulled into the IDE and found to work!

Here is an export of that project: SEMC_SDK_PROJ
Quick edits showing cpu cycles used for test of 4KB region using 8/16/32 bit access, the 32 bit test was edited so far with just putting the offset index into each of the 32KB of SRAM, then confirming in a second pass those values were returned.

@Dogbone06 is shipping one of the DIY Teensy bootloader 1062 PCB's with the same 32 MB SDRAM here. Hope is that given the working NXP example and settings the same can be achieved on this PCB to work with PJRC's cores seeing it as a T_MM since it is built with a 16 MB Flash, but not otherwise pin compatible on this iteration.

Learning the NXP IDE is a project in itself - On a laptop the IDE&SDK was installed, and the above exported project was imported in the IDE using the Quickstart panel's Import (File import failed?). In searching about a dozen failure posts for SDRAM with IMXRT MCU's were found before the one indicating a way to find the SEMC example used.

If anyone more familiar with NXP's IDE having an EVK 1060 wants to try it, please do. @Dogbone06 shared the 9.2 MB project file linked above. His goal is to see it work and share any result of a working board here.

The only cool thing so far is that TyCommander works well for SerMon to the EVKB board while debugging! (Thanks again @Koromix)

And kudos to PJRC on the Teensy under Arduino being so much easier to use and post 'sketch source' instead of a 9+ MB zipped Project!
 
Are you still planning to share the PCB files and schematic? If so, I'll add a link to this forum thread on the T4 bootloader page.
Yes, I will share it now. I've used EasyEDA to do it, so I will upload:
PDF of the schematic as well as the Schematic and PCB files as JSON, which is used to import/open on EasyEDA for anyone to use.

This way, anyone can edit the Schematic and PCB and thus improve it, as it's only a very "simple" dev board that works but is far from pretty.
 
Here are the files. I've added Gerber, BOM, Pick and Place just like @Paul requested above.
The JSON files are used to import to EasyEDA to gain full edit access. Anyone who has used it will know.
 

Attachments

  • SDRAM_Teensy_Devboard.zip
    1.3 MB · Views: 213
Wow - 7 views on the pcb's ZIP - before download here.

FedEx says the populated PCB will arrive here Sat 23rd ... will see how it goes from there.
 
I'm following this project with great interest. However the programming required to get the sdram chip working is way above my skill level. I Have some bootloader and imrxt chips from Paul ready to go if you can get it working.

I hope to modify dogbones board (without touching the sd lines) and try and get 24 sequential lines out on a gpio to run a 24bit 800 x 600 display with backbuffers.

The LCDIF pinputs are interesting, however the 2d graphics engine built into the chip would be too complex to be usable.
 
I'm following this project with great interest. However the programming required to get the sdram chip working is way above my skill level. I Have some bootloader and imrxt chips from Paul ready to go if you can get it working.

I hope to modify dogbones board (without touching the sd lines) and try and get 24 sequential lines out on a gpio to run a 24bit 800 x 600 display with backbuffers.

The LCDIF pinputs are interesting, however the 2d graphics engine built into the chip would be too complex to be usable.
I have a previous dev board that Dogbone created without the SDRAM.
Just like the new dev board, it has all the FlexIO2 pins broken out, which also happen to be the eLCDIF pins.

I did get 24-bit 8080 working with an RM68120 480*800 display via FLEXIO and it looked great, but never tested beyond displaying an image and some LVGL widgets.
Code it not online (yet) but will happily share of you want it
 
I have a previous dev board that Dogbone created without the SDRAM.
Just like the new dev board, it has all the FlexIO2 pins broken out, which also happen to be the eLCDIF pins.

I did get 24-bit 8080 working with an RM68120 480*800 display via FLEXIO and it looked great, but never tested beyond displaying an image and some LVGL widgets.
Code it not online (yet) but will happily share of you want it
The main goal of this SDRAM is of course to enable large screens with good performance. Feel free to share the code in this thread as it's very much relevant to the SDRAM itself. Hopefully many people will benefit from all this. Defragster will recieve his Dev board in just a few days!
 
I'm really curious what kind of read/write speeds you will get compared to the onboard ram. If you get it working some bench marks would be great!

I believe you can do burst or single read/writes on sdram

Sdram needs constant refreshing? Is that all built into the ram?
 
Not gotten the @Dogbone06 test board yet {last FedEx report still in Europe} [nor has the process of munging the 200+ lines of init code from NXP IDE to PJRC cores been started or examined for any pin or clock conflicts ] - but planning to incorporate the PJRC PSRAM varied values testing into the NXP IDE for the EVKB board here. That will give a better idea of throughput PSRAM versus SDRAM.

It is clocked at 166 MHz so speed will at best be similar to the DMAMEM RAM2 (25% of TCM RAM1) on T_4.x. and only 16 bus bits wired to SDRAM. NXP default config puts 768 KB into their DMAMEM area so that could be tested against SDRAM for that size area.

Saw a note that write speed is faster than read speed and current test suggests that is the case for full 32MB write then reading back:
SEMC SDRAM Memory 32 bit Write Start, Start Address 0x80000000, Data Length 33554432 !
ALL Write took 183133 micros
SEMC SDRAM Read 32 bit Data Start, Start Address 0x80000000, Data Length 33554432 !
ALL Read&Test took 524138 micros
Write is just putting loop index into SDRAM at ~170 MB/sec and read back with test against index value showing ~61 MB/sec.
This is a full debug with 0 optimizations.

It seems the refresh is handled by MCU hardware as the setup config has refresh params associated with it.
 
Legend mate. If it can match ram2 speed that's pretty good and very usable.

It could be a potential for teensy 4.2. I reckon there would be a market for the fastest arduino compatible MC with a decent amount of fast ram.
 
@defragster
Got curious so I pulled out the 1160EVKB and ran the SEMC test with a custom micros functions that I believe @manitou put together a very long time ago.

Here are the times:
Code:
SEMC SDRAM Example Start!

 SEMC SDRAM Memory 32 bit Write Start, Start Address 0x80000000, Data Length 4096 !
    SEMC SDRAM Memory 32 bit Write Time (uS) 132

 SEMC SDRAM Read 32 bit Data Start, Start Address 0x80000000, Data Length 4096 !
    SEMC SDRAM Memory 32 bit Read Time (uS) 232

 SEMC SDRAM 32 bit Data Write and Read Compare Start!
    SEMC SDRAM Memory 32 bit R/W Time (uS) 106
 SEMC SDRAM 32 bit Data Write and Read Compare Succeed!

 SEMC SDRAM Memory 16 bit Write Start, Start Address 0x80000000, Data Length 4096 !
    SEMC SDRAM Memory 16 bit Write Time (uS) 202

 SEMC SDRAM Read 16 bit Data Start, Start Address 0x80000000, Data Length 4096 !
 SEMC SDRAM Memory 16 bit Read Time (uS) 127

 SEMC SDRAM 16 bit Data Write and Read Compare Start!
     SEMC SDRAM Memory 16 bit Read/Write Time (uS) 103
 SEMC SDRAM 16 bit Data Write and Read Compare Succeed!

 SEMC SDRAM Memory 8 bit Write Start, Start Address 0x80000000, Data Length 4096 !
    SEMC SDRAM Memory 8 bit Write Time (uS) 145

 SEMC SDRAM Read 8 bit Data Start, Start Address 0x80000000, Data Length 4096 !
    SEMC SDRAM Memory 8 bit Read Time (uS) 120

 SEMC SDRAM 8 bit Data Write and Read Compare Start!
 SEMC SDRAM 8 bit Data Write and Read Compare Succeed!
    SEMC SDRAM Memory 8 bit Read/Write Time (uS) 5039

 SEMC SDRAM Example End.
 
@Dogbone06 - @defragster
Thats the way it looks :) based on the sketch - also assumes the micros function is correct. @defragster can probably confirm.

Out of curiosity I have a Arduino Giga that a couple of us have been experimenting with. It has a SDRAM but using a STM32H7 - probably similar to the 1170 which has CM7/CM4 cores. Just ran the same sketch as on the 1060EVK (adapter for arduino) and got this:

Code:
DRAM_DEVICE->SDCMR: 0
initializing external ram
remap ram to 0x60000000
malloc_addblock: allocate 6291456 bytes

 SDRAM Memory 32 bit Write Start, Start Address 0x60000000, Data Length 4096 !
    SDRAM Memory 32 bit Write Time (uS) 181

 SDRAM Read 32 bit Data Start, Start Address 0x60000000, Data Length 4096 !
    SDRAM Memory 32 bit Read Time (uS) 152

 SDRAM 32 bit Data Write and Read Compare Start!
    SDRAM Memory 32 bit R/W Time (uS) 62
 SDRAM 32 bit Data Write and Read Compare Succeed!

 SDRAM Memory 16 bit Write Start, Start Address 0x60000000, Data Length 4096 !
    SDRAM Memory 16 bit Write Time (uS) 89
 SDRAM Read 16 bit Data Start, Start Address 0x60000000, Data Length 4096 !

 SDRAM Memory 16 bit Read Time (uS) 79
 SDRAM 16 bit Data Write and Read Compare Start!
     SDRAM Memory 16 bit Read/Write Time (uS) 57
 SDRAM 16 bit Data Write and Read Compare Succeed!

 SDRAM Memory 8 bit Write Start, Start Address 0x60000000, Data Length 4096 !
    SDRAM Memory 8 bit Write Time (uS) 56
 SDRAM Read 8 bit Data Start, Start Address 0x60000000, Data Length 4096 !
    SDRAM Memory 8 bit Read Time (uS) 56
 SDRAM 8 bit Data Write and Read Compare Start!

 SDRAM 8 bit Data Write and Read Compare Succeed!
    SDRAM Memory 8 bit Read/Write Time (uS) 2822
 SDRAM Example End.

a little slower than the 1060EVKB which I believe has a 1064 chip on it. Also not sure what the clocks are set at for SDRAM (the giga runs at 240Mhz though).

Here is the sketch that I used if anyone is interested:

Code:
#include "SDRAM.h"
uint32_t now;

REDIRECT_STDOUT_TO(Serial);

#define PRINTF printf

#define EXAMPLE_SEMC_START_ADDRESS SDRAM_START_ADDRESS

#define SEMC_EXAMPLE_DATALEN (0x1000U)
#define SEMC_EXAMPLE_WRITETIMES (1000U)


uint32_t sdram_writeBuffer[SEMC_EXAMPLE_DATALEN];
uint32_t sdram_readBuffer[SEMC_EXAMPLE_DATALEN];

void setup(){

    Serial.begin(115200);
    while(!Serial && millis() < 5000) {}

    /* Allocates a 2MB buffer at the begining of SDRAM */
    SDRAM.begin(SDRAM_START_ADDRESS + 2 * 1024 * 1024);

    /* 32Bit data read and write. */
    SEMC_SDRAMReadWrite32Bit();
    /* 16Bit data read and write. */
    SEMC_SDRAMReadWrite16Bit();
    /* 8Bit data read and write. */
    SEMC_SDRAMReadWrite8Bit();

    PRINTF("\r\n SDRAM Example End.\r\n");
}

void loop(){}

void SEMC_SDRAMReadWrite32Bit(void)
{
    uint32_t index;
    uint32_t datalen = SEMC_EXAMPLE_DATALEN;
    uint32_t *sdram = (uint32_t *)EXAMPLE_SEMC_START_ADDRESS; /* SDRAM start address. */
    bool result = true;

    PRINTF("\r\n SDRAM Memory 32 bit Write Start, Start Address 0x%x, Data Length %d !\r\n", sdram, datalen);

    now = micros();
    /* Prepare data and write to SDRAM. */
    for (index = 0; index < datalen; index++)
    {
        sdram_writeBuffer[index] = index;
        sdram[index] = sdram_writeBuffer[index];
    }

    PRINTF("\tSDRAM Memory 32 bit Write Time (uS) %u\n", (micros() - now));

    PRINTF("\r\n SDRAM Read 32 bit Data Start, Start Address 0x%x, Data Length %d !\r\n", sdram, datalen);
    /* Read data from the SDRAM. */
    now = micros();
    for (index = 0; index < datalen; index++)
    {
        sdram_readBuffer[index] = sdram[index];
    }
    PRINTF("\tSDRAM Memory 32 bit Read Time (uS) %u\n", (micros() - now));

    PRINTF("\r\n SDRAM 32 bit Data Write and Read Compare Start!\r\n");
    /* Compare the two buffers. */
    now = micros();
    while (datalen--)
    {
        if (sdram_writeBuffer[datalen] != sdram_readBuffer[datalen])
        {
            result = false;
            break;
        }
    }

    if (!result)
    {
        PRINTF("\r\n SDRAM 32 bit Data Write and Read Compare Failed!\r\n");
    }
    else
    {
        PRINTF("\tSDRAM Memory 32 bit R/W Time (uS) %u", (micros() - now));
        PRINTF("\r\n SDRAM 32 bit Data Write and Read Compare Succeed!\r\n");
    }
}

static void SEMC_SDRAMReadWrite16Bit(void)
{
    uint32_t index;
    uint32_t datalen = SEMC_EXAMPLE_DATALEN;
    uint16_t *sdram = (uint16_t *)EXAMPLE_SEMC_START_ADDRESS; /* SDRAM start address. */
    bool result = true;

    PRINTF("\r\n SDRAM Memory 16 bit Write Start, Start Address 0x%x, Data Length %d !\r\n", sdram, datalen);

    memset(sdram_writeBuffer, 0, sizeof(sdram_writeBuffer));
    memset(sdram_readBuffer, 0, sizeof(sdram_readBuffer));

    /* Prepare data and write to SDRAM. */
    now = micros();
    for (index = 0; index < datalen; index++)
    {
        sdram_writeBuffer[index] = index % 0xFFFF;
        sdram[index] = sdram_writeBuffer[index];
    }
    PRINTF("\tSDRAM Memory 16 bit Write Time (uS) %u", (micros() - now));

    PRINTF("\r\n SDRAM Read 16 bit Data Start, Start Address 0x%x, Data Length %d !\r\n", sdram, datalen);
    /* Read data from the SDRAM. */
    now = micros();
    for (index = 0; index < datalen; index++)
    {
        sdram_readBuffer[index] = sdram[index];
    }
    PRINTF("\r\n SDRAM Memory 16 bit Read Time (uS) %u", (micros() - now));

    PRINTF("\r\n SDRAM 16 bit Data Write and Read Compare Start!\r\n");
    /* Compare the two buffers. */
    now = micros();
    while (datalen--)
    {
        if (sdram_writeBuffer[datalen] != sdram_readBuffer[datalen])
        {
            result = false;
            break;
        }
    }

    if (!result)
    {
        PRINTF("\r\n SDRAM 16 bit Data Write and Read Compare Failed!\r\n");
    }
    else
    {
        PRINTF("\t SDRAM Memory 16 bit Read/Write Time (uS) %u", (micros() - now));
        PRINTF("\r\n SDRAM 16 bit Data Write and Read Compare Succeed!\r\n");
    }
}

static void SEMC_SDRAMReadWrite8Bit(void)
{
    uint32_t index;
    uint32_t datalen = SEMC_EXAMPLE_DATALEN;
    uint8_t *sdram = (uint8_t *)EXAMPLE_SEMC_START_ADDRESS; /* SDRAM start address. */
    bool result = true;

    PRINTF("\r\n SDRAM Memory 8 bit Write Start, Start Address 0x%x, Data Length %d !\r\n", sdram, datalen);

    memset(sdram_writeBuffer, 0, sizeof(sdram_writeBuffer));
    memset(sdram_readBuffer, 0, sizeof(sdram_readBuffer));

    /* Prepare data and write to SDRAM. */
    now = micros();
    for (index = 0; index < datalen; index++)
    {
        sdram_writeBuffer[index] = index % 0x100;
        sdram[index] = sdram_writeBuffer[index];
    }
    PRINTF("\tSDRAM Memory 8 bit Write Time (uS) %u", (micros() - now));

    PRINTF("\r\n SDRAM Read 8 bit Data Start, Start Address 0x%x, Data Length %d !\r\n", sdram, datalen);
    /* Read data from the SDRAM. */
    now = micros();
    for (index = 0; index < datalen; index++)
    {
        sdram_readBuffer[index] = sdram[index];
    }
    PRINTF("\tSDRAM Memory 8 bit Read Time (uS) %u", (micros() - now));

    PRINTF("\r\n SDRAM 8 bit Data Write and Read Compare Start!\r\n");
    /* Compare the two buffers. */
    now = micros();
    while (datalen--)
    {
        if (sdram_writeBuffer[datalen] != sdram_readBuffer[datalen])
        {
            result = false;
            break;
        }
    }

    if (!result)
    {
        PRINTF("\r\n SDRAM 8 bit Data Write and Read Compare Failed!\r\n");
    }
    else
    {
        PRINTF("\r\n SDRAM 8 bit Data Write and Read Compare Succeed!\r\n");
        PRINTF("\tSDRAM Memory 8 bit Read/Write Time (uS) %u", (micros() - now));
    }
}
 
Back
Top