DIY编程器网

 找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 1306|回复: 0
打印 上一主题 下一主题

[待整理] 嵌入式软件开发之: 进一步存储器映射考虑事项

[复制链接]
跳转到指定楼层
楼主
发表于 2014-10-10 07:23:40 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
        13.6  进一步存储器映射考虑事项

        上一节介绍了如何使用Scatter文件对程序的代码和数据进行放置。但这些方法只有在外设和堆栈限制在源文件或头文件中定义好的前提下才能使用。为了增加程序的灵活性,最好在Scatter文件中设置这些信息,本节将介绍这些方法。
         
        13.6.1  在Scatter文件中定位目标外设

        通常情况下,外设寄存器的内存映射地址是在源文件或头文件中定义的“硬编码(hard-code)”。但为了增加代码的可移植性,可以在源文件中声明一个映射到外设寄存器的结构,并在这个结构在Scatter文件中定位。
         
        下面的例子定义了映射32位寄存器的定时器的C结构。
         
        struct {
               volatile unsigned ctrl; /* timer 控制寄存器 */
               volatile unsigned tmr;  /* timer值   */
        } timer_regs;
         
        要把该结构放在存储器映射的特定地址,需创建一个新的执行区来装入该结构。
         
        下面的例子说明了在Scatter文件中将timer_regs结构定位在0x40000000地址处。
         
        ROM_LOAD  0x24000000 0x04000000
        {
            ; ...
            TIMER 0x40000000 UNINIT
            {
                timer_regs.o (+ZI)
            }
            ; ...
        }
         
        需要特别注意的是,在应用程序启动过程中不将这些寄存器的内容初始化为零,因为这些地址对应的是外设寄存器,如果将其初始化为0,很可能改变系统的状态。必须将执行域的属性标记为UNINIT,这样可避免该区中的ZI数据初始化为零。
         
        13.6.2  在Scatter文件中放置堆和栈

        ARM公司建议,在Scatter文件中指定堆和栈的位置。这主要有两个主要优点:
        ·  有关存储器映射的所有信息保存在一个文件中;
        ·  改变堆和栈只要求重新链接,而不需要重新编译。
         
        1.显示放置标号

        为了在Scatter文件中放置堆栈,必须在源文件中定义Scatter文件的参照符号。下面的例子在名为stackheap.s的汇编文件中创建标有stack_base和heap_base的符号。这样就可以在Scatter文件的执行域中定位每个符号。
         
                   AREA   stacks, DATA, NOINIT
                   EXPORT stack_base
        stack_base        SPACE   1
                   AREA   heap, DATA, NOINIT
                   EXPORT heap_base
         
        heap_base         SPACE   1
             END
         
        下面的Scatter文件说明了如何在地址0x20000放置堆基址,如何在地址0x40000放置栈基址。堆基址和栈基址的位置可通过分别编辑其执行区予以改变。但该方法的缺点是在该栈区的上部占用一个字的内存区域放置SPACE(stack_base)变量。
         
        LOAD_FLASH 0x24000000 0x04000000
        {
            ; ...
            HEAP 0x20000 UNINIT
            {
                stackheap.o (heap)
            }
            STACKS 0x40000 UNINIT
            {
                stackheap.o (stacks)
            }
            ; ...
        }
         
        图13.17显示了堆和栈在内存中的放置情况。
       

        图13.17  显示设置符号放置堆栈

         
        2.使用链接程序生成符号

        该方法需要在目标文件中指定堆和栈的大小。首先,在一个汇编源文件中为堆和栈定义一个适当大小的区域。使用SPACE命令保留一个清零的存储器块。然后,为该区域设置NOINIT属性,避免在链接时被修改。这样避免了显示放置堆栈标号而浪费内存空间。
         
        下面的例子显示了如何在汇编源文件中预留出堆栈区域。
         
                AREA stack, DATA, NOINIT
            SPACE   0x3000                  ;为栈预留的空间
                AREA heap, DATA, NOINIT
            SPACE   0x3000                  ;为堆预留的空间
                END
         
        最后,可以在Scatter文件中定义执行域放置系统堆栈。
         
        下面的例子显示了如何在Scatter文件中使用由联接器生成的符号放置堆栈。
         
        LOAD_FLASH 0x24000000 0x04000000
        {
            :
            STACK 0x1000 UNINIT            ;length = 0x3000
            {
                stackheap.o (stack)         ;stack = 0x4000 to 0x1000
            }
            HEAP 0x15000 UNINIT            ;length = 0x3000
            {
                stackheap.o (heap)          ;heap = 0x15000 to 0x18000
            }
        }
         
        链接程序生成了指向每个执行区基址和限制的符号,可将其引入目标代码,供__user_initial_stackheap()函数使用:
         
        Image$$STACK$$ZI$$Limit     = 0x4000
        Image$$STACK$$ZI$$Base      = 0x1000
        Image$$HEAP$$ZI$$Base       = 0x15000
        Image$$HEAP$$ZI$$Limit      = 0x18000
         
        下面的例子通过使用DCD伪操作赋予这些链接符号更有意义的名称,可使该代码可读性更高。
         
                 IMPORT           ||Image$$STACKS$$ZI$$Base||
                 IMPORT           ||Image$$STACKS$$ZI$$Limit||
                 IMPORT           ||Image$$HEAP$$ZI$$Base||
                 IMPORT           ||Image$$HEAP$$ZI$$Limit||
            stack_base  DCD       ||Image$$STACKS$$ZI$$Limit||        ; = 0x4000
            stack_limit DCD       ||Image$$STACKS$$ZI$$Base||         ; = 0x1000
            heap_base   DCD        ||Image$$HEAP$$ZI$$Base||           ; = 0x15000
            heap_limit  DCD       ||Image$$HEAP$$ZI$$Limit||          ; = 0x18000
         
        这样如果需要改变系统堆栈的设置,可以通过编辑Scatter文件中的执行域很容易地改变,而不需要重新编译源文件。
         
        3.使用Scatter文件的EMPTY属性

        该方法使用了Scatter文件执行域的EMPTY属性。该属性使得定义的区域不包括目标代码或数据。这是定义堆和栈的一个方便方法。区域的长度在EMPTY属性后指定。对于存储器中向上增长的堆,其区域的长度为正。对于栈,其长度被标为负数,说明其在存储器中是向下增长的。
         
        下面的例子显示了如何在Scatter文件中使用EMPTY属性定义堆栈。
         
        ROM_LOAD 0x24000000 0x04000000
        {
            ...
            HEAP 0x30000 EMPTY 0x3000
            {
            }
            STACKS 0x40000 EMPTY -0x3000
            {
            }
            ...
        }
         
        该方法的优点是堆和栈的大小和位置是在一个地方定义的,即在Scatter文件中,而不必为堆栈创建stackheap.s源文件。
         
        链接时,链接程序生成代表这些EMPTY区的符号。
         
        Image$$HEAP$$ZI$$Base         = 0x30000
        Image$$HEAP$$ZI$$Limit        = 0x33000
        Image$$STACKS$$ZI$$Base        = 0x3D000
        Image$$STACKS$$ZI$$Limit       = 0x40000
         
        应用程序代码可处理这些符号,如下例所示。
         
                       IMPORT        ||Image$$HEAP$$ZI$$Base||
                       IMPORT        ||Image$$HEAP$$ZI$$Limit||
        heap_base       DCD          ||Image$$HEAP$$ZI$$Base||
        heap_limit      DCD          ||Image$$HEAP$$ZI$$Limit||
                       IMPORT        ||Image$$STACKS$$ZI$$Base||
                       IMPORT        ||Image$$STACKS$$ZI$$Limit||
        stack_base      DCD          ||Image$$STACKS$$ZI$$Limit||
        stack_limit      DCD
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|文字版|手机版|DIY编程器网 ( 桂ICP备14005565号-1 )

GMT+8, 2024-11-30 16:50 , 耗时 0.104573 秒, 22 个查询请求 , Gzip 开启.

各位嘉宾言论仅代表个人观点,非属DIY编程器网立场。

桂公网安备 45031202000115号

DIY编程器群(超员):41210778 DIY编程器

DIY编程器群1(满员):3044634 DIY编程器1

diy编程器群2:551025008 diy编程器群2

QQ:28000622;Email:libyoufer@sina.com

本站由桂林市临桂区技兴电子商务经营部独家赞助。旨在技术交流,请自觉遵守国家法律法规,一旦发现将做封号删号处理。

快速回复 返回顶部 返回列表