本帖最后由 kai迪皮 于 2024-3-4 16:01 编辑
#申请原创# @21小跑堂
1 背景
最近接到个需求,在生产电脑上(Windows),使用J-Link Commander + jlink V9工具对生产出的两款产品板卡的程序的分别烧录。画个图简单示意一下,相当于:
A产品的主控是APM32F030R8,B产品的主控是GD32E230C8。这两款产品的程序文件不一样,但是外形基本一致,为降低生产的技术员对产品程序进行烧录时需要额外人工识别主控芯片(人工识别有一定概率出错),减少生产耗时,需要我们使用技术手段去完成对不同产品分别下载不同程序的工作。让技术员拿到产品,点击一下就能完成固件烧录的工作。
基于这个需求,本文将记录开发该程序的过程。
2 技术思路
首先先明确使用的工具和生产环境。
1. Windows PC(7以上)
2. J-Link Commander
3. J-Link V9
由于生产环境电脑使用的系统是Windows 7,且使用的烧录工具是J-Link Commander + J-Link V9。我们可以使用脚本通过J-Link Commander + J-Link V9去识别产品主控的特征码,从而控制下载的程序文件。
基本思路如下:
3 熟悉JLink命令脚本
我们在批命令状态下获取MCU的特征码或者下载程序需要对JLink命令有一定的熟悉。
3.1 CPUID 确认
如我们需要读取 MCU的特征码,我们需要先写一个读取特征码的脚本配置。
1. 指定连接方式是SWD
2. 设备选择 M0 内核(读取CPUID)
3. 设置连接速度是 1000 KHz
4. 停止内核
5. 退出
最后输出的脚本如下:
si 1
device CORTEX-M0
speed 1000
halt
sleep 100
q
我们把上面的代码保存为:tempCommandFile.jlink,然后使用J-Link Commander打开,会发现输出的内容如下:
Selecting SWD as current target interface.
Selecting 1000 kHz as target interface speed
Target connection not established yet but required for command.
Device "CORTEX-M0" selected.
Connecting to target via SWD
Found SW-DP with ID 0x0BC11477
DPIDR: 0x0BC11477
Scanning AP map to find all available APs
AP[1]: Stopped AP scan as end of AP map has been reached
AP[0]: AHB-AP (IDR: 0x04770031)
Iterating through AP map to find AHB-AP to use
AP[0]: Core found
AP[0]: AHB-AP ROM base: 0xE00FF000
CPUID register: 0x410CC601. Implementer code: 0x41 (ARM)
Found Cortex-M0 r0p1, Little endian.
FPUnit: 4 code (BP) slots and 0 literal slots
CoreSight components:
ROMTbl[0] [url=home.php?mod=space&uid=72445]@[/url] E00FF000
ROMTbl[0][0]: E000E000, CID: B105E00D, PID: 000BB008 SCS
ROMTbl[0][1]: E0001000, CID: B105E00D, PID: 000BB00A DWT
ROMTbl[0][2]: E0002000, CID: B105E00D, PID: 000BB00B FPB
Cortex-M0 identified.
Reset delay: 0 ms
Reset type NORMAL: Resets core & peripherals via SYSRESETREQ & VECTRESET bit.
Reset: Halt core after reset via DEMCR.VC_CORERESET.
Reset: Reset device via AIRCR.SYSRESETREQ.
PC = 080000E0, CycleCnt = 00000000
R0 = FFFFFFFF, R1 = FFFFFFFF, R2 = FFFFFFFF, R3 = FFFFFFFF
R4 = FFFFFFFF, R5 = FFFFFFFF, R6 = FFFFFFFF, R7 = FFFFFFFF
R8 = FFFFFFFF, R9 = FFFFFFFF, R10= FFFFFFFF, R11= FFFFFFFF
R12= FFFFFFFF
SP(R13)= 20000410, MSP= 20000410, PSP= FFFFFFFC, R14(LR) = FFFFFFFF
XPSR = F1000000: APSR = NZCVq, EPSR = 01000000, IPSR = 000 (NoException)
CFBP = 00000000, CONTROL = 00, FAULTMASK = 00, BASEPRI = 00, PRIMASK = 00
FPU regs: FPU not enabled / not implemented on connected CPU.
Sleep(100)
Script processing completed.
这里面的“CPUID register: 0x410CC601.”便是我们所需要使用的东西。我们实际上对APM32F030R8和GD32E230C8进行CPUID register读取。会发现:
1. APM32F030R8 CPUID register: 0x410CC601.
2. GD32E230C8 CPUID register: 0x411CD200.
3.2 程序下载
使用J-Link Commander及其脚本对芯片进行下载,如APM32F030R8,我们需要:
1. 设备选择APM32F030R8
2. 指定连接方式是SWD
3. 设置连接速度是 4000 KHz
4. 停止内核
5. 选择下载的程序,如:apm32f030_loadfile.hex
6. 复位芯片
7. 运行程序
8. 退出
我们把上面的操作用指令的形式进行运行操作如下:
JLink.exe -Device APM32F030R8 -If SWD -Speed 4000 -AutoConnect 1 -CommanderScript apm32f030_loadfile.jlink
apm32f030_loadfile.jlink内容为:
h
loadfile loadfile\apm32f030_loadfile.hex //loadfile 不提供下载后校验的功能,下载后校验的功能需要 loadbin verifybin 功能
r
g
exit
4 批命令控制流程
我们在上文基本完成了技术实现的流程梳理和使用jlink对目标MCU的识别和程序的下载。下面就使用批命令脚本,作为流程控制。
4.1 MCU验证
我们要识别“ CPUID register: ”后面的内容,以判断当前连接的MCU是啥型号的。代码如下:
REM 创建J-Link命令脚本来读取Core ID
(
ECHO si 1
ECHO device CORTEX-M0
ECHO speed 1000
ECHO halt
ECHO sleep 100
ECHO q
) > "%JLINK_SCRIPT_PATH%tempCommandFile.jlink"
REM 执行JLink命令脚本,并将输出保存到临时文件中
"%JLINK_EXE%" -CommanderScript "%JLINK_SCRIPT_PATH%tempCommandFile.jlink" > "%JLINK_SCRIPT_PATH%tempDeviceInfo.txt"
REM 从临时文件中读取CPUID register的值 这里读到的内容eg:CPUID register: 0x410CC601.
FOR /F "tokens=3" %%i IN ('findstr /C:"CPUID register" "%JLINK_SCRIPT_PATH%tempDeviceInfo.txt"') DO (
SET "CPUID=%%i"
REM 下面这行用于打印出CPUID register的值
ECHO CPUID : %%i
)
4.2 程序下载验证
还有我们要判断程序下载是否成功:
ECHO Device : APM32F030
ECHO ****************************************************************
ECHO Download : apm32f030_loadfile.hex...
"%JLINK_EXE%" -Device APM32F030R8 -If SWD -Speed 4000 -AutoConnect 1 -CommanderScript "%JLINK_SCRIPT_PATH%apm32f030_loadfile.jlink" > "%JLINK_SCRIPT_PATH%log\apm32f030_loadfile_log_!TIMESTAMP!.txt"
REM 检查烧录结果
FOR /F "tokens=*" %%a IN ('findstr /C:"O.K." "%JLINK_SCRIPT_PATH%log\apm32f030_loadfile_log_!TIMESTAMP!.txt"') DO (
SET "FLASH_RESULT=%%a"
)
4.3 日志输出
为便于记录下载的过程,我这里保留了下载的日志信息。后续可以通过工具可以知道下载了多少个产品,分别有多少个APM32F030R8主控的,多少GD32E230C8主控的。
首先是时间戳计算:
REM 根据当前日期获取,年月日串
SET yyyy=%date:~,4%
SET mm=%date:~5,2%
SET day=%date:~8,2%
SET "YYYYmmdd=%yyyy%%mm%%day%"
REM 把年月日串中的空格替换为0
SET "YYYYmmdd=%YYYYmmdd: =0%"
REM 根据当前时间获取,时分秒串
SET hh=%time:~0,2%
SET mi=%time:~3,2%
SET ss=%time:~6,2%
SET "hhmiss=%hh%%mi%%ss%"
SET "hhmiss=%hhmiss: =0%"
REM 把时间串中的:替换为0
SET "hhmiss=%hhmiss::=0%"
REM 把时间串中的空格替换为0
SET "hhmiss=%hhmiss: =0%"
REM 根据日期时间生成文件名称,中间以HH区分日期和时间部分
SET "TIMESTAMP=%YYYYmmdd%_%hhmiss%"
然后输出log文件名:
> "%JLINK_SCRIPT_PATH%log\apm32f030_loadfile_log_!TIMESTAMP!.txt"
5 验证效果
最后上一下效果:
这里是代码:
APM32F030_GD32E230_jlink区分并自动下载.zip
(19.85 KB)
补充使用说明:
1. J-Link安装路径修改。J-Link_Commander_user_apm32f030_gd32e230_log.bat,行3,的JLink安装路径与自己的路径相符合。
2. 脚本下载log是否删除设置。J-Link_Commander_user_apm32f030_gd32e230_log.bat,行82、行96,加入REM 则保留log,去除REM 则删除log。(REM 即注释含义)
3. 下载程序设置。下载的程序放在loadfile文件夹中,在apm32f030_loadfile.jlink/gd32e230_loadfile.jlink中使用(相对路径),可修改apm32f030_loadfile.jlink/gd32e230_loadfile.jlink中的行2,已修改下载的文件。
使用注意事项:
1. 保存路径建议以全英文(包括不含中文空格)。
2. 脚本判断是否下载成功是以“.bat”中去分析下载log中是否有“O.K.”字符来进行的。请留意:修改“.jlink”中的相关下载指令后修改匹配字符的内容。
不知道是否能帮上你的忙,请在评论区留言讨论吧。
|
@21小跑堂 :感谢支持
一种为简化人工烧录芯片识别和防止错烧的解决办法,通过识别识别MCU特征码自动区分下载烧录固件,很有现实意义的操作。