IMX6ULL学习笔记_Boot和裸机篇(2)--- SEGGER Embedded Studio基本相关配置
项目开源链接以及作者信息
项 | 参数 |
---|---|
github主页 | https://github.com/snqx-lqh |
github项目地址 | https://github.com/snqx-lqh/IMX6ULL_LearningRecord |
gitee项目地址 | https://gitee.com/snqx-lqh/IMX6ULL_LearningRecord |
作者 VX | Qinghua_Li7 |
📖 欢迎交流 如果对你有帮助,希望可以帮我点个赞👍和收藏,谢谢
基础环境
裸机程序编写软件:SEGGER Embedded Studio V8.24 。 可以直接在官网查看相关下载。下载下来后,直接按照安装引导安装,其他直接默认,只有安装位置选择的时候不要装在D盘就可以了。
https://www.segger.com/downloads/embedded-studio/
如果不想在官网安装,也可以选择我提供的网盘版本
通过网盘分享的文件:Setup_EmbeddedStudio_v824_Windows_x86_64.exe
链接: https://pan.baidu.com/s/1GIbzdmYmjjapKnZWyVQNJQ 提取码: vw7x
–来自百度网盘超级会员v6的分享
新建工程
1、打开软件,我们新建一个工程
2、选择建立一个新的解决方案
3、选择Cotex-A的解决方案,因为我们用的IMX是Cotex-A并且选择一个路径名和工程名。
4、在选择目标设备中,我们搜索我们的芯片型号
5、编译环境默认。
6、添加程序,默认
7、配置方案,也默认
8、全部配置好后,就会生成工程。SEGGER_Flash_ARM.icf 是链接文件,main是编译文件,.s的是启动文件。
系统相关配置
1、tab键的位宽配置以及自动格式化等。
它默认使用的是8位的宽度,有的时候我看着就不太习惯,一般习惯了4位的宽度。
首先点击Tools中的Option选项。
然后选择Languages,就会发现多种语言都可以自行配置一些模式。
每个参数代表的含义如下。
Column Guide Columns:
作用:用于在编辑器中显示一条或多条竖直参考线,方便控制代码宽度。
典型用途:比如写 C 代码时常设定在 80 或 120 列,帮助保持行长度规范。
值的形式:可以是一个数字(单条竖线)或逗号分隔的一组数字(多条竖线)。
例子:80,120 → 在第 80 和第 120 列显示竖线。
Indent Mode:
作用:定义缩进方式。
常见选项:
None → 不自动缩进。
Auto → 根据代码结构自动缩进。
Smart → 更智能的缩进,会参考上下文(如 {}、case 等)。
常用设置:一般选 Smart,写代码比较顺手,它会在换行的时候自动缩进。
Indent Size:
作用:定义 一个缩进层级 占用多少列(空格数)。
区别于 Tab Size:即使使用 Tab 键缩进,显示时也会按此值计算缩进层级。
例子:Indent Size = 4 → 每次缩进 4 列。
On Type Formatting:
Yes → 开启输入时自动格式化。
在你输入特定符号(如 ;、{、}、回车等)时,编辑器会自动调整缩进和代码对齐。
效果类似于 Visual Studio/Eclipse 的“实时格式化”。
No → 关闭输入时自动格式化。
只有在你手动触发格式化(比如 Ctrl+Shift+F)时才会调整缩进和排版。建议不打开,可以自己尝试。我的尝试是感觉比较乱。
Tab Size:
作用:控制 Tab 字符在编辑器中显示时占用的列数。
注意:Tab Size ≠ Indent Size。
例子:
Indent Size = 4, Tab Size = 8 → 输入缩进时用空格,4 列一个缩进;但 Tab 字符会显示为 8 列宽。
通常建议两者保持一致(比如都设 4)。
Use Tabs:
作用:控制按下 Tab 键 时,插入的是 制表符(Tab 字符) 还是 空格。
选项:
Yes → 插入真实的 Tab 字符。
No → 插入若干个空格(数量由 Indent Size 决定)。
常用习惯:团队开发时,通常会统一设置为 No(用空格),避免不同编辑器/环境对 Tab 渲染不一致。
User-Defined Keywords:
作用:自定义关键字(用于语法高亮)。
用法:输入你想高亮的单词(可逗号分隔)。
例子:
MYMACRO,DEBUG_PRINT → 这些会像关键字一样高亮显示。
场景:适合给项目中常用的宏、函数加上额外的高亮。一般不常用,自己配置吧。
下面给出我的配置项,我只配置了C/C++的,因为常用的文件也就这几个。其他的可以根据需求配置。
2、修改字体大小
首先点击Tools中的Option选项。然后找到Text Editor中的font,根据需求自己修改字体大小。
3、修改主题配色
首先点击Tools中的Option选项。然后找到Color Schemes,里面有多种主题,可以自己选择尝试。
工程相关配置
上面的是软件整体的相关配置,然后就是每个项目都有自己单独可配置的事项。在右键Project后,选择Option
1、增加用户头文件包含路径
头文件需要包含到工程,才能够正常编译,不然你每次编译工程都需要写相对路径。找到Preprocessor->User Include Directories。然后点击后面的点,就可以增加你的文件路径了,每行单独放置一个路径,建议使用相对路径。
比如我下面这样,增加的文件路径,是你实际的文档管理器中的路径,不是工程中的路径。
2、增加全局宏定义
找到Preprocessor->Preprocessor Definitions。然后点击后面的点,就可以增加你的全局宏定义了,也是每行一个宏定义即可。
3、生成Bin文件
有的时候,我们需要生成Bin文件
找到Linker->Additional Output Format。然后点击后面的下拉框,就可以选择想要生成的文件是什么类型。
ICF 配置
icf中存放的一般就是链接文件,包含怎么链接这个文件。
我们直接看这个默认的文件。然后一步步的解析这个文件。
(这部分内容是Ai生成的,后续可能会根据理解修改)
define memory with size = 4G;define region FLASH = FLASH1;
define region RAM = RAM1;//
// Block definitions
//
define block vectors { section .vectors }; // Vector table section
define block vectors_ram { section .vectors_ram }; // Vector table section
define block ctors { section .ctors, section .ctors.*, block with alphabetical order { init_array } };
define block dtors { section .dtors, section .dtors.*, block with reverse alphabetical order { fini_array } };
define block exidx { section .ARM.exidx, section .ARM.exidx.* };
define block tbss { section .tbss, section .tbss.* };
define block tdata { section .tdata, section .tdata.* };
define block tls with fixed order { block tbss, block tdata };
define block tdata_load { copy of block tdata };
define block heap with auto size = __HEAPSIZE__, alignment = 8, /* fill =0x00, */ readwrite access { };
define block stack with size = __STACKSIZE__, alignment = 8, /* fill =0xCD, */ readwrite access { };
define block stack_abt with size = __STACKSIZE_ABT__, alignment = 8 { };
define block stack_fiq with size = __STACKSIZE_FIQ__, alignment = 8 { };
define block stack_und with size = __STACKSIZE_UND__, alignment = 8 { };
define block stack_irq with size = __STACKSIZE_IRQ__, alignment = 8 { };
define block stack_svc with size = __STACKSIZE_SVC__, alignment = 8 { };
//
// Explicit initialization settings for sections
// Packing options for initialize by copy: packing=auto/lzss/zpak/packbits
//
do not initialize { section .non_init, section .non_init.*, section .*.non_init, section .*.non_init.* };
do not initialize { section .no_init, section .no_init.*, section .*.no_init, section .*.no_init.* }; // Legacy sections, kept for backwards compatibility
do not initialize { section .noinit, section .noinit.*, section .*.noinit, section .*.noinit.* }; // Legacy sections, used by some SDKs/HALs
do not initialize { block vectors_ram };
initialize by copy with packing=auto { section .data, section .data.*, section .*.data, section .*.data.* }; // Static data sections
initialize by copy with packing=auto { section .fast, section .fast.*, section .*.fast, section .*.fast.* }; // "RAM Code" sections#define USES_ALLOC_FUNC \linked symbol malloc || linked symbol aligned_alloc || \linked symbol calloc || linked symbol reallocinitialize by calling __SEGGER_init_heap if USES_ALLOC_FUNC { block heap }; // Init the heap if one is required
initialize by calling __SEGGER_init_ctors { block ctors }; // Call constructors for global objects which need to be constructed before reaching main (if any). Make sure this is done after setting up heap.//assert with warning "free() linked into application but there are no calls to an allocation function!" {
// linked symbol free => USES_ALLOC_FUNC
//};assert with error "heap is too small!" { USES_ALLOC_FUNC => size of block heap >= 48 };
assert with error "heap size not a multiple of 8!" { USES_ALLOC_FUNC => size of block heap % 8 == 0 };
assert with error "heap not correctly aligned!" { USES_ALLOC_FUNC => start of block heap % 8 == 0 };//
// Explicit placement in FLASHn
//
place in FLASH1 { section .FLASH1, section .FLASH1.* };
//
// FLASH Placement
//
place at start of FLASH { block vectors }; // Vector table section
place in FLASH with minimum size order { block tdata_load, // Thread-local-storage load imageblock exidx, // ARM exception unwinding blockblock ctors, // Constructors blockblock dtors, // Destructors blockreadonly, // Catch-all for readonly data (e.g. .rodata, .srodata)readexec // Catch-all for (readonly) executable code (e.g. .text)};//
// Explicit placement in RAMn
//
place in RAM1 { section .RAM1, section .RAM1.* };
//
// RAM Placement
//
place at start of RAM { block vectors_ram };
place in RAM with auto order { section .fast, section .fast.*, // "ramfunc" sectionblock tls, // Thread-local-storage blockreadwrite, // Catch-all for initialized/uninitialized data sections (e.g. .data, .noinit)zeroinit // Catch-all for zero-initialized data sections (e.g. .bss)};
place in RAM { block heap }; // Heap reserved block
place in RAM { block stack_abt,block stack_fiq,block stack_und,block stack_irq,block stack_svc};
place at end of RAM { block stack }; // Stack reserved block at the end
1、定义整体空间大小
在文件开头定义了整个地址空间大小,这里假设地址空间是4G,这是默认生成的,没有做修改。实际工程会在后面把它细分为 Flash、RAM 等区域。
define memory with size = 4G;
2、内存区域定义
定义逻辑上的 FLASH 区域 和 RAM 区域,指向具体的物理存储器段(FLASH1 / RAM1 在芯片包的默认 memory map 中已有定义),具体的定义起始地址和区间在如图所示,它使用的是继承的通用配置。这个配置中
Flash1的起始地址是0x60000000,大小是0x02000000,也就是32MB大小。
RAM1的起始地址是0x00900000,大小是0x00020000,也就是128KB大小。
这个地址,我们后续会改变,但是这里暂时不做过多解释,当把ICF文件介绍完后再做解释。
后面所有的 place in FLASH / place in RAM 就是往这些区域里放内容。
define region FLASH = FLASH1;
define region RAM = RAM1;
实际使用的时候,我会修改这部分地址,改成如下,定义成自己想要运行的地址空间。
define region FLASH2 = [from 0x87800000 to 0x87FFFFFF];
define region RAM2 = [from 0x80000000 to 0x8003FFFF];define region FLASH = FLASH2;
define region RAM = RAM2;
3、Block定义
Block = 一组 section 的集合,用来做统一管理/布局。
define block vectors { section .vectors };
define block ctors { section .ctors, ... };
define block dtors { section .dtors, ... };
...
define block heap with auto size = __HEAPSIZE__, alignment = 8 { };
define block stack with size = __STACKSIZE__, alignment = 8 { };
常见的:
vectors → 中断向量表
ctors / dtors → C++ 全局对象的构造函数 / 析构函数列表
heap → 堆,大小由 HEAPSIZE 宏决定
stack → 主堆栈区
stack_irq、stack_svc 等 → ARM 的各个模式下的专用栈
4、初始化策略
do not initialize { section .non_init, ... };
initialize by copy with packing=auto { section .data, ... };
initialize by copy with packing=auto { section .fast, ... };
初始化策略,决定上电/复位时如何处理不同段:
do not initialize → 不清零、不初始化(例如保留断电数据的 RAM 段)
initialize by copy → 从 Flash 拷贝到 RAM(典型:.data 段的初始化)
initialize by zero(zeroinit)→ 清零(典型:.bss 段)
这里用 packing=auto → 让编译器自动选择压缩方式来减小镜像体积。
5、特殊初始化
initialize by calling __SEGGER_init_heap if USES_ALLOC_FUNC { block heap };
initialize by calling __SEGGER_init_ctors { block ctors };
在系统初始化时:
如果工程中用到了 malloc/calloc 等,就会调用 __SEGGER_init_heap 来初始化堆。
如果有 C++ 全局对象,就会调用 __SEGGER_init_ctors 来运行构造函数。
6、断言检查
assert with error "heap is too small!" { USES_ALLOC_FUNC => size of block heap >= 48 };
对配置进行合法性校验:
堆必须至少 48 字节以上。
堆必须 8 字节对齐。
如果使用了 malloc 等分配函数,却没有足够的堆,就报错。
7、FLASH 中的放置规则
place at start of FLASH { block vectors };
place in FLASH with minimum size order { block tdata_load, block exidx, block ctors, block dtors, readonly, readexec };
定义代码和常量在 Flash 中的布局顺序:
首先放向量表 (vectors) 在 Flash 起始位置。
然后放线程局部存储镜像、异常索引表、构造函数、析构函数、只读数据 .rodata,最后是代码 .text。
8、RAM 中的放置规则
place at start of RAM { block vectors_ram };
place in RAM with auto order { section .fast, block tls, readwrite, zeroinit };
place in RAM { block heap };
place in RAM { block stack_abt, ... };
place at end of RAM { block stack };
RAM 中的放置:
开头放 vectors_ram(有些 MCU 可以让向量表搬到 RAM)。
再放 .fast(运行在 RAM 的函数),TLS(线程局部存储)、.data、.bss。
中间放 heap、异常模式下的独立栈。
RAM 末尾放主堆栈(stack)。