How to config HyperRAM after initialization in MCXN947

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to config HyperRAM after initialization in MCXN947

700 Views
TomC818
Contributor III

Hi, 

I am using a custom designed MCXN947 board with 64MB of external Hyper RAM (W959D8NFYA), I have followed MCX N947:FlexSPI Connecting to HyperRAM - Analysis and Configuration to set up the initialization code for the hyper RAM and tested successfully. 

However, when I tried to load a large file from sd card (with the help of FatFs) I am getting mysterious bit flip which corrupts my data in hyper RAM. I am copy the data to the hyper RAM through direct access, so each time on 1 block of data should be written.

TomC818_0-1764322578207.png

TomC818_1-1764322622291.png



Is there anything I have done wrong in the configuration?

#include "fsl_device_registers.h"

#include "fsl_debug_console.h"

#include <stdio.h>

#include "fsl_cache.h"

#include "fsl_common.h"

#include "fsl_gpio.h"

#include "fsl_edma.h"

#include "peripherals.h"

#include <stdbool.h>

#include <stdint.h>

#include "fsl_flexspi.h"

#include "fsl_flexspi_edma.h"

#include "fsl_cache_lpcac.h"

#include "fsl_gpio.h"

#include "hyperram_init.h"

#include "MCXN947_cm33_core0_COMMON.h"

#include "fsl_reset.h"

uint8_t write_test_block[CONFIG_MAX_BLOCK_SIZE] __attribute__((aligned(32)));

uint8_t read_test_block[CONFIG_MAX_BLOCK_SIZE] __attribute__((aligned(32)));

uint8_t hyperram_spoof[CONFIG_MAX_BLOCK_SIZE] __attribute__((aligned(32)));

enum

{

    READ_DATA,

    WRITE_DATA,

    READ_REG,

    WRITE_REG,

};

edma_transfer_config_t transferConfig;

edma_config_t userConfig;

volatile bool g_Transfer_Done = false;

void SysTick_Handler(void);

flexspi_device_config_t hyperRAM_config =

    {

        .flexspiRootClk = 40000000,

        .isSck2Enabled = false,

        .flashSize = (0x10000U),

        .CSIntervalUnit = kFLEXSPI_CsIntervalUnit1SckCycle,

        .CSInterval = 2,

        .CSHoldTime = 3,

        .CSSetupTime = 3,

        .columnspace = 3,

        .dataValidTime = 3,

        .enableWordAddress = true,

        .AWRSeqIndex = 1,

        .AWRSeqNumber = 1,

        .ARDSeqIndex = 0,

        .ARDSeqNumber = 1,

        .AHBWriteWaitUnit = kFLEXSPI_AhbWriteWaitUnit2AhbCycle,

        .AHBWriteWaitInterval = 0,

        .enableWriteMask = true,

};

uint32_t hyperRAM_LUT[64] =

    {

        /* Read Data */

        [0] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xA0, kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18),

        [1] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10, kFLEXSPI_Command_DUMMY_RWDS_DDR, kFLEXSPI_8PAD, 0x07),

        [2] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_DDR, kFLEXSPI_8PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00),

        /* Write Data */

        [4] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x20, kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18),

        [5] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10, kFLEXSPI_Command_DUMMY_RWDS_DDR, kFLEXSPI_8PAD, 0x07),

        [6] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_DDR, kFLEXSPI_8PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00),

        /* Read Register */

        [8] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xE0, kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18),

        [9] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10, kFLEXSPI_Command_DUMMY_RWDS_DDR, kFLEXSPI_8PAD, 0x07),

        [10] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_DDR, kFLEXSPI_8PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00),

        /* Write Register */

        [12] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x60, kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18),

        [13] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10, kFLEXSPI_Command_WRITE_DDR, kFLEXSPI_8PAD, 0x07),

        [14] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_DDR, kFLEXSPI_8PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_8PAD, 0x00),

};

void EDMA_1_CH0_IRQHandler(void)

{

    if ((EDMA_GetChannelStatusFlags(FLEXSPI0_RX_DMA_BASEADDR, FLEXSPI0_RX_DMA_CHANNEL) & kEDMA_InterruptFlag) != 0U)

    {

        EDMA_ClearChannelStatusFlags(FLEXSPI0_RX_DMA_BASEADDR, FLEXSPI0_RX_DMA_CHANNEL, kEDMA_InterruptFlag);

        g_Transfer_Done = true;

    }

}

void EDMA_1_CH1_IRQHandler(void)

{

    if ((EDMA_GetChannelStatusFlags(FLEXSPI0_TX_DMA_BASEADDR, FLEXSPI0_TX_DMA_CHANNEL) & kEDMA_InterruptFlag) != 0U)

    {

        EDMA_ClearChannelStatusFlags(FLEXSPI0_TX_DMA_BASEADDR, FLEXSPI0_TX_DMA_CHANNEL, kEDMA_InterruptFlag);

        g_Transfer_Done = true;

    }

}

static status_t flexspi_hyper_ram_reset(FLEXSPI_Type *base)

{

    flexspi_transfer_t hyperRAM;

    status_t status;

    /* Write data */

    hyperRAM.deviceAddress = 0x0U;

    hyperRAM.port = kFLEXSPI_PortA1;

    hyperRAM.cmdType = kFLEXSPI_Command;

    hyperRAM.SeqNumber = 1;

    hyperRAM.seqIndex = 4;

    status = FLEXSPI_TransferBlocking(base, &hyperRAM);

    if (status == kStatus_Success)

    {

        for (uint32_t i = 150000; i > 0; i--)

        {

            __NOP();

        }

    }

    return status;

}

status_t hyperRAM_mem_init(bool enable_cache)

{

    edma_config_t userConfig;

    EDMA_GetDefaultConfig(&userConfig);

    EDMA_Init(DMA1, &userConfig);

    EnableIRQ(EDMA_1_CH0_IRQn);

    flexspi_config_t config;

    cache64_config_t cacheCfg;

    status_t status = kStatus_Success;

    RESET_PeripheralReset(kFLEXSPI_RST_SHIFT_RSTn);

    FLEXSPI_GetDefaultConfig(&config);

    config.ahbConfig.enableAHBPrefetch = true;

    config.ahbConfig.enableAHBBufferable = true;

    config.ahbConfig.enableReadAddressOpt = true;

    config.ahbConfig.enableAHBCachable = true;

    config.rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackFromDqsPad;

    for (uint8_t i = 1; i < FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT - 1; i++)

    {

        config.ahbConfig.buffer[i].bufferSize = 0;

    }

    config.ahbConfig.buffer[0].masterIndex = 4;

    config.ahbConfig.buffer[0].bufferSize = 512;

    config.ahbConfig.buffer[0].enablePrefetch = true;

    config.ahbConfig.buffer[0].priority = 0;

    config.ahbConfig.buffer[FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT - 1].bufferSize = 512;

#if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN)

    config.enableCombination = true;

#endif

    FLEXSPI_Init(HYPERRAM_FLEXSPI, &config);

    FLEXSPI_SetFlashConfig(HYPERRAM_FLEXSPI, &hyperRAM_config, kFLEXSPI_PortA1);

    FLEXSPI_UpdateLUT(HYPERRAM_FLEXSPI, 0, hyperRAM_LUT, ARRAY_SIZE(hyperRAM_LUT));

;

    FLEXSPI_SoftwareReset(HYPERRAM_FLEXSPI);

    status = flexspi_hyper_ram_reset(HYPERRAM_FLEXSPI);

    if (status != kStatus_Success)

    {

        PRINTF("failed to reset hyperRAM....\r\n");

        return status;

    }

    FLEXSPI_SoftwareReset(HYPERRAM_FLEXSPI);

    if (enable_cache)

    {

        CACHE64_GetDefaultConfig(&cacheCfg);

        CACHE64_Init(CACHE64_POLSEL0, &cacheCfg);

        CACHE64_EnableWriteBuffer(CACHE64_CTRL0, false);

        CACHE64_EnableCache(CACHE64_CTRL0);

    }

    return status;

}

uint32_t get_vendor_id(FLEXSPI_Type *base, int regAddr)

{

    uint32_t vendor_id = 0;

    status_t status;

    uint32_t buffer = 0;

    flexspi_transfer_t hyperRAM;

    hyperRAM.deviceAddress = regAddr;

    PRINTF("accessing address:0x%x\r\n", regAddr);

    hyperRAM.port = kFLEXSPI_PortA1;

    hyperRAM.cmdType = kFLEXSPI_Read;

    hyperRAM.SeqNumber = 1;

    hyperRAM.seqIndex = 2;

    hyperRAM.data = &buffer;

    hyperRAM.dataSize = 4;

    PRINTF("Reading id\r\n");

    status = FLEXSPI_TransferBlocking(base, &hyperRAM);

    vendor_id = buffer & 0xffff;

    PRINTF("vendor id: 0x%4x\r\n", vendor_id);

    PRINTF("status:%d\r\n", status);

    return vendor_id;

}

And this is the header I added:


#ifndef HYPERRAM_INIT_H_

#define HYPERRAM_INIT_H_

#include <stdbool.h>

#include <stdint.h>

#include "fsl_common.h"

#ifdef __cplusplus

extern "C"

{

#endif

#define HyperRAM_write_buffer (1024)

#define HyperRAM_read_buffer (1024)

#define HYPERRAM_FLEXSPI FLEXSPI0

#define HYPERRAM_FLEXSPI_BASE_ADDRESS FlexSPI0_AMBA_BASE

#define HYPERRAM_FLEXSPI_PORT kFLEXSPI_PortA1

#define HYPERRAM_FLEXSPI_AMBA_BASE FlexSPI_AMBA_BASE

#define MAX_COLUMN_SIZE (30)

#define HYPERRAM_CMD_LUT_SEQ_IDX_READDATA 0

#define HYPERRAM_CMD_LUT_SEQ_IDX_WRITEDATA 4  

#define HYPERRAM_CMD_LUT_SEQ_IDX_READREG 8    

#define HYPERRAM_CMD_LUT_SEQ_IDX_WRITEREG 12

#define CONFIG_MAX_BLOCK_SIZE (16384)

    status_t hyperRAM_mem_init(bool enable_cache);

#ifdef __cplusplus

}

#endif

#endif



Labels (1)
0 Kudos
Reply
5 Replies

646 Views
Harry_Zhang
NXP Employee
NXP Employee

HI @TomC818 

 status_t hyperRAM_mem_init(bool enable_cache);

HyperRAM is not cache-coherent. If your region is mapped as cacheable, then CPU writes may stay in D-cache , HyperRAM has stale data,CPU reads may return stale cached data.

So i think you can try to disable Cache.

BR

Harry 

0 Kudos
Reply

643 Views
TomC818
Contributor III

@Harry_Zhang I have tried without enabling Cache64 of the Flexspi already and still getting wrongful data but flipping. I wonder is this related to the misconfiguration of the hyper RAM, because I am using direct pointer already the only the target address should get the data, but as you can see in the memory monitor of the attached image, somehow 0x8000_0030 is also getting updated which is not supposed to happen.

0 Kudos
Reply

552 Views
Harry_Zhang
NXP Employee
NXP Employee

Hi @TomC818 

I don't think this is a configuration issue with HyperRAM.

I think you can reproduce it with minimal SD free code (excluding FATfs/SD DMA), and turn off all SD/Tfat related files first. If this is not a problem, the problem is more likely to lie in the SD card read path (DMA, FatFs, buffer management).

BR

Harry

0 Kudos
Reply

498 Views
TomC818
Contributor III

Hi @Harry_Zhang ,


I use f_read first to load a 32KB chunk to the on-chip SRAM first and then copy the data from SRAM to external HyperRAM; I have checked the data in the SRAM and it seems to be correct. Here is the memory monitor on the SRAM range.

TomC818_0-1765254953956.png
But when copied from the SRAM to HyperRAM I am getting data corruption only at specific offset, shown here:

TomC818_1-1765255077588.png


I have re-run the program several times and the data corruption only occur at specific addresses, here shown at 0x30 and 0x7c, so it is unlikely to be a signal integrity issue. I think this is the same bit flipping issue as mentioned before. As mentioned, I am already not using cache for the Flexspi. 

FYI, I have tested with some simpler R/W test with increments , (i.e. loops with i++) which is successful and the data I checked manually with memory monitor is correct.

I tried direct access and DMA method already which both result in the data corruption in the mentioned offset.

 

0 Kudos
Reply

391 Views
Harry_Zhang
NXP Employee
NXP Employee

Hi @TomC818 

I think you can use byte by byte writing for comparative testing.

If there are no errors when writing byte by byte (i.e. there are no more errors at 0x30/0x7c before), but you previously encountered errors when writing with memcpy/32-bit, it indicates that it was caused by a sudden write width/misalignment.

You can force alignment, use byte writing, or adjust the write width.

BR

Harry

0 Kudos
Reply