本帖最后由 ylslib 于 2018-4-30 14:36 编辑
3.3 示例3.3.1 程序描述 (1)首先将地址 0x20020000(SRAM1)处开始的 128 字节初始化为 0x55。
(2)将 Flash 中的 128 字节的常量数组 aSRC_Const_Buffer 拷贝到 SRAM1 地址 0x20020000(pBuffer)。
(3)配置并使能 DMA,通过 DMA 将数据从 SRAM1 的地址 0x20020000 处拷贝到 DTCM RAM 中的数组 aDST_Buffer 中。
(4)将 Flash 中的数组 aSRC_Const_Buffer 与 DMA 读出的数组 aDST_Buffer 进行比较。 显然,这个例子中的 cache 一致性问题, 展示的是上面(图3.1)的第一种情况。也就是在 Write-back 策略下,CPU 先去更新相应的 cache-line,然后 DMA 去访问对应的内存,从而导致数据不一致的现象。
程数据的传输流程和路径如下图所示:
图3.3 Cache 示例数据传输框图
3.3.2 复现 cache 一致性问题 我们先来按照示例要求编写代码,复现 cache 一致性问题。有些人可能会疑惑,变量数据怎么放到 Flash、SRAM1、DTCM?实际上,可以通过一些相关的配置文件进行设置,比如 icf 文件、scatter 文件等,当然,这跟所使用开发环境和编译工具链有关。
本文所使用的环境是 IAR,其链接文件 *.icf 如下:
然后将 aSRC_Const_Buffer 数组定义为常量,即可分配到 RO 区域,aDST_Buffer 定义为普通的全局变量或静态变量即可,因为内存区域从 0x20000000 开始,也就是 DTCM RAM。
好了,代码主体部分如下:
(完整的代码可以在 http://download.csdn.net/download/luckydarcy/10104739 下载) - #define SRAM1_ADDRESS_START (0x20020000UL)
- static const uint32_t aSRC_Const_Buffer[BUFFER_SIZE] =
- {
- 0x01020304, 0x05060708, 0x090A0B0C, 0x0D0E0F10,
- 0x11121314, 0x15161718, 0x191A1B1C, 0x1D1E1F20,
- 0x21222324, 0x25262728, 0x292A2B2C, 0x2D2E2F30,
- 0x31323334, 0x35363738, 0x393A3B3C, 0x3D3E3F40,
- 0x41424344, 0x45464748, 0x494A4B4C, 0x4D4E4F50,
- 0x51525354, 0x55565758, 0x595A5B5C, 0x5D5E5F60,
- 0x61626364, 0x65666768, 0x696A6B6C, 0x6D6E6F70,
- 0x71727374, 0x75767778, 0x797A7B7C, 0x7D7E7F80
- };
- static uint32_t aDST_Buffer[BUFFER_SIZE];
- int main(void)
- {
- uint32_t counter = 0;
- uint32_t *pBuffer = (uint32_t*)SRAM1_ADDRESS_START;
- if (HAL_Init() != HAL_OK)
- {
- Error_Handler();
- }
- /* Initialize LEDs */
- BSP_LED_Init(LED1);
- /* Configure the system clock to 216 MHz */
- SystemClock_Config();
- BSP_LCD_Config();
- /* Set to 1 if an transfer error is detected */
- transferErrorDetected = 0;
- /* Fill 128 bytes with 0x55 pattern */
- memset((uint8_t*)SRAM1_ADDRESS_START, 0x55, sizeof(aSRC_Const_Buffer));
- /* TODO:Enable MPU and change SRAM region attribute
- * set write-back policy on SRAM */
- MPU_Config();
- /* Enable Data cache */
- SCB_EnableDCache();
- /* Copy data from Flash to SRAM by CPU */
- for (counter = 0; counter < (sizeof(aSRC_Const_Buffer)/4); counter++)
- {
- *pBuffer++ = aSRC_Const_Buffer[counter];
- }
- //* Configure and enable the DMA stream for Memory to Memory transfer */
- DMA_Config();
- /* Wait for DMA end-of-transfer */
- while(TransferCompleteFlag == RESET)
- {
- }
- /* Check data integrity*/
- pBuffer = (uint32_t*)&aDST_Buffer;
- for(counter = 0; counter <(sizeof(aSRC_Const_Buffer)/4); counter++)
- {
- if(aSRC_Const_Buffer[counter] != *pBuffer)
- {
- compareErrorDetected++;
- }
- pBuffer++;
- }
- if (compareErrorDetected != 0)
- {
- /* Toggle LED1 */
- BSP_LED_Off(LED1);
- compareErrorDetected = 0;
- BSP_LCD_DisplayStringAtLine(10, (uint8_t *)" Data comparation failed! ");
- }
- else
- {
- /* Turn LED1 on */
- BSP_LED_On(LED1);
- BSP_LCD_DisplayStringAtLine(10, (uint8_t *)" Data comparation success! ");
- }
- while (1)
- {
- }
- }
- static void MPU_Config(void)
- {
- /* Disable MPU */
- MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
- /* Configure RAM region as Region N°0, 256kB of size and R/W region */
- MPU->RNR = SRAM1_REGION_NUMBER;
- MPU->RBAR = SRAM1_ADDRESS_START;
- /* Write-Back policy */
- MPU->RASR = SRAM1_SIZE | MPU_RASR_C_Msk | MPU_RASR_B_Msk | SRAM1_ACCESS_PERMISSION | 1<<MPU_RASR_TEX_Pos;
- /* Enable MPU */
- MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;
- }
为了确保 aSRC_Const_Buffer 在 Flash,aDST_Buffer 在 DTCM,我们可以在编译完之后查看 *.map 文件,如下:
图3.4 检查常量和变量分配情况
下载到 STM32F769I-DISCO 板子上,显然,由于此时开启了 D-Cache,会出现数据不一致的现象,执行结果如下所示:
图3.5 Cache 数据不一致
|