BSP

针对STM32F7系列平台的MPU,Cache特性,使用RT-Thread需要注意哪些问题?

发布于 2017-05-08 11:59:58
由于工作的需要,需要在STM32F7平台上进行开发。看了一下,RT-Thread的BSP下已经包含了STM32F7平台的移植,准备基于这个BSP进行后续的工作。感谢提供F7平台移植的大侠!

大致了解了一下STM32F7,除了外设和底层库的变化之外,最主要的是MPU和Cache特性的引入。之前还是单片机的开发思路,没有深入的了解过微处理器中MPU,Cache的特性;看了一些文档,越看越没底的感觉。想请教一下大家,在F7平台上使用RT-Thread的话,对于MPU和Cache的使用需要注意些什么?

因为了解不深,不知道该提哪些具体的问题,可能问题比较笼统,先问几个比较困惑、没有把握的问题:
1)用作RT-Thread的系统Heap的Memory,属性应该怎么设置?不设置Cacheable?
所有动态创建的线程,实际上都是分配在系统的Heap上的,包括任务堆栈。如果设置成Cacheable的话,因为任务切换的位置事先是不知道的,怎么保证数据一致性的问题?
2)如果线程中有针对Memory的操作,比如说rt_memcpy之类的,如果操作的是Cacheable的Memory的话,如果发生任务切换,怎样保证一致性问题?
以上两点从根本上来说应该是一个问题,就是任务切换时数据一致性的问题?

将系统的Heap设置成Non-Cacheable是不是就可以了?

3)我看RT-Thread的发布说明里,也提到了F7平台上的Cache特性,主要强调了使能Cache时,DMA操作的数据一致性问题。这个是否如一些应用笔记说的,在DMA操作的前后加入针对Cache的Clear,Invalidate之类的相关操作就可以解决?

4)很多文档提出了很多应用场景,也有一些指导性的原则。但针对使用了OS的系统来说,有没有相关的原则,比如说系统的Heap应该设置成什么属性?静态内存应该设置成什么属性?中断服务程序对于内存的操作有什么新的约束或限制?

5)F7是有D-Cache,I-Cache。OS层面和应用层面,要考虑I-Cache吗?

啰嗦了一堆,感觉完全不知道在说什么。就当是抛砖引玉,希望得到大家的指导。
SDRAM属性.png

查看更多

关注者
0
被浏览
4.2k
17 个回答
softwind
softwind 2017-05-08
还有就是F7的BSP中,关于MPU的部分,
  /* Configure the MPU attributes as WB for SDRAM */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0xC0000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_8MB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

HAL_MPU_ConfigRegion(&MPU_InitStruct);

/* Configure the MPU attributes as none-cache for 1MB SDRAM */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0xC0100000;
MPU_InitStruct.Size = MPU_REGION_SIZE_1MB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER2;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

HAL_MPU_ConfigRegion(&MPU_InitStruct)


然后系统的Heap是这样定义的:
#ifdef RT_USING_EXT_SDRAM
rt_system_heap_init((void*)EXT_SDRAM_BEGIN, (void*)EXT_SDRAM_END);
sram_init();
#else
rt_system_heap_init((void*)HEAP_BEGIN, (void*)HEAP_END);
#endif


也就是说把整个的外部SDRAM作为System Heap;但SDRAM又定义了两个具有不同的MPU属性Region,而且是Overlapped的,这是出于什么样的考虑?
bernard
bernard 2017-05-08
1. 尽量使用cache,这样才能加速代码执行效率;不管是静态还是heap,都全开cache;
2. cache一致性问题在于多硬件访问的情况,例如cpu访问(其他cpu访问),dma访问(通用dma、外设专用dma)。这个时候就要考虑一致性的问题,该flush就flush,或者invalid等等。
3. mpu,很早就有了,可以查看相关的arm芯片说明文档.
4. 注意下cache line大小的问题,这部分有的时候最好是做cache line对齐的
softwind
softwind 2017-05-08
1. 尽量使用cache,这样才能加速代码执行效率;不管是静态还是heap,都全开cache;
2. cache一致性问题在于多硬件访问的情况,例如cpu访问(其他cpu访问),dma访问(通用dma、外设专用dma)。这个时候就要考虑一致性的问题,该flush就flush,或者invalid等等。


1)如果没有多硬件访问,全开cache的话,不会影响任务切换,也就是说任务堆栈的数据一致性与cache无关?
2)只在多硬件访问的时候,需要考虑数据一致性的问题?


3. mpu,很早就有了,可以查看相关的arm芯片说明文档.
4. 注意下cache line大小的问题,这部分有的时候最好是做cache line对齐的

多谢bernard指点方向,我再看看相关文档。
softwind
softwind 2017-05-09
另外,考虑到DMA访问时数据一致性的问题,F7平台上的一些底层的驱动也需要改写?
比如说SD卡,以太网这些用到了DMA传输的外设驱动。
bernard
bernard 2017-05-09
另外,考虑到DMA访问时数据一致性的问题,F7平台上的一些底层的驱动也需要改写?
比如说SD卡,以太网这些用到了DMA传输的外设驱动。


of course
softwind
softwind 2017-05-09
另外,考虑到DMA访问时数据一致性的问题,F7平台上的一些底层的驱动也需要改写?
比如说SD卡,以太网这些用到了DMA传输的外设驱动。


of course


看来还有很多工作要做。多谢指教。
softwind
softwind 2017-05-09
1. 尽量使用cache,这样才能加速代码执行效率;不管是静态还是heap,都全开cache;
2. cache一致性问题在于多硬件访问的情况,例如cpu访问(其他cpu访问),dma访问(通用dma、外设专用dma)。这个时候就要考虑一致性的问题,该flush就flush,或者invalid等等。


1)全开cache的话,不会影响任务切换,也就是说任务堆栈的数据一致性与cache无关?
softwind
softwind 2017-05-09
或者说在OS或RT-Thread内核的层面需要考虑Cache和数据一致性的问题吗?
bernard
bernard 2017-05-09
按理说,OS层面应该要考虑cache line大小的。至于说cache与否与任务切换等的关系,那么这部分能加速尽量加速,特别是最好有TCM,能够让OS内核部分代码和CPU主频跑在一致频率上
softwind
softwind 2017-05-09
按理说,OS层面应该要考虑cache line大小的。至于说cache与否与任务切换等的关系,那么这部分能加速尽量加速,特别是最好有TCM,能够让OS内核部分代码和CPU主频跑在一致频率上


就是说主要是效率优化方面的问题。
那么当前rt-thread在F7平台上的实现(基于STM32F7 Disco平台的BSP),Cache全开的话,内核的安全性是不受影响的?主要是在设备驱动和应用层需要考虑多硬件访问的数据一致性问题?
softwind
softwind 2017-05-12
关于RT-Thread在STM32F7平台上的移植,还想请教一下,
在int mpu_init(void)函数中,对外部SDRAM的Memory属性的设置是有什么特别的考虑吗?
int mpu_init(void)
{
MPU_Region_InitTypeDef MPU_InitStruct;

/* Disable the MPU */
HAL_MPU_Disable();

/* Configure the MPU attributes as WT for SRAM */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x20010000;
MPU_InitStruct.Size = MPU_REGION_SIZE_256KB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

HAL_MPU_ConfigRegion(&MPU_InitStruct);

/* Configure the MPU attributes as WB for SDRAM */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0xC0000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_8MB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

HAL_MPU_ConfigRegion(&MPU_InitStruct);

/* Configure the MPU attributes as none-cache for 1MB SDRAM */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0xC0100000;
MPU_InitStruct.Size = MPU_REGION_SIZE_1MB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER2;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

HAL_MPU_ConfigRegion(&MPU_InitStruct);

/* Enable the MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
return 0;
}


SRAM设置成WT(Write Through)可以理解;
外部的SDRAM(8MB)全部用作系统的Heap,设置的属性是成WB(Write Back;No Write Allocate),为什么又单独划分出一块(1MB,而且是在中间位置),访问属性是NonCacheable。
[img]SDRAM属性.png[/img]
这样划分是出于什么样的考虑和应用场景?如果使用rt-thread的内存分配函数,应用程序获得的内存实际上可能具有不同的属性?
bernard
bernard 2017-05-12
none-cache适合做dma,只是说cpu访问效率变低了些,,,所以最终情况还是看实际需求
softwind
softwind 2017-05-12
none-cache适合做dma,只是说cpu访问效率变低了些,,,所以最终情况还是看实际需求


将空间划分为不同的属性在访问效率和数据安全性之间取得平衡,这点可以理解。

只是不明白rtthread在STM32F7-Disco平台上的这个BSP,8M的外部SDRAM已经初始化为System Heap,又在中间划分一段空间指定为NonCacheable的。这样System Heap空间就有了两种Cache属性,而且是地址不连续的。我的理解是,这段不同属性的空间是否应该放在8M空间的头或者尾比较合理呀?然后System Heap空间对应缩小。不然,用rt_malloc()得到的内存空间属性是不确定的。
jw__liu
jw__liu 2019-03-09
顶起等待大佬的回答。
HappyTime
HappyTime 2019-03-11
jw__liu 发表于 2019-3-9 11:10
顶起等待大佬的回答。


:P帮你一下 最近看到这个问题,也是云里雾里
我夏了夏天
我夏了夏天 认证专家 2019-03-11
HappyTime 发表于 2019-3-11 08:29
帮你一下 最近看到这个问题,也是云里雾里


还回答什么问题呀,很久的帖子了

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友