硬汉嵌入式论坛

 找回密码
 立即注册
查看: 28386|回复: 20
收起左侧

[有问必答] 请教一下,如何使用STM32F4 的CCM RAM??

[复制链接]

2

主题

27

回帖

2

积分

新手上路

积分
2
发表于 2014-5-20 22:04:05 | 显示全部楼层 |阅读模式
最近在使用F4时,开的资源比较多,编译提示内存不足,后来统计了下,超过128K就会提示内存不足
而F4里有192K RAM,这样的话,那个64K的CCM RAM没有被用起来。
请问如何把CCM RAM利用起来?如何能把数组定义到CCM区?
请大神指点[s:148]
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2014-5-22 10:21:00 | 显示全部楼层
直接用个指针,指向这个地址就行,然后就可以使用了。
回复

使用道具 举报

2

主题

27

回帖

2

积分

新手上路

积分
2
 楼主| 发表于 2014-5-22 23:10:42 | 显示全部楼层

回 eric2013 的帖子

eric2013:直接用个指针,指向这个地址就行,然后就可以使用了。 (2014-05-22 10:21)
难道必须用地址一个个去指定吗,而不能用让编译器去连接到这个区吗
回复

使用道具 举报

116

主题

800

回帖

1148

积分

至尊会员

积分
1148
QQ
发表于 2014-5-26 09:01:19 | 显示全部楼层
貌似地址不连续的,编译器无法自动分配
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2014-5-26 12:57:49 | 显示全部楼层

Re:回 eric2013 的帖子

159hjx:

难道必须用地址一个个去指定吗,而不能用让编译器去连接到这个区吗

也可以在这里设置:
1.png
回复

使用道具 举报

116

主题

800

回帖

1148

积分

至尊会员

积分
1148
QQ
发表于 2014-5-29 10:41:59 | 显示全部楼层
可以同时打勾吗?那样编译器会自动分配不?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2014-5-29 10:43:07 | 显示全部楼层

回 jcx0324 的帖子

jcx0324:可以同时打勾吗?那样编译器会自动分配不? (2014-05-29 10:41) 
是的,好像是优先使用IRAM1,用完了就用2
回复

使用道具 举报

2

主题

27

回帖

2

积分

新手上路

积分
2
 楼主| 发表于 2014-6-6 23:04:09 | 显示全部楼层
不过从我的使用来看,好像不是 IRAM1 , 2优先使用的问题。
你若勾选使用IRAM2,则编译器会自动分配为 .ANY (+ZW +ZI ) 段到这里来,但这样编译的程序是不能运行的。
F4的 IRAM2 是不能分配 .ANY 的
回复

使用道具 举报

2

主题

27

回帖

2

积分

新手上路

积分
2
 楼主| 发表于 2014-6-6 23:08:01 | 显示全部楼层
从F4的相关资料和多次验证得到, F4 的IRAM1 可以分配 .ANY 段,并且F4的外设RAM 一定要分配到IRAM1里来(特别是DMA访问的RAM,绝对不能放到IRAM2), IRAM2 只能分配除外设用到RAM 以外的 (+ZW +ZI ) 段
回复

使用道具 举报

0

主题

3

回帖

0

积分

新手上路

积分
0
发表于 2014-8-12 21:47:26 | 显示全部楼层
请问楼主问题解决了吗?
回复

使用道具 举报

0

主题

3

回帖

0

积分

新手上路

积分
0
发表于 2014-8-12 21:55:21 | 显示全部楼层
“从F4的相关资料和多次验证得到, F4 的IRAM1 可以分配 .ANY 段,并且F4的外设RAM 一定要分配到IRAM1里来(特别是DMA访问的RAM,绝对不能放到IRAM2), IRAM2 只能分配除外设用到RAM 以外的 (+ZW +ZI ) 段”这里怎么分配呢?
回复

使用道具 举报

0

主题

3

回帖

0

积分

新手上路

积分
0
发表于 2014-8-12 23:11:07 | 显示全部楼层
如果勾选了IRAM2,通过查看map可以知道优先使用IRAM2,也就是64K那部分,貌似很危险,不能直接这样做。
回复

使用道具 举报

0

主题

3

回帖

0

积分

新手上路

积分
0
发表于 2017-4-7 19:34:12 | 显示全部楼层
IRAM2的64k只能由cpu通过Dbus访问,
外设不能访问,
keil勾选,编译器自动分配可能会把外设访问RAM分配进来
回复

使用道具 举报

20

主题

249

回帖

309

积分

高级会员

积分
309
发表于 2017-4-7 22:27:53 | 显示全部楼层
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\\config\\ide\\IcfEditor\\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
define symbol __ICFEDIT_region_ROM_end__   = 0x080FFFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__   = 0x2001FFFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x10000;
define symbol __ICFEDIT_size_heap__   = 0x500;
/**** End of ICF editor section. ###ICF###*/

define symbol __region_RAM1_start__ = 0x10000000;
define symbol __region_RAM1_end__   = 0x1000FFFF;

define memory mem with size = 4G;
define region ROM_region   = mem:[from __ICFEDIT_region_ROM_start__   to __ICFEDIT_region_ROM_end__];
define region RAM_region   = mem:[from __ICFEDIT_region_RAM_start__   to __ICFEDIT_region_RAM_end__];
define region RAM1_region  = mem:[from __region_RAM1_start__   to __region_RAM1_end__];

define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };
define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };

initialize by copy { readwrite };
do not initialize  { section .noinit };

place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };

place in ROM_region   { readonly };
place in RAM_region   { readwrite,block HEAP};
place in RAM1_region  { block CSTACK };



在IAR下可以使用上面的配置文件即可。定义了CCM 64K放CSTACK。

2017-04-07_223112.png
回复

使用道具 举报

5

主题

109

回帖

124

积分

初级会员

积分
124
发表于 2017-11-2 14:35:29 | 显示全部楼层
我们知道STM32F4当中有个CCM内存,如图所示,这个内存是挂在D总线上直接和内核相连,因此除了内核之外谁都不能访问,那么我们怎么将其利用起来呢?网上这个资料还真的很少,今天我就给大家分享一下,献给那些还不知道的人,如有错漏,还请指正。



首先,我们可以使用Keil的设置选项,将IRAM2打勾,让编译器选择什么时候使用这个内存。显然,我们还可以将这两个地址修改一下,将IRAM1改为0x10000000,这样,编译器就会优先分配CCM内存。



我们来看看结果,在MAP文件中,表明确实使用了这段内存,但是因为我们使用的内存较少, 还没有用到CCM。



这种自动分配的方式有什么问题呢?这段内存是内核专有的,除了内核任何其它总线都不能访问,这就意味着,一旦编译器将数据分配到CCM中,而同时使用了DMA访问,显然会出问题。

于是我们就想到了自己分配这段内存,__attribute__((at(address)))这个语句就是专门干这事的,然后我们可以这么做:

    [li]int vat[10] __attribute__((at(0x10000000))) = {1,2,3,4,5,6,7,8,9,10};[/li]
复制代码

再次编译以后,发现确实如我们所愿,我们将一段数据放在在了CCM内存中:

    [li]    Execution Region RW_IRAM2 (Base: 0x10000000, Size: 0x00000028, Max: 0x00010000, ABSOLUTE)
    [/li][li]
    [/li][li]    Base Addr    Size         Type   Attr      Idx    E Section Name        Object
    [/li][li]
    [/li][li]    0x10000000   0x00000028   Data   RW            7    .ARM.__AT_0x10000000  main.o
    [/li][li][/li]
复制代码

太好了,那么我们能不能将FreeRTOS的数据放进CCM中呢?将FreeRTOS要使用的内存全部移到CCM中,使其成为专有内存,显然会提高FreeRTOS的运行速度。

那么怎么放?首先我们想到了heap4.c这个文件当中有这么一段:

    [li]/* Allocate the memory for the heap. */
    [/li][li]#if( configAPPLICATION_ALLOCATED_HEAP == 1 )
    [/li][li]        /* The application writer has already defined the array used for the RTOS
    [/li][li]        heap - probably so it can be placed in a special segment or address. */
    [/li][li]        extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
    [/li][li]#else
    [/li][li]        static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
    [/li][li]#endif /* configAPPLICATION_ALLOCATED_HEAP */[/li]
复制代码
这是FreeRTOS中堆内存的分配,我们可以加入__attribute__将其放进CCM中,这样做没有问题,但是去修改FreeRTOS的源代码显然不是明智之举。事到如今,我们只能自己定义链接器的储存器映射了。

修改Keil的Linker选项,我们把Use Memory Layout from Targer Dialog的钩去掉。



然后在Objects的目录中找到一个后缀为sct的文件,打开之后如图所示:



由于我们只需要将RTOS的数据放入CCM中,于是我们可以这样修改,CCM_IRAM的名字是我自己取的,你可以改成任何你喜欢的,比如什么LOVEYOU之类的:




然后在链接器中选择我们自己的文件:



现在,映像文件变成了这样:



是不是很简单呢?系统堆栈仍然在主内存中,而FreeRTOS的堆内存已经移到了CCM中,由于互不影响,这里我分配了50K的空间专门给FreeRTOS使用。我们甚至还可以配置MPU将这段内存配置为特权级,避免一般任务修改等等,怎么使用,那就是你的事了。



原文出处
回复

使用道具 举报

356

主题

2180

回帖

3253

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3253
发表于 2017-11-13 09:53:43 | 显示全部楼层

回 打洞者 的帖子

打洞者:我们知道STM32F4当中有个CCM内存,如图所示,这个内存是挂在D总线上直接和内核相连,因此除了内核之外谁都不能访问,那么我们怎么将其利用起来呢?网上这个资料还真的很少,今天我就给大家分享一下,献给那些还不知道的人,如有错漏,还请指正。



首先,我们可以 .. (2017-11-02 14:35)
非常棒!

我有个简单的用法,一般用到大RAM都是emwin和RTOS。emWin中设定RAM比较简单,那么就把那个64K CCM指定给emWin就好了。CCM被完全占用了,其他的数据自然就不会到其他RAM了。
回复

使用道具 举报

0

主题

3

回帖

10

积分

新手上路

积分
10
发表于 2018-3-27 11:58:18 | 显示全部楼层
caicaptain2 发表于 2017-11-13 09:53
非常棒!

我有个简单的用法,一般用到大RAM都是emwin和RTOS。emWin中设定RAM比较简单,那么就把那个64K C ...

你好!
请教一下, 如何把64k的CCM指定给WMWIN呢?
我勾选了这里IRAM2, 然后指定CCM的地址0x10000000给EMWIN, 分配64k.结果不行哦, 是不是缺了什么步骤?
可以说明一下吗>?


回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2018-3-27 12:16:32 | 显示全部楼层
队长给我球 发表于 2018-3-27 11:58
你好!
请教一下, 如何把64k的CCM指定给WMWIN呢?
我勾选了这里IRAM2, 然后指定CCM的地址0x10000000给EMW ...

GUIConf.c文件

  1. #include "GUI.h"
  2. #include "bsp.h"

  3. /*********************************************************************
  4. *
  5. *       Defines
  6. *
  7. **********************************************************************
  8. */
  9. //
  10. // Define the available number of bytes available for the GUI
  11. //
  12. #define EX_SRAM   0  /*1 used extern sram, 0 used internal sram */

  13. #if EX_SRAM
  14. #define GUI_NUMBYTES  (1024*1024*2)
  15. #else
  16. #define GUI_NUMBYTES  (64*1024)
  17. #endif

  18. /* Define the average block size */
  19. #define GUI_BLOCKSIZE 0x80

  20. static U32 aMemory[GUI_NUMBYTES / 4] __attribute__((at(0x10000000)));

  21. /*********************************************************************
  22. *
  23. *       Public code
  24. *
  25. **********************************************************************
  26. */
  27. /*********************************************************************
  28. *
  29. *       GUI_X_Config
  30. *
  31. * Purpose:
  32. *   Called during the initialization process in order to set up the
  33. *   available memory for the GUI.
  34. */
  35. void GUI_X_Config(void)
  36. {
  37. #if EX_SRAM
  38.         static U32 *aMemory;
  39.         aMemory = (U32 *)EXT_SRAM_ADDR;
  40.        
  41.         /*  Assign memory to emWin */
  42.         GUI_ALLOC_AssignMemory(aMemory, GUI_NUMBYTES);
  43.         GUI_ALLOC_SetAvBlockSize(GUI_BLOCKSIZE);
  44. #else       
  45.         /* 32 bit aligned memory area */

  46.         /*  Assign memory to emWin */
  47.         GUI_ALLOC_AssignMemory(aMemory, GUI_NUMBYTES);
  48.         GUI_ALLOC_SetAvBlockSize(GUI_BLOCKSIZE);
  49. #endif
  50. }
复制代码


回复

使用道具 举报

2

主题

569

回帖

575

积分

金牌会员

积分
575
发表于 2018-5-13 15:44:59 | 显示全部楼层
感谢eric2013版主大神,把CCM划分为EMWIN专属,已经用上了。
回复

使用道具 举报

5

主题

212

回帖

227

积分

高级会员

积分
227
发表于 2018-5-14 13:19:04 | 显示全部楼层
好帖子,涨经验了
回复

使用道具 举报

1

主题

25

回帖

28

积分

新手上路

积分
28
发表于 2019-6-12 12:00:34 | 显示全部楼层
打洞者 发表于 2017-11-2 14:35
我们知道STM32F4当中有个CCM内存,如图所示,这个内存是挂在D总线上直接和内核相连,因此除了内核之外谁都 ...

牛人呀。佩服。好文章。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-12 16:07 , Processed in 0.057683 second(s), 33 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表