SylixOS启动脚本分析

      本周学习了一些ARM指令、伪指令、链接脚本命令等,并对整个编译过程、elf文件有了更加深入的理解。ARM指令在ARM架构参考手册里面有了详细的介绍,这里不再列出,以下是一些GCC链接脚本命令的分析。
      以SylixOS启动脚本为例,分析一下链接脚本相关命令。SylixOS链接文件包括config.h、config.lds、SylixOSBSP.ld,它们位于BSP板级支持包根目录内。

      config.h文件定义了RAM、ROM的基址和大小,定义了TXET、DATA、DMA、APP段的大小,config.h文件定义如下:
/****************************************************************
ROM RAM 相关配置
****************************************************************/
#define BSP_CFG_ROM_BASE (0x00000000)
#define BSP_CFG_ROM_SIZE (4 * 1024 * 1024)
#define BSP_CFG_RAM_BASE (0x30000000)
#define BSP_CFG_RAM_SIZE (64 * 1024 * 1024)
#define BSP_CFG_TEXT_SIZE (6 * 1024 * 1024)
#define BSP_CFG_DATA_SIZE (18 * 1024 * 1024)
#define BSP_CFG_DMA_SIZE (6 * 1024 * 1024)
#define BSP_CFG_APP_SIZE (34 * 1024 * 1024)
#define BSP_CFG_BOOT_STACK_SIZE (128 * 1024)

       config.lds文件定义如下:
MEMORY
{
TEXT (rx) : ORIGIN = (0x30000000), LENGTH =(6 * 1024 * 1024)
DATA (rw) : ORIGIN = (0x30000000) + ((6 *1024 * 1024)), LENGTH = (18 * 1024 * 1024)
}
BOOT_STACK_SIZE = (128 * 1024);

       MEMORY命令用来描述目标内存块的位置和大小,config.lds文件定义了两个内存块区域,TEXT(可读可执行)和DATA(可读可写),ORIGIN表示内存区域的起始地址,LENGTH表示内存长度。
       SylixOSBSP.ld文件定义如下:
INCLUDE "config.lds"
OUTPUT_FORMAT(elf32-littlearm) /* 二进制文件格式 */
OUTPUT_ARCH(ARM) /* ARM架构 */
/*
* SECTIONS命令告诉编译器如何将输入段映射到输出段,以及输出段在内存中的位置
*/
SECTIONS
{
/***************************************************************************
代码段 LMA == VMA== ORIGIN(TEXT)
ORIGIN(TEXT)表示TEXT内存块区域的起始地址
.text段是可执行代码段
***************************************************************************/
.text : {
*(.vector)
*(.text)
*(.text.*) /* cpp namespace function */
*(.romrun) /* ROM 中必须的函数 */
*(.rodata) /* read-only data (constants) */
*(.rodata*)
*(.glue_7)
*(.glue_7t)
} >TEXT /* >TEXT表示该段属于TEXT内存块 */
/***************************************************************************
GOT
***************************************************************************/
.got : {
*(.got.plt)
*(.got)
} >TEXT
/***************************************************************************
.ARM.exidxis sorted, so has to go in its own output section.
***************************************************************************/
.ARM.exidx: {
. =ALIGN(4);
PROVIDE(__exidx_start = .);
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
. =ALIGN(4);
PROVIDE(__exidx_end = .);
} >TEXT
/***************************************************************************
.data 段数据初始化内容放在这里
PROVIDE用来定义一个符号(如果程序中定义则忽略该定义,使用程序中定义的)
它的语法是 PROVIDE(symbol= expression)
***************************************************************************/
. =ALIGN(4);
PROVIDE(_etext = .);
/***************************************************************************
数据段
.data 段运行地址 VMA 为 ORIGIN(DATA), 装载地址 LMA 为 _etext,
连接器会将 .data 的初始化数据放在 _etext 的地方, 然后启动程序必须将 _etext 的内容搬运到
VMAORIGIN(DATA) 中. 大小等于 SIZEOF(.data)
下面的定义说明.data段的运行地址是DATA内存块的首地址,装载地址为_etext(AT命令指定)
从.data段开始,程序的装载地址和运行地址均不相同,个人理解
***************************************************************************/
.dataORIGIN(DATA) : AT (_etext) {
. =ALIGN(4);
PROVIDE (_data = .);
*(.data)
. =ALIGN(4);
PROVIDE (_edata = .);
} >DATA
/***************************************************************************
清零段
NOLOAD 表示不装载, 启动程序只需要借助 __bss_start 和 __bss_end 两个符号指定的起始地址和结束地址
将 .bss 区域清零即可. (注意 *.noinit 可以不进行清零)
***************************************************************************/
.bss(NOLOAD) : {
. =ALIGN(4);
*(.noinit)
. =ALIGN(4);
PROVIDE (__bss_start = .);
*(.bss)
. =ALIGN(4);
*(COMMON)
. =ALIGN(4);
PROVIDE (__bss_end = .);
} >DATA
/***************************************************************************
栈段
SylixOS 启动时使用,异常入口也使用
***************************************************************************/
.stack (NOLOAD) : {
. =ALIGN(8);
PROVIDE (__stack_start = .);
. +=BOOT_STACK_SIZE;
. =ALIGN(8);
PROVIDE (__stack_end = .);
} >DATA
/***************************************************************************
内核堆段
***************************************************************************/
.heap(NOLOAD) : {
. =ALIGN(8);
PROVIDE (__heap_start = .);
__heap_end = ORIGIN(DATA) + LENGTH(DATA) - 128;
PROVIDE (__heap_end = .);
} >DATA
}
      由于.data段的装载地址与运行地址不相同,那么在C代码运行之前,需要汇编去实现将.data段的数据从装载地址拷贝到运行地址处,然后程序才可以正常运行。初始化代码在startup.S中实现。
      至于.bss段、.stack段、.heap段,里面的值并不重要,不需要装载进BIN文件,只需记录它们的起始地址和结束地址,再进行相应操作即可。
--------------------- 
作者:jiangheng12138 
来源:CSDN 
原文:https://blog.csdn.net/automan12138/article/details/77478315 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenWrt 是一个基于 Linux 的嵌入式操作系统,它提供了一个灵活的平台,可以在各种路由器和嵌入式设备上运行。您可以使用启动脚本来配置和定制 OpenWrt 的启动过程。 OpenWrt 使用的启动脚本是 `/etc/init.d` 目录下的脚本文件。这些脚本文件使用了类似于传统的 SysVinit 启动脚本的语法。 要创建一个启动脚本,请按照以下步骤操作: 1. 在 `/etc/init.d` 目录下创建一个新的脚本文件,例如 `myscript`。 ``` root@OpenWrt:~# cd /etc/init.d root@OpenWrt:/etc/init.d# touch myscript ``` 2. 编辑这个脚本文件并添加所需的配置和命令。您可以使用任何文本编辑器来编辑脚本文件。 ``` root@OpenWrt:/etc/init.d# vi myscript ``` 在脚本文件中,您可以编写启动、停止和重启服务、加载模块、设置环境变量等操作。 3. 添加可执行权限到脚本文件。 ``` root@OpenWrt:/etc/init.d# chmod +x myscript ``` 4. 在 `/etc/rc.d` 目录下创建一个符号链接,将脚本文件链接到适当的运行级别。 ``` root@OpenWrt:/etc/init.d# cd /etc/rc.d root@OpenWrt:/etc/rc.d# ln -s ../init.d/myscript S99myscript ``` 这将在启动时执行脚本文件。 5. 最后,您可以使用以下命令来启动、停止或重启脚本。 ``` root@OpenWrt:~# /etc/init.d/myscript start root@OpenWrt:~# /etc/init.d/myscript stop root@OpenWrt:~# /etc/init.d/myscript restart ``` 请注意,这只是一个简单的示例,您可以根据自己的需求编写更复杂的启动脚本。另外,建议您在编辑和测试脚本之前先备份相关文件,以免出现意外情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值