[原创] helper2416_内存分配实现_有分析

lyzhangxiang   2014-8-21 22:04 楼主
好了,昨天我们的RTOS已经跑起来了,相关的DRAM划分也说的比较清楚了,这里我主要实现内存分配,使用自带的微型库。
相关细节,主要参考ARM官方的doc,方法如下
1)进入如下地址
http://infocenter.arm.com/help/index.jsp

2)搜索关键字即可,如
__user_initial_stackheap
__initial_sp
__heap_base
__heap_limit

arm-doc.jpg

好了,这里需要指定堆栈,有两种方法

1)通过汇编代码
新建一个heap.S文件,内容如下
  1. ;-------------------------------------------------------------------------------
  2. ; 堆栈
  3. ;-------------------------------------------------------------------------------
  4.         AREA          |.text|, CODE, READONLY
  5.        
  6.        
  7.     EXPORT __initial_sp
  8. __initial_sp EQU 0x30800000                ;STACK栈顶

  9.     EXPORT __heap_base
  10. __heap_base EQU  0x30200000                ;HEAP起始地址

  11.     EXPORT __heap_limit
  12. __heap_limit EQU 0x30600000               ;HEAP结束地址


  13.         END
  14.        
  15. ;-------------------------------------------------------------------------------
  16. ; 文件结束
  17. ;-------------------------------------------------------------------------------
主要依据如下,可参考中文资料在ARM的文档中,右边目录可以找到位于:
ARM 软件开发工具--->RealView Development Suite---->Version 4.0 中文用户手册
创建堆.jpg

创建堆栈.jpg

2)通过分散加载描述文件
  1. LR_ROM1 0x30800000 0x2800000          {                    ; load region size_region
  2.         RW_ROM1 0x30800000 0x2800000 {                  ; load address = execution address
  3.                 *.o (RESET, +First)
  4.                 .ANY (+RO +RW)
  5.         }
  6.         RW_RAM1 0x33000000 0x1000000 {  
  7.                 .ANY(+ZI)
  8.         }
  9.        
  10.         ARM_LIB_HEAP  0x30200000 EMPTY  0x00400000 {
  11.                
  12.         }
  13.     ARM_LIB_STACK 0x30800000 EMPTY -0x00200000 {
  14.                
  15.         }
  16. }
主要依据,如下

分散加载描述文件.jpg



----------------------------------------------------------------------------------------------------------------------------------------

重要提示,请看官方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的工具可以获取到更多原滋原味的支持文档,对开发尤其是裸机开发帮助很大。

我的测试程序如下:
  1.        
  2. /**
  3. * @brief  malloc_test
  4. * @note   内存分配测试
  5. * @param  none
  6. * @retval none
  7. */
  8. void malloc_test(void)
  9. {
  10.         int *ptr1;
  11.         int *ptr2;
  12.         int *ptr3;
  13.         int *ptr4;
  14.         OS_ALLOC_SR();
  15.        
  16.     ptr1 = (int *)malloc(sizeof(int) * 10);  
  17.     if (ptr1) {
  18.                 OS_ENTER_CRITICAL();
  19.         DEBUG1("Prt1 alloc at address: %x", (unsigned int)ptr1);  
  20.                 OS_EXIT_CRITICAL();
  21.         } else {
  22.         DEBUG0("No enough memory!");  
  23.         }
  24.     free(ptr1);
  25.         DEBUG0("Ptr1 free!");  
  26.        
  27.         ptr2 = (int *)malloc(sizeof(int) * 20);  
  28.     if (ptr2) {
  29.                 OS_ENTER_CRITICAL();
  30.         DEBUG1("Prt2 alloc at address: %x", (unsigned int)ptr2);  
  31.                 OS_EXIT_CRITICAL();
  32.         } else {
  33.         DEBUG0("No enough memory!");  
  34.         }
  35.     free(ptr2);
  36.         DEBUG0("Ptr2 free!");  

  37.        
  38.         ptr3 = (int *)malloc(sizeof(int) * 10);  
  39.     if (ptr3) {
  40.                 OS_ENTER_CRITICAL();
  41.         DEBUG1("Prt3 alloc at address: %x", (unsigned int)ptr3);  
  42.                 OS_EXIT_CRITICAL();
  43.         } else {
  44.         DEBUG0("No enough memory!");  
  45.         }
  46.        
  47.        
  48.         ptr4 = (int *)malloc(sizeof(int) * 20);  
  49.     if (ptr4) {
  50.                 OS_ENTER_CRITICAL();
  51.         DEBUG1("Ptr4 alloc at address: %x", (unsigned int)ptr4);  
  52.                 OS_EXIT_CRITICAL();
  53.         } else {
  54.         DEBUG0("No enough memory!");  
  55.         }
  56.         free(ptr3);
  57.     free(ptr4);
  58.         DEBUG0("Ptr3 free!");
  59.         DEBUG0("Ptr4 free!");  

  60. }
这里有一点疑问,还没解决,就是那个长的printf需要在临界区,不然会abort异常。我尝试使用短的,没有问题,为了调试,这里加上临界区保护,感觉是模式设置有问题,有可能是MMU那块,不一定。printf我使用微型库自带的或者我自己的开源的都是一样,跑一下就直接异常了。

我的调试结果,可以看出地址是我们指定Heap的0x030200000,两种方式都可以。
run.jpg

这篇帖子主要用于告诉大家如何使用MDK开发工具,想了解细节的东西,直接去看ARM的文档,一定能找到你的答案。
有问题希望大家一起讨论。


电工

回复评论 (1)

大家有问题可以跟帖交流,裸机开发必备的帮助文档
电工
点赞  2014-8-22 23:04
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复