2025-09-24 11:25 AM
I am using an STM32H743 FMC to connect to the FPGA to do data transfer. (SRAM type with 16-bit data. I tried this on an STM32F429 and the test was successful)
The test is to send some amount of data to the FPGA through FMC.
The code is quite simple. Write some data to 0x6000 0000 and check if the FPGA can get the data correctly.
My discovery is that if only a small amount of data has been sent and chip select signal FMC_NE1 will remain high and no waveform can be observed...
Send 100 data and FMC_NE1 remains high
If I send lots of data(for example, 10000 data) then FPGA can receive data correctly, but the data FPGA receives starts from 2020(this number is also random, some time 1820 some time 3020, etc)
This phenomenon does not happen on F429... If I send 10 data and the FPGA can receive 10 data correctly...
2025-09-24 11:52 AM - edited 2025-09-24 11:54 AM
I wonder whether it is related to some sort of cache coherency problem since 0x6000_0000 address is marked as "Normal" and "Write back, write allocate cache attribute". You can try adding an MPU entry for this address range and mark this range as non-cached. If you want this region cached, you can also use the SCB_CleanDCache_by_Addr() to flush the data you wrote from the cache. Size argument to this API which is in bytes should be multiples of cache line size, like multiples of 32 bytes.
Double check the FMC clock configuration, if you are using two different CubeMX configuration files(.ioc) for STM32F and STM32H. You can also compare the FMC and RCC register setup to make sure both STM32F and STM32H are configured similarly.
2025-09-24 12:25 PM - edited 2025-09-24 12:33 PM
Hello @snkparty1 ,
If you need to communicate with a FPGA over FMC you need to configure the region at that address (in your case 0x6xxx xxxx) as Device or Strongly-ordred using the MPU.
Try this MPU config, just put the size of the FPGA region:
static void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct;
/* Disable the MPU */
HAL_MPU_Disable();
/* Configure the MPU as Strongly ordered for not defined regions */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x00;
MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x87;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* Enable the access to 0x60000000 address keeping the Strongly ordered config */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x60000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_<Size Region>;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.SubRegionDisable = 0x0;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* Enable the MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}