学习时长:约 30 分钟
难度级别:⭐⭐☆☆☆
前置知识:第 2.1 节项目目录结构
- 掌握 Keil MDK-ARM 的安装与配置
- 学会导入和配置 OneOS-Lite 项目
- 掌握编译、下载和调试流程
- 能够解决常见的编译和调试问题
| 软件 | 版本要求 | 说明 |
|---|
| Keil MDK-ARM | 5.25 或更高 | 集成开发环境 |
| 芯片支持包 | 对应芯片型号 | Device Family Pack |
| J-Link / ST-Link | 最新驱动 | 调试器及驱动 |
- 下载安装 Keil MDK-ARM(uVision5)
- 在 Pack Installer 中安装对应芯片的 Device Family Pack
- 安装调试器驱动(J-Link 或 ST-Link)
- 获取 OneOS-Lite 源码
- 打开 Keil uVision5
- 选择
Project → Open Project - 导航到项目目录,选择
.uvprojx 文件
# 使用模板创建项目
cp -r templates/stm32f103zet6-atk-elite projects/my_project
cd projects/my_project
在 Options for Target → Device 中选择正确的芯片型号:
| 开发板 | 芯片型号 |
|---|
| STM32F103 精英版 | STM32F103ZE |
| STM32F407 探索者 | STM32F407ZG |
| STM32F429 阿波罗 | STM32F429IG |
Options for Target → C/C++ (AC6)
| 选项 | 推荐设置 | 说明 |
|---|
| Optimization | -O0(调试)/ -O2(发布) | 优化级别 |
| Warnings | -Wall -Wextra | 开启所有警告 |
| One ELF Section per Function | 勾选 | 减小代码体积 |
| Language C | C99 | C 语言标准 |
Options for Target → C/C++ → Define
USE_STDPERIPH_DRIVER // 使用标准外设库
STM32F10X_HD // 芯片型号定义
OS_USING_CONSOLE // OneOS 控制台
Options for Target → C/C++ → Include Paths
典型的头文件路径配置:
..\..\..\kernel\include
..\..\..\arch\arm\armv7m\include
..\..\..\drivers\include
..\..\..\components\fs\include
..\..\..\components\net\include
..\board\CMSIS
..\board\StdPeriph\inc
Options for Target → Linker
- 勾选
Use Memory Layout from Target Dialog - 或手动指定分散加载文件(
.sct)
; 分散加载文件示例
LR_IROM1 0x08000000 0x00080000 { ; 加载区域(Flash 512KB)
ER_IROM1 0x08000000 0x00080000 { ; 执行区域
*.o (RESET, +First) ; 向量表放在最前面
*(InRoot$$Sections) ; 库段
.ANY (+RO) ; 只读数据
}
RW_IRAM1 0x20000000 0x00010000 { ; RAM 区域(64KB)
.ANY (+RW +ZI) ; 读写和零初始化数据
}
}
Options for Target → Debug
| 调试器 | 接口 | 适用场景 |
|---|
| J-Link / J-Trace | SWD / JTAG | 通用调试,速度快 |
| ST-Link Debugger | SWD | STM32 系列 |
| CMSIS-DAP | SWD | 开源调试器 |
Options for Target → Debug → Settings
| 设置项 | 推荐值 |
|---|
| Port | SWD(推荐) |
| Max Clock | 根据硬件能力(通常 5MHz) |
| Reset | SYSRESETREQ |
| Connect | Normal |
| Reset after Connect | 勾选 |
Options for Target → Utilities → Settings
- 选择对应的 Flash 编程算法
- 勾选
Reset and Run(下载后自动运行)
- 点击
Build(F7)编译当前文件 - 点击
Rebuild 重新编译全部文件 - 查看
Build Output 窗口确认编译结果
Build Output 示例:
compiling os_task.c...
linking...
Program Size: Code=28456 RO-data=1234 RW-data=456 ZI-data=8192
FromELF: creating hex file...
".\Objects\project.axf" - 0 Error(s), 0 Warning(s).
Build Time Elapsed: 00:00:05
- 连接调试器到开发板
- 开发板上电
- 点击
Download(F8)下载程序 - 观察开发板运行情况
从编译输出中分析内存使用:
| 段 | 含义 | 存储位置 |
|---|
| Code | 代码段 | Flash |
| RO-data | 只读数据(常量) | Flash |
| RW-data | 已初始化读写数据 | Flash → RAM |
| ZI-data | 零初始化数据(BSS) | RAM |
Flash 占用 = Code + RO-data + RW-data
RAM 占用 = RW-data + ZI-data
| 窗口 | 用途 |
|---|
| Register | 查看 CPU 寄存器值 |
| Memory | 查看内存内容 |
| Watch | 监控变量值变化 |
| Call Stack | 查看函数调用栈 |
| Serial | 串口输出查看 |
// 硬件断点(Cortex-M3/M4 支持 6-8 个)
// 在代码行前双击设置
// 条件断点
// 右键断点 → Condition → 输入条件表达式
// 例如: i == 100
// 数据断点(监视内存地址变化)
// Debug → Breakpoints → New → Access
#include "core_cm3.h"
void Measure_Execution_Time(void)
{
// 使能 DWT 周期计数器
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
uint32_t start = DWT->CYCCNT;
Function_To_Measure();
uint32_t cycles = DWT->CYCCNT - start;
printf("Cycles: %lu, Time: %lu us\r\n",
cycles, cycles / (SystemCoreClock / 1000000));
}
| 错误 | 原因 | 解决方案 |
|---|
undefined symbol | 链接器找不到符号 | 检查源文件是否添加;确认库文件路径 |
section overlaps | 内存区域重叠 | 调整分散加载文件大小 |
core_cm3.h not found | CMSIS 头文件缺失 | 检查芯片支持包安装 |
invalid register | 汇编语法错误 | 检查编译器版本和语法 |
| 问题 | 原因 | 解决方案 |
|---|
| 无法连接调试器 | 连接或配置问题 | 检查连接线、供电、接口设置 |
| 程序运行异常 | 多种可能 | 检查栈/堆大小、HardFault 信息 |
| 断点无效 | 代码被优化 | 使用 -O0 编译 |
- 启用编译器优化
-O2 - 使用内联函数减少调用开销
- 优化循环和条件判断
- 减少全局变量使用
- 分析
.map 文件了解内存分布
本节介绍了 OneOS-Lite 在 Keil5 MDK-ARM 下的开发环境配置:
- 环境准备:安装 Keil5、芯片支持包、调试器驱动
- 项目配置:目标设备、编译器选项、头文件路径、链接器配置
- 编译下载:编译流程、下载步骤、内存使用分析
- 调试技巧:断点设置、执行时间测量、常用调试窗口
- 问题排解:常见编译/调试错误及解决方案