popsonic的个人空间 https://blog.eetop.cn/81174 [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

嵌入系统中存储器的分配和使用(初学篇)

已有 1531 次阅读| 2007-2-5 18:46

天气: 晴朗
心情: 高兴
上次一位小兄弟请我写一点关于ADS里的内容。这个嘛比较基础一些。不过谁不是从基础来的呢。
好吧,我今天就写一些,关于启动代码里的存储器分配方面的东西,可能对初学者有些帮助,高手们就不用看了。呵呵。
1。存储器的概念
    存储器从读取和写入的角度来讲可以分为2类,只读存储器和读写存储器。只读存储器是指可以通过一定手段写入,但不可以直接用指令写入,比如地址访问 (*(Uint8 *)0x00002000)=5; 一般这样是会引发取数错误(DataAbort)。只读存储器可以通过电擦写,也有少些部分的是通过紫外线光擦写的。还有一些比如flash 是通过IAP的函数来擦除的。读写存储器是指可以即时的读出和写入数据的。所以,只读存储器又叫做(ROM)read only memory ;读写存储器叫(RAM)Radom Access Memory.
2。程序中的数据区和程序区在存储器中的位置
    程序中的代码区和数据区是分开的。代码区是不修改的,一旦通过编译指令就是固定的,所以我们可以把他们放到只读存储器中去,可以访问但不会修改。数据区的内容是可以修改的,当然也有const (义的数据是不能修改的)。它们被放在RAM中。对应于ads 中只读的会叫RO 可写的叫 RW 当然还有一种叫ZI这个是zero initial的缩写,在这个区的内容将会现被初始化为0。
    说完了几个区,我们来看一下程序中的数据区的构成。首先会是有一个全局数据区,这个里面的内容是我们在程序中的全局变量。再次,是一个堆区和栈区,打个比方。
uint k; //stored in the beginning of the ram area.
void test_func1()
{
    uint32 i,j;//stored in the system stack flag3
    ..........
}

void test_func2()
{
    uint32 i;//stored in the system stack flag2
    ...........
}
   
void main(void)
{
    uint32 i;//stored in the system stack  flag1
    uint8 *P;
    test_func1();
    test_func2();
    P=(uint8 *)malloc(sizeof(uint8));  
}
k 是一个全局变量,它在编译的时候就已经确定了位置,被分配在 0x40000004的位置(打个比方ram是在0x40000000开始的)
堆是从0x40001000~0x40005FFF;栈是从0x40007FFFF~0x40006000(因为栈是从上往下增张的)。
在主函数中的i其实是从栈里分配的。此时的cpu 的sp(堆栈指针)会往下压然后数据被存入堆栈。
在调用test_func1()的时候sp 又压了2次,分配了8个字节的空间给i,j;当退出test_func1()的时候,sp又回到了进入testfunc1()之前的状况,所以你在使用递归函数的时候,最好注意一下你的栈的大小。调用test_func2()的时候栈分配了4个字节的地址给i;当回到main函数的时候堆栈又恢复了原先的状态。
P=(uint8 *)malloc(sizeof(uint8)); 这个是从堆区分配内存并将地址返回给p指针。
通过malloc函数分配的块都是从堆区里分配出来的。
不过笔者并不推荐在嵌入环境中使用这个函数。因为在反复调用的时候你会发现会产生很多碎片,这样在程序运行的时候会造成内存无法分配。比较好的做法是一次分配大的区,然后从这个区里去自己管理。比如一次分配申请uint8 MEM[32][200];这样的方法让系统编译的时候就直接把它分配好,然后从这个区里去使用。(ucos 就是这样的方法)

3。注意的问题
在分配的时候要注意不能一次申请超过内存大小的堆。在进行指针访问的时候如果指到只读存储器并且进行写操作的时候容易产生Read/Write error 的错误,AXD会报!如果指到一个不存在的地址会产生DataAbort 的异常。分配栈最好分配在整个内存的最高端。
4。实例
代码都在单位呢,明天写吧,呵呵。
继续!
ROM_LOAD 0x0
{
    ROM_EXEC 0x00000000
    {
        Startup.o (vectors, +First)
        * (+RO)
    }
    IRAM 0x40000000
    {
        Startup.o (MyStacks)
        * (+RW,+ZI)
    }
    HEAP +0 UNINIT
    {
        Startup.o (Heap)
    }
    STACKS 0x40008000 UNINIT
    {
        Startup.o (Stacks)
    }
}
这一段代码就是我们上面讲的几个区。ROM_EXEC这个地方是从(0x0000000)开始的只读区域,可以存放执行的代码。当然如果flash是nand flash 那么这个区域也是不可以用的。
IRAM 是数据区。全局变量被分配在这个地址。  heap 这个就是堆了,紧跟这上面的区域。 STACKS是栈,是在整个RAM的最顶层。

点赞

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 1

    粉丝
  • 0

    好友
  • 1

    获赞
  • 29

    评论
  • 访问数
关闭

站长推荐 上一条 /1 下一条

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-5-2 11:16 , Processed in 0.025168 second(s), 17 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部