一、链接脚本的简单常识

  有时候我们很多文件需要链接到指定的区域,或者叫做段里面,比如在 Linux 里面初始化函数就会放到 init 段里面。因此我们需要能够自定义一些段,这些段的起始地址我们可以自由指定,同样的我们也可以指定一个文件或者函数应该存放到哪个段里面去。要完成这个功能我们就需要使用到链接脚本,链接脚本用于描述文件应该如何被链接在一起形成最终的可执行文件。其主要目的是描述输入文件中的段如何被映射到输出文件中,并且控制输出文件中的内存排布。比如我们编译生成的文件一般都包含 text 段、 data 段等等。
  链接脚本的语法很简单,就是编写一系列的命令,这些命令组成了链接脚本,每个命令是一个带有参数的关键字或者一个对符号的赋值,可以使用分号分隔命令。像文件名之类的字符串可以直接键入,也可以使用通配符“*”。最简单的链接脚本可以只包含一个命令“SECTIONS”,我们可以在这一个“SECTIONS”里面来描述输出文件的内存布局。我们一般编译出来的代码都包含在 text、 data、 bss 和 rodata 这四个段内,假设现在的代码要被链接到 0X10000000 这个地址,数据要被链接到 0X30000000 这个地方,下面就是完成此功能的最简单的链接脚本:

SECTIONS{. = 0X10000000;
.text : {*(.text)}
. = 0X30000000;
.data ALIGN(4) : { *(.data) }
.bss ALIGN(4) : { *(.bss) }}

  第 1 行我们先写了一个关键字“SECTIONS”,后面跟了一个大括号,这个大括号和第 7 行的大括号是一对,这是必须的。看起来就跟 C 语言里面的函数一样。
  第 2 行对一个特殊符号“.”进行赋值,“.”在链接脚本里面叫做定位计数器,默认的定位计数器为 0。我们要求代码链接到以 0X10000000 为起始地址的地方,因此这一行给“.”赋值0X10000000,表示以 0X10000000 开始,后面的文件或者段都会以 0X10000000 为起始地址开始链接。
  第 3 行的“.text”是段名,后面的冒号是语法要求,冒号后面的大括号里面可以填上要链接到“.text”这个段里面的所有文件,“(.text)”中的“”是通配符,表示所有输入文件的.text段都放到“.text”中。
  第 4 行,我们的要求是数据放到 0X30000000 开始的地方,所以我们需要重新设置定位计数器“.”,将其改为 0X30000000。如果不重新设置的话会怎么样?假设“.text”段大小为 0X10000,那么接下来的.data 段开始地址就是 0X10000000+0X10000=0X10010000,这明显不符合我们的要求。所以我们必须调整定位计数器为 0X30000000。
  第 5 行跟第 3 行一样,定义了一个名为“.data”的段,然后所有文件的“.data”段都放到这里面。但是这一行多了一个“ALIGN(4)”,这是什么意思呢?这是用来对“.data”这个段的起始地址做字节对齐的, ALIGN(4)表示 4 字节对齐。也就是说段“.data”的起始地址要能被 4 整除,一般常见的都是 ALIGN(4)或者 ALIGN(8),也就是 4 字节或者 8 字节对齐。
  第 6 行定义了一个“.bss”段,所有文件中的“.bss”数据都会被放到这个里面,“.bss”数据就是那些定义了但是没有被初始化的变量。

二、STM32跑MicroPython的连接脚本分析

  MicroPython官方已经将的固件移植到STM32上,而且支持许多种型号的STM32,分析以1.16版本MicroPython的PYBV10为例。
  首先在工程的Makefile中看到一句:
  include $(BOARD_DIR)/mpconfigboard.mk
  知道Makefile要包含mpconfigboard.mk文件。

MCU_SERIES = f4
CMSIS_MCU = STM32F405xx
AF_FILE = boards/stm32f405_af.csv
ifeq ($(USE_MBOOT),1)
# When using Mboot all the text goes together after the filesystem
LD_FILES = boards/stm32f405.ld boards/common_blifs.ld
TEXT0_ADDR = 0x08020000
else
# When not using Mboot the ISR text goes first, then the rest after the filesystem
LD_FILES = boards/stm32f405.ld boards/common_ifs.ld
TEXT0_ADDR = 0x08000000
TEXT1_ADDR = 0x08020000
endif# MicroPython settings
MICROPY_VFS_LFS2 = 1

  从mpconfigboard.mk文件中可以看出PYBV10根据是否使用USE_MBOOT分两种工作模式。USE_MBOOT工作模式是可IAP升级的模式。
  首先不可升级时stm32f405.ld和common_ifs.ld如下

/*GNU linker script for STM32F405
*//* Specify the memory areas */
MEMORY
{FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 1024K /* entire flash */FLASH_ISR (rx)  : ORIGIN = 0x08000000, LENGTH = 16K /* sector 0 */FLASH_FS (rx)   : ORIGIN = 0x08004000, LENGTH = 112K /* sectors 1,2,3,4 are for filesystem */FLASH_TEXT (rx) : ORIGIN = 0x08020000, LENGTH = 896K /* sectors 5,6,7,8,9,10,11 */CCMRAM (xrw)    : ORIGIN = 0x10000000, LENGTH = 64KRAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 128K
}/* produce a link error if there is not this amount of RAM for these sections */
_minimum_stack_size = 2K;
_minimum_heap_size = 16K;/* Define the stack.  The stack is full descending so begins just above last byteof RAM.  Note that EABI requires the stack to be 8-byte aligned for a call. */
_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve;
_sstack = _estack - 16K; /* tunable *//* RAM extents for the garbage collector */
_ram_start = ORIGIN(RAM);
_ram_end = ORIGIN(RAM) + LENGTH(RAM);
_heap_start = _ebss; /* heap starts just after statically allocated memory */
_heap_end = _sstack;
/* Memory layout for internal flash storage configuration:FLASH_ISR   .isr_vectorFLASH_TEXT  .textFLASH_TEXT  .dataRAM         .dataRAM         .bssRAM         .heapRAM         .stack
*/ENTRY(Reset_Handler)/* define output sections */
SECTIONS
{/* The startup code goes first into FLASH */.isr_vector :{. = ALIGN(4);KEEP(*(.isr_vector)) /* Startup code *//* This first flash block is 16K annd the isr vectors only take upabout 400 bytes. So we pull in a couple of object files to pad itout. */. = ALIGN(4);/* NOTE: If you update the list of files contained in .isr_vector,then be sure to also update smhal/Makefile where it forciblybuilds each of these files with -Os */*/ff.o(.text*)*/vfs_fat_*.o(.text*)*/py/formatfloat.o(.text*)*/py/parsenum.o(.text*)*/py/mpprint.o(.text*). = ALIGN(4);} >FLASH_ISR/* The program code and other data goes into FLASH */.text :{. = ALIGN(4);*(.text*)          /* .text* sections (code) */*(.rodata*)        /* .rodata* sections (constants, strings, etc.) *//*  *(.glue_7)   */    /* glue arm to thumb code *//*  *(.glue_7t)  */    /* glue thumb to arm code */. = ALIGN(4);_etext = .;        /* define a global symbol at end of code */} >FLASH_TEXTINCLUDE common_extratext_data_in_flash_text.ldINCLUDE common_bss_heap_stack.ld
}

  首先在stm32f405.ld中指定了存储的区域。主要定义了中断 、文件系统、 代码和RAM段等。common_ifs.ld文件中说明.isr_vector 放置中断(>FLASH_ISR)中,.text放置代码段中(>FLASH_TEXT)。中间的112K为文件系统。
  可升级(使用Mboot)时,common_blifs.ld的文件为

/* Memory layout for bootloader and internal filesystem configuration (this here describes the app part):FLASH_TEXT  .isr_vectorFLASH_TEXT  .textFLASH_TEXT  .dataRAM         .dataRAM         .bssRAM         .heapRAM         .stack
*/ENTRY(Reset_Handler)/* define output sections */
SECTIONS
{/* The startup code goes first into FLASH */.isr_vector :{. = ALIGN(4);KEEP(*(.isr_vector)) /* Startup code */. = ALIGN(4);} >FLASH_TEXT/* The program code and other data goes into FLASH */.text :{. = ALIGN(4);*(.text*)          /* .text* sections (code) */*(.rodata*)        /* .rodata* sections (constants, strings, etc.) *//*  *(.glue_7)   */    /* glue arm to thumb code *//*  *(.glue_7t)  */    /* glue thumb to arm code */. = ALIGN(4);_etext = .;        /* define a global symbol at end of code */} >FLASH_TEXTINCLUDE common_extratext_data_in_flash_text.ldINCLUDE common_bss_heap_stack.ld
}

  说明.isr_vector和.text都放到了代码段内(>FLASH_TEXT),前面的FLASH_ISR段预留给了Mboot使用,打开mboot文件夹找到了stm32_memory.ld文件和stm32_sections.ld文件。
  stm32_sections.ld文件内容为:

/*Linker script fragment for mboot on an STM32xxx MCU.This defines the memory sections for the bootloader to use.
*/MEMORY
{FLASH_BL (rx)   : ORIGIN = 0x08000000, LENGTH = 32KRAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 120K
}

  stm32_memory.ld文件内容为:

/*Linker script fragment for mboot on an STM32xxx MCU.This needs the following MEMORY sections to be defined: FLASH_BL, RAM.
*//* produce a link error if there is not this amount of RAM for these sections */
_minimum_stack_size = 8K;/* Define tho top end of the stack.  The stack is full descending so begins justabove last byte of RAM.  Note that EABI requires the stack to be 8-bytealigned for a call. */
_estack = ORIGIN(RAM) + LENGTH(RAM);ENTRY(Reset_Handler)SECTIONS
{/* The startup code goes first into FLASH */.isr_vector :{. = ALIGN(4);KEEP(*(.isr_vector)) /* Startup code */. = ALIGN(4);} >FLASH_BL/* The program code and other data goes into FLASH */.text :{. = ALIGN(4);*(.text*)*(.rodata*). = ALIGN(4);_etext = .;} >FLASH_BL/* used by the startup to initialize data */_sidata = LOADADDR(.data);/* Initialized data section */.data :{. = ALIGN(4);_sdata = .;*(.data*). = ALIGN(4);_edata = .;} >RAM AT> FLASH_BL/* Zeroed-out data section */.bss :{. = ALIGN(4);_sbss = .;*(.bss*)*(COMMON). = ALIGN(4);_ebss = .;} >RAM/* Uninitialized data section */.nozero_bss (NOLOAD) :{. = ALIGN(4);*(.nozero_bss*). = ALIGN(4);} >RAM/* this just checks there is enough RAM for the stack */.stack :{. = ALIGN(4);. = . + _minimum_stack_size;. = ALIGN(4);} >RAM.ARM.attributes 0 : { *(.ARM.attributes) }
}

  可以看到,mboot相当于bootloader,它只是依据FLSH和RAM将存储划分内存FLASH_BL和RAM。并将isr_vector和text链接到FLASH_BL,将data、bss 、nozero_bss和stack链接到RAM。

STM32跑MicroPython的链接脚本分析相关推荐

  1. uboot.lds链接脚本分析

     LDFLAGS += -Bstatic -T /board/smdk2410/u-boot.lds -Ttext 0x33F80000中-Ttext 0x33F80000是指定代码段text的首地址 ...

  2. STM32启动文件和链接脚本

    目录 参考 铺垫 SP PC LR vector table .text .rodata .data .bss 参考 STM32处理器启动代码的理解https://blog.csdn.net/qq_3 ...

  3. STM32链接脚本STM32F407ZETx_FLASH.ld

    目录 环境 参考 链接脚本简介 STM32F407ZETx_FLASH.ld文件分析 控制输出文件中内存布局 SECTIONS 环境 代码:STM32CUBEMX-linux版V6.5.0 + STM ...

  4. linux内核链接脚本vmlinux.lds分析(十一)

    vmlinux.lds.S主要是用来组织内核的每个函数存放在内核镜像文件的位置.编译内核源码生成内核文件的过程分两步,一个是"编译",另一个是"链接"的过程,v ...

  5. FreeNOS-kernel目录下boot.S、链接脚本kernel.ld文件分析(四)

    上节提到过引导程序在将控制权交给内核时,相关寄存器状态已确定,并且程序入口地址为boot.S文件中的_start,下个面就来看看boot.S文件. kernel目录下文件如下: 其中Sconscrip ...

  6. IMX6ULL-UBOOT分析(1):链接脚本u-boot.lds、Systemp.map和u-boot.map分析

    链接脚本u-boot.lds.Systemp.map和u-boot.map分析 1.u-boot.lds 2.System.map和u-boot.map 1.u-boot.lds 以下为IMX6ULL ...

  7. 【linux kernel】基于ARM64分析linux内核的链接脚本vmlinux.lds.S

    文章目录 一.导读 二.链接器是什么 三.链接脚本 四.linux内核的链接脚本 4-1 头文件包含描述 4-2 参数设置和宏定义描述 4-3 SECTIONS内容分析 五.linux内核的" ...

  8. lds链接脚本基础与例子分析

    1.基础 (1)段 .data段包含初始值非0的全局变量(不管静态还是非静态) .rodata段包含被const修饰的初始值非0的全局变量 .bss段包含初始值为0或未初始的全局变量(不管有没有con ...

  9. python stm32f401_NUCLEO-F401RE(STM32F401RE)开发板跑Micropython平台

    NUCLEO-F401RE(STM32F401RE)开发板跑Micropython平台 开发准备: 软件:DfuSeDemo.STM32 ST-LINK Utility.虚拟串口驱动.OpenIOE. ...

最新文章

  1. Cell Reports:张瑞福团队揭示抗生素调控微生物肥料菌种根表定殖成膜的新机制...
  2. php getimagesize图片宽高反了_PHP实现简单验证码识别
  3. Jackson 配置 ObjectMapper
  4. VSTO之旅系列(五):创建Outlook解决方案
  5. android 字母搜索栏,android仿微信通讯录搜索示例(匹配拼音,字母,索引位置)
  6. Java 代码实现pdf转word文件 | 无损转换完整代码教程
  7. 西瓜数据集介绍以及获取。
  8. python列表所有元素平均值_python—组合数据类型
  9. win10 账户密码忘记的解决办法
  10. 华为手机pc模式机型_哪些手机型号外接便携显示器能实现PC电脑模式
  11. java 暴露接口_Java基于spring暴露接口供外部调用
  12. luogu P2184 贪婪大陆
  13. 大众点评数据爬虫思路[更新版]
  14. [7 kyu] Exes and Ohs
  15. Fer2013 数据集人脸表情识别 详细代码
  16. QMap 迭代器崩溃分析
  17. 张勋说:钢渣处理工艺流程图及解析
  18. 选择一个日志文件系统
  19. 中谷项目(九)—如何将图片存入数据库并从中读取
  20. php中soap使用,SoapServer服务端编写,SoapClient客户端编写

热门文章

  1. win2012R2安装KB2919355 补丁的问题
  2. 2021首届-西部云安全峰会来了!9月26日西安见!
  3. silverlight4/5 修改源码实现 DataGrid 中文按拼音排序
  4. b spring之扩展ioc机制
  5. SpringBoot配置文件的说明
  6. 在软件工程领域,搞科研的这十年!
  7. 企业信息化改革怎么做?
  8. 计算机网络-拥塞控制/HTTP/URL
  9. MT8665芯片处理器,MT8665模块方案开发
  10. ASCII码的大小写转换