STM32H7's FMC peripheral does not work properly when DCACHE is enabled [ST official application note]
[Copy link]
Note PreviewPreface Some time ago, I received a question from a customer. The customer described that when using the FMC of STM32H7, if DCACHE is enabled, it does not work properly. The data is not written to the memory outside the FMC, and there is no waveform jump when measuring the FMC interface. But it works normally without DCACHE. In fact, for this problem, it is easy to understand if you understand the architecture of STM32H7. Let's take a look at what exactly makes the customer feel that the FMC does not work properly after enabling DCACHE. STM32H7 Architecture The following is the part related to FMC in the STM32H7 architecture diagram. As can be seen from the figure, STM32H7 is based on the Cortex-M7 core, and the internal Cortex-M7 core has a 16KB DCACHE and a 16KB ICACHE. The core is connected to the 64-bit AXI bus matrix through the AXIM bus, and is connected to the FMC interface through this bus matrix. That is to say, when DCACHE is enabled, the operation of the memory on the FMC interface is through the core cache (CACHE). The benefit of enabling CACHE is that it can increase the speed of the core accessing the memory. Why can using cache increase the speed? Because when operating the cacheable memory, the core does not directly operate these memories every time, but reads data from the cache, or writes the data to the cache first. Seeing this, do you think it is somewhat related to the phenomenon mentioned by the previous customer? Cache operation Simply put, there are two ways for cache to work: write back and write through. Write back means that the data is only written to the cache, and then synchronized to the next level of memory later. Write through means that the data is written to the cache and the next level of memory at the same time every time. This method can solve the problem of data inconsistency, but it will also consume more bus access. The cache operation mode has a default setting after the cache is enabled. That is, the following table: Please refer to AN4839 for more information on the use of Cache. Problem Analysis and Solution The customer connected an FPGA through the NOR storage controller of FMC. The mapped address range is 0x60000000~0x7FFFFFFF. As can be seen from the above figure, its default cache operation mode is WBWA (write-back write allocation). In other words, when DCACHE is turned on, all operations on this address range will go to the cache first. This also explains why the customer found that the data was not actually written to the external memory. The customer's data needs to be written to the FPGA in real time for calculation. So for this application scenario, the write-back setting is not suitable. For this customer's application, you can configure it through the MPU and set the CACHE in the address range of 0x60000000~0x7FFFFFFF to write-through mode, so that the data will be written to the FPGA in real time. For this situation, we can solve this problem through the MPU. Through the MPU, you can configure the access rights and cache strategies of different memory spaces. The HAL library provides corresponding functions and routines. Refer to the routines and use the following code to solve the customer's problem. Data is written directly to the FPGA every time, instead of being cached in the kernel's DCACHE. - //MPU related define #define FPGA_ADDRESS_START (0x60000000UL) #define FPGA_SIZE MPU_REGION_SIZE_64MB #define FPGA_REGION_NUMBER MPU_REGION_NUMBER0 #define FPGA_ACCESS_PERMISSION MPU_REGION_FULL_ACCESS void MPU_Config(void) { MPU_Region_InitTypeDef MPU_InitStruct; /* Disable MPU */ HAL_MPU_Disable(); /* Configure FPGA region as Region N?, 64MB of size and R/W region */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.BaseAddress = FPGA_ADDRESS_START; MPU_InitStruct.Size = FPGA_SIZE; MPU_InitStruct.AccessPermission = FPGA_ACCESS_PERMISSION; MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; MPU_InitStruct.Number = FPGA_REGION_NUMBER; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /* Enable MPU */ HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); }
复制代码 Summary The use of CACHE can help us improve the performance of program execution, but it will also cause inconsistent data between cache and secondary memory and uncertain program execution time caused by buffer misses. Customers need to make choices based on actual applications. For data with high real-time requirements, you can use MPU to configure it as a write-through method as before, or put the data in DTCM RAM. In addition, in this article, only part of the storage area mapped by FMC is configured with MPU. In actual use, the properties of all used storage spaces (such as Flash, SRAM areas) should be configured according to actual conditions to avoid causing other problems. For details, please refer to AN4838. Download:
|