好了,昨天我们的RTOS已经跑起来了,相关的DRAM划分也说的比较清楚了,这里我主要实现内存分配,使用自带的微型库。
相关细节,主要参考ARM官方的doc,方法如下
1)进入如下地址
http://infocenter.arm.com/help/index.jsp
2)搜索关键字即可,如
__user_initial_stackheap
__initial_sp
__heap_base
__heap_limit
好了,这里需要指定堆栈,有两种方法
1)通过汇编代码
新建一个heap.S文件,内容如下
- ;-------------------------------------------------------------------------------
- ; 堆栈
- ;-------------------------------------------------------------------------------
- AREA |.text|, CODE, READONLY
-
-
- EXPORT __initial_sp
- __initial_sp EQU 0x30800000 ;STACK栈顶
- EXPORT __heap_base
- __heap_base EQU 0x30200000 ;HEAP起始地址
- EXPORT __heap_limit
- __heap_limit EQU 0x30600000 ;HEAP结束地址
-
- END
-
- ;-------------------------------------------------------------------------------
- ; 文件结束
- ;-------------------------------------------------------------------------------
主要依据如下,可参考中文资料
在ARM的文档中,右边目录可以找到位于:
ARM 软件开发工具--->RealView Development Suite---->Version 4.0 中文用户手册
2)通过分散加载描述文件
- LR_ROM1 0x30800000 0x2800000 { ; load region size_region
- RW_ROM1 0x30800000 0x2800000 { ; load address = execution address
- *.o (RESET, +First)
- .ANY (+RO +RW)
- }
- RW_RAM1 0x33000000 0x1000000 {
- .ANY(+ZI)
- }
-
- ARM_LIB_HEAP 0x30200000 EMPTY 0x00400000 {
-
- }
- ARM_LIB_STACK 0x30800000 EMPTY -0x00200000 {
-
- }
- }
主要依据,如下
----------------------------------------------------------------------------------------------------------------------------------------
重要提示,请看官方doc复制的原文
从 RVCT v2.x 及更低版本移植到 RVCT v4.0
在 RVCT 2.x 及更低版本中,__user_initial_stackheap() 的缺省实现使用符号 Image$$ZI$$Limit 的值。 如果链接器使用分散加载描述文件(使用 --scatter 命令行选项指定),则不会定义该符号;因此,如果使用的是分散加载描述文件,则必须重新实现__user_initial_stackheap(),否则,链接步骤将会失败。
另外,您也可以使用 __user_setup_stackheap()(而不是 __user_initial_stackheap())来升级源代码。
从 RVCT v3 移植到 RVCT v4.0
在 RVCT v3.x 和更高版本中,库包含更多的 __user_initial_stackheap() 实现,并且可通过分散加载描述文件中提供的信息自动选择正确的实现。 这意味着,如果使用的是分散加载文件,则不需要重新实现该函数。 有关详细信息,请参阅使用分散加载描述文件。
----------------------------------------------------------------------------------------------------------------------------------------
因为我在参考ARM文档之前,在网上看了一些前人的总结,基本上都要说需要自行实现__user_setup_stackheap(),其实这里我们可以看出来高版本的已经不需要了,很智能啊。在这以前我一直在用IAR,现在我算是知道使用ARM的工具可以获取到更多原滋原味的支持文档,对开发尤其是裸机开发帮助很大。
我的测试程序如下:
-
- /**
- * @brief malloc_test
- * @note 内存分配测试
- * @param none
- * @retval none
- */
- void malloc_test(void)
- {
- int *ptr1;
- int *ptr2;
- int *ptr3;
- int *ptr4;
- OS_ALLOC_SR();
-
- ptr1 = (int *)malloc(sizeof(int) * 10);
- if (ptr1) {
- OS_ENTER_CRITICAL();
- DEBUG1("Prt1 alloc at address: %x", (unsigned int)ptr1);
- OS_EXIT_CRITICAL();
- } else {
- DEBUG0("No enough memory!");
- }
- free(ptr1);
- DEBUG0("Ptr1 free!");
-
- ptr2 = (int *)malloc(sizeof(int) * 20);
- if (ptr2) {
- OS_ENTER_CRITICAL();
- DEBUG1("Prt2 alloc at address: %x", (unsigned int)ptr2);
- OS_EXIT_CRITICAL();
- } else {
- DEBUG0("No enough memory!");
- }
- free(ptr2);
- DEBUG0("Ptr2 free!");
-
- ptr3 = (int *)malloc(sizeof(int) * 10);
- if (ptr3) {
- OS_ENTER_CRITICAL();
- DEBUG1("Prt3 alloc at address: %x", (unsigned int)ptr3);
- OS_EXIT_CRITICAL();
- } else {
- DEBUG0("No enough memory!");
- }
-
-
- ptr4 = (int *)malloc(sizeof(int) * 20);
- if (ptr4) {
- OS_ENTER_CRITICAL();
- DEBUG1("Ptr4 alloc at address: %x", (unsigned int)ptr4);
- OS_EXIT_CRITICAL();
- } else {
- DEBUG0("No enough memory!");
- }
- free(ptr3);
- free(ptr4);
- DEBUG0("Ptr3 free!");
- DEBUG0("Ptr4 free!");
- }
这里有一点疑问,还没解决,就是那个长的printf需要在临界区,不然会abort异常。我尝试使用短的,没有问题,为了调试,这里加上临界区保护,感觉是模式设置有问题,有可能是MMU那块,不一定。printf我使用微型库自带的或者我自己的开源的都是一样,跑一下就直接异常了。
我的调试结果,可以看出地址是我们指定Heap的0x030200000,两种方式都可以。
这篇帖子主要用于告诉大家如何使用MDK开发工具,想了解细节的东西,直接去看ARM的文档,一定能找到你的答案。
有问题希望大家一起讨论。