1. 本文要解决什么问题
本文记录一次在 Windows 下使用 Keil MDK 配置 TI MSPM0G3507 开发环境时遇到的完整排错过程。
目标是让 Keil 能够正常编译 MSPM0G3507 的空白工程:
empty_LP_MSPM0G3507_nortos_keil
排查过程中主要遇到了以下几类问题:
系统找不到指定的路径。
armclang: error: no such file or directory: '../ti_msp_dl_config.c'
error: 'ti_msp_dl_config.h' file not found
Couldn't find .metadata\product.json
Invalid argument '-s': File "C:\.metadata\product.json" does not exist
error: 'ti/devices/msp/msp.h' file not found
L6002U: Could not open file ../../source/ti/driverlib/lib/keil/m0p/mspm0g1x0x_g3x0x/driverlib.a
这些错误看起来分散,但本质上都和一个问题有关:
Keil 工程被移动后,工程里的相对路径不再指向正确的 MSPM0 SDK 目录,导致 SysConfig 脚本、SDK 头文件和 driverlib 静态库都找不到。
2. 我的环境信息
本文中的路径和版本来自本次实际排错环境:
Keil MDK 编译器:ARMCLANG V6.24
Keil 安装路径:C:\d\Keil5\MDK\ARM\ARMCLANG\Bin
MSPM0 SDK 路径:C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05
SysConfig 路径:C:\Ti\SYSCONFIG\sysconfig_cli.bat
工程路径:C:\Ti\Project\empty\keil
工程名:empty_LP_MSPM0G3507_nortos_keil
芯片/开发板:MSPM0G3507 / LP_MSPM0G3507
如果你的安装路径不同,需要把本文中的路径替换成你自己电脑上的真实路径。
例如:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05
需要替换为你自己的 MSPM0 SDK 安装目录。
3. 背景知识:为什么 MSPM0 工程依赖 SysConfig
TI MSPM0 工程通常不是纯手写初始化代码,而是通过 SysConfig 生成一部分外设配置代码。
工程里会有一个文件:
empty.syscfg
这个文件不是 C 源码,而是 SysConfig 的配置文件。Keil 在编译前会先调用 TI 的 SysConfig 工具,根据 empty.syscfg 生成下面两个文件:
ti_msp_dl_config.c
ti_msp_dl_config.h
然后工程中的业务代码再包含这个头文件:
#include "ti_msp_dl_config.h"
所以如果 SysConfig 没有正常运行,就会出现:
../ti_msp_dl_config.c 找不到
ti_msp_dl_config.h file not found
这类错误不是 C 代码写错了,而是编译前的代码生成步骤没有成功执行。
4. 第一个问题:Before Build 找不到 syscfg.bat
最开始 Keil 编译时出现了下面的日志:
Before Build - User command #1: cmd.exe /C "C:\Ti\Project\empty\keil\../../tools/keil/syscfg.bat 'C:\Ti\Project\empty\keil\' empty.syscfg"
系统找不到指定的路径。
后面紧跟着出现:
armclang: error: no such file or directory: '../ti_msp_dl_config.c'
../empty.c(33): error: 'ti_msp_dl_config.h' file not found
4.1 原因分析
Keil 的 Before Build 命令中使用了相对路径:
../../tools/keil/syscfg.bat
当前工程路径是:
C:\Ti\Project\empty\keil
所以这个相对路径实际会被解析为:
C:\Ti\Project\tools\keil\syscfg.bat
但是 syscfg.bat 实际在 MSPM0 SDK 目录中:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\tools\keil\syscfg.bat
因此 Keil 找不到脚本。
4.2 解决方法
进入 Keil:
Project -> Options for Target -> User -> Before Build/Rebuild
把 Before Build 命令改成绝对路径:
cmd.exe /C call "C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\tools\keil\syscfg.bat" "C:\Ti\Project\empty\keil" empty.syscfg
这里需要注意两点:
第一,使用 call 调用 .bat 文件。
第二,工程路径最后不要加反斜杠:
"C:\Ti\Project\empty\keil"
不要写成:
"C:\Ti\Project\empty\keil\"
否则 Windows 命令行解析引号时容易出错。
5. 第二个问题:cmd /C 引号解析错误
修改命令后,曾经出现过下面的错误:
'C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\tools\keil\syscfg.bat" "C:\Ti\Project\empty\keil\' 不是内部或外部命令,也不是可运行的程序或批处理文件。
5.1 原因分析
原命令类似这样:
cmd.exe /C "C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\tools\keil\syscfg.bat" "C:\Ti\Project\empty\keil\" empty.syscfg
cmd.exe /C 后面如果第一个内容就是带引号的可执行路径,后面又接参数,Windows 有时会把命令和参数拼接错。
5.2 解决方法
使用 call:
cmd.exe /C call "C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\tools\keil\syscfg.bat" "C:\Ti\Project\empty\keil" empty.syscfg
重新编译后,Keil 日志中能看到:
Using Sysconfig Tool from "C:\Ti\SYSCONFIG\sysconfig_cli.bat"
说明 syscfg.bat 已经被成功调用。
6. 第三个问题:Couldn't find .metadata\product.json
虽然 syscfg.bat 已经被调用,但又出现了新的错误:
"Couldn't find .metadata\product.json"
Invalid argument '-s': File "C:\.metadata\product.json" does not exist
6.1 原因分析
MSPM0 SDK 根目录下有一个重要文件:
.metadata\product.json
正常情况下,它应该位于:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\.metadata\product.json
但是 TI 提供的 tools\keil\syscfg.bat 默认会从工程目录开始,一层一层向上查找 .metadata\product.json。
当前工程在:
C:\Ti\Project\empty\keil
脚本会依次查找:
C:\Ti\Project\empty\keil\.metadata\product.json
C:\Ti\Project\empty\.metadata\product.json
C:\Ti\Project\.metadata\product.json
C:\Ti\.metadata\product.json
C:\.metadata\product.json
它不会自动跳到:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05
所以最后报错:
File "C:\.metadata\product.json" does not exist
6.2 解决方法一:把工程放回 SDK 根目录
这是最推荐的方式。
如果参考的教程要求把 empty 工程复制到 SDK 根目录下,那么工程路径应该类似:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\empty\keil
而不是:
C:\Ti\Project\empty\keil
这样 syscfg.bat 从工程目录向上查找时,就能找到:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\.metadata\product.json
此时 Before Build 可以使用相对路径:
cmd.exe /C call "$P../../tools/keil/syscfg.bat" "$P" empty.syscfg
其中 $P 是 Keil 当前工程目录。
如果工程位于:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\empty\keil
那么:
$P../../tools/keil/syscfg.bat
就会指向:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\tools\keil\syscfg.bat
6.3 解决方法二:工程放在外部目录时,固定 SDK_ROOT
如果必须把工程放在:
C:\Ti\Project\empty\keil
那么就不能继续依赖 syscfg.bat 自动向上查找 SDK 根目录,而应该在脚本里固定 SDK 路径。
可以备份原始文件:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\tools\keil\syscfg.bat
然后把它改成类似下面的版本:
@echo off
set "SYSCFG_PATH=C:\Ti\SYSCONFIG\sysconfig_cli.bat"
set "SDK_ROOT=C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05"
if not exist "%SYSCFG_PATH%" (
echo Couldn't find SysConfig Tool: "%SYSCFG_PATH%"
exit /b 1
)
if not exist "%SDK_ROOT%\.metadata\product.json" (
echo Couldn't find SDK product file: "%SDK_ROOT%\.metadata\product.json"
exit /b 1
)
set "PROJ_DIR=%~1"
set "PROJ_DIR=%PROJ_DIR:'=%"
set "SYSCFG_FILE=%~2"
set "SYSCFG_FILE=%SYSCFG_FILE:'=%"
if "%PROJ_DIR:~-1%"=="\" set "PROJ_DIR=%PROJ_DIR:~0,-1%"
echo Using SysConfig Tool from "%SYSCFG_PATH%"
echo Using SDK from "%SDK_ROOT%"
echo Project dir: "%PROJ_DIR%"
echo Syscfg file: "%SYSCFG_FILE%"
call "%SYSCFG_PATH%" -o "%PROJ_DIR%\.." -s "%SDK_ROOT%\.metadata\product.json" --compiler keil "%PROJ_DIR%\%SYSCFG_FILE%"
改完后,Keil 的 Before Build 保持:
cmd.exe /C call "C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\tools\keil\syscfg.bat" "C:\Ti\Project\empty\keil" empty.syscfg
成功时日志应该出现:
Using SysConfig Tool from "C:\Ti\SYSCONFIG\sysconfig_cli.bat"
Using SDK from "C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05"
Project dir: "C:\Ti\Project\empty\keil"
Syscfg file: "empty.syscfg"
不应该再出现:
Couldn't find .metadata\product.json
Invalid argument '-s': File "C:\.metadata\product.json" does not exist
7. 第四个问题:ti/devices/msp/msp.h file not found
解决 SysConfig 脚本调用后,继续编译时出现:
..\ti_msp_dl_config.h(54): error: 'ti/devices/msp/msp.h' file not found
54 | #include <ti/devices/msp/msp.h>
| ^~~~~~~~~~~~~~~~~~~~~~
7.1 原因分析
ti_msp_dl_config.h 中包含了:
#include <ti/devices/msp/msp.h>
这个头文件属于 MSPM0 SDK,通常位于:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\source\ti\devices\msp\msp.h
由于代码中写的是:
#include <ti/devices/msp/msp.h>
所以 Keil 的 Include Path 必须包含 SDK 的 source 目录:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\source
如果 Include Path 没加这个目录,编译器就无法找到 ti/devices/msp/msp.h。
7.2 解决方法
进入 Keil:
Project -> Options for Target -> C/C++ (AC6) -> Include Paths
添加:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\source
如果你的工程放在 SDK 根目录下,也可以使用相对路径:
../../source
如果后续出现 CMSIS 相关头文件找不到,可以再添加:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\source\third_party\CMSIS\Core\Include
但针对本文中的 msp.h 报错,首先需要添加的是:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\source
7.3 验证方法
重新 Rebuild。
如果这个问题解决,日志中不应该再出现:
'ti/devices/msp/msp.h' file not found
编译阶段应该能够通过,并进入链接阶段。
8. 第五个问题:链接阶段找不到 driverlib.a
编译阶段通过后,又遇到链接错误:
linking...
.\Objects\empty_LP_MSPM0G3507_nortos_keil.axf: error: L6002U: Could not open file ../../source/ti/driverlib/lib/keil/m0p/mspm0g1x0x_g3x0x/driverlib.a: No such file or directory
8.1 原因分析
这次不是头文件找不到,而是链接器找不到静态库:
driverlib.a
Keil 工程里原来的库路径是:
../../source/ti/driverlib/lib/keil/m0p/mspm0g1x0x_g3x0x/driverlib.a
如果工程在 SDK 根目录下,例如:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\empty\keil
那么这个相对路径能正确指向:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\source\ti\driverlib\lib\keil\m0p\mspm0g1x0x_g3x0x\driverlib.a
但当前工程在:
C:\Ti\Project\empty\keil
相对路径会被解析为:
C:\Ti\Project\source\ti\driverlib\lib\keil\m0p\mspm0g1x0x_g3x0x\driverlib.a
这个路径不存在,所以链接失败。
8.2 解决方法
先确认真实库文件是否存在。
在 CMD 中运行:
dir C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\source\ti\driverlib\lib\keil\m0p\mspm0g1x0x_g3x0x\driverlib.a
如果文件存在,就说明只是 Keil 工程里的库路径错了。
进入 Keil:
Project -> Options for Target -> Linker
查找是否存在:
../../source/ti/driverlib/lib/keil/m0p/mspm0g1x0x_g3x0x/driverlib.a
把它改成绝对路径:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\source\ti\driverlib\lib\keil\m0p\mspm0g1x0x_g3x0x\driverlib.a
如果 Keil 对反斜杠兼容不好,可以写成:
C:/Ti/M0_SDK/mspm0_sdk_2_02_00_05/source/ti/driverlib/lib/keil/m0p/mspm0g1x0x_g3x0x/driverlib.a
也可以在 Keil 左侧工程树中找到 driverlib.a,右键查看属性,把它的路径从相对路径改成 SDK 中的真实路径。
8.3 如果找不到 driverlib.a
如果上面的 dir 命令提示找不到文件,可以在 SDK 目录中搜索:
dir C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\driverlib.a /s
找到真实路径后,再把 Keil 里的库路径改成对应位置。
9. 两种可行的最终配置方案
经过排查,可以总结出两种可行方案。
方案 A:工程放在 SDK 根目录下
这是最接近 TI 官方例程和教程设计的方式。
目录结构如下:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05
├── .metadata
│ └── product.json
├── source
├── tools
│ └── keil
│ └── syscfg.bat
└── empty
└── keil
└── empty_LP_MSPM0G3507_nortos_keil.uvprojx
Keil 的 Before Build:
cmd.exe /C call "$P../../tools/keil/syscfg.bat" "$P" empty.syscfg
Include Path 使用:
../../source
driverlib.a 使用:
../../source/ti/driverlib/lib/keil/m0p/mspm0g1x0x_g3x0x/driverlib.a
这种方式的优点是:相对路径基本不用改。
缺点是:工程需要放在 SDK 目录下,不太适合后续自己管理多个项目。
方案 B:工程放在自定义目录,所有 SDK 路径改成绝对路径
如果希望工程放在:
C:\Ti\Project\empty\keil
那么必须处理三类路径。
第一,Before Build 调用 SDK 中的 syscfg.bat:
cmd.exe /C call "C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\tools\keil\syscfg.bat" "C:\Ti\Project\empty\keil" empty.syscfg
第二,syscfg.bat 里固定 SDK_ROOT:
set "SDK_ROOT=C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05"
第三,Keil 的 Include Path 加 SDK source:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\source
第四,Linker 中的 driverlib.a 改成绝对路径:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\source\ti\driverlib\lib\keil\m0p\mspm0g1x0x_g3x0x\driverlib.a
这种方式的优点是:工程可以放在自己的项目目录中。
缺点是:需要手动维护路径。如果换 SDK 版本,需要同步修改路径。
10. 如何验证最终配置成功
配置完成后,在 Keil 中执行:
Project -> Rebuild all target files
成功时应该满足以下条件。
第一,SysConfig 阶段不再出现:
Couldn't find .metadata\product.json
第二,编译阶段不再出现:
'ti/devices/msp/msp.h' file not found
第三,链接阶段不再出现:
L6002U: Could not open file driverlib.a
第四,最终应该生成:
Objects\empty_LP_MSPM0G3507_nortos_keil.axf
Keil 输出中应该类似:
0 Error(s), 0 Warning(s)
Target created.
如果能看到 Target created,说明工程已经完成编译和链接。
11. 常见问题汇总
问题一:系统找不到指定的路径
现象:
Before Build - User command #1: cmd.exe /C "...\tools/keil/syscfg.bat ..."
系统找不到指定的路径。
原因:
Keil 的 Before Build 命令中 syscfg.bat 路径错误。通常是工程被复制到了 SDK 外部目录,导致相对路径失效。
解决:
把 Before Build 改成真实路径:
cmd.exe /C call "C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\tools\keil\syscfg.bat" "C:\Ti\Project\empty\keil" empty.syscfg
或者把工程放回 SDK 根目录,继续使用相对路径。
验证:
重新编译后,日志中应该出现:
Using Sysconfig Tool from "C:\Ti\SYSCONFIG\sysconfig_cli.bat"
问题二:ti_msp_dl_config.h file not found
现象:
../empty.c(33): error: 'ti_msp_dl_config.h' file not found
原因:
SysConfig 没有成功运行,导致 ti_msp_dl_config.c 和 ti_msp_dl_config.h 没有生成。
解决:
先修复 Before Build 中的 SysConfig 调用命令,确保 empty.syscfg 能生成对应 C/H 文件。
验证:
工程目录上一级应该能看到:
ti_msp_dl_config.c
ti_msp_dl_config.h
问题三:Couldn't find .metadata\product.json
现象:
"Couldn't find .metadata\product.json"
Invalid argument '-s': File "C:\.metadata\product.json" does not exist
原因:
syscfg.bat 没有找到 SDK 根目录。常见原因是工程不在 SDK 目录树下。
解决:
推荐把工程放到 SDK 根目录下:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\empty\keil
如果必须放在外部目录,则修改 syscfg.bat,固定:
set "SDK_ROOT=C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05"
验证:
重新编译后,不应再出现 C:\.metadata\product.json 相关错误。
问题四:ti/devices/msp/msp.h file not found
现象:
error: 'ti/devices/msp/msp.h' file not found
原因:
Keil Include Path 没有包含 MSPM0 SDK 的 source 目录。
解决:
在 Keil 中添加 Include Path:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\source
验证:
重新编译后,不再出现 msp.h file not found。
问题五:L6002U Could not open driverlib.a
现象:
L6002U: Could not open file ../../source/ti/driverlib/lib/keil/m0p/mspm0g1x0x_g3x0x/driverlib.a
原因:
链接器中的 driverlib.a 路径仍然是相对路径,但工程已经不在 SDK 根目录下,相对路径解析错误。
解决:
把库文件路径改成绝对路径:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\source\ti\driverlib\lib\keil\m0p\mspm0g1x0x_g3x0x\driverlib.a
验证:
重新 Rebuild,链接阶段不再报 L6002U。
12. 工程化建议
如果只是跟着教程跑通第一个工程,建议使用方案 A:把工程放到 SDK 根目录下。这样最少改路径,最容易和教程保持一致。
如果后续要自己维护多个项目,建议使用方案 B:工程放在自己的项目目录中,但要统一管理 SDK 路径。
可以约定一个固定 SDK 根目录:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05
然后在 Keil 中统一使用绝对路径:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\source
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\tools\keil\syscfg.bat
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\source\ti\driverlib\lib\keil\m0p\mspm0g1x0x_g3x0x\driverlib.a
这样即使工程移动,编译也不会因为相对路径失效。
但这种方式也有代价:如果升级 SDK 版本,例如从:
mspm0_sdk_2_02_00_05
升级到:
mspm0_sdk_2_xx_xx_xx
需要同步修改 Keil 工程中的路径。
13. 完整复现清单
13.1 准备文件
需要准备:
Keil MDK
MSPM0 SDK
TI SysConfig
MSPM0G3507 Keil 示例工程
本文环境中的关键路径是:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05
C:\Ti\SYSCONFIG\sysconfig_cli.bat
C:\Ti\Project\empty\keil
13.2 检查 SysConfig
确认文件存在:
dir C:\Ti\SYSCONFIG\sysconfig_cli.bat
13.3 检查 SDK product.json
确认文件存在:
dir C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\.metadata\product.json
13.4 检查 SDK 头文件
确认文件存在:
dir C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\source\ti\devices\msp\msp.h
13.5 检查 driverlib.a
确认文件存在:
dir C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\source\ti\driverlib\lib\keil\m0p\mspm0g1x0x_g3x0x\driverlib.a
如果找不到,搜索:
dir C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\driverlib.a /s
13.6 配置 Before Build
Keil 中配置:
Project -> Options for Target -> User -> Before Build/Rebuild
如果工程在 SDK 外部目录,使用:
cmd.exe /C call "C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\tools\keil\syscfg.bat" "C:\Ti\Project\empty\keil" empty.syscfg
13.7 配置 Include Path
Keil 中配置:
Project -> Options for Target -> C/C++ (AC6) -> Include Paths
添加:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\source
13.8 配置 driverlib.a
Keil 中配置:
Project -> Options for Target -> Linker
把 driverlib.a 路径改成:
C:\Ti\M0_SDK\mspm0_sdk_2_02_00_05\source\ti\driverlib\lib\keil\m0p\mspm0g1x0x_g3x0x\driverlib.a
13.9 Rebuild 验证
在 Keil 中执行:
Project -> Rebuild all target files
成功时应该看到:
Target created.
0 Error(s), 0 Warning(s)
14. 总结
这次 Keil 配置 MSPM0G3507 环境的核心问题不是编译器错误,也不是 C 代码错误,而是工程路径移动后,TI 示例工程中的相对路径失效。
整个排错过程可以归纳为三类路径问题:
第一,SysConfig 脚本路径错误,导致 ti_msp_dl_config.c/h 无法生成。
第二,SDK Include Path 缺失,导致 ti/devices/msp/msp.h 找不到。
第三,driverlib 静态库路径错误,导致链接器找不到 driverlib.a。
如果按教程把工程放在 SDK 根目录下,很多相对路径可以直接成立。如果要把工程放到自己的项目目录中,就需要把 SysConfig、SDK source、driverlib.a 这几个路径全部改成明确的绝对路径。
遇到这类问题时,不要只盯着最后一条报错。Keil 的日志要从上往下看,第一条路径错误往往才是真正根因。后面的 ti_msp_dl_config.h not found、msp.h not found、driverlib.a not found,通常都是前面路径配置错误引发的连锁反应。