Diy teensy sdram solder yourself

So I finally got around to doing some more on this.

After a bit of testing I've realised the sdram test was failing only on 32 bit reads. Setting the test buffer to 16 bit there would be no failures.

So on the second burst of the read it must have been failing? (16 bit data bus to read 32 bits)

I adjusted the following after sdram begin and it now passes the sdram library tests

PAD = 0x000000D0;

IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_08 = PAD;
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_09 = PAD;
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_10 = PAD;
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_11 = PAD;
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_12 = PAD;
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_13 = PAD;
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_14 = PAD;
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_15 = PAD;

Slower slew. Lowers drive strength. Hysteresis off
 
As per the post above, that was fixing the SDRAM to not fail on reads when running at 221mhz

So the problem i had was a bunch of extra pins not accessible through the standard digital write, as they where not defined. Also trying to map existing pins was a bit tricky and i didnt want to edit the teensy core pins.

If its any use to anyone ever i made a pins.h file you can do digital inputs and outputs refering to the pins as GPIO_B1_08, GPIO_SD_B1_03, GPIO_AD_B1_03 etc. Its all based off Macros and no analog use etc.

So you can go

Code:
#include "Pins.h"

#define PIN_MYPIN GPIO_AD_B1_10

void setup()
{
  //Digital Write with GPIO naming
  PINMODE_PAD_OUTPUT(GPIO_SD_B1_03);
  DIGITALWRITE_PAD(GPIO_SD_B1_03, true);
 
  //Digital Read with GPIO naming
  PINMODE_PAD_INPUT(GPIO_AD_B1_09);
  bool p = DIGITALREAD_PAD(GPIO_AD_B1_09);

  //Can also use macros to refer to pin
  PINMODE_PAD_OUTPUT(PIN_MYPIN);
  DIGITALWRITE_PAD(PIN_MYPIN, false);
}

void loop()
{
 
}

This is Pins.h
Code:
#include "imxrt.h"

struct PadDesc
{
  volatile uint32_t *dr;
  volatile uint32_t *gdir;
  volatile uint32_t *dr_set;
  volatile uint32_t *dr_clear;
  volatile uint32_t *mux;
  volatile uint32_t *pad;
  uint32_t           mask;
  uint8_t            mux_alt;
};

#define PAD_DESC(name, gpio_num, bit_idx, alt)                                   \
  static constexpr PadDesc PADDESC_##name = {                                    \
    &GPIO##gpio_num##_DR, &GPIO##gpio_num##_GDIR,                                \
    &GPIO##gpio_num##_DR_SET, &GPIO##gpio_num##_DR_CLEAR,                        \
    &IOMUXC_SW_MUX_CTL_PAD_##name, &IOMUXC_SW_PAD_CTL_PAD_##name,                \
    (1u << (bit_idx)), (alt)                                                     \
  }

static inline void PinModePadOutput(const PadDesc &p)
{
  *p.mux = p.mux_alt;
  *p.gdir |= p.mask;
}

static inline void PinModePadInput(const PadDesc &p)
{
  *p.mux = p.mux_alt;
  *p.gdir &= ~p.mask;
}

static inline void DigitalWritePadFast(const PadDesc &p, bool high)
{
  if (high) *p.dr_set = p.mask;
  else      *p.dr_clear = p.mask;
}

static inline bool DigitalReadPadFast(const PadDesc &p)
{
  return (*p.dr & p.mask) != 0;
}

#define _CONCAT(a,b) a##b
#define CONCAT(a,b)  _CONCAT(a,b)
#define PINMODE_PAD_OUTPUT(name)     PinModePadOutput(CONCAT(PADDESC_, name))
#define PINMODE_PAD_INPUT(name)      PinModePadInput(CONCAT(PADDESC_, name))
#define DIGITALWRITE_PAD(name, val)  DigitalWritePadFast(CONCAT(PADDESC_, name), (val))
#define DIGITALREAD_PAD(name)        DigitalReadPadFast(CONCAT(PADDESC_, name))

PAD_DESC(GPIO_AD_B0_00, 6,  0, 5);
PAD_DESC(GPIO_AD_B0_01, 6,  1, 5);
PAD_DESC(GPIO_AD_B0_02, 6,  2, 5);
PAD_DESC(GPIO_AD_B0_03, 6,  3, 5);
PAD_DESC(GPIO_AD_B0_04, 6,  4, 5);
PAD_DESC(GPIO_AD_B0_05, 6,  5, 5);
PAD_DESC(GPIO_AD_B0_06, 6,  6, 5);
PAD_DESC(GPIO_AD_B0_07, 6,  7, 5);
PAD_DESC(GPIO_AD_B0_08, 6,  8, 5);
PAD_DESC(GPIO_AD_B0_09, 6,  9, 5);
PAD_DESC(GPIO_AD_B0_10, 6, 10, 5);
PAD_DESC(GPIO_AD_B0_11, 6, 11, 5);
PAD_DESC(GPIO_AD_B0_12, 6, 12, 5);
PAD_DESC(GPIO_AD_B0_13, 6, 13, 5);
PAD_DESC(GPIO_AD_B0_14, 6, 14, 5);
PAD_DESC(GPIO_AD_B0_15, 6, 15, 5);
PAD_DESC(GPIO_AD_B1_00, 6, 16, 5);
PAD_DESC(GPIO_AD_B1_01, 6, 17, 5);
PAD_DESC(GPIO_AD_B1_02, 6, 18, 5);
PAD_DESC(GPIO_AD_B1_03, 6, 19, 5);
PAD_DESC(GPIO_AD_B1_04, 6, 20, 5);
PAD_DESC(GPIO_AD_B1_05, 6, 21, 5);
PAD_DESC(GPIO_AD_B1_06, 6, 22, 5);
PAD_DESC(GPIO_AD_B1_07, 6, 23, 5);
PAD_DESC(GPIO_AD_B1_08, 6, 24, 5);
PAD_DESC(GPIO_AD_B1_09, 6, 25, 5);
PAD_DESC(GPIO_AD_B1_10, 6, 26, 5);
PAD_DESC(GPIO_AD_B1_11, 6, 27, 5);
PAD_DESC(GPIO_AD_B1_12, 6, 28, 5);
PAD_DESC(GPIO_AD_B1_13, 6, 29, 5);
PAD_DESC(GPIO_AD_B1_14, 6, 30, 5);
PAD_DESC(GPIO_AD_B1_15, 6, 31, 5);

PAD_DESC(GPIO_B0_00, 7,  0, 5);
PAD_DESC(GPIO_B0_01, 7,  1, 5);
PAD_DESC(GPIO_B0_02, 7,  2, 5);
PAD_DESC(GPIO_B0_03, 7,  3, 5);
PAD_DESC(GPIO_B0_04, 7,  4, 5);
PAD_DESC(GPIO_B0_05, 7,  5, 5);
PAD_DESC(GPIO_B0_06, 7,  6, 5);
PAD_DESC(GPIO_B0_07, 7,  7, 5);
PAD_DESC(GPIO_B0_08, 7,  8, 5);
PAD_DESC(GPIO_B0_09, 7,  9, 5);
PAD_DESC(GPIO_B0_10, 7, 10, 5);
PAD_DESC(GPIO_B0_11, 7, 11, 5);
PAD_DESC(GPIO_B0_12, 7, 12, 5);
PAD_DESC(GPIO_B0_13, 7, 13, 5);
PAD_DESC(GPIO_B0_14, 7, 14, 5);
PAD_DESC(GPIO_B0_15, 7, 15, 5);
PAD_DESC(GPIO_B1_00, 7,  16, 5);
PAD_DESC(GPIO_B1_01, 7,  17, 5);
PAD_DESC(GPIO_B1_02, 7,  18, 5);
PAD_DESC(GPIO_B1_03, 7,  19, 5);
PAD_DESC(GPIO_B1_04, 7,  20, 5);
PAD_DESC(GPIO_B1_05, 7,  21, 5);
PAD_DESC(GPIO_B1_06, 7,  22, 5);
PAD_DESC(GPIO_B1_07, 7,  23, 5);
PAD_DESC(GPIO_B1_08, 7,  24, 5);
PAD_DESC(GPIO_B1_09, 7,  25, 5);
PAD_DESC(GPIO_B1_10, 7,  26, 5);
PAD_DESC(GPIO_B1_11, 7,  27, 5);
PAD_DESC(GPIO_B1_12, 7,  28, 5);
PAD_DESC(GPIO_B1_13, 7,  29, 5);
PAD_DESC(GPIO_B1_14, 7,  30, 5);
PAD_DESC(GPIO_B1_15, 7,  31, 5);

PAD_DESC(GPIO_SD_B0_00, 8, 12, 5);
PAD_DESC(GPIO_SD_B0_01, 8, 13, 5);
PAD_DESC(GPIO_SD_B0_02, 8, 14, 5);
PAD_DESC(GPIO_SD_B0_03, 8, 15, 5);
PAD_DESC(GPIO_SD_B0_04, 8, 16, 5);
PAD_DESC(GPIO_SD_B0_05, 8, 17, 5);
PAD_DESC(GPIO_SD_B1_00, 8, 0, 5);
PAD_DESC(GPIO_SD_B1_01, 8, 1, 5);
PAD_DESC(GPIO_SD_B1_02, 8, 2, 5);
PAD_DESC(GPIO_SD_B1_03, 8, 3, 5);
PAD_DESC(GPIO_SD_B1_04, 8, 4, 5);
PAD_DESC(GPIO_SD_B1_05, 8, 5, 5);
PAD_DESC(GPIO_SD_B1_06, 8, 6, 5);
PAD_DESC(GPIO_SD_B1_07, 8, 7, 5);
PAD_DESC(GPIO_SD_B1_08, 8, 8, 5);
PAD_DESC(GPIO_SD_B1_09, 8, 9, 5);
PAD_DESC(GPIO_SD_B1_10, 8,10, 5);
PAD_DESC(GPIO_SD_B1_11, 8,11, 5);
 
Last edited:
So i have had a play with the SDRAM Pad Settings. I have managed to get SDRAM running stable at 240mhz

My original problem from going 198 to 221 was pad EMC_08. Just adjusting the rate on that made it stable to 227mhz.

Doing some tests clearing an 800 x 480 x 16bit back buffer while the lcd_if engine is also outputting to the display (Im not sure if the lcdif has started reading sdram and outputting the frame at the time of clear)

166mhz. 2606 microseconds. 281MiB/s
198mhz. 2145 microseconds. 341MiB/s
221mhz. 1891 microseconds. 387MiB/s
227mhz. 1841 microseconds. 397MiB/s
240mhz. 1737 microseconds. 421MiB/s


Adjusting to the following ive managed to get success running the check_fixed_pattern and check_lfsr_pattern at 240mhz

Code:
uint32_t padClock = 0x000100F1;
uint32_t padDQS = 0x000100F1;
uint32_t padDQ = 0x000000D8;
uint32_t padDMX   = 0x000000D0;
uint32_t padADDR  = 0x000000E0;
uint32_t padExtra = 0x000000E1;

IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_00 = padDQ;   // D0
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_01 = padDQ;   // D1
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_02 = padDQ;   // D2
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_03 = padDQ;   // D3
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_04 = padDQ;   // D4
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_05 = padDQ;   // D5
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_06 = padDQ;   // D6
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_07 = padDQ;   // D7
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_08 = padExtra;  // DM0

IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_09 = padADDR; // A0
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_10 = padADDR; // A1
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_11 = padADDR; // A2
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_12 = padADDR; // A3
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_13 = padADDR; // A4
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_14 = padADDR; // A5
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_15 = padADDR; // A6
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_16 = padADDR; // A7
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_17 = padADDR; // A8
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_18 = padADDR; // A9
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_19 = padADDR; // A11
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_20 = padADDR; // A12
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_23 = padADDR; // A10
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_21 = padADDR; // BA0
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_22 = padADDR; // BA1
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_24 = padADDR; // CAS
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_25 = padADDR; // RAS
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_28 = padADDR; // WE
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_29 = padADDR; // CS0
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_27 = padADDR; // CKE
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_26 = padClock; // CLK
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_39 = padDQS;   // DQS
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_30 = padDQ;   // D8
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_31 = padDQ;   // D9
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_32 = padDQ;   // D10
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_33 = padDQ;   // D11
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_34 = padDQ;   // D12
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_35 = padDQ;   // D13
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_36 = padDQ;   // D14
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_37 = padDQ;   // D15
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_38 = padDMX;  // DM1
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_40 = padADDR; // MD0
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_41 = padADDR; // MD1
 
Last edited:
Back
Top