ADS 1.2 mem.scf 文件注释

本文详细介绍了ARM系统中使用Scatter文件进行内存布局配置的方法。包括ROM_LOAD、ROM_EXEC的定义,以及如何设置不同类型的内存区域如IRAM、ERAM、STACKS等。此外还讲解了如何通过Scatter文件重定向特定函数的位置。

;转载请写明作者及出处-木瓜-和讯

;总共三个分散加载文件mem_a.scf,mem_b.scf,mem_c.scf,区别是加载地址不一样

;具体加载哪个,在DebugInExram->ARM Linker->Scatter定义,链接类型选择Scattered

;image entry point一定要跟ROM_LOAD值一样

;ROM_LOAD 为加载区的名称,其后面的0x00000000 表示加载区的起始地址(存放程序代码的起始地址)
ROM_LOAD 0x0
{
; ROM_EXEC 描述了执行区的地址,放在第一块位置定义
    ROM_EXEC 0x00000000
    {
;从起始地址开始放置向量表(即Startup.o(vectors, +First),其中Startup.o 为Startup.s 的目标文件)

; +First表示Vector段放在最前面

        Startup.o (vectors, +First)

;接着放置其它代码(即* (+RO)),* 是通配符,类似WINDOW下搜索用的通配符
        * (+RO)
    }
;变量区IRAM 的起始地址为0x40000000
    IRAM 0x40000000
    {
;放置Startup.o (MyStacks)
        Startup.o (MyStacks)
    }
; +0表示接着上一段,UNINIT 表示不初始化
    STACKS_BOTTOM +0 UNINIT      
    {
;放置AREA    StackBottom, DATA, NOINIT
        Startup.o (StackBottom)
    }
;接着从0x40004000 开始,放置 AREA    Stacks, DATA, NOINIT,UNINIT 表示不初始化
    STACKS 0x40004000 UNINIT
    {
        Startup.o (Stacks)
    }
;外部RAM从0x80000000开始为变量区

;如果片外RAM起始地址不为0x8000 0000,则需要修改mem_.scf文件
    ERAM 0x80000000
    {
        * (+RW,+ZI)
    }
;+0表示接着上一段,UNINIT 表示不初始化
    HEAP +0 UNINIT
    {
;放置堆底, AREA    Heap, DATA, NOINIT
        Startup.o (Heap)
    }
;接着在外部0x80080000 放置堆顶

;这个地址是片外RAM 的结束地址,根据实际情况修改
    HEAP_BOTTOM 0x80080000 UNINIT
    {
        Startup.o (HeapTop)
    }
}

;重定向__user_initial_stackheap 函数

;分配新的bottom_of_heap地址等,R0-R3是函数必须的返回值,返回bottom_of_heap的值

;通过分散加载描述文件,重定向其位置,bottom_of_heap等已经在Startup.s中定义为DATA类型

__user_initial_stackheap   
    LDR   r0,=bottom_of_heap
;    LDR   r1,=StackUsr
    LDR   r2,=top_of_heap
    LDR   r3,=bottom_of_Stacks
    MOV   pc,lr

 


;文章出处:http://www.diybl.com/course/3_program/rg/200865/122670.html

 

 

在 lwIP 协议栈中,`mem.c` 和 `mem.h` 文件主要负责内存堆管理功能,用于实现动态内存分配和释放。它们共同构成了一个用于管理堆内存的系统,使得 lwIP 能够高效地分配和释放内存块以支持网络协议操作。 ### mem.h 文件功能 `mem.h` 主要用于声明与内存管理相关的函数、宏定义以及数据结构。其中包括一些用于字节对齐计算的宏定义,这些宏在内存池实现和其他内存管理中被广泛使用。例如,对齐操作通常是为了确保内存访问的高效性,尤其是在某些硬件平台上,未对齐的内存访问可能会导致性能下降甚至异常。 此外,`mem.h` 还声明了内存管理相关的结构体,例如 `struct mem`,它用于描述内存块的管理信息,包括内存块的大小、使用状态等信息。这些结构体和宏定义为 `mem.c` 中的具体实现提供了基础支持。 ### mem.c 文件功能 `mem.c` 是内存堆管理功能的主要实现文件,其中定义了 `struct mem` 结构体的具体使用方式,并实现了内存分配和释放的核心逻辑。 在 `mem.c` 中,定义了一个全局变量 `lfree`,它是一个指向 `struct mem` 的指针,用于指向最靠前的空闲内存块。通过 `lfree`,系统可以快速找到可用的空闲内存块并进行分配[^2]。为了支持多任务环境下的正确性,`lfree` 被声明为 `volatile` 类型,这确保了在操作系统环境中,编译器不会对内存访问进行优化,从而保证了内存访问的可见性和顺序性。 `mem.c` 中还实现了内存分配函数(如 `mem_malloc`)和释放函数(如 `mem_free`),这些函数通过维护一个内存堆来动态管理内存块。内存分配函数会查找足够大的空闲内存块,并将其分割以满足请求;而释放函数则会将内存块标记为空闲,并尝试合并相邻的空闲块以减少内存碎片。 ### 内存池管理的补充 虽然 `mem.c` 和 `mem.h` 主要关注堆内存管理,但在 lwIP 中,内存池管理(如 `memp.c`)则用于管理特定类型对象的预分配内存池[^3]。这种设计使得 lwIP 能够更高效地处理固定大小的对象分配,例如网络连接控制块、协议控制块等,从而避免了频繁的动态内存分配带来的性能开销。 ```c struct mem { size_t next, prev; // 指向下一个和上一个内存块的索引 }; ``` 上述代码片段展示了 `struct mem` 的定义,它用于描述每个内存块的管理信息,包括指向相邻内存块的索引,这对于内存块的合并和分割操作至关重要。 ### 相关问题 1. lwIP 中内存池(memp.c)与内存堆(mem.c)的区别是什么? 2. 如何在多任务环境下确保 lwIP 内存管理的线程安全性? 3. 在 lwIP 中,`mem_malloc` 和 `mem_free` 函数的具体实现逻辑是怎样的? 4. 为什么在 lwIP 的 `mem.c` 文件中,`lfree` 指针需要被声明为 `volatile`? 5. lwIP 中的内存碎片问题是如何通过内存堆管理机制解决的?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值