OrangePi Zero 3学习笔记(Android篇)8 - OpenOCD
目录
1. libjaylink
2. hidapi
3. libgpiod
4. libcapstone
5. libftdi1
6. OpenOCD
7. ftdi配置
7.1 指定ftdi驱动
7.2 指定具体设备
7.3 指定通道
7.4 初始化GPIO状态
7.5 定义信号
7.6 使能SWD
8. 验证
8.1 添加工程
8.2 添加权限
8.3 运行结果
所有的关联库都是基于Ubuntu中编译过,然后再使用NDK编译出当前版本的so文件。
1. libjaylink
使用NDK编译libjaylink,然后将libjaylink.so加入到Android源代码中。
2. hidapi
由于Android源代码里面已经有这个库了,可以直接把libhidapi.so拷贝到NDK的sysroot里面使用。
3. libgpiod
先在Ubuntu中查一下当前的版本
$ sudo apt install libgpiod-dev
正在读取软件包列表... 完成
正在分析软件包的依赖关系树... 完成
正在读取状态信息... 完成
libgpiod-dev 已经是最新版 (1.6.3-1build1)。
升级了 0 个软件包,新安装了 0 个软件包,要卸载 0 个软件包,有 9 个软件包未被升级。
然后找到1.6.3版本(新的 版本API函数变了,编译不过)下载源代码
libgpiod/libgpiod.git - C library and tools for interacting with the linux GPIO character device
NDK编译错误处理:
- tools-common.c:24:9: error: 'program_invocation_name' undeclared (first use in this function)
./autogen.sh --enable-tools=no --host=$HOST --prefix=$SYSROOT/usr
关闭tools的功能。
#!/bin/sh./autogen.sh --enable-tools=no --host=$HOST --prefix=$SYSROOT/usr
./configure --host=$HOST --target=$TARGET --prefix=$SYSROOT/usr --with-pic
make
make install
- src/rtt/rtt.c:232:67: error: declaration of 'read' shadows a global declaration [-Werror=shadow]
这个错误是变量read已经被申明为一个全局申明(NDK里面已经有一个read了),将这个变量改成其他名字sinkread.
4. libcapstone
sudo apt install libcapstone-dev获取版本号
libcapstone-dev 已经是最新版 (4.0.2-5)。
下载对应的源代码https://github.com/capstone-engine/capstone/archive/refs/tags/4.0.2.tar.gzhttps://github.com/capstone-engine/capstone/archive/refs/tags/4.0.2.tar.gz
envsetup.sh里面只需要设置NDK变量
#!/bin/shexport ROOT=~/Project
export NDK=$ROOT/android-ndk-r17c
根目录下执行
./make.sh cross-android arm
虽然会编译出错,但是可以看到生成了so库文件,将这个文件拷贝到NDK的sysroot/usr/lib中。
5. libftdi1
参考之前的文章,生成libftdi1。
6. OpenOCD
将上面的库文件分别放好文件夹内。envsetup.sh内容如下:
#!/bin/shexport ROOT=~/Project
export NDK=$ROOT/android-ndk-r17c
export TARGET=arm-linux-androideabi
export ARCH=arm
export HOST=$TARGET
export SYSROOT=$NDK/sysroot
export TOOLCHAIN=$NDK/toolchains/$TARGET-4.9/prebuilt/linux-x86_64
export API=26export CC=$TOOLCHAIN/bin/$TARGET-gcc
export CXX=$TOOLCHAIN/bin/$TARGET-g++
#export CPP="$TOOLCHAIN/bin/$TARGET-gcc -E"
export AR=$TOOLCHAIN/bin/$TARGET-ar
export AS=$CC
export LD=$TOOLCHAIN/bin/$TARGET-ld
export RANLIB=$TOOLCHAIN/bin/$TARGET-ranlib
export STRIP=$TOOLCHAIN/bin/$TARGET-stripexport CFLAGS="--sysroot=$NDK/platforms/android-$API/arch-$ARCH \-D__ANDROID_API__=$API \-DNDEBUG \-I$NDK/sysroot/usr/include \-I$NDK/sysroot/usr/include/$TARGET \-fPIC -fPIE -Wno-attributes -Wno-unused-variable -Wno-unused-function"
export CXXFLAGS=$CFLAGS
#export CPPFLAGS=$CFLAGS
export LDFLAGS="-pthread -lc -L\"$SYSROOT/usr/lib\" -pie"export PATH=$PATH:$TOOLCHAIN/bin/
编译脚本build.sh
#!/bin/sh./autogen.sh --host=$HOST
./configure --host=$HOST --target=$TARGET --prefix=$SYSROOT/usr --with-pic
make
将OpenOCD编译好的openocd拷贝到external/openocd中,android.bp文件内容:
cc_prebuilt_binary {name: "openocd",
// proprietary: true,
// vendor: true,
// check_elf_files: false,target: {android_arm: {srcs: ["arm-linux-androideabi/openocd"],},},shared_libs: ["libcapstone","libftdi1","libgpiod","libhidapi","libjaylink","libusb1.0",],
}
修改/device/softwinner/apollo/apollo_p2.mk,添加以下内容:
PRODUCT_PACKAGES += libconfuse.so
PRODUCT_PACKAGES += libusb-1.0.so
PRODUCT_PACKAGES += libusb1.0.so
PRODUCT_PACKAGES += libftdi1.so
PRODUCT_PACKAGES += libjaylink.so
PRODUCT_PACKAGES += libgpoid.so
PRODUCT_PACKAGES += libcapstone.so
PRODUCT_PACKAGES += openocd
烧录后执行openocd -v,可以看到
console:/ $ ./system/bin/openocd -v
Open On-Chip Debugger 0.12.0+dev-00801-g133dd9d66-dirty (2024-12-10-15:06)
Licensed under GNU GPL v2
For bug reports, readhttp://openocd.org/doc/doxygen/bugs.html
7. ftdi配置
可以结合源代码openocd-code/src/jtag/drivers/ftdi.c和openocd-code/tcl/interface/ftdi/um232h.cfg学习了解ftdi(H系列)的配置方式。
可以新建一个ftdi_mpsse.cfg文件,具体支持的命令列表可以看ftdi.c中的命令数组ftdi_subcommand_handlers。
PS: 可以在windows里面操作,注意需要使用Zadig将驱动改为winusb
7.1 指定ftdi驱动
adapter driver ftdi
这一步是必须的,表示当前的设备驱动采用ftdi驱动,即ftdi的mpsse模式。
7.2 指定具体设备
如果只有一个设备,可以通过VID和PID指定
# FT232H
#ftdi vid_pid 0x0403 0x6014
# FT2232H
#ftdi vid_pid 0x0403 0x6010
# FT4232H
ftdi vid_pid 0x0403 0x6011
也可以通过设备描述符指定
ftdi device_desc "FTDI FT4232H MiniModule"
如果是多个设备,可以通过serial指定
adapter serial "FT9PQ9R2"
以上3种方式是可以同时设定的。
7.3 指定通道
对于FT2232H和FT4232H来说,通道数都是2个,所以需要参数指定操作哪个通道。
# channel would be 0 or 1
ftdi channel 1
7.4 初始化GPIO状态
GPIO一共16个,参数是uint16_t型的十六进制,第一个参数表示GPIO输出的电平,0表示低电平,1表示高电平,第二个参数表示GPIO方向,0表示输入,1表示输出。命令格式:
"data direction"
以SWD接口方式为例,BD0表示SWCLK,BD1和BD2表示SWIO的输出输入管脚,BD3作为nReset脚。
# FT4232H minimodule channel 1 (Channel B)
# CN2-18 - SWCLK
# CN2-17 - SWDIO
# CN2-20 - SWDIO
# CN2-19 - nRESET
ftdi layout_init 0x0000 0x000b
7.5 定义信号
将一个或多个FTDI GPIO控制的信号定义为数据和/或输出使能。命令格式:
"name [-data mask|-ndata mask] [-oe mask|-noe mask] [-alias|-nalias name]"
可以参考函数ftdi_set_signal理解信号的意义。GPIO支持3种状态,0,1和高阻态。
name: 信号的名字,特殊信号名称保留给 nTRST、nSRST 和 LED(用于闪烁)
data: 数据的位置,不需要取反
ndata: 对应data取反
-oe/noe: 输出使能,和data意义一样,前缀n表示取反
-alias/-nalisas: 这个是别名的意思,当GPIO被共用的时候使用
ftdi layout_signal nSRST -data 0x0008 -oe 0x0008
该信号名字是nSRST,与目标板上的系统复位信号相连,可以直接对目标系统复位。PS:nTRST用来对TAPController进行复位,一般不用。
-data 0x0008表示nSRST使用的是bit3,而-oe则表示输出使能
对于swd应用,则必须设置SWD_EN信号和SWDIO_OE信号
ftdi layout_signal SWD_EN -data 0
ftdi layout_signal SWDIO_OE -data 0
当选择SWD协议时,SWD_EN会被设置为1,此时SWDIO会被设置输入脚。
7.6 使能SWD
transport select swd
8. 验证
8.1 添加工程
在device/softwinner/apollo/apollo-p2/里面新建文件夹openocd_example_ftdi
新建文件app_openocd.sh,内容如下:
#!/bin/sh/system/bin/openocd -f "/system/bin/cfg_openocd/ftdi_mpsse.cfg" -f "/system/bin/cfg_openocd/stm32f1x.cfg" -c "program /system/bin/cfg_openocd/stm32f10x.hex verify reset exit"
再在这个文件夹内新建文件夹cfg_openocd,新建文件ftdi_mpsse.cfg
adapter driver ftdi# FT232H
#ftdi vid_pid 0x0403 0x6014
# FT2232H
#ftdi vid_pid 0x0403 0x6010
# FT4232H
ftdi vid_pid 0x0403 0x6011 #ftdi device_desc "FTDI FT4232H MiniModule"
adapter serial "FT9PQ9R2"# channel would be 0 or 1
ftdi channel 1 # FT4232H minimodule channel 1 (Channel B)# CN2-19 - nRESET
ftdi layout_init 0x0000 0x000b#ftdi layout_signal nSRST -data 0x0008 -oe 0x0008
ftdi layout_signal SWD_EN -data 0
ftdi layout_signal SWDIO_OE -data 0transport select swd
拷贝openocd源代码里面\scripts\target\stm32f1x.cfg文件(根据目标mcu修改)到cfg_openocd中,并修改:
source [find cfg_openocd/scripts/target/swj-dp.tcl]
source [find cfg_openocd/scripts/mem_helper.tcl]
拷贝openocd源代码里面\scripts\target\swj-dp.tcl到cfg_openocd\scripts\target\中
拷贝openocd源代码里面\scripts\mem_helper.tcl到cfg_openocd\scripts\中
在device/softwinner/apollo/apollo_p2.mk里面添加:
PRODUCT_COPY_FILES += \$(PRODUCT_DEVICE_PATH)/openocd_example_ftdi/app_openocd.sh:$(TARGET_COPY_OUT_SYSTEM)/bin/app_openocd.sh \$(PRODUCT_DEVICE_PATH)/openocd_example_ftdi/cfg_openocd/ftdi_mpsse.cfg:$(TARGET_COPY_OUT_SYSTEM)/bin/cfg_openocd/ftdi_mpsse.cfg \$(PRODUCT_DEVICE_PATH)/openocd_example_ftdi/cfg_openocd/stm32f1x.cfg:$(TARGET_COPY_OUT_SYSTEM)/bin/cfg_openocd/stm32f1x.cfg \$(PRODUCT_DEVICE_PATH)/openocd_example_ftdi/cfg_openocd/stm32f10x.hex:$(TARGET_COPY_OUT_SYSTEM)/bin/cfg_openocd/stm32f10x.hex \$(PRODUCT_DEVICE_PATH)/openocd_example_ftdi/cfg_openocd/scripts/mem_helper.tcl:$(TARGET_COPY_OUT_SYSTEM)/bin/cfg_openocd/scripts/mem_helper.tcl \$(PRODUCT_DEVICE_PATH)/openocd_example_ftdi/cfg_openocd/scripts/target/swj-dp.tcl:$(TARGET_COPY_OUT_SYSTEM)/bin/cfg_openocd/scripts/target/swj-dp.tcl
8.2 添加权限
在device/softwinner/apollo/common/system/init.sun50iw9p1.usb.rc添加(无效):
on property:sys.usb.config=accessory && property:sys.usb.configfs=1write /config/usb_gadget/g1/idVendor 0x0403
在device/softwinner/common/sepolicy/vendor/新建文件openocd.de
type openocd, coredomain;
type openocd_exec, system_file_type, exec_type, file_type;
init_daemon_domain(openocd)
然后在device/softwinner/common/sepolicy/vendor/file_contexts添加
/system/bin/openocd u:object_r:openocd_exec:s0
dmesg看一下输出log,可以看到有权限问题
[ 1235.009038] [ T189] type=1400 audit(1734420131.609:149): avc: denied { read } for comm="openocd" name="busnum" dev="sysfs" ino=26492 scontext=u:r:shell:s0 tcontext=u:object_r:sysfs:s0 tclass=file permissive=1
[ 1235.009444] [ T189] type=1400 audit(1734420131.609:150): avc: denied { open } for comm="openocd" path="/sys/devices/platform/soc@3000000/5310400.ohci2-controller/usb5/busnum" dev="sysfs" ino=26492 scontext=u:r:shell:s0 tcontext=u:object_r:sysfs:s0 tclass=file permissive=1
分析第一条权限提示:
a. 缺什么权限: denied { read },即缺read权限
b. 谁缺权限:scontext=u:r:shell:s0,即shell缺权限
c. 对什么缺少权限:tcontext=u:object_r:sysfs:s0,即对sysfs缺权限
d. 什么类型的文件:tclass=file,即file类型
可以先在system/sepolicy/private/shell.te根据上面的4点添加新的权限:
allow shell sysfs:file read;
然后编译会失败,根据提示可以在system/sepolicy/private/coredomain.te查到
# /sysneverallow {coredomain-init-ueventd-vold} sysfs:file no_rw_file_perms;
即不允许在shell.te里面添加对应的权限,所以要把shell.te的添加去掉,但是这里提示对应ueventd是例外,所以在device/softwinner/apollo/common/system/ueventd.sun50iw9p1.rc添加
/dev/bus/usb/* 0777 system system
8.3 运行结果
Open On-Chip Debugger 0.12.0+dev-00801-g133dd9d66-dirty (2024-12-10-15:06)
Licensed under GNU GPL v2
For bug reports, readhttp://openocd.org/doc/doxygen/bugs.html
Info : FTDI SWD mode enabled
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x2ba01477
Info : [stm32f1x.cpu] Cortex-M3 r2p1 processor detected
Info : [stm32f1x.cpu] target has 6 breakpoints, 4 watchpoints
Info : [stm32f1x.cpu] Examination succeed
Info : [stm32f1x.cpu] starting gdb server on 3333
Info : Listening on port 3333 for gdb connections
[stm32f1x.cpu] halted due to breakpoint, current mode: Thread
xPSR: 0x01000000 pc: 0x080038ec msp: 0x20005000
** Programming Started **
Info : device id = 0x20036410
Info : flash size = 128 KiB
Warn : Adding extra erase range, 0x080052e8 .. 0x080053ff
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **
shutdown command invoked