Call to arms | Teensy + SDRAM = true

Quick update: I went ahead and ordered a set of the Shields I was playing with at PCBWay
1717604227648.png

Sort of chicken and egg... Won't know if it works until we receive the boards.
The files are up in my github project:

This is the layout2 version. The only differences was I swapped the location of the two Camera connectors, as the FlexIO connector has more signals in common with the RA8876 connector and as well the CAM_CSI has more in common with the other display.
Note: I put in the center a Teensy like connector. In theory one can hook up an Audo board, But pins 7,8, 20... Are used in other things as
well so allowed a solder jumper to be cut and can jumper to a different pin... Pins 2-5 are not available on this board as it is used in your
EMC connections. So by default nothing is connected to them, but can jumper... I also put on a couple of QWIIC connectors (Wire and Wire1)

Now back to playing
 
If you wanted to add another SDRAM, you just tap most of the existing signals and take a new CS from one of the SEMC CSX pins. Think of it like SPI with loads more pins, and the restriction that the track lengths need to all match each other as much as possible.
 
What do you need 2x for
Design decisions. The SEMC only supports up to 512 Mbit per chip. I guess it's time to explain the full design of the game console.

The system itself will have 3 iMXRT1062 chips. One is the application processor (turboed to 1 GHz) paired with 128 MB of RAM. The next uses a software rendering library (so I can get semi-decent realtime shading) and has 64 MB of VRAM. This chip will be displaying rendered 2d/3d graphics through the RGB interface, which is then hooked up to an ADV7513. The 3rd chip is the security processor and kind of acts as a north and south bridge (since it interfaces with the wifi and Bluetooth cards, the USB SSD, and gpio). Then, there's a boot processor (the esp32 is my choice due to the integrated wifi/bt, decent amount of I/O, and no requirement for power sequencing).

I spent multiple weeks figuring out how to prevent the system from becoming bandwidth-constrained, and I'm happy with my results to that end.

If you have additional questions or criticisms regarding the system architecture, please let me know!
 
If you wanted to add another SDRAM, you just tap most of the existing signals and take a new CS from one of the SEMC CSX pins. Think of it like SPI with loads more pins, and the restriction that the track lengths need to all match each other as much as possible.
I had wondered if I needed to length tune them, and how to go about doing that. I'll try relocating the SDRAM so it's above the iMXRT and mirroring the traces to another SDRAM near it (of course with a separate CS). Do the track lengths have to match the other SDRAM's as well or can they be independent to some degree? I don't think the other chip would care about different timings for a different chip but this kind of 'intuition' has come back to bite me before. Hard. Additionally, my PCB design skills aren't great so I'll probably have to do multiple runs. Would you guys be okay if I opened a separate thread for peer-reviewing my PCB once it's ready?
 
Design decisions. The SEMC only supports up to 512 Mbit per chip. I guess it's time to explain the full design of the game console.

The system itself will have 3 iMXRT1062 chips. One is the application processor (turboed to 1 GHz) paired with 128 MB of RAM. The next uses a software rendering library (so I can get semi-decent realtime shading) and has 64 MB of VRAM. This chip will be displaying rendered 2d/3d graphics through the RGB interface, which is then hooked up to an ADV7513. The 3rd chip is the security processor and kind of acts as a north and south bridge (since it interfaces with the wifi and Bluetooth cards, the USB SSD, and gpio). Then, there's a boot processor (the esp32 is my choice due to the integrated wifi/bt, decent amount of I/O, and no requirement for power sequencing).

I spent multiple weeks figuring out how to prevent the system from becoming bandwidth-constrained, and I'm happy with my results to that end.

If you have additional questions or criticisms regarding the system architecture, please let me know!

This is no easy task. It will be very cool
To see if you succeed. I truly hope so!

How do you plan to integrate WiFi and Bluetooth to the Teensy, any library in mind?
 
This is no easy task. It will be very cool
To see if you succeed. I truly hope so!

How do you plan to integrate WiFi and Bluetooth to the Teensy, any library in mind?
Yes I'm sure it will take absolutely forever. My last system I did was comparatively weak and took over a year in development time. I learned a lot of what I currently know about system development from it. The rest came from research on the Wii, 3DS, and PS3.

I plan to use the boot processor (ESP32) via a custom API for networking and I/O needs. I'll link the design document here soon.

UPDATE:
Here is the design document:
 
Hello,

I see some nice boards here. Just my 2 cents. From the pictures, I see no reverse voltage protection diode (or FET transistor) on external power connections. Murphy's law says you will connect it wrong the first time.

Angelo
 
Something I just noticed: on PJRC's T4 schematic, EMC_01 is shown connected to PTA1 on the bootloader. On the SDRAM board EMC_01 goes to the SDRAM... and judging from the schematic, PTA1 is left floating?
PTA1.png
 
Something I just noticed: on PJRC's T4 schematic, EMC_01 is shown connected to PTA1 on the bootloader. On the SDRAM board EMC_01 goes to the SDRAM... and judging from the schematic, PTA1 is left floating?
View attachment 34608
I am unsure actually. The reason why that one is floating by itself is that the pin most likely got moved in the schematic. Never even saw the floating one there. But yes EMC_01 is used by SDRAM.
 
@Dogbone06 are the CC pins on the USB Host port left unconnected? They should really have ~50K pull-ups connected to 5V to properly look like a host port to usb-c capable devices.

5.1k for each CC pin as per the standard on the first port.

The second port I’m unsure of now that you mention it!
 
5.1k pulldown is standard for ports on devices (ports that want power). 50k pullup is used on host ports (ports that supply power).

I don’t have the schematic in front of me now but I’m 99% sure that the CC pins in the host port is connected to the USD-PD chip which negotiates with the client. So it’s all good.
 
5.1k pulldown is standard for ports on devices (ports that want power). 50k pullup is used on host ports (ports that supply power).
The CC Pins are supposed to be connected to the USB-PD CC pins on the IC to negotiate. But they are not. The naming of them was wrong (human error). Good thing you catched this, the PCB's for Gen5 are not assembled yet, so I can pull the handbrake and alter them!
 
Let's talk of this in March or later. For now I'm trying to help in small but important ways, but I'm currently working on other projects so I just can't get more involved in SDRAM. Just to be realistic, that'll probably still be the case by March time frame too.
@Paul - New DevBoard 5 out of the oven and March is behind us ...
 
Sorry, I have been goofing off today. Been playing more with the possibility of having Variants, work with Teensy 4.x.
Or at least a good subset of stuff.

Earlier I had support for allowing you to declare your own pin tables.
I have the FlexIO library not care about fixed tables, but instead map the pin passed in to IMXRT pin and look it up in table of all flexio pins
XBar allow overwrite of table
CSI - I am doing like FlexIO.
PWM - allow overwrite of table.

newer stuff
Analog - allow overwrite of table.

Serial Object - been hacking on it today, where hopefully allow you to overwrite the RX pin table, Tx pin table...
Reworked the hardware table and the like... And now testing...

More to come
 
Nice - very nice @KurtE - if a variants scheme works to allow DIY boards to be fitted to the TD install!

About 24 hours since last update to the USA FedEx package ... still in France? ...
 
Nice - very nice @KurtE - if a variants scheme works to allow DIY boards to be fitted to the TD install!
That is the idea. For example, I am not going to take over my MICROMOD board type for DEVBOARD as I use MICROMODs...

Note: I am playing with a sort of related diversion:
Here is a sketch I have that blinks the LED on my T4.1
C++:
#include <core_pin_names.h>

void setup() {
    // put your setup code here, to run once:
    while (!Serial && millis() < 4000) {}
    Serial.begin(115200);
    if (CrashReport) Serial.print(CrashReport);
    pinMode(B0_03, OUTPUT);
    Serial.printf("Port Set:%p Clear:%p Toggle:%p mask:%x\n", &CORE_PIN13_PORTSET, &CORE_PIN13_PORTCLEAR, &CORE_PIN13_PORTTOGGLE, CORE_PIN13_BITMASK);
}

void loop() {
    // put your main code here, to run repeatedly:
    digitalWrite(B0_03, HIGH);
    delay(500);
    digitalWrite(B0_03, LOW);
    delay(5000);
    digitalToggle(B0_03);
    delay(250);
    digitalToggle(B0_03);
    delay(250);
    if (Serial.available()) {
        while(Serial.read() != -1) {}
        while(Serial.read() == -1) {}
        while(Serial.read() != -1) {}
    }
}

My include file (WIP)
C++:
// PinName values: 32 bit top 16 - offset in EMC table, low 8 bits 0-4 GPIO PIN 5-7 On Port #
typedef enum {
    AD_B0_00 = 0x0BC0000, AD_B0_01 = 0x0C00001, AD_B0_02 = 0x0C40002, AD_B0_03 = 0x0C80003, AD_B0_04 = 0x0CC0004, AD_B0_05 = 0x0D00005, AD_B0_06 = 0x0D40006, AD_B0_07 = 0x0D80007,
    AD_B0_08 = 0x0DC0008, AD_B0_09 = 0x0E00009, AD_B0_10 = 0x0E4000A, AD_B0_11 = 0x0E8000B, AD_B0_12 = 0x0EC000C, AD_B0_13 = 0x0F0000D, AD_B0_14 = 0x0F4000E, AD_B0_15 = 0x0F8000F,
    AD_B1_00 = 0x0FC0010, AD_B1_01 = 0x1000011, AD_B1_02 = 0x1040012, AD_B1_03 = 0x1080013, AD_B1_04 = 0x10C0014, AD_B1_05 = 0x1100015, AD_B1_06 = 0x1140016, AD_B1_07 = 0x1180017,
    AD_B1_08 = 0x11C0018, AD_B1_09 = 0x1200019, AD_B1_10 = 0x124001A, AD_B1_11 = 0x128001B, AD_B1_12 = 0x12C001C, AD_B1_13 = 0x130001D, AD_B1_14 = 0x134001D, AD_B1_15 = 0x138001F,
    B0_00 = 0x13C0020, B0_01 = 0x1400021, B0_02 = 0x1440022, B0_03 = 0x1480023, B0_04 = 0x14C0024, B0_05 = 0x1500025, B0_06 = 0x1540026, B0_07 = 0x1580027,
    B0_08 = 0x15C0028, B0_09 = 0x1600029, B0_10 = 0x164002A, B0_11 = 0x168002B, B0_12 = 0x16C002C, B0_13 = 0x170002D, B0_14 = 0x174002E, B0_15 = 0x178002F,
    B1_00 = 0x17C0030, B1_01 = 0x1800031, B1_02 = 0x1840032, B1_03 = 0x1880033, B1_04 = 0x18C0034, B1_05 = 0x1900035, B1_06 = 0x1940036, B1_07 = 0x1980037,
    B1_08 = 0x19C0038, B1_09 = 0x1A00039, B1_10 = 0x1A4003A, B1_11 = 0x1A8003B, B1_12 = 0x1AC003C, B1_13 = 0x1B0003D, B1_14 = 0x1B4003D, B1_15 = 0x1B8003F,
    EMC_00 = 0x0140060, EMC_01 = 0x0180061, EMC_02 = 0x01C0062, EMC_03 = 0x0200063, EMC_04 = 0x0240064, EMC_05 = 0x0280065, EMC_06 = 0x02C0066, EMC_07 = 0x0300067,
    EMC_08 = 0x0340068, EMC_09 = 0x0380069, EMC_10 = 0x03C006A, EMC_11 = 0x040006B, EMC_12 = 0x044006C, EMC_13 = 0x048006D, EMC_14 = 0x04C006E, EMC_15 = 0x050006F,
    EMC_16 = 0x0540070, EMC_17 = 0x0580071, EMC_18 = 0x05C0072, EMC_19 = 0x0600073, EMC_20 = 0x0640074, EMC_21 = 0x0680075, EMC_22 = 0x06C0076, EMC_23 = 0x0700077,
    EMC_24 = 0x0740078, EMC_25 = 0x0780079, EMC_26 = 0x07C007A, EMC_27 = 0x080007B, EMC_28 = 0x084007C, EMC_29 = 0x088007D, EMC_30 = 0x08C007D, EMC_31 = 0x090007F,
    EMC_32 = 0x0940052, EMC_33 = 0x0980053, EMC_34 = 0x09C0054, EMC_35 = 0x0A00055, EMC_36 = 0x0A40056, EMC_37 = 0x0A80057, EMC_38 = 0x0AC0058, EMC_39 = 0x0B00059,
    EMC_40 = 0x0B4005A, EMC_41 = 0x0B8005B, SD_B0_00 = 0x1BC004C, SD_B0_01 = 0x1C0004D, SD_B0_02 = 0x1C4004E, SD_B0_03 = 0x1C8004F, SD_B0_04 = 0x1CC0050, SD_B0_05 = 0x1D00051,
    SD_B1_00 = 0x1D40040, SD_B1_01 = 0x1D80041, SD_B1_02 = 0x1DC0042, SD_B1_03 = 0x1E00043, SD_B1_04 = 0x1E40044, SD_B1_05 = 0x1E80045, SD_B1_06 = 0x1EC0046, SD_B1_07 = 0x1F00047,
    SD_B1_08 = 0x1F40048, SD_B1_09 = 0x1F80049, SD_B1_10 = 0x1FC004A, SD_B1_11 = 0x200004B
} IMXRT_PIN_t;

inline void digitalWrite(IMXRT_PIN_t pin_name, uint8_t val) {
    uint32_t mask = 1 << (pin_name & 0x1f);
    if (val) {
        volatile uint32_t *reg = (volatile uint32_t*)((uint8_t *)&GPIO6_DR_SET + 0x4000 * ((pin_name >> 5) & 0x7));
        *reg = mask;
    } else {
        volatile uint32_t *reg = (volatile uint32_t*)((uint8_t *)&GPIO6_DR_CLEAR + 0x4000 * ((pin_name >> 5) & 0x7));
        *reg = mask;
    }
}
inline void digitalToggle(IMXRT_PIN_t pin_name) {
    uint32_t mask = 1 << (pin_name & 0x1f);
    volatile uint32_t *reg = (volatile uint32_t*)((uint8_t *)&GPIO6_DR_TOGGLE + 0x4000 * ((pin_name >> 5) & 0x7));
    Serial.printf("Toggle %x Reg:%x mask:%x\n", pin_name, reg, mask);
    *reg = mask;
}

void pinMode(IMXRT_PIN_t pin_name, uint8_t mode)
{
    // generate PAD and MUX register from name...
    volatile uint32_t *mux = (volatile uint32_t *)(IMXRT_IOMUXC_ADDRESS + (pin_name >> 16));
    volatile uint32_t *pad = (volatile uint32_t *)(IMXRT_IOMUXC_ADDRESS + (pin_name >> 16) + 0x1f0);
    volatile uint32_t *gdir = (volatile uint32_t*)((uint8_t *)&GPIO6_GDIR + 0x4000 * ((pin_name >> 5) & 0x7));
    uint32_t mask = 1 << (pin_name & 0x1f);

    Serial.printf("pinMode %x mux:%p pad:%p gdir:%p mask:%x\n", pin_name, mux, pad, gdir, mask);

    const struct digital_pin_bitband_and_config_table_struct *p;
    if (mode == OUTPUT || mode == OUTPUT_OPENDRAIN) {
        *gdir |= mask; // TODO: atomic
        if (mode == OUTPUT) {
            *pad = IOMUXC_PAD_DSE(7);
        } else { // OUTPUT_OPENDRAIN
            *pad = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_ODE;
        }
    } else {
        *gdir &= ~(p->mask); // TODO: atomic
        if (mode == INPUT) {
            *pad = IOMUXC_PAD_DSE(7);
        } else if (mode == INPUT_PULLUP) {
            *pad = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(3) | IOMUXC_PAD_HYS;
        } else if (mode == INPUT_PULLDOWN) {
            *pad = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(0) | IOMUXC_PAD_HYS;
        } else { // INPUT_DISABLE
            *pad = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_HYS;
        }
    }
    mux = 5 | 0x10;
}
 
Back
Top