使用Keil的MicroLIB时自动设置堆大小——玩嵌入式以来最高难度

Keil编译项目,如果使用微库MicroLIB,就可以使用malloc。微库内部位置一个堆管理模块。
芯片的RAM大小是固定了的,前面分为全局变量,后面分给堆和栈,这是一般开发方式。
但是我们在开发项目的过程中,市场遇到各种各样问题,栈穿透到堆里面,或者堆不够大,相当烦人!
有时候就在想,何不让全局变量以外的所有RAM给堆栈共用?
因为堆从低到高分配,而栈从高到低分配,理论上是可行的!

但是堆的分配由__heap_base和__heap_limit两个标签决定,不是变量又不能改!

因为我们使用很多种芯片,每一种芯片的RAM大小都有可能不同。
而SmartOS追求跨平台,不想为不同芯片做太多设置。
之前我们已经实现了通过修改MSP把栈顶移到RAM最高处,这样子栈可以得到最大利用!
但是堆还是不好搞!

今晚再次遇到堆不够用的情况,__heap_limit如果分配过大,在小容量芯片就会出错。
忍无可忍,决定分析一下微库是怎么管理堆的。

首先打开项目编译后生成的链接地址映射文件Linker Address Map,我们这里是SmartOSF0_Debug.map
找到符号表段Global Symbols
    __heap_base                              0x200005a0   Data           0  startup_stm32f0xx.o(HEAP)
    __heap_limit                             0x200005a0   Data           0  startup_stm32f0xx.o(HEAP)
    __initial_sp                             0x200005c0   Data           0  startup_stm32f0xx.o(STACK)
从这里可以看出,堆栈已经分配好了。


堆分配使用的是malloc函数,上图找到它位于Keil库文件mc_p.l中
我的目录是D:\Keil\ARM\ARMCC\lib\armlib

轮到法宝IDA上阵,选择malloc.o,太简单了,只有malloc/free两个函数
汇编图形界面如下:


手头的IDA没有ARM插件,否则一个F5就可以得到malloc的C源代码。
好好工作赚钱卖ARM插件吧。。。

没有工具辅助,那就自己来写吧!


上面是手工写的C代码,被注释的是最原始的汇编写法,然后逐步精简优化。
大概摸清楚了malloc的机制,关键点在于初始化那里,用到了__heap_limit
而__heap_limit作为常量被编译到Flash里面去了,内存里面无法动态修改。
实在没办法,只好字节写代码来接替它初始化整个堆了。
我写的初始化代码如下:

附上malloc/free代码,不完整,只能大概了解它的机制:

void free(void* p)
{
    if(!p) return 0;
    
    r3 = __microlib_freelist;
    void* r2 = 0;
    p -= 4;
    void* r1 = *r3; // r1 = r3->node
    while(r1)
    {
        if(r1 > p) break;
        r2 = r1;
        r1 = *(r1 + 4); // r1 = r1->next
    }
    if(!r2)
        r3->node = p;
    else
    {
        r3 = *r2;
        r4 = p - r2;
        if(r4 != r3)
            *(r2 + 4) = p;
        else
        {
            p = *p;
            p += r3;
            
        }
    }
}

typedef struct
{
    uint size;
    void* next;
} Node;

__microlib_freelist:
    Node* _freelist;

__microlib_freelist_initialised:
    int _freelist_initialised = 0;

void* malloc(int size)
{
    /*r0 += 0x0b;
    r0 >>= 3;
    r0 <<= 3;*/
    r1 = (size + 11) & 0xFFFFFFF8;
    r7 = __microlib_freelist_initialised;
    r6 = 0;

    /*r2 = __microlib_freelist;
    if(!*r2 && !*r7)*/
    if(!_freelist && !_freelist_initialised)
    {
        /*r2 = __microlib_freelist;
        r0 = __heap_base + 4;
        *r2 = r0;
        r2 = __heap_limit;
        r2 -= r0;
        r2 &= 0xFFFFFFF0;
        *r0 = r2;
        *(r0 + 4) = 0;
        *r7 = 1;*/

        _freelist = (Node*)(__heap_base + 4);
        _freelist->size = (__heap_limit - __heap_base - 4) & 0xFFFFFFF8;
        _freelist->next = 0;
        _freelist_initialised = 1;
    }

    //r2 = __microlib_freelist;
    r0 = _freelist;
    while(true)
    {
        /*r0 = *r2;
        if(!r0)
        {
            r0 = r6;
            break;
        }*/
        //r0 = *r2;
        if(!r0) return 0;

        //r3 = *r0;
        r3 = r0->size;
        if(r3 <= r1) break;
        
        //r2 = r0 + 4;
        //r2 = r0->next;
        r0 = *(r0->next);
    }
    if(r3 <= r1)
    {
        //r3 = *(r0 + 4);
        /*r3 = _freelist->next;
        *r2 = r3;*/
        _freelist->size = r1;
        _freelist = _freelist->next;
        return &;
    }
    else
    {
        /*r4 = r3 - r1;
        r3 = r0 + r1;
        r5 = *(r0 + 4);
        *r3 = r4;
        r3 +=4 ;
        *(r3 + 4) = r5;
        r3 +=4 ;
        r3 -= 8;// 减8为了回到r3开始*/
        
        Node* lst = (void*)_freelist + r1;
        lst->size = _freelist->size - r1;
        lst->next = _freelist->next;
        
        _freelist->size = r1;
        _freelist = lst;
        
        return &lst->next;
    }
    
    return r0;
}

End.

                             转石头大哥
时间: 2024-12-19 15:15:21

使用Keil的MicroLIB时自动设置堆大小——玩嵌入式以来最高难度的相关文章

FireFox每次刷新时自动检查网页更新,无需手动清空缓存的设置方法

做技术,经常在写页面的时候需要多次刷新测试,可是浏览器都有自己的 缓存机制,一般CSS和图片都会被缓存在本地,这样我们修改的CSS就看不到效果 了,每次都去清空缓存,再刷新看效果,这样操作太麻烦了.在IE下我们可以直接 去修改internet选项/常规/浏览历史记录/到internet临时文件选项的设置中,将检查网页中的较新版 本改成每次访问此页时检查.这样我们就不用去清空缓存,每次刷新都能看到最新 的网页内容了. 以下内容由BIWEB网站系统创始人ArthurXF倾情奉献,那么在firefox

设置Myeclipse中的代码格式化、注释模板及保存时自动格式化

1:设置注释的模板: 下载此模板:  codetemplates.xml 搜索Dangzhang,将其改为你自己的姓名,保存 打开eclipse/myeclipse选择 window-->Preferences-->JAVA-->Code-->Code Templates 右边点Import 选择你写好的模板.xml文件导入进去即可 2:设置格式化的模板: 格式化模板:eclipse-formatter.xml 格式化模版方法同上,只是不是选择Code Templates ,而是选

IE/Firefox每次刷新时自动检查网页更新,无需手动清空缓存的设置方法

浏览器都有自己的 缓存机制,一般CSS和图片都会被缓存在本地,这样我们修改的CSS就看不到效果 了,每次都去清空缓存,再刷新看效果,这样操作太麻烦了.在IE下我们可以直接 去修改internet选项/常规/浏览历史记录/到internet临时文件选项的设置中,将检查网页中的较新版 本改成每次访问此页时检查.这样我们就不用去清空缓存,每次刷新都能看到最新 的网页内容了. 在firefox我们找遍 了所有的设置选项,竟然没有发现向IE那样的每次访问此页检查的选项.那么我们 怎么办呢?看到很多朋友在f

MySQL 创建表时,设置时间字段自动插入当前时间

MySQL 创建表时,设置时间字段自动插入当前时间 DROP TABLE IF EXISTS `CONTENT`; CREATE TABLE `CONTENT` ( `ID` char(20) NOT NULL, `CURRENT_TIME` timestamp not null default current_timestamp, PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

[UE4]工程设置:自动捕获鼠标、通过代码设置鼠标显示隐藏、输入模式、编译时自动保存

一.在4.20版本中运行游戏,在没有进行任何设置的情况下,游戏不会自动捕获鼠标,游戏不会接受输入,需要手动点一下游戏界面才行.如果要跟老版本一样运行游戏自动捕获鼠标,需要进行设置 二.也可以通过代码的方式设置鼠标显示隐藏和输入模式 三.编译时自动保存 原文地址:https://www.cnblogs.com/timy/p/10189754.html

堆大小设置

堆大小设置 JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制:系统的可用虚拟内存限制:系统的可用物理内存限制.32位系统下,一般限制在1.5G~2G:64为操作系统对内存无限制.我在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m. 典型设置: java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -Xmx3550m:设置JVM最大可用内存为3550M. -Xms355

STM32启动时RAM空间堆(Heap)和栈(stack)的分配 总结

STM32再启动的时候RAM首先分配给使用到的全局变量,及调用库占用的一些数据(不太清楚是什么数据) ,然后再将剩余的空间分配给Heap和stack. 以下是网上关于Heap和Stack的说: (1)栈区(stack):由编译器自动分配和释放,存放函数的参数值.局部变量的值等,其操作方式类似 于数据结构中的栈. (2)堆区(heap):一般由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收.分配 方式类似于数据结构中的链表. (3)全局区(静态区)(static):全局变量和静态变

MySQL自动设置create_time和update_time

参考表结构 CREATE TABLE `t_baby` ( `baby_id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) NOT NULL, `nickname` varchar(64) DEFAULT NULL, `avatar` varchar(64) DEFAULT '', `sex` int(2) unsigned NOT NULL DEFAULT '0' COMMENT '0:未知:\\n 1:男:\\n 2:女.', `bi

Eclipse保存时自动格式化代码

        使用Eclipse很长时间了,但是Eclipse有好多快捷好用的功能没有使用,现在在广州做项目,好多东西之前只是听过或者是简单的用,只是用到了皮毛,从身边人身上学到了一些东西,从eclipse软件使用开始分享.          eclipse保存时自动格式化代码,只需要在eclipse里设置一下就可以,eclipse自带这个功能,只是默认没有选中,要实现这个功能,只需要选上即可.具体的步骤:windows-->Preferences-->Java --> Editor-