|
|
@@ -2,6 +2,22 @@ |
|
|
|
|
|
|
|
## 1.1 各类文件含义 |
|
|
|
|
|
|
|
| 文件 | 作用功能 | |
|
|
|
| ------------------- | ------------------------------------------------------------ | |
|
|
|
| `.eww`工作空间文件 | 顶层容器,管理**多个相关联的工程** | |
|
|
|
| `.ewp`工程文件 | 存储单个工程的**完整配置** | |
|
|
|
| `.cspy`工程配置文件 | 保存调试会话的**具体硬件配置**(仅调试相关)。 | |
|
|
|
| `.ewd`调试会话文件 | | |
|
|
|
| `.dep`依赖文件 | | |
|
|
|
| `.icf`链接脚本 | 代码数据在芯片芯片内存中的物理布局,设置栈和堆其实地址及大小 | |
|
|
|
| `.ewt`模板文件 | | |
|
|
|
| .s汇编源文件 | 经汇编器生成.o文件**1. 芯片启动初始化** **2. 硬件底层操作****中断服务函数 | |
|
|
|
| .a二进制静态库 | | |
|
|
|
| .map | 看内存存储地址, | |
|
|
|
| | | |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 1.2 新建项目 |
|
|
|
|
|
|
|
* 新建项目 |
|
|
@@ -32,51 +48,156 @@ |
|
|
|
|
|
|
|
 |
|
|
|
|
|
|
|
## 工程配置 |
|
|
|
# 工程配置 |
|
|
|
|
|
|
|
### 2.1设备配置 |
|
|
|
## 2.1设备配置 |
|
|
|
|
|
|
|
>  |
|
|
|
|
|
|
|
### 2.2 编译配置 |
|
|
|
## 2.2 编译配置 |
|
|
|
|
|
|
|
> 优化等级 |
|
|
|
### 2.2.1优化等级 |
|
|
|
|
|
|
|
 |
|
|
|
|
|
|
|
> 硬件浮点 |
|
|
|
> |
|
|
|
| 等级 | 行为 | 场景 | |
|
|
|
| -------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | |
|
|
|
| **None(无优化)** | 完全不优化,代码按原始顺序逐行编译。 | 初级调试阶段(变量未被优化,便于观察) 排查编译器行为异常问题 | |
|
|
|
| **Low(低优化)** | 基础优化:删除无操作指令、合并重复加载操**保持函数栈帧完整** | 日常调试开发,对执行速度要求不高的模块 | |
|
|
|
| **Medium(中优化)** | 开启函数内联(小函数直接展开)循环展开,寄存器复用加强 | 需要兼顾速度和体积的应用,发布版本的预备测试阶段,**影响调试**时局部变量观察 | |
|
|
|
| **High(高优化)** | 激进策略:向量化指令、分支预测优化,**大幅调整代码结构**(如重排指令流水线) | 对实时性要求高的场景(电机控制、信号处理)资源宽裕但性能吃紧的模块; **可能暴露隐藏的时序BUG 调试时变量可能(被优化掉)** | |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 2.2.2 硬件浮点 |
|
|
|
|
|
|
|
>  |
|
|
|
|
|
|
|
> 文件路径 |
|
|
|
### 2.2.3 文件路径 |
|
|
|
|
|
|
|
> - **设置位置**: |
|
|
|
> `Project > Options > C/C++ Compiler > Preprocessor`(相对路径) |
|
|
|
> - `Additional include directories`头文件 |
|
|
|
> - `Defined symbols`(预定义全局宏) |
|
|
|
> |
|
|
|
> 预处理 |
|
|
|
> 预编译处理 |
|
|
|
> |
|
|
|
> * 定义STM32F401xx,预编译宏识别芯片型号 |
|
|
|
> * .h中寄存器映射结构被激活 |
|
|
|
> |
|
|
|
>  |
|
|
|
|
|
|
|
### 2.3.4 库文件路径 |
|
|
|
|
|
|
|
> `Project > Options > Linker > Library` |
|
|
|
> |
|
|
|
>  |
|
|
|
|
|
|
|
### 2.2.5 输出. |
|
|
|
|
|
|
|
> 输出.Hex |
|
|
|
1. 编译输出 |
|
|
|
|
|
|
|
`Project > Options > General Output` |
|
|
|
|
|
|
|
**Output directory**生成 .o/.d 文件的目录 |
|
|
|
|
|
|
|
**Intermediate files directory**临时文件目录 |
|
|
|
|
|
|
|
2. 可执行文件 |
|
|
|
|
|
|
|
 |
|
|
|
|
|
|
|
3. 输出hex文件 |
|
|
|
|
|
|
|
*  |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 2.3 调试器配置 |
|
|
|
## 2.3 调试器配置 |
|
|
|
|
|
|
|
 |
|
|
|
|
|
|
|
### 2.4 库相关配置 |
|
|
|
## 2.4 库相关配置 |
|
|
|
|
|
|
|
### 2.4.1 库类型 |
|
|
|
|
|
|
|
 |
|
|
|
| **库类型** | **文件格式** | **使用场景** | **配置入口** | |
|
|
|
| :--------------: | :----------: | :---------------: | :------------------------------: | |
|
|
|
| **静态库** | `.a` | 核心算法/驱动封装 | Linker > Library | |
|
|
|
| **运行时库** | 内置 | 标准C/C++函数支持 | General Options > Library Config | |
|
|
|
| **第三方源码库** | `.c`/`.h` | 开源组件集成 | C/C++ Compiler > Preprocessor | |
|
|
|
| **系统库** | `.lib` | 操作系统接口 | Linker > Extra Library Search | |
|
|
|
|
|
|
|
### 2.5 静态库封装 |
|
|
|
 |
|
|
|
|
|
|
|
## 2.5 静态库封装 |
|
|
|
|
|
|
|
### 创建库工程 |
|
|
|
|
|
|
|
1. 建项目`Project > Create New Project...` → 选择 **Library** 模板 → 输入库名称(如 `MyLib`)→ 指定芯片型号。 |
|
|
|
2. 右键工程名 → `Add` → 添加库功能的源文件(`.c`/`.cpp`)和头文件(`.h`)。 |
|
|
|
|
|
|
|
* 排除不要生成的库文件 |
|
|
|
|
|
|
|
 |
|
|
|
|
|
|
|
 |
|
|
|
|
|
|
|
## 工程调试 |
|
|
|
--- |
|
|
|
|
|
|
|
## 2.6 调用 |
|
|
|
|
|
|
|
### 3.1断点 |
|
|
|
1. 将静态库头文件(.h)复制到inc目录 |
|
|
|
|
|
|
|
2. **添加头文件路径** |
|
|
|
`Project > Options > C/C++ Compiler > Preprocessor` → 填写头文件路径(如 `$PROJ_DIR$\inc`)。 |
|
|
|
|
|
|
|
3. 链接库文件 |
|
|
|
|
|
|
|
* `Project > Options > Linker > Library` → 添加库搜索路径(如 `$PROJ_DIR$\..\MyLib\Output\Release`)。 |
|
|
|
* 在 **Additional libraries** 中填写库名(如 `MyLib`,**不带扩展名**)。 |
|
|
|
* 若有多个库,用空格分隔(`MyLib1 MyLib2`)。 |
|
|
|
|
|
|
|
4. 代码调用 |
|
|
|
|
|
|
|
~~~ c |
|
|
|
#include "mylib_functions.h" // 静态库头文件 |
|
|
|
|
|
|
|
int main() { |
|
|
|
lib_init(); // 调用库的初始化函数 |
|
|
|
int result = calculate(3, 5); // 调用库的计算函数 |
|
|
|
while(1); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
~~~ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# iar功能 |
|
|
|
|
|
|
|
## 图标 |
|
|
|
|
|
|
|
 |
|
|
|
|
|
|
|
> 1. 搜索功能 |
|
|
|
> 2. 替换内容 |
|
|
|
> 3. 跳转到指定行 |
|
|
|
> 4. 书签(在光标所指处,进行书签添加删除) |
|
|
|
> 5. 进行书签跳转 |
|
|
|
|
|
|
|
 |
|
|
|
|
|
|
|
> 1. 编译当前文件 |
|
|
|
> 2. 编译所有文件 |
|
|
|
> 3. 在光标出添加断点 |
|
|
|
> 4. 下载并进入调试 |
|
|
|
> 5. 直接进行调试 |
|
|
|
|
|
|
|
# 工程调试 |
|
|
|
|
|
|
|
## 断点 |
|
|
|
|
|
|
|
 |
|
|
|
|
|
|
@@ -92,14 +213,205 @@ |
|
|
|
|
|
|
|
 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 数据断点 |
|
|
|
|
|
|
|
全局变量可以打数据断点,局部变量不可以. |
|
|
|
|
|
|
|
 |
|
|
|
|
|
|
|
| **特性** | 数据断点 | 条件断点 | |
|
|
|
| :----------: | :--------------: | :-------------------: | |
|
|
|
| **触发条件** | 内存访问 | 代码位置 + 自定义条件 | |
|
|
|
| **硬件依赖** | 是(DWT单元) | 否 | |
|
|
|
| **数量限制** | 4个(Cortex-M) | 无 | |
|
|
|
| **性能影响** | 零开销 | 条件计算引入延迟 | |
|
|
|
| **典型场景** | 全局变量篡改监控 | 循环内定点检查 | |
|
|
|
|
|
|
|
1. **数据断点** → 用于捕获 **不可预测** 的内存篡改 |
|
|
|
2. **条件断点** → 用于 **可预测逻辑错误** 的定位 |
|
|
|
3. **性能敏感时**:用 `if(cond){bkpt;}` 替代复杂条件断点 |
|
|
|
4. **多地址监控**:采用分组轮换策略 |
|
|
|
|
|
|
|
* 监控信息 |
|
|
|
|
|
|
|
`查看变量值,和存储所在的寄存器值` |
|
|
|
|
|
|
|
 |
|
|
|
|
|
|
|
| **工具类型** | 数据刷新机制 | 显示格式控制 | 适用场景 | |
|
|
|
| :-------------: | :--------------------: | :----------: | :------------------: | |
|
|
|
| **Watch** | 手动刷新(暂停时) | ✅ 支持 | 分析暂停时的变量快照 | |
|
|
|
| **Live Watch** | 自动实时刷新(运行中) | ❌ 不支持 | 监控运行时动态变化 | |
|
|
|
| **Quick Watch** | 单次快照 | ✅ 支持 | 快速查看复杂表达式 | |
|
|
|
| **Locals** | 局部变量窗口 | | | |
|
|
|
| .Auto | 自动显示表达式/变量窗 | | | |
|
|
|
| static | 静态变量窗口 | | | |
|
|
|
|
|
|
|
* 寄存器信息 |
|
|
|
|
|
|
|
 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
* 内存信息 |
|
|
|
|
|
|
|
 |
|
|
|
|
|
|
|
 |
|
|
|
|
|
|
|
| 普通内存 | 简单内存 | |
|
|
|
| ------------ | ------------ | |
|
|
|
| 使用地址索引 | 变量名称索引 | |
|
|
|
|
|
|
|
___ |
|
|
|
|
|
|
|
|
|
|
|
* 汇编窗口 |
|
|
|
|
|
|
|
 |
|
|
|
* 栈信息汇编信息 |
|
|
|
*  |
|
|
|
|
|
|
|
 |
|
|
|
|
|
|
|
* 单步调试 |
|
|
|
*  |
|
|
|
|
|
|
|
编译-下载调试---开始-跳出--复位 |
|
|
|
 |
|
|
|
|
|
|
|
* 编译 |
|
|
|
|
|
|
|
* 全编译(make) |
|
|
|
|
|
|
|
* | **编译 (Compile)** | Ctrl+F7 | **当前文件**((`.c/.cpp/.s`)) | 生成 `.o` 对象文件 | |
|
|
|
| ---------------------- | ------- | -------------------------------- | --------------------------- | |
|
|
|
| **全编译 (Make)** | F7 | 全部文件 | 增量编译+链接 → 生成 `.out` | |
|
|
|
| **重建 (Rebuild All)** | - | **所有文件** | 全量编译+链接 → 完整输出 | |
|
|
|
|
|
|
|
编译-下载调试 |
|
|
|
|
|
|
|
* 在光标处添加断点 |
|
|
|
* 下载调试 |
|
|
|
* 调试 |
|
|
|
* 停止调试 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 图标 | 作用 | |
|
|
|
| -------------- | ------------------------------------------------------------ | |
|
|
|
| step over | 不进入内部直接得到结果 | |
|
|
|
| step into | 执行下一条语句,若遇到函数调用则进入该函数内部 | |
|
|
|
| step out | 立即执行完当前函数,并返回到调用该函数的位置 | |
|
|
|
| Run to Cursor | 全速执行到光标所在行暂停临时断点 | |
|
|
|
| Next Statement | **强制修改程序计数器(PC)**,将下条执行语句重定向到光标位置,程序暂停时执行 | |
|
|
|
|
|
|
|
# 拓展 |
|
|
|
|
|
|
|
## 调试器 |
|
|
|
|
|
|
|
stlink启动三种模式 |
|
|
|
|
|
|
|
| **复位模式** | **操作原理** | **适用场景** | **IAR 配置路径** | |
|
|
|
| :---------------------: | :---------------------------------: | :------------------------------: | :----------------------------------: | |
|
|
|
| **硬件复位 (Hardware)** | 拉低目标芯片的 **NRST 引脚** | 1. 芯片完全卡死 2. Flash锁死 | `Debugger > Setup > Reset: Hardware` | |
|
|
|
| **内核复位 (Core)** | 通过 **Cortex-M 调试端口** 复位内核 | 1. 保留外设状态 2. 快速重启调试 | `Debugger > Setup > Reset: Core` | |
|
|
|
| **系统复位 (System)** | 触发 **SYSRESETREQ 信号** | 1. 复位内核+外设 2. 模拟上电复位 | `Debugger > Setup > Reset: System` | |
|
|
|
| **软件复位 (Software)** | 写 **AIRCR 寄存器** | 1. 无NRST引脚设计 2. 远程复位 | `Debugger > Setup > Reset: Software` | |
|
|
|
|
|
|
|
| ST-link | j-link | I-Jet Trace | |
|
|
|
| -------- | ------------ | ----------- | |
|
|
|
| 低速5M | 较高 | 高速50M | |
|
|
|
| 便宜 | | 贵 | |
|
|
|
| | | iar深度绑定 | |
|
|
|
| SWD/JTAG | JTAG/SWD/SWO | 多ETM | |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 上电启动 |
|
|
|
|
|
|
|
* 硬件启动,启动 |
|
|
|
|
|
|
|
## 寄存器相关 |
|
|
|
|
|
|
|
| **寄存器** | **别名** | **位宽** | **核心作用** | **是否可自由使用** | |
|
|
|
| :--------: | :------------------: | :------: | :----------------------------: | :----------------: | |
|
|
|
| **R0-R12** | 通用寄存器 | 32-bit | 数据存储与运算 | ✅ 是 | |
|
|
|
| **R13** | SP (Stack Pointer) | 32-bit | 栈指针(管理函数调用栈) | ⚠️ 受限 | |
|
|
|
| **R14** | LR (Link Register) | 32-bit | 保存函数返回地址 | ⚠️ 受限 | |
|
|
|
| **R15** | PC (Program Counter) | 32-bit | 程序计数器(指向下条指令地址) | ❌ 不可直接修改 | |
|
|
|
| **xPSR** | 程序状态寄存器 | 32-bit | 记录运算状态(零/负/进位等) | ⚠️ 受限 | |
|
|
|
|
|
|
|
单片机启动项 |
|
|
|
|
|
|
|
## **Debugger和Download** |
|
|
|
|
|
|
|
| **特性** | **Debugger(调试器)** | **Download(下载)** | |
|
|
|
| :----------: | :------------------------: | :------------------------: | |
|
|
|
| **核心目标** | **实时监控与分析**程序行为 | **单向传输**固件到目标芯片 | |
|
|
|
| | 需支持调试协议的接口 | 只需物理连接 | |
|
|
|
| | 开发/测试 | 量产/维护 | |
|
|
|
|
|
|
|
## 栈使用空间大小分析 |
|
|
|
|
|
|
|
### 1.静态分析 |
|
|
|
|
|
|
|
`project-->options-->linker-->list-->Generate linker map file-->stack usage analysis` |
|
|
|
|
|
|
|
```yaml |
|
|
|
A[Project > Options] --> B[Linker] |
|
|
|
B --> C[List] |
|
|
|
C --> D[勾选 Generate linker map file] |
|
|
|
D --> E[勾选 Generate stack usage analysis] |
|
|
|
``` |
|
|
|
|
|
|
|
 |
|
|
|
|
|
|
|
| **选项名称** | **作用** | **推荐场景** | |
|
|
|
| :-------------------------------: | :----------------------------------------: | :----------------------: | |
|
|
|
| **✓ Generate linker map file** | 生成 `.map` 文件(内存布局详情+符号地址) | **必选**(内存分析必备) | |
|
|
|
| **✓ Generate log file** | 生成链接日志(库引用/段合并记录) | 调试链接问题时启用 | |
|
|
|
| **▢ Automatic library selection** | 自动选择依赖库(跳过未使用的库) | 启用可减小固件体积 | |
|
|
|
| **▢ Initialization decisions** | 记录全局变量初始化顺序(C++中关键) | C++多模块初始化调试 | |
|
|
|
| **▢ Module selections** | 列出所有被链接的 `.o/.a` 文件 | 检查冗余模块/库依赖 | |
|
|
|
| **▢ Redirected symbols** | 显示重定向符号(如 `printf` 重定向到串口) | 自定义库函数调试 | |
|
|
|
| **▢ Section selections** | 输出每个段(section)的详细地址分配 | 手动优化内存布局时 | |
|
|
|
| **▢ Stack usage call graph** | **栈使用调用图**(函数调用链+最大栈消耗) | **栈溢出分析必备** | |
|
|
|
| **▢ Unused section fragments** | 标记被丢弃的未使用段(如未调用的函数) | 清理死代码优化 Flash | |
|
|
|
| **▢ Veneer statistics** | 统计中断桥接(veneer)数量(跨域调用开销) | 长跳转指令优化 | |
|
|
|
|
|
|
|
> 编译生成静态文件然后进行分析 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 2.动态分析 |
|
|
|
|
|
|
|
## .icf文件分析 |
|
|
|
|
|
|
|
### 2.为变量分配固定内存块 |
|
|
|
|
|
|
|
#### 1. **定义内存块** |
|
|
|
|
|
|
|
```c |
|
|
|
define block MY_DATA_BLOCK with size = 256, alignment = 4 { }; |
|
|
|
``` |
|
|
|
|
|
|
|
#### 2. **分配区域** |
|
|
|
|
|
|
|
```c |
|
|
|
place in RAM_region { block MY_DATA_BLOCK }; |
|
|
|
``` |
|
|
|
|
|
|
|
#### 3. **C 代码中使用** |
|
|
|
|
|
|
|
```c |
|
|
|
#pragma location = "MY_DATA_BLOCK" |
|
|
|
__no_init uint8_t sensorBuffer[256]; // 分配到自定义块 |
|
|
|
``` |
|
|
|
|
|
|
|
#### 4. **高级用法:绝对地址分配** |
|
|
|
|
|
|
|
```c |
|
|
|
// 强制变量到0x20001000 |
|
|
|
#pragma location = 0x20001000 |
|
|
|
__no_init volatile uint32_t systemFlags; |
|
|
|
``` |