How to use FMC controller at H743ZI2?

Hi all,

I am testing for FMC controller by NUCLEO_H743ZI2 and mbed studio. The version of mbed is latest(5.15)
When I using HAL function call HAL_SRAM_Read_8b() then below error info appeared. I also try many of class to fix thread, mutex, EventQueue e.g… But all failed.

++ MbedOS Fault Handler ++
FaultType: HardFault
Context:
R0 : 00000003
R1 : 00000018
R2 : 08007D18
R3 : 08008D29
R4 : 240025F4
R5 : 00000001
R6 : 60000080
R7 : 24002750
R8 : 24006A0C
R9 : FFFFFFFF
R10 : 24004C3C
R11 : 00000000
R12 : 080102E9
SP : 240069F0
LR : 08007CED
PC : 08007CEC
xPSR : 61000000
PSP : 240069D0
MSP : 2407FF88
CPUID: 411FC271
HFSR : 40000000
MMFSR: 00000000
BFSR : 00000082
UFSR : 00000000
DFSR : 0000000B
AFSR : 00000000
BFAR : 60000080
Mode : Thread
Priv : Privileged
Stack: PSP
– MbedOS Fault Handler –
++ MbedOS Error Info ++
Error Status: 0x80FF013D Code: 317 Module: 255
Error Message: Fault exception
Location: 0x8007CEC
Error Value: 0x240026C0
Current Thread: application_unnamed_thread Id: 0x24004DBC Entry: 0x8009D51 StackSize: 0x1000 StackMem: 0x24005A48 SP: 0x240069F0
For more info, visit: mbedos-error
– MbedOS Error Info –

Below is the code I used:

#include “mbed.h”

Serial debug0(PD_8, PD_9);

InterruptIn button(PC_13);

volatile bool Read_flag;

SRAM_HandleTypeDef hsram1;

static void MX_GPIO_Init(void);
static void MX_FMC_Init(void);
static void Error_Handler(void);

uint8_t get_from_sram_3(uint32_t a);

uint32_t fsmc_addr;

uint8_t get_from_sram_3(uint32_t a)
{
uint8_t Sram_rx[0];

fsmc_addr = 0x60000000 | a;

HAL_SRAM_Read_8b(&hsram1, (uint32_t*)(0x60000000|a), Sram_rx, 1);

return Sram_rx[0];
}

void Get_8b()
{
debug0.printf(“Get_8b start\r\n”);

get_from_sram_3(0x80);
get_from_sram_3(0x81);
get_from_sram_3(0x82);
get_from_sram_3(0x83);

}

int main() {

MX_GPIO_Init();
MX_FMC_Init();

debug0.baud(115200);

Read_flag = false;

button.rise(Get_8b);

debug0.printf(“Start\r\n”);

while(1){}

}

void MX_GPIO_Init()
{
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
}

/* FMC initialization function */
static void MX_FMC_Init(void)
{

/* USER CODE BEGIN FMC_Init 0 */

/* USER CODE END FMC_Init 0 */

FMC_NORSRAM_TimingTypeDef Timing = {0};

/* USER CODE BEGIN FMC_Init 1 */

/* USER CODE END FMC_Init 1 */

/** Perform the SRAM1 memory initialization sequence
/
hsram1.Instance = FMC_NORSRAM_DEVICE;
hsram1.Extended = FMC_NORSRAM_EXTENDED_DEVICE;
/
hsram1.Init /
hsram1.Init.NSBank = FMC_NORSRAM_BANK1;
hsram1.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;
hsram1.Init.MemoryType = FMC_MEMORY_TYPE_SRAM;
hsram1.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_8;
hsram1.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;
hsram1.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;
hsram1.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
hsram1.Init.WriteOperation = FMC_WRITE_OPERATION_DISABLE;
hsram1.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;
hsram1.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;
hsram1.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
hsram1.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;
hsram1.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
hsram1.Init.WriteFifo = FMC_WRITE_FIFO_ENABLE;
hsram1.Init.PageSize = FMC_PAGE_SIZE_NONE;
/
Timing /
Timing.AddressSetupTime = 15;
Timing.AddressHoldTime = 15;
Timing.DataSetupTime = 255;
Timing.BusTurnAroundDuration = 15;
Timing.CLKDivision = 16;
Timing.DataLatency = 17;
Timing.AccessMode = FMC_ACCESS_MODE_A;
/
ExtTiming */

if (HAL_SRAM_Init(&hsram1, &Timing, NULL) != HAL_OK)
{
Error_Handler( );
}

/* USER CODE BEGIN FMC_Init 2 */

/* USER CODE END FMC_Init 2 */
}

void Error_Handler()
{
debug0.printf(“Initail SRAM fail\r\n”);

Do anyone have any idea how to implement the function?

Hi Terry,

This uint8_t Sram_rx[0]; doesn’t make sense to me, you should at least create 1-element array or to allocate a space with malloc or new.

Regards,
Desmond

Hi Desmond,

Because I did the varieties of test, so it have some dump in the code. I change the code you can see below:

#include "mbed.h"

Serial debug0(PD_8, PD_9);

InterruptIn button(PC_13);

SRAM_HandleTypeDef hsram1;

static void MX_GPIO_Init(void);
static void MX_FMC_Init(void);
static void Error_Handler(void);
/*
One time read 4 bytes by 8 bits data width
*/
bool get_from_sram_4(uint32_t addr,uint8_t* RX_data)
{
  return HAL_SRAM_Read_8b(&hsram1, (uint32_t*)(0x60000000|addr), RX_data, 4);
}

void Get_8b()
{
  uint8_t *ptr = new uint8_t[4]();

  debug0.printf("Get_8b start\r\n");

  if (get_from_sram_4(0x80,ptr))//address0x80~0x83
  {
    debug0.printf("Get_8b function success\r\n");
    debug0.printf("Byte 0=%X\r\n",*ptr);
    debug0.printf("Byte 1=%X\r\n",*(ptr+1));
    debug0.printf("Byte 2=%X\r\n",*(ptr+2));
    debug0.printf("Byte 3=%X\r\n",*(ptr+3));
  }
  else
    debug0.printf("Get_8b function fail\r\n");

  delete [] ptr;
}

int main() {

  MX_GPIO_Init();
  MX_FMC_Init();

  debug0.baud(115200);

  button.rise(Get_8b);

  debug0.printf("Start\r\n");

  while(1){}

}

void MX_GPIO_Init()
{
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOE_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOG_CLK_ENABLE();
}

/* FMC initialization function */
static void MX_FMC_Init(void)
{

  /* USER CODE BEGIN FMC_Init 0 */

  /* USER CODE END FMC_Init 0 */

  FMC_NORSRAM_TimingTypeDef Timing = {0};

  /* USER CODE BEGIN FMC_Init 1 */

  /* USER CODE END FMC_Init 1 */

  /** Perform the SRAM1 memory initialization sequence
  */
  hsram1.Instance = FMC_NORSRAM_DEVICE;
  hsram1.Extended = FMC_NORSRAM_EXTENDED_DEVICE;
  /* hsram1.Init */
  hsram1.Init.NSBank = FMC_NORSRAM_BANK1;
  hsram1.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;
  hsram1.Init.MemoryType = FMC_MEMORY_TYPE_SRAM;
  hsram1.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_8;
  hsram1.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;
  hsram1.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;
  hsram1.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
  hsram1.Init.WriteOperation = FMC_WRITE_OPERATION_DISABLE;
  hsram1.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;
  hsram1.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;
  hsram1.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
  hsram1.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;
  hsram1.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
  hsram1.Init.WriteFifo = FMC_WRITE_FIFO_ENABLE;
  hsram1.Init.PageSize = FMC_PAGE_SIZE_NONE;
  /* Timing */
  Timing.AddressSetupTime = 15;
  Timing.AddressHoldTime = 15;
  Timing.DataSetupTime = 255;
  Timing.BusTurnAroundDuration = 15;
  Timing.CLKDivision = 16;
  Timing.DataLatency = 17;
  Timing.AccessMode = FMC_ACCESS_MODE_A;
  /* ExtTiming */

  if (HAL_SRAM_Init(&hsram1, &Timing, NULL) != HAL_OK)
  {
    Error_Handler( );
  }

  /* USER CODE BEGIN FMC_Init 2 */

  /* USER CODE END FMC_Init 2 */
}

static void Error_Handler()
{
  debug0.printf("Initail SRAM fail\r\n");
}

When I push the bottom on H743ZI2, the result show:

++ MbedOS Error Info ++
Error Status: 0x80010133 Code: 307 Module: 1
Error Message: Mutex: 0x240021B4, Not allowed in ISR context
Location: 0x80109AD
Error Value: 0x240021B4
Current Thread: main Id: 0x24004424 Entry: 0x800CFB9 StackSize: 0x1000 StackMem: 0x24001170 SP: 0x2407FED4
For more info, visit: mbedos-error
– MbedOS Error Info –

The debug message:

debug0.printf("Get_8b start\r\n");

Even show on terminal…

Hi Terry,

printf() is not allowed in ISR because of -DMBED_TRAP_ERRORS_ENABLED=1 seeting in profiles.
That causes error Not allowed in ISR context.

Regards,
Desmond

Hi Desmond,

I reduced the code like below. It only left a HAL code and without printf() . But LD1 flash always and like before the condition of error.

int main() {

  MX_GPIO_Init();
  MX_FMC_Init();

  uint8_t data_out[4];

  HAL_SRAM_Read_8b(&hsram1, (uint32_t*)(0x60000000), data_out, 4);

  while(1){}

}

And I disassemble HAL_SRAM_Read_8b to analyze and found it will show fail at line debug0.printf(“5\r\n”);. It means I cannot get “5” and jump out mbed error message.

static HAL_StatusTypeDef HAL_SRAM_Read_8b_alpha(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint8_t *pDstBuffer, uint32_t BufferSize)
{
  uint32_t size;
  __IO uint8_t *psramaddress = (uint8_t *)pAddress;
  uint8_t * pdestbuff = pDstBuffer;
  HAL_SRAM_StateTypeDef state = hsram->State;

  debug0.printf("1\r\n");

  /* Check the SRAM controller state */
  if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED))
  { debug0.printf("2 ,%d\r\n",state);
    /* Process Locked */
    __HAL_LOCK(hsram);

    /* Update the SRAM controller state */
    hsram->State = HAL_SRAM_STATE_BUSY;
    debug0.printf("3\r\n");
    /* Read data from memory */
    for (size = BufferSize; size != 0U; size--)
    {
      debug0.printf("4\r\n");
      *pdestbuff = *psramaddress; debug0.printf("5\r\n");
      pdestbuff++;                debug0.printf("6\r\n");
      psramaddress++;             debug0.printf("7\r\n");
    }
    debug0.printf("8\r\n");
    /* Update the SRAM controller state */
    hsram->State = state;

    /* Process unlocked */
    __HAL_UNLOCK(hsram);
  }
  else
  {
    return HAL_ERROR;
  }

  return HAL_OK;
}  

The code I use on keil MDK is working. It must has a thing I don’t take care well. Could you give more tips to me?

Hi Terry,

What’s the error status this time? If Keil MDK works, I would try to check the optimization and memory alignment.

Hi Desmond,

Below are the information:

++ MbedOS Fault Handler ++

FaultType: HardFault

Context:
R0 : 60000000
R1 : 00000018
R2 : 08007C78
R3 : 080089D9
R4 : 2400216C
R5 : 24002320
R6 : 24002474
R7 : 00000001
R8 : 00000000
R9 : 00000000
R10 : 00000000
R11 : 00000000
R12 : 0800F771
SP : 24002150
LR : 08007C27
PC : 08007C2A
xPSR : 61000000
PSP : 240020E8
MSP : 2407FF88
CPUID: 411FC271
HFSR : 40000000
MMFSR: 00000000
BFSR : 00000082
UFSR : 00000000
DFSR : 0000000B
AFSR : 00000000
BFAR : 60000000
Mode : Thread
Priv : Privileged
Stack: PSP

– MbedOS Fault Handler –

++ MbedOS Error Info ++
Error Status: 0x80FF013D Code: 317 Module: 255
Error Message: Fault exception
Location: 0x8007C2A
Error Value: 0x240023E8
Current Thread: main Id: 0x240041D4 Entry: 0x800C8E1 StackSize: 0x1000 StackMem: 0x24001170 SP: 0x24002150
For more info, visit: mbedos-error
– MbedOS Error Info –

I used logic analyzer and found the controller have not worked also.
Below is FMC work normally on keil MDK. The code is from STM32cubeMX.

Below is the condition on mbed. CE don’t work correctly.

It looks like the SRAM module isn’t initialized correctly, have yore referred here?

Hi Desmond,

You are right. I did not trace MSPinit… Now I can see the initial reaction from IOs. Thank you very much.
But I encounter anther problem. Below waveform are the tests by using HAL_SRAM_Read_8b in different code.

HAL_SRAM_Read_8b(&sramHandle, (uint32_t *)0x60000000, pData, uwDataSize) != HAL_OK)
HAL_SRAM_Read_8b(&sramHandle, (uint32_t *)0x60000001, pData, uwDataSize) != HAL_OK)

This is I call twice HAL_SRAM_Read_8b in a time. The picture show whole waveform on keil. CE trigger twice and A0 from 0 to 1.

This is the condition on mbed and can find address bus meet some problem. If I call this function again, it will not reaction on IOs.

I got the return code always is HAL_OK on mbed. It is very strange.

And thank you for your time again.

Hi Terry,

I don’t really understand you question, are you saying HAL_SRAM_Read_8b() doesn’t work well when being called over than 3 times?

(uint32_t *)0x60000001 shouldn’t be used, the address should be 4-byte aligned.

Hi Desmond,

My question is I cannot execute HAL_SRAM_Read_8b() property over twice. Also the wave give wrong action. But I’m solving now. It is related to D-cache. I call SCB_DisableDCache() before HAL_SRAM_Read_8b(). And it’s work.
Thank you for your kind assistance.

Hi, using hsram1.Init.WriteOperation = FMC_WRITE_OPERATION_DISABLE; cause the faulting of Mbed you should use hsram1.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE; instead.