【ARM Cortex-M7 使用 Python 脚本通过 J-link 烧录 bin 文件 】
文章目录
-
- 简介
-
- 1.1.1 J-link 信息扫描
- 1.1.2 j-link 烧写脚本
简介
固件烧录有很多方式,比如 uart, usb, spi等,这里主要介绍的是 Cortex-M7
的J-link的烧写方式,J-link debuger 通过 DAP 可以访问 SoC 中 memory-maped 地址,所以可以通过 j-link 读写 SoC 中的地址来完成镜像的烧写。
一般的烧写都是烧写 xxx.img(rt-thread.bin)
固件,通常来说 img 固件是在 二进制 bin
文件的基础上加了一个 header
而已,这个 header
里面包含了一些信息,比如 固件的大小,固件运行的平台架构(ARM/X86/Power PC)及 OS(RTOS/Linux...)
,固件的 load 地址
及 运行地址
等。
而 bin
文件的产生是来自于 elf
文件,通常使用 gcc
编译出来最原始的可执行文件是 elf
文件,由于 elf
文件里包含了需要 debug 信息及一些 基本上用不到的信息,所以会将 elf 文件通过 一些命令将(objcopy
)进行删减,删减之后剩余的部分就是 bin
文件了。
通常 elf
文件到 bin
再到 img
文件都是在编译脚本里做好的,有时还会对 img
进行加密操作,用来做安全启动使用。
1.1.1 J-link 信息扫描
J-link 自带 loadbin
命令,也即直接 load
二进制文件,在执行下图中的"USB" 命令之前需要先把板子上电然后连接上 j-link, 连上 j-link 之后执行 usb 命令可以自动完成对 cortex-m7
的扫描,从下面打印的信息可以看到扫描出来的内容主要是 Coresight 中的一些组件,比如 DWT/FPB/ITM/ETM/CTI等,还有 Cache
的信息。
1.1.2 j-link 烧写脚本
import os
import time
# import subprocesscmd= 'C:\\\\Users\\\\admin\\\\Desktop\\\\USBRelay\\\\CommandApp_USBRelay.exe QAAMZ open 1'
p=os.popen(cmd)
time.sleep(1)
cmd= 'C:\\\\Users\\\\admin\\\\Desktop\\\\USBRelay\\\\CommandApp_USBRelay.exe QAAMZ close 1'
p=os.popen(cmd)# read rtthread.bin and get the entry point
img_path=r"X:\\demo_test\\rtos\\rt-thread\\rt-thread\\bsp\\demo\\demo_test\\demo_test_fpga\\rtthread.bin"
with open(img_path, 'rb') as f:f.seek(4,0) # seek entry point positionfirstline = f.read(4)#print(firstline)#print('entry point: %x%x%x%x' %(firstline[3],firstline[2],firstline[1],firstline[0]))ep_int=int(firstline[3])<<24 | int(firstline[2])<<16 | int(firstline[1])<<8 | int(firstline[0])ep_hex=hex(ep_int)print(ep_hex)f.close()# create jlink download script
current_path = os.getcwd()
with open(current_path + '/' + 'rtos_download.jlink', 'w', encoding='utf-8') as f:f.write('r'+'\\n') # reset socf.write('h'+'\\n') # stop cpuf.write('power off mpu'+'\\n') # disable mpuf.write('speed 50000'+'\\n') #check jtag speedf.write('loadbin X:\\\\demo_test\\\\rtos\\\\rt-thread\\\\rt-thread\\\\bsp\\\\demo\\\\demo_test\\\\demo_test_fpga\\\\rtthread.bin, 0x0'+'\\n')f.write('setpc ' + ep_hex +'\\n')f.write('g'+'\\n')f.write('exit'+'\\n')f.close# run jlink download script
time.sleep(1)
cmd="jlink.exe D:\\\\zhushiqiang\\\\jlink_download\\\\rtos_download.jlink"
p=os.popen(cmd)
#print("p.read(): {}\\n".format(p.read()))
上面python脚本主要包含以下内容:
- 对板子进行reset 操作,这里使用的是工具 CommandApp_USBRelay 来通过继电器来对 板子机型 reset操作,也可以通过写 SoC 的reset 寄存器来进行reset 操作, 这里做 reset 的作用主要是保证一个干净的环境;
- 通过python脚本获取编译出来的镜像的 entry_point 的值,后面通过设置PC的值为 entry_point的值即可启动 rtos 镜像;
- 通过python创建 烧写脚本 rtos_download.jlink, 该脚本中的主要内容包含:
- 使用 jlink “r” 命令来 reset cpu;
- 使用 jlink “h” 命令来stop cpu(halt cpu);
- 关掉 mpu,因为有时 在bootloader 阶段会对使用 MPU 来限制某些内存的访问,这样有可能导致 cpu 无法从从被限制的内存中获取所要执行的code 或者数据,需要注意的是 “power off mpu” 这条命令有可能无效,这个时候需要单独使用 “w4” 来写 mpu 的寄存器disable mpu功能;
- 配置 j-link的传输速率;
- 使用 loadbin 命令将 rt-thread.bin load到 0x0 地址处,具体 load 到哪个位置还需要根据链接脚本中的配置来配置;
- 配置 PC的值为 entry_point的值;
- 执行 go 命令 开始 run。
在 j-link 脚本开发好后,就可以执行该脚本进行烧录来运行 rtos了。