cancel
Showing results for 
Search instead for 
Did you mean: 

didn't properly able to read and write of FMC_norflash @0x60000000

jr_engr_mbed
Senior

Screenshot (1264).png

HI,

For testing and debugging FMC_norflash(MT28EW01aba) with custom h753 board, I used h743i-eval example as it is for read,write,erase, hence, i could read Manufactring code in memory browser, but in live expression i see address is different, so, where should i check for proper tx and rx data to be match.

#include "main.h"

#include "stm32h7xx_hal.h"

#include "stdio.h"



#define BUFFER_SIZE ((uint32_t)0x1000) // Buffer size for read/write operations



#define NOR_BANK_ADDR ((uint32_t)0x60000000) // Base address of the NOR flash

#define ERASE_TIMEOUT 0x00A00000U // Timeout for erase operation

#define PROGRAM_TIMEOUT 0x00001000U // Timeout for program operation

#define WRITE_READ_ADDR ((uint32_t)0x8000) // Address offset for read/write operations



#define MANUFACTURER_CODE ((uint16_t)0x0089) // Expected Manufacturer code

#define DEVICE_CODE1 ((uint16_t)0x227E) // Expected Device code 1

#define DEVICE_CODE2 ((uint16_t)0x2221) // Expected Device code 2

#define DEVICE_CODE3 ((uint16_t)0x2200) // Expected Device code 3

#define NOR_STATUS_READ_ID_ERROR 0x01 // Custom error code for read ID error

#define NOR_STATUS_ID_ERROR 0x02 // Custom error code for ID mismatch



/* Private variables ---------------------------------------------------------*/

uint16_t aTxBuffer[BUFFER_SIZE];

uint16_t aRxBuffer[BUFFER_SIZE];

__IO uint32_t uwWriteReadStatus = 0;

uint32_t uwIndex = 0;



NOR_HandleTypeDef hnor1;

NOR_IDTypeDef NOR_Id;

FMC_NORSRAM_TimingTypeDef NOR_Timing;



/* Private typedef -----------------------------------------------------------*/

typedef enum

{

FAILED = 0,

PASSED = !FAILED

} TestStatus;



/* Private function prototypes -----------------------------------------------*/

void SystemClock_Config(void);

static void MX_GPIO_Init(void);

HAL_StatusTypeDef MX_FMC_Init(void);

void Error_Handler(void);

static void Fill_Buffer(uint16_t *pBuffer, uint32_t uwBufferLenght, uint16_t uwOffset);

static TestStatus Buffercmp(uint16_t *pBuffer1, uint16_t *pBuffer2, uint16_t BufferLength);

static void CPU_CACHE_Enable(void);

static void MPU_Config(void);



/* Main Program --------------------------------------------------------------*/

int main(void)

{

/* Enable CPU Cache */

CPU_CACHE_Enable();



/* MPU Configuration */

MPU_Config();



/* HAL Initialization */

HAL_Init();



/* Configure the system clock */

SystemClock_Config();



/* Initialize GPIO */

MX_GPIO_Init();



/* Initialize FMC (NOR flash) */

if (MX_FMC_Init() != HAL_OK)

{

Error_Handler();

}



/* Fill the buffer to write */

Fill_Buffer(aTxBuffer, BUFFER_SIZE, 0xD20F);

for (int i = 0; i < BUFFER_SIZE; i++) {

printf("aTxBuffer[%d] = 0x%X\n", i, aTxBuffer[i]);

}



/* Erase the NOR flash block */

if (HAL_NOR_Erase_Block(&hnor1, WRITE_READ_ADDR, NOR_BANK_ADDR) != HAL_OK)

{

Error_Handler();

}



/* Wait until NOR is ready */

if(HAL_NOR_GetStatus(&hnor1, NOR_BANK_ADDR, ERASE_TIMEOUT) != HAL_NOR_STATUS_SUCCESS)

{

Error_Handler();

}



/* Write data to the NOR memory */

for (uwIndex = 0; uwIndex < BUFFER_SIZE; uwIndex++)

{

if (HAL_NOR_Program(&hnor1, (uint32_t *)(NOR_BANK_ADDR + WRITE_READ_ADDR + 2 * uwIndex), &aTxBuffer[uwIndex]) != HAL_OK)

{

Error_Handler();

}



/* Check the status after each write operation */

if(HAL_NOR_GetStatus(&hnor1, NOR_BANK_ADDR, PROGRAM_TIMEOUT) != HAL_NOR_STATUS_SUCCESS)

{

Error_Handler();

}

}



/* Read data back from NOR flash */

if(HAL_NOR_ReadBuffer(&hnor1, NOR_BANK_ADDR + WRITE_READ_ADDR, aRxBuffer, BUFFER_SIZE) != HAL_OK)

{

Error_Handler();

}



/* Checking data integrity */

uwWriteReadStatus = Buffercmp(aTxBuffer, aRxBuffer, BUFFER_SIZE);



if (uwWriteReadStatus != PASSED)

{

/* Toggle the LED connected to GPIOI Pin 8 to indicate an error */

while(1)

{

HAL_GPIO_TogglePin(GPIOI, GPIO_PIN_8);

HAL_Delay(500);

}

}

else

{

// Optionally, indicate success by turning on an LED or similar

HAL_GPIO_WritePin(GPIOI, GPIO_PIN_8, GPIO_PIN_SET);

}



/* Infinite loop */

while (1)

{

}

}



/* Helper Functions ----------------------------------------------------------*/



/* Function to fill the buffer with test data */

static void Fill_Buffer(uint16_t *pBuffer, uint32_t uwBufferLenght, uint16_t uwOffset)

{

uint16_t tmpIndex = 0;



/* Put in global buffer different values */

for (tmpIndex = 0; tmpIndex < uwBufferLenght; tmpIndex++ )

{

pBuffer[tmpIndex] = tmpIndex + uwOffset;

}

}



/* Function to compare two buffers */

static TestStatus Buffercmp(uint16_t* pBuffer1, uint16_t* pBuffer2, uint16_t BufferLength)

{

while (BufferLength--)

{

if (*pBuffer1 != *pBuffer2)

{

return FAILED;

}

pBuffer1++;

pBuffer2++;

}

return PASSED;

}

HAL_StatusTypeDef MX_FMC_Init(void)

{

FMC_NORSRAM_TimingTypeDef Timing = {0};



hnor1.Instance = FMC_NORSRAM_DEVICE;

hnor1.Extended = FMC_NORSRAM_EXTENDED_DEVICE;

hnor1.Init.NSBank = FMC_NORSRAM_BANK1;

hnor1.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;

hnor1.Init.MemoryType = FMC_MEMORY_TYPE_NOR;

hnor1.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16;

hnor1.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;

hnor1.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;

hnor1.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;

hnor1.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE;

hnor1.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;

hnor1.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;

hnor1.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_ENABLE;

hnor1.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;

hnor1.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;

hnor1.Init.WriteFifo = FMC_WRITE_FIFO_DISABLE;

hnor1.Init.PageSize = FMC_PAGE_SIZE_NONE;



Timing.AddressSetupTime = 15;

Timing.AddressHoldTime = 15;

Timing.DataSetupTime = 255;

Timing.BusTurnAroundDuration = 15;

Timing.CLKDivision = 16;

Timing.DataLatency = 17;

Timing.AccessMode = FMC_ACCESS_MODE_A;



if (HAL_NOR_Init(&hnor1, &Timing, NULL) != HAL_OK)

{

Error_Handler();

}



/* Read & Check the NOR device IDs */

if (HAL_NOR_Read_ID(&hnor1, &NOR_Id) != HAL_OK)

{

/* NOR read ID Error */

return NOR_STATUS_READ_ID_ERROR;

}



/* Test the NOR ID correctness */

if ((NOR_Id.Manufacturer_Code != MANUFACTURER_CODE) ||

(NOR_Id.Device_Code1 != DEVICE_CODE1) ||

(NOR_Id.Device_Code2 != DEVICE_CODE2) ||

(NOR_Id.Device_Code3 != DEVICE_CODE3))

{

/* NOR ID not correct */

return NOR_STATUS_ID_ERROR;

}



printf("Manufacturer Code: 0x%X\n", NOR_Id.Manufacturer_Code);

printf("Device Code 1: 0x%X\n", NOR_Id.Device_Code1);

printf("Device Code 2: 0x%X\n", NOR_Id.Device_Code2);

printf("Device Code 3: 0x%X\n", NOR_Id.Device_Code3);



return HAL_OK;

}

1 ACCEPTED SOLUTION

Accepted Solutions

@jr_engr_mbed wrote:

After successfully testing read, write, and erase functions in CubeIDE,



@jr_engr_mbed wrote:

I created a loader that appears to be working correctly. I tested this by programming a bin file of a GPIO example at 0x60000000 and verified its functionality.

Is this the correct approach?   


If you succeeded with your own loader you can go ahead. Just noticed you are using the old tool STLink-Utility, I suggest to use STM32CubeProgrammer instead. See how you can add your loader in it in this tread.

Also, this article as it may help you.

 


Additionally, I need guidance on how to implement image data in NOR Flash for TouchGFX. Where should I make the necessary changes to see the results on the display?

I suggest to open a new thread regarding TouchGFX.

 

 

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

View solution in original post

6 REPLIES 6
SofLit
ST Employee

Hello @jr_engr_mbed ,

First, in next time please paste your code using </> button. Review the tips on how to post a thread here.

I've edited your post then.

Second, what if you disable the cache? do you have the same behavior?

 

 

 

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

Subject: NOR Flash Testing Update and Questions

Hi [SofLit_st employee],

Thank you for guiding me on how to post code. I wanted to provide you with an update. I was able to see the TX buffer and RX buffer data at the address 0x60000000. I believe this indicates that I am successfully writing and reading data from the NOR flash.

I set breakpoints before the erase, write, and read operations. When I reached the erase function, I saw 0xFFFFFFFF, and I observed data in the TX and RX buffers. Could you please confirm if this indicates that the NOR flash is functioning correctly? This is my first time working with NOR flash and FMC, so I want to make sure everything is as expected.

I also have a few questions:

  1. TX and RX Buffer Addresses: Why are the addresses of the TX and RX buffers showing as 0x24000078?
  2. Target Not Responding: I'm encountering an error that says "target not responding" when I place a breakpoint at the Erase_Chip function. Could you please help me understand why this might be happening?
  3. next how to take this for creating external loader to combine with my touchgfx project.?

I’ve attached all relevant images and code for your reference.Thank you for your assistance!

Best regards,
[jr_mbed_engr

Screenshot (1295).png

]

>> "target not responding"

Tends to be indicative that you've crash the core, or it's stalling with wait-states trying to access a memory that isn't responding, or timeout is longer than the debugger is willing to wait around.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

 

  1. Hi Tesla Delorean,

 

Thank you for your prompt response. When I debug without breakpoints, I don't encounter the "target not responding" error.,shall I confirm that my flash memory can perform read, write, and erase operations successfully, and can be used as a BSP for creating an external loader to store my TouchGFX assets?

 

Following your guidance from the previous post, I've made these adjustments. How should I proceed from here? Should I keep this  same project file for creating loader by including loader.c src.c loader.h and generate Elf.file? Right 

Hi,

After successfully testing read, write, and erase functions in CubeIDE, I moved forward without following all the steps in EWARM. Instead, I used a similar example( M29W128GH) from GitHub for MT28EW01GABA specifically the FMC_norflash example, which I imported into EWARM. I modified the def.c file according to the memory datasheet, updating the size and page read size from 16MB to 32MB. After building the project, I created a loader that appears to be working correctly. I tested this by programming a bin file of a GPIO example at 0x60000000 and verified its functionality.

Is this the correct approach? Since the loader.c file is similar to my tested application code using the HAL library, should I proceed with this loader to store my TouchGFX images? Additionally, I need guidance on how to implement image data in NOR Flash for TouchGFX. Where should I make the necessary changes to see the results on the display?

Screenshot (1331).png

Screenshot (1332).png

  


@jr_engr_mbed wrote:

After successfully testing read, write, and erase functions in CubeIDE,



@jr_engr_mbed wrote:

I created a loader that appears to be working correctly. I tested this by programming a bin file of a GPIO example at 0x60000000 and verified its functionality.

Is this the correct approach?   


If you succeeded with your own loader you can go ahead. Just noticed you are using the old tool STLink-Utility, I suggest to use STM32CubeProgrammer instead. See how you can add your loader in it in this tread.

Also, this article as it may help you.

 


Additionally, I need guidance on how to implement image data in NOR Flash for TouchGFX. Where should I make the necessary changes to see the results on the display?

I suggest to open a new thread regarding TouchGFX.

 

 

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.