Call to arms | Teensy + SDRAM = true

@mjs513, 4096 bytes in 132uS, that's 29 Megabytes per second, correct? :giggle:
Ok redid the 1060EVKB sketch to calculate uS based on clock cycles. Looks exactly the same:
Code:
 SEMC SDRAM Example Start!

 SEMC SDRAM Memory 32 bit Write Start, Start Address 0x80000000, Data Length 4096 !
32 bit Write Clock Cycles == > 78801
32 bit Write uS == > 131

 SEMC SDRAM Read 32 bit Data Start, Start Address 0x80000000, Data Length 4096 !
32 bit Read Clock Cycles == > 232

 SEMC SDRAM 32 bit Data Write and Read Compare Start!

 SEMC SDRAM 32 bit Data Write and Read Compare Succeed!

 SEMC SDRAM Memory 16 bit Write Start, Start Address 0x80000000, Data Length 4096 !
16 bit Write Clock Cycles == > 204

 SEMC SDRAM Read 16 bit Data Start, Start Address 0x80000000, Data Length 4096 !
16 bit Read Clock Cycles == > 127

 SEMC SDRAM 16 bit Data Write and Read Compare Start!

 SEMC SDRAM 16 bit Data Write and Read Compare Succeed!

 SEMC SDRAM Memory 8 bit Write Start, Start Address 0x80000000, Data Length 4096 !
8 bit Write Clock Cycles == > 146

 SEMC SDRAM Read 8 bit Data Start, Start Address 0x80000000, Data Length 4096 !
8 bit Read Clock Cycles == > 120

 SEMC SDRAM 8 bit Data Write and Read Compare Start!

 SEMC SDRAM 8 bit Data Write and Read Compare Succeed!

 SEMC SDRAM Example End.
Note: I forgot to enable float so for the 32bit write its actually 131.82 us :)
 
30 Megabytes per second seems good, how many Megabytes per second can the PSRAM's do? It's fun to see how many times faster the SDRAM is.

And also compare the SDRAM to the ordinary RAM in the NXP.
 
30 Megabytes per second seems good, how many Megabytes per second can the PSRAM's do? It's fun to see how many times faster the SDRAM is.
Modify the test sketch to use EXTMEM instead of sdram like this:
Code:
uint32_t sdram_writeBuffer[SEMC_EXAMPLE_DATALEN];
uint32_t sdram_readBuffer[SEMC_EXAMPLE_DATALEN];
EXTMEM uint32_t sdram[SEMC_EXAMPLE_DATALEN];

Ok as for your question, seems faster if I did the sketch right......

Code:
SDRAM Memory 32 bit Write Start, Start Address 0x70000000, Data Length 4096 !
    SDRAM Memory 32 bit Write Time (uS) 628

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

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

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

 SDRAM Memory 16 bit Read Time (uS) 8
 SDRAM 16 bit Data Write and Read Compare Start!
     SDRAM Memory 16 bit Read/Write Time (uS) 27
 SDRAM 16 bit Data Write and Read Compare Succeed!
----------------------------------------------

 SDRAM Memory 8 bit Write Start, Start Address 0x70000000, Data Length 4096 !
    SDRAM Memory 8 bit Write Time (uS) 20

 SDRAM Read 8 bit Data Start, Start Address 0x70000000, Data Length 4096 !
    SDRAM Memory 8 bit Read Time (uS) 7

 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) 31
----------------------------------------------

 SDRAM Example End.

Here is the sketch:
Code:
uint32_t now;

#define PRINTF Serial.printf

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

uint32_t sdram_writeBuffer[SEMC_EXAMPLE_DATALEN];
uint32_t sdram_readBuffer[SEMC_EXAMPLE_DATALEN];
EXTMEM uint32_t sdram[SEMC_EXAMPLE_DATALEN];

void setup(){

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

    /* 32Bit data read and write. */
    SEMC_SDRAMReadWrite32Bit();
    Serial.println("----------------------------------------------");

    /* 16Bit data read and write. */
    SEMC_SDRAMReadWrite16Bit();
    Serial.println("----------------------------------------------");

    /* 8Bit data read and write. */
    SEMC_SDRAMReadWrite8Bit();
    Serial.println("\n----------------------------------------------");

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

void loop(){}

void SEMC_SDRAMReadWrite32Bit(void)
{
    uint32_t index;
    uint32_t datalen = SEMC_EXAMPLE_DATALEN;
    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;
    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;
    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\n", (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\n", (micros() - now));

    PRINTF("\r\n SDRAM 8 bit Data Write and Read Compare Start!");
    /* 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));
    }
}
 
Fun @mjs513! - I bumped the test area from 4K to 12K when run before - and I just used the CYCCNT/600 for micros in that test ... I haven't gotten back to yet. The default 1MB RAM break on NXP IDE is 128/128/768 instead of the {512 TCM SLIDING I&D}/512 SDRAM so going much larger with the static test buffer blew up DTCM. SO I did the MOD to just fill with loop values - and have the PJRC PSRAM test open to test with.

Yes @manitou passed the GPT micros() to me as well - must be in a separate file.

The EVKB uses the 1062 B release like current T_4.x's.
 
calcs in post #21 gave this for the full 32MB pass:
...
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:

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.
...
Using this for micros macro mapping to a simulator using CYCCNT:
#define ARM_DWT_CYCCNT (*(volatile uint32_t *)0xE0001004) // Cycle count register uint32_t microsSim() { // return MSDK_GetCpuCycleCount()/600; return ARM_DWT_CYCCNT/600; } #define micros microsSim

Current edit of the SEMC SDRAM test code here - with commented copy of @manitou provided micros using GPT at end - and pulled in code needed to init and Toggle USER_LED - with 12KB of testing instead of 4KB in _DATALEN.
And added SEMC_SDRAMReadWrite32BitAll() runs through all 32MB of SDRAM {though .LD only reserves 30MB of length it works?
> Oddly that 32MB showed SUCCESS when the three example SEMC 32/26/8 bit reads failed:
C:
/*
 * Copyright 2017-2020 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
#include "fsl_debug_console.h"
#include "fsl_device_registers.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
#include "fsl_semc.h"
// #include "stdio.h"

#include "system_MIMXRT1062.h"
/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define EXAMPLE_SEMC               SEMC
#define EXAMPLE_SEMC_START_ADDRESS (0x80000000U)
#define EXAMPLE_SEMC_CLK_FREQ      CLOCK_GetFreq(kCLOCK_SemcClk)

#define SEMC_EXAMPLE_DATALEN    12*1024 // (0x1000U)
// #define SEMC_EXAMPLE_WRITETIMES (1000U)

#define EXAMPLE_LED_GPIO     BOARD_USER_LED_GPIO
#define EXAMPLE_LED_GPIO_PIN BOARD_USER_LED_GPIO_PIN
/*
GPIO_PinWrite(EXAMPLE_LED_GPIO, EXAMPLE_LED_GPIO_PIN, 1U);
*/
/*******************************************************************************
 * Prototypes
 ******************************************************************************/
extern status_t BOARD_InitSEMC(void);
static void SEMC_SDRAMReadWrite32BitAll(void);
static void SEMC_SDRAMReadWrite32Bit(void);
static void SEMC_SDRAMReadWrite16Bit(void);
static void SEMC_SDRAMReadWrite8Bit(void);
/*******************************************************************************
 * Variables
 ******************************************************************************/

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

/*******************************************************************************
 * Code
 ******************************************************************************/
status_t BOARD_InitSEMC(void)
{
    semc_config_t config;
    semc_sdram_config_t sdramconfig;
    uint32_t clockFrq = EXAMPLE_SEMC_CLK_FREQ;

    /* Initializes the MAC configure structure to zero. */
    memset(&config, 0, sizeof(semc_config_t));
    memset(&sdramconfig, 0, sizeof(semc_sdram_config_t));

    /* Initialize SEMC. */
    SEMC_GetDefaultConfig(&config);
    config.dqsMode = kSEMC_Loopbackdqspad; /* For more accurate timing. */
    SEMC_Init(SEMC, &config);

    /* Configure SDRAM. */
    sdramconfig.csxPinMux           = kSEMC_MUXCSX0;
    sdramconfig.address             = 0x80000000;
    sdramconfig.memsize_kbytes      = 32 * 1024; /* 32MB = 32*1024*1KBytes*/
    sdramconfig.portSize            = kSEMC_PortSize16Bit;
    sdramconfig.burstLen            = kSEMC_Sdram_BurstLen8;
    sdramconfig.columnAddrBitNum    = kSEMC_SdramColunm_9bit;
    sdramconfig.casLatency          = kSEMC_LatencyThree;
    sdramconfig.tPrecharge2Act_Ns   = 18; /* Trp 18ns */
    sdramconfig.tAct2ReadWrite_Ns   = 18; /* Trcd 18ns */
    sdramconfig.tRefreshRecovery_Ns = 67; /* Use the maximum of the (Trfc , Txsr). */
    sdramconfig.tWriteRecovery_Ns   = 12; /* 12ns */
    sdramconfig.tCkeOff_Ns =
        42; /* The minimum cycle of SDRAM CLK off state. CKE is off in self refresh at a minimum period tRAS.*/
    sdramconfig.tAct2Prechage_Ns       = 42; /* Tras 42ns */
    sdramconfig.tSelfRefRecovery_Ns    = 67;
    sdramconfig.tRefresh2Refresh_Ns    = 60;
    sdramconfig.tAct2Act_Ns            = 60;
    sdramconfig.tPrescalePeriod_Ns     = 160 * (1000000000 / clockFrq);
    sdramconfig.refreshPeriod_nsPerRow = 64 * 1000000 / 8192; /* 64ms/8192 */
    sdramconfig.refreshUrgThreshold    = sdramconfig.refreshPeriod_nsPerRow;
    sdramconfig.refreshBurstLen        = 1;
    return SEMC_ConfigureSDRAM(SEMC, kSEMC_SDRAM_CS0, &sdramconfig, clockFrq);
}

#if defined(CACHE_MAINTAIN) && CACHE_MAINTAIN
#include "fsl_cache.h"
#endif

#define ARM_DWT_CYCCNT          (*(volatile uint32_t *)0xE0001004) // Cycle count register
uint32_t microsSim() {
//    return MSDK_GetCpuCycleCount()/600;
    return ARM_DWT_CYCCNT/600;
}
#define micros microsSim
/*!
 * @brief Main function
 */
int main(void)
{
    /* Hardware initialize. */
    BOARD_ConfigMPU();
    BOARD_InitBootPins();
    BOARD_InitBootClocks();

    CLOCK_InitSysPfd(kCLOCK_Pfd2, 29);
    /* Set semc clock to 163.86 MHz */
    CLOCK_SetMux(kCLOCK_SemcMux, 1);
    CLOCK_SetDiv(kCLOCK_SemcDiv, 1);
    USER_LED_INIT(1U);
    BOARD_InitDebugConsole();

        PRINTF("\n SEMC SDRAM Example Start! 12/21 \n");
        PRINTF(__FILE__);
        PRINTF("\n float? %f\n", 0.01234f);
    PRINTF("\t HELLO WORLD!\n");
    if (BOARD_InitSEMC() != kStatus_Success)
    {
        PRINTF("\r\n SEMC SDRAM Init Failed\n");
    }
    else
    {
        PRINTF("\r\n SEMC SDRAM Init Succeeded!\n");
        USER_LED_TOGGLE();
    }
    uint32_t aTime;
    /* 32Bit data read and write. */
    //aTime = MSDK_GetCpuCycleCount();
    aTime = micros();
    SEMC_SDRAMReadWrite32BitAll();
    aTime = micros()-aTime;
    PRINTF("\t ALL Write-Test took %d micros\n", aTime);
    USER_LED_TOGGLE();

    /* 32Bit data read and write. */
    aTime = micros();
    SEMC_SDRAMReadWrite32Bit();
    aTime = micros()-aTime;
    PRINTF("\t Write-Test took %d micros\n\n", aTime);
    USER_LED_TOGGLE();

    /* 16Bit data read and write. */
    aTime = micros();
    SEMC_SDRAMReadWrite16Bit();
    aTime = micros()-aTime;
    PRINTF("\t Write-Test took %d micros\n\n", aTime);
    USER_LED_TOGGLE();

    /* 8Bit data read and write. */
    aTime = micros();
    SEMC_SDRAMReadWrite8Bit();
    aTime = micros()-aTime;
    PRINTF("\t Write-Test took %d micros\n\n", aTime);

    PRINTF(" SEMC SDRAM Example End.\n");
    GPIO_PinWrite(EXAMPLE_LED_GPIO, EXAMPLE_LED_GPIO_PIN, 1U);
    while (1)
    {
    }
}

void SEMC_SDRAMReadWrite32BitAll(void) {
    uint32_t index;
    uint32_t datalen = 32 * 1024 * 1024 / sizeof(uint32_t);
    uint32_t *sdram = (uint32_t*) EXAMPLE_SEMC_START_ADDRESS; /* SDRAM start address. */
    bool result = true;

    PRINTF("\n SEMC SDRAM Memory 32 bit Write Start, Start Address 0x%x, Data Length %d !\n",
            sdram, datalen * sizeof(uint32_t));
    /* Prepare data and write to SDRAM. */
    uint32_t aTime;
    /* 32Bit data read and write. */
    aTime = micros();
    for (index = 0; index < datalen; index++) {
        sdram[index] = index;
    }
    aTime = micros() - aTime;
    PRINTF("\t ALL Write took %d micros\n", aTime);
    PRINTF("SEMC SDRAM Read 32 bit Data Start, Start Address 0x%x, Data Length %d !\n",
            sdram, datalen * sizeof(uint32_t));

#if defined(CACHE_MAINTAIN) && CACHE_MAINTAIN
    x // no cache here
    DCACHE_InvalidateByRange(EXAMPLE_SEMC_START_ADDRESS, 4U * SEMC_EXAMPLE_DATALEN);
#endif

    aTime = micros();
    /* Read data from the SDRAM. */
    for (index = 0; index < datalen; index++) {
        if (sdram[index] != index) {
            result = false;
            break;
        }
    }
    aTime = micros()-aTime;
    PRINTF("\t ALL Read&Test took %d micros\n", aTime);

    if (!result) {
        PRINTF("ALL SEMC SDRAM 32 bit Data Write and Read Compare Failed!\n\n");
    } else {
        PRINTF("ALL SEMC SDRAM 32 bit Data Write and Read Compare Succeed!\n");
    }
}

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("\n SEMC SDRAM Memory 32 bit Write Start, Start Address 0x%x, Data Length %d !\n", sdram, datalen);
    /* Prepare data and write to SDRAM. */
    for (index = 0; index < datalen; index++)
    {
        sdram_writeBuffer[index] = index;
        sdram[index]             = sdram_writeBuffer[index];
    }

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

#if defined(CACHE_MAINTAIN) && CACHE_MAINTAIN
    DCACHE_InvalidateByRange(EXAMPLE_SEMC_START_ADDRESS, 4U * SEMC_EXAMPLE_DATALEN);
#endif

    /* Read data from the SDRAM. */
    for (index = 0; index < datalen; index++)
    {
        sdram_readBuffer[index] = sdram[index];
    }

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

    if (!result)
    {
        PRINTF("\n SEMC SDRAM 32 bit Data Write and Read Compare Failed!\n");
    }
    else
    {
        PRINTF("\n SEMC SDRAM 32 bit Data Write and Read Compare Succeed!\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("\n SEMC SDRAM Memory 16 bit Write Start, Start Address 0x%x, Data Length %d !\n", sdram, datalen);

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

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

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

#if defined(CACHE_MAINTAIN) && CACHE_MAINTAIN
    DCACHE_InvalidateByRange(EXAMPLE_SEMC_START_ADDRESS, 4U * SEMC_EXAMPLE_DATALEN);
#endif

    /* Read data from the SDRAM. */
    for (index = 0; index < datalen; index++)
    {
        sdram_readBuffer[index] = sdram[index];
    }

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

    if (!result)
    {
        PRINTF("\n SEMC SDRAM 16 bit Data Write and Read Compare Failed!\n");
    }
    else
    {
        PRINTF("\n SEMC SDRAM 16 bit Data Write and Read Compare Succeed!\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("\n SEMC SDRAM Memory 8 bit Write Start, Start Address 0x%x, Data Length %d !\n", sdram, datalen);

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

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

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

#if defined(CACHE_MAINTAIN) && CACHE_MAINTAIN
    DCACHE_InvalidateByRange(EXAMPLE_SEMC_START_ADDRESS, 4U * SEMC_EXAMPLE_DATALEN);
#endif

    /* Read data from the SDRAM. */
    for (index = 0; index < datalen; index++)
    {
        sdram_readBuffer[index] = sdram[index];
    }

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

    if (!result)
    {
        PRINTF("\n SEMC SDRAM 8 bit Data Write and Read Compare Failed!\n");
    }
    else
    {
        PRINTF("\n SEMC SDRAM 8 bit Data Write and Read Compare Succeed!\n");
    }
}

/*
// GPT 1MHz micro() manitou
#include <stdio.h>
#include <math.h>
#include "fsl_debug_console.h"
#include "board.h"

#include "fsl_gpio.h"

#include "pin_mux.h"
#include "clock_config.h"
#include "fsl_clock.h"

// micros for SDK using GPT   add gpt component to project
#include "fsl_gpt.h"
#define GPTx GPT1

void micros_init() {
    // run GPT at 1mhz
    gpt_config_t gptConfig;

    CLOCK_SetMux(kCLOCK_PerclkMux, 0);
    CLOCK_SetDiv(kCLOCK_PerclkDiv, 0);

    GPT_GetDefaultConfig(&gptConfig);

    // * Initialize GPT module
    GPT_Init(GPTx, &gptConfig);

    // * Divide GPT clock source frequency by 150 inside GPT module
    GPT_SetClockDivider(GPTx, CLOCK_GetFreq(kCLOCK_IpgClk) / 1000000);
    GPT_StartTimer(GPTx);
}

uint32_t micros() {
    return GPT_GetCurrentTimerCount(GPTx);
}

void delay(uint32_t ms) {
    uint32_t t = micros();
    while(micros() < t + 1000*ms);
}

#define PRREG(z) printf(#z" 0x%x\n",z)
#define ARM_DEMCR               (*(volatile uint32_t *)0xE000EDFC) // Debug Exception and Monitor Control
#define ARM_DEMCR_TRCENA                (1 << 24)        // Enable debugging & monitoring blocks
#define ARM_DWT_CTRL            (*(volatile uint32_t *)0xE0001000) // DWT control register
#define ARM_DWT_CTRL_CYCCNTENA          (1 << 0)                // Enable cycle count
#define ARM_DWT_CYCCNT          (*(volatile uint32_t *)0xE0001004) // Cycle count register


int main(void) {


    // * Board pin, clock, debug console init *
    BOARD_ConfigMPU();
    BOARD_InitPins();
    BOARD_BootClockRUN();
    BOARD_InitDebugConsole();

    micros_init();
    uint32_t us = micros();
    delay(10);
    PRINTF("%d us  %d\n",us, micros());
    printf("printf %.2f\n",-1.234);
    PRINTF("PRINTF %.2f\n",-1.234);
    while(1){
        delay(1000);
    }

}
*/
 
Hi @defragster
Yep same code for micros. Left over from beta testing of the Teensy 4.0 when @manitou and I were playing with the EVKB.

for cycle counts was using the following (found it on line - link somewhere in the beta test thread) code:

Code:
//******************************************************************************
#define InitCycleCounter() \
  CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk
  /*!< TRCENA: Enable trace and debug block DEMCR (Debug Exception and Monitor Control Register */

#define ResetCycleCounter() \
  DWT->CYCCNT = 0
  /*!< Reset cycle counter */

#define EnableCycleCounter() \
  DWT->CTRL |= DWT_CTRL_CYCEVTENA_Msk
  /*!< Enable cycle counter */

#define DisableCycleCounter() \
  DWT->CTRL &= ~DWT_CTRL_CYCEVTENA_Msk
  /*!< Disable cycle counter */

#define GetCycleCounter() \
  DWT->CYCCNT
  /*!< Read cycle counter register */

/* Systick Start */
#define TimerCount_Start() do{\
InitCycleCounter(); \
ResetCycleCounter(); \
EnableCycleCounter(); \
}while(0)

/* Systick Stop and retrieve CPU Clocks count */
#define TimerCount_Stop(Value) do {\
DisableCycleCounter(); \
Value = GetCycleCounter(); \
}while(0)

int32_t cycles;

So to use:
Code:
    TimerCount_Start();
    for (index = 0; index < datalen; index++)
    {
        sdram_writeBuffer[index] = index;
        sdram[index] = sdram_writeBuffer[index];
    }
    TimerCount_Stop(cycles);
    PRINTF("32 bit Write Clock Cycles == > %d\r\n", cycles);
 
The CYCCNT is already running on EVKB - it is used by the native MSDK_GetCpuCycleCount() commented now in my post/code.
I got the #define form the manitou code he shared.- so using it directly. Resetting and Stopping the CYCCNT doesn't seem like a good idea as it might be used otherwise - like on Teensy 4.x I used that in getting micros() offset from last millis() tick.
Testing for T_4.x code is reads that register value in about 3 clock ticks - so no worry about it not being 'correct' it will always have the same 3 tick shift in the measure, and stopping/starting it might even let it run longer?
 
Christmas came early! Left is a bare PCB (in real GOLD) backside - and the populated working board on the right.
BLUE (led) BLINK WORKING!
1703367007247.png

TyCommander recognizes PJRC bootloader seeing the 16MB FLASH!
1703367034948.png


Sending 'Bootloader' command - or pressing 'Program Button' and the Orange Bootloader LED lights and sits in PJRC HalfKay!
1703367048319.png


Has two USB-C Device connectors - and plugging into either seems to work - except in bootloader on left USB the BLUE LED stays on dim? So the two are not 'the same' in use? <edit2> speculating this is there being are two caps with one for each USB connector and doing a quick plug is affecting the power reg setup has both charged. Just got repro going the other way.

Board works for upload of two altered Blink with added Serial.print() to TyCommander!
 
Last edited:
Ran PinTest - it runs - but as T_MM - those pins on the correct ports are showing responding to GND and 3.3V!
about 20 pins moved to SDRAM support. Other mappable pins are brought to the other side 'just because' in two groups of 15 it seems.

@luni PinList just gave a crossref checklist of those present/missing - have to verify SDRAM using the missing and then assure they are not adjusted in cores startup.c.

Fun ahead - and holidays.
 
Needed a close ')' See PR: PR 728
Looks like we've never had defines for the SEMC register bit fields. I've just now added them to imxrt.h.

T:\T_Drive\arduino-1.8.19\hardware\teensy\avr\cores\teensy4/imxrt.h:8540:41: error: expected ',' or ')', found "("
8540 | #define SEMC_SDRAMCR0_BL(n ((uint32_t)(n & 0x07)<<4))
| ^
Error compiling for board Teensy 4.1.
 
Last edited:
If you want to help out with this for the community. I’ll send you a board free of charge!

I give up - I will play along with the dev. But curiosity got to me and you know what they say "curiosity kills the cat but satisfaction brought him back." :) But @defragster may have it all done by the time I get the board :) I'll IM you with my info.
 
Even if Defragster get's it running, there will probably be some fine tuning.
I'll send you the board on monday with one of the faster shipping options. :giggle:
 
I'll send you the board on monday with one of the faster shipping options.
Just sent you the shipping info. Only good thing is that I live in NYC so things then to get here a bit faster :) Looking forward. Already started looking at the manual and nxp driver. I know I am going to regret these words but actually doesn't look as bad as working with LUTS.
 
Started fleshing out a couple pin tables, Not sure based on the markings the following pins a bit mismatch??? I am using @KurtE's T41 pin spreadsheet.

1. Batt_in
2. LRCLK
3. MCLK




PINSEMC_PINIO_MUXCTL_Pad
EMC_00SEMC_D0
0​
0x0110F9u
EMC_01SEMC_D1
0​
0x0110F9u
EMC_02SEMC_D2
0​
0x0110F9u
EMC_03SEMC_D3
0​
0x0110F9u
EMC_04SEMC_D4
0​
0x0110F9u
EMC_05SEMC_D5
0​
0x0110F9u
EMC_06SEMC_D6
0​
0x0110F9u
EMC_07SEMC_D7
0​
0x0110F9u
EMC_08SEMC_DM0
0​
0x0110F9u
EMC_09SEMC_A0
0​
0x0110F9u
EMC_10SEMC_A1
0​
0x0110F9u
EMC_11SEMC_A2
0​
0x0110F9u
EMC_12SEMC_A3
0​
0x0110F9u
EMC_13SEMC_A4
0​
0x0110F9u
EMC_14SEMC_A5
0​
0x0110F9u
EMC_15SEMC_A6
0​
0x0110F9u
EMC_16SEMC_A7
0​
0x0110F9u
EMC_17SEMC_A8
0​
0x0110F9u
EMC_18SEMC_A9
0​
0x0110F9u
EMC_19SEMC_A11
0​
0x0110F9u
EMC_20SEMC_A12
0​
0x0110F9u
EMC_21SEMC_BA0
0​
0x0110F9u
EMC_22SEMC_BA1
0​
0x0110F9u
EMC_23SEMC_A10
0​
0x0110F9u
EMC_24SEMC_CAS
0​
0x0110F9u
EMC_25SEMC_RAS
0​
0x0110F9u
EMC_26SEMC_CLK
0​
0x0110F9u
EMC_27SEMC_CKE
0​
0x0110F9u
EMC_28SEMC_WE
0​
0x0110F9u
EMC_29SEMC_CS0
0​
0x0110F9u
EMC_30SEMC_D8
0​
0x0110F9u
EMC_31SEMC_D9
0​
0x0110F9u
EMC_32SEMC_D10
0​
0x0110F9u
EMC_33SEMC_D11
0​
0x0110F9u
EMC_34SEMC_D12
0​
0x0110F9u
EMC_35SEMC_D13
0​
0x0110F9u
EMC_36SEMC_D14
0​
0x0110F9u
EMC_37SEMC_D15
0​
0x0110F9u
EMC_38SEMC_DM1
0​
0x0110F9u
EMC_39SEMC_DQS (to gnd)
1​
0x0110F9u
EMC_40ENET_MD0
0​
0x0110F9u
EMC_41ENET_MDIO
0​
0x0110F9u
PinNameGPIOSerialI2CSPIPWMCANAudioXBARFlexIOAnalogSD/CSI/LCDColumn1
12B0_01
2.1​
SPI(4) MISOQT1_1MQS_LEFT
2:01​
11B0_02
13B0_03
2.3​
SPI(4) SCKQT2_01_RX
2:03​
MM 40B0_04
2:04​
Wire3(2) SCLQT2_1
2:04​
LCD_DATA0MM
MM 41B0_05
2:05​
Wire3(2) SDAQT2_2
2:05​
LCD_DATA1MM
MM 42B0_06
2:06​
QT3_0
2:06​
LCD_DATA2MM
MM 43B0_07
2:07​
QT3_1
2:07​
LCD_DATA3MM
MM 44B0_08
2:08​
QT3_2
2:08​
LCD_DATA4MM
MM 45B0_09
2:09​
QT4_0
2:09​
LCD_DATA5MM
6B0_10
2.1​
PWM2_A2, QT4_11:TX3_RX1
2:10​
B0_11
2.11​
PWM2_B2,QT4_21:TX2_RX2
2:11​
B0_12
2.12​
1:TX1_RX3IO-10
2:12​
B0_13
B0_14
B0_15
8B1_00
2.16​
Serial2(4) TXPWM1_A31:RX_DATAIO-142:16, 3:16
7B1_01
2.17​
Serial2(4) RXPWM1_B31:TX_DATAIO-152:17, 3:17
36B1_02
2.18​
SPI(4) CS2PWM2_A31:TX_BCLKIO-162:18,3:18
37B1_03
2.19​
SPI(4) CS1PWM2_B31:TX_SYNCIO-172:19,3:19
B1_04
B1_05
B1_06
B1_07
B1_08
B1_09
B1_10
B1_11
35B1_12
2.28​
Serial8(5) TX2:28,3:28
34B1_13
2.29​
Serial8(5) RX2:29,3:29
PinNameGPIOSerialI2CSPIPWMCANAudioXBARFlexIOAnalogSD/CSI/LCD
14/A0AD_B1_02
1.18​
Serial3(2) TXQT3_2SPDIF_OUT
3:02​
A1:7, A2:7
15/A1AD_B1_03
1.19​
Serial3(2) RXQT3_3SPDIF_IN
3:03​
A1:8, A2:8
17/A3AD_B1_06
1.22​
Serial4(3) TXWire1(3) SDASPDIF_LOCK
3:06​
A1:11, A2:11CSI_VSYNC
18/A4AD_B1_01
1.17​
Serial3(2) RTSWire(1) SDAQT3_1
3:01​
A1:6, A2:6
19/A5AD_B1_00
1.16​
Serial3(2) CTSWire(1) SCLQT3_0
3:00​
A1:5, A2:5
23/A9AD_B1_09
1.25​
PWM4_A11_RX1:MCLK
3:09​
A1:14, A2:14CSI_D8
24/A10AD_B0_12
1.12​
Serial6(1) TXWire2(4) SCLPWM1_X2A1:1
25/A11AD_B0_13
1.13​
Serial6(1) RXWire2(4) SDAPWM1_X3GPT1_CLKA1:2
26/A12AD_B1_14
1.3​
SPI1(3) MOSI1:TX_BCLK
3:14​
A2:3CSI_D3
27/A13AD_B1_15
1.31​
SPI1(3) SCK1:TX_SYNC
3:15​
A2:4CSI_D2
 
Unfortunately, so the package won’t be picked up until Wednesday. But I’m gonna use DHL Express, they’re fast.
Yea from JLCPCB (China) to the UK I always use Fedex. Including manuf. (PCB + Surface Mount Assembly) time the boards are in my hands in 7 days which I think is really good.
 
Let's talk about C29. Is this capacitor (or any part) soldered on the boards made so far?

1703432231188.png


For DQS to work properly, this EMC_39 pin needs to be floating. If a capacitor is soldered at C29, SDRAM might still be able to work but DQS would need to be configured for internal timing only.
 
Let's talk about C29. Is this capacitor (or any part) soldered on the boards made so far?

View attachment 32717

For DQS to work properly, this EMC_39 pin needs to be floating. If a capacitor is soldered at C29, SDRAM might still be able to work but DQS would need to be configured for internal timing only.
Interesting! I followed the EVAL schematic. It is indeed a cap on the board.
Could be removed to make floating.
 
Some info/discussion below:

What is the function of the DQS line with SDRAM?​


All communityThis categoryThis boardKnowledge baseUsersProducts

‎10-19-2020 12:43 PM

2,173 Views
gerry1

gerry1
Contributor I

What is the purpose and function of the DQS signal in the SEMC SDRAM interface?




0 Kudos
REPLY
All forum topics

6 Replies



2 weeks ago

169 Views
Alessandro_Morgan

Alessandro_Morgan
Contributor I

Dear Felipe,

You reported here:

"The recommendation is to leave the pin floating and internal loopback enabled as this is needed for SDRAM read and write operations at 166 MHz, otherwise performance will not be optimal."

This seems to conflict with the IMXRT1064 datasheet where if the loopback is set internal (SEMC_MCR.DQSMD = 0x0) the minimum setup data time is 8.67ns resulting in a maxim speed of around 115MHZ since Hold time is 0ns.
Is it something I am missing?

Moreover if we set the "external loopback" how the SEMC_DQS trace have to be routed in PCB?
Just leave the pad unconnected without any trace?

Kind Regards,
Alessandro

0 Kudos
REPLY



‎10-21-2020 01:24 PM

2,156 Views
FelipeGarcia

NXP Employee
FelipeGarcia
NXP Employee

Hi Gerry,
DQS signal is to compensate the delay of data path and clock. Certain devices use this pin to indicate the dummy cycles needed (before Program/Read data transfer).
Best regards,
Felipe
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
- We are following threads for 7 weeks after the last post, later replies are ignored. Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
------------------------------------------------------------------------------

0 Kudos
REPLY

‎10-21-2020 01:30 PM

2,152 Views
gerry1

gerry1
Contributor I

Hi Felipe,
Thanks for the response however you don't explain how this is signal is used in the RT1050 with SDRAM. Is it an input to the 1050? If so, how is it used internally and how is it normally connected to external circuitry?
Regards,
Gerry

0 Kudos
REPLY
‎10-23-2020 04:31 PM

2,137 Views
FelipeGarcia

NXP Employee
FelipeGarcia
NXP Employee

Hi Gerry,
SEMC_DQS is input/output when the MCU writes data to the SDRAM, it outputs the DQS in the center of the data it is writing. When reading data, the SDRAM sends the DQS edge aligned with the data.

image.png

The recommendation is to leave the pin floating and internal loopback enabled as this is needed for SDRAM read and write operations at 166 MHz, otherwise performance will not be optimal.
image.png

Best regards,
Felipe
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
- We are following threads for 7 weeks after the last post, later replies are ignored. Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
------------------------------------------------------------------------------



0 Kudos
REPLY





‎10-23-2020 05:01 PM

2,131 Views
gerry1

gerry1
Contributor I

Hi Felipe,
Thanks for the information and the recommendation not to use the DQS line. However, I would like to understand it's function in detail. Is there documentation about this functionality with timing diagrams?
Regards,
Gerry

0 Kudos
REPLY





‎10-27-2020 10:32 AM

2,108 Views
FelipeGarcia

NXP Employee
FelipeGarcia
NXP Employee

Hi Gerry,
You can find timing diagrams in our Reference Manual.
Regards,
Felipe
 
Good for us is that this Cap can be removed easily. When I’m at the computer next time I’ll post a screenshot of which one it is.
 
Back
Top