OpenOCD 添加 Air001

前言

  • 1)AIR001 简介:

    • (1)采用 PY32F003 的 TSSOP20 封装的 MCU

    • (2)采用 Cortex-M0+ 内核

    • (3)内置 32KB 的 Flash、4KB 的 RAM

    • (4)芯片集成多路 USART、IIC、SPI 等通讯外设

    • (5)5 个 16 位定时器、1 路 ADC、2 路比较器。

    • (6)最重要的是只要 7 毛多一片。

  • 2)SWD 下载接口:

    • SWDIO:PA13
    • SWCLK:PA14
  • 3)引脚图:

  • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 4)本文介绍了两种烧录算法来实现 OpenOCD 对 Air001 芯片的支持。

1 烧录算法——寄存器

  • 1)所谓寄存器烧录,即是使用 OpenOCD 通过 MEM-AHP 控制 FLASH 所在的 AHB 总线,进而控制 FLASH 读写相关寄存器来进行烧录。

  • 2)优点就是实现比较简单,但一个 32KB 的 image 烧录用了 90 多秒,呵呵。该方式可以用来熟悉 OpenOCD 代码,以及在不了解 ARM 汇编指令下使用。当对 OpenOCD 代码以及汇编指令有一定了解后,就可以实现同/异步烧录算法了。

1.1 air001.cfg 文件说明

  • 1)在 /tcl/target 目录下,添加 air001.cfg 文件。

  • 2)因为 AIR001 采用 Cortex-M0+ 内核,所以这里复制 tcl/target/stm32l0.cfg 一份,并重命名为 air001.cfg

  • 3)修改:

    # 第 14 行,修改芯片名称。
    # set _CHIPNAME stm32l0
    set _CHIPNAME air001
    
    # 第 38 行,修改芯片 ID。(可能需要等首次下载时获取到)
    # set _CPUTAPID 0x0bc11477
    set _CPUTAPID 0x0bc11477
    
    # 第 51 行,设置 FLASH 大小。air001 芯片只有 32KB 大小,即 0x00008000
    # flash bank $_FLASHNAME stm32lx 0x08000000 0 0 0 $_TARGETNAME
    flash bank $_FLASHNAME air001 0x00008000 0 0 0 $_TARGETNAME
    
    # 有一个 stm32l0_enable_HSI16() 的函数,不知道干嘛的,删掉
    
    # 最下边有一个配置 DEBUG 寄存器的功能,这个就需要根据芯片的寄存器手册来进行修改了
    $_TARGETNAME configure -event examine-end {
        # DBGMCU_CR |= DBG_STANDBY | DBG_STOP | DBG_SLEEP
        mmw 0x40015804 0x00000002 0
    
        # Stop watchdog counters during halt
        # DBGMCU_APB1_FZ |= DBG_IWDG_STOP | DBG_WWDG_STOP
        mmw 0x40015808 0x00001800 0
    }
    
  • 4)关于修改 air001.cfg 文件最后的 DBGMCU_CR 配置:

    • (1)DBGMCU_CR 寄存器(地址偏移 0x04)的地址:
      • 在这里插入图片描述

      • 由此可得,DBGMCU_CR = 0x4001 5804

    • (2)air001 芯片只有 DEBUG_CR 的 DBG_STOP(位于 bit1)
  • 5)关于修改 air001.cfg 文件最后的 DBGMCU_APB1_FZ 配置:

    • (1)DBGMCU_APB1_FZ 寄存器偏移地址为 0x08,DBG_IWDG_STOP 和 DBG_WWDG_STOP 分别位于其 bit12 和 bit11 位。

1.2 air001.c 文件说明

  • 1)在 /src/flash/nor 目录下,添加 air001.c 文件。用于告知 openocd 芯片的 flash 烧录流程。

  • 2)air001.c 文件中的宏定义、函数等均围绕以下内容来建立:

    const struct flash_driver air001_flash = {
            .name = "air001",
            .commands = air001_command_handlers,
            .flash_bank_command = air001_flash_bank_command,
            .erase = air001_erase,
            .write = air001_write,
            .read = default_flash_read,
            .probe = air001_probe,
            .auto_probe = air001_auto_probe,
            .erase_check = default_flash_blank_check,
            .protect_check = air001_protect_check,
            .info = air001_get_info,
            .free_driver_priv = default_flash_free_driver_priv,
    };
    
  • 3)接下来,按照 air001_flash 结构中定义的函数顺序,依次实现

1.3 drivers.c 文件说明

  • 1)drivers.c 文件位于 /src/flash/nor 目录下,该文件主要用于根据驱动名称查找驱动。 这里根据 1.2 中的驱动名称添加一下就可以了:
    ......
    extern const struct flash_driver air001_flash;
    ......
    
    static const struct flash_driver * const flash_drivers[] = {
            ......
            &air001_flash,
            ......
    

1.4 Makefile.am 文件说明

  • 1)这里的 Makefile.am 文件位于 /src/flash/nor 目录下,指明了该目录下源文件的编译规则。因此这里需要修改让 openocd 编译时引用到上述新增的文件。
    ......
    NOR_DRIVERS = \
        %D%/air001.c \
    ......
    

2 烧录算法——异步烧录

2.1 异步烧录算法

  • 1)烧录程序:主要就是在 RAM 中分配两块工作空间

    • 一块用来运行 air001.inc 文件内的汇编代码(该代码实现 image 从 RAM 到 FLASH 的搬运工作)
    • 一块尽可能大,用来作为一个循环的 FIFO,可以在 OpenOCD 将 image 写进来的同时,AIR001 通过上述的汇编代码读取数据并写入 FLASH。
  • 参考:https://zhuanlan.zhihu.com/p/593389551

    • 大佬这篇文章写的非常非常好,清晰明了地说明异常烧录的原理。

2.2 关于汇编代码

  • 1)汇编代码位于 /contrib/loaders/flash/airm2m/air001.inc 文件中。

  • 2)这里可以参考 stm32f1x.S 文件,不同点在于:

    • (1)stm32f1x.s 中,每次只能写入半字(2 个字节)
    • (2)air001 芯片需要在每 31 个字写入后,将 FLASH_CR->PGSTRT(bit19) 置 1,最后再写入第 32 个字。
  • 3)汇编文件编写完成后,在 air001.S 文件所在目录直接 make,即可生成 air001.inc 文件。前提是需要仿照 /contrib/loaders/flash/stm32/Makefile创建自已的 Makefile

3 编译与测试

3.1 编译 OpenOCD

# 启动项测试
./bootstrap

# 创建编译目录
mkdir openocd-clion-build
cd openocd-clion-build

# 配置
../configure --enable-ftdi

# 编译
make -j4 && make install

3.2 测试日志

  • 1)首先在 MSYS2 中输入:openocd -d3 -f interface/cmsis-dap.cfg -f target/air001.cfg 以启动 OpenOCD。

  • 2)通过 telnet 127.0.0.1 4444 连接到 OpenOCD 服务端:

    $ telnet 127.0.0.1 4444
    Trying 127.0.0.1...
    Connected to 127.0.0.1.
    Escape character is '^]'.
    Open On-Chip Debugger
    > halt
    [air001.cpu] halted due to debug-request, current mode: Thread
    xPSR: 0x21000000 pc: 0x080071f8 msp: 0x20000ff0
    > flash write_image erase "D:\\_Workspace\\11_MCU\\07_LuatOS\\Air001\\Air001_001_GCCTemplate\\cmake-build-debug\\Air001_000_GCCTemplate.hex"
    device id = 0x60001000
    AIR001 flash size is 32kb, base address is 0x08000000
    auto erase enabled
    wrote 32768 bytes from file D:\_Workspace\11_MCU\07_LuatOS\Air001\Air001_001_GCCTemplate\cmake-build-debug\Air001_000_GCCTemplate.hex in 3.767980s (8.493 KiB/s)
    
    > reset
    > halt
    [air001.cpu] halted due to debug-request, current mode: Thread
    xPSR: 0x01000000 pc: 0x080071f4 msp: 0x20000ff0
    > flash write_image erase "D:\\_Workspace\\11_MCU\\07_LuatOS\\Air001\\Air001_001_GCCTemplate\\cmake-build-debug\\Air001_000_GCCTemplate.hex"
    auto erase enabled
    wrote 16384 bytes from file D:\_Workspace\11_MCU\07_LuatOS\Air001\Air001_001_GCCTemplate\cmake-build-debug\Air001_000_GCCTemplate.hex in 2.048985s (7.809 KiB/s)
    
    > reset
    > shutdown
    shutdown command invoked
    Connection closed by foreign host.
    
    • 可以发现,32 KB 写入只需要 3.767980s (8.493 KiB/s);16 KB 写入则需要 2.048985s (7.809 KiB/s)。

4 附录1:ARM Cortex-M0+ 汇编指令

  • 1)以下测试结果基于 arm-none-eabi-gcc 和 Cortex-M0+ 平台。根据《STM32F0系列Cortex-M0原理与实践》、《嵌入式系统设计基础及应用——基于ARM Cortex-M4微处理器》整理。

  • 2)ARM Cortex-M0+ Thumb 指令集只能使用前8个(R0-R7)寄存器。

  • 3)N、Z、C、V 标志位是什么

    • Negative:表示结果为负数时 N 标志位置 1。如 cmp 指令相减时小于 0
    • Zero:表示结果为零时 Z 标志位置 1。如 cmp 指令比较两个数相等时,可通过 beq 跳转;比较两个数不相等时,可通过 bne 跳转。
    • Carry:表示加减法运算导致最高位有进位或借位时 C 标志位置 1。而 bcc 指令在 C = 0 时跳转
    • oVerflow:表示有符号数运算时超出表示范围则 V 标志位置 1。
  • 4)通用寄存器:

    • 在这里插入图片描述

4.1 数据处理指令

  • 1)数据传输指令

    助记符操作数操作含义影响标志位测试
    MOV{S}Rd, Rm传送 Rd 数据到 RmN,Zmovs r0, #0x1
    movs R1,R0
    mov R1,R0
    MVN{S}Rd, RmRm 位取反后,传送到 RdN,Zmvns r7, r6
    MRS(略)
    MSR(略)
  • 2)算术运算指令

    助记符操作数操作含义影响标志位测试
    ADD{S}{Rd,} Rn, <Rm|#imm>N,Z,C,Vadd r2, r3
    add r2, r2, r3
    adds r2, #1
    adds r2, r3
    adds r2, r2, #1
    adds r2, r2, r3
    ADCS{Rd,} Rn, Rm带进位加N,Z,C,V
    SUBS{Rd,} Rn, <Rm|#imm>减法N,Z,C,Vsubs r2, #1
    subs r2, r3
    subs r2, r2, #1
    subs r2, r2, r3
    SBC{S}{Rd,} Rn, Rm带符号减N,Z,C,V
    RSB{S}{Rd,} Rn, #0逆向减法N,Z,C,V
    MULSRd, Rn, Rm乘法N,Z
  • 3)逻辑运算指令

    助记符操作数操作含义影响标志位测试
    ANDS{Rd,} Rn, Rm位与计算N,Zands r2, r3
    ands r2, r2, r3
    ORRS{Rd,} Rn, Rm逻辑或N,Zorrs r2, r3
    orrs r2, r2, r3
    EORS{Rd,} Rn, Rm异或N,Zeors r2, r3
    eors r2, r2, r3
    BICS{Rd,} Rn, Rm位清除N,Zbics r2, r3
    bics r2, r2, r3
  • 4)移位指令

    助记符操作数操作含义影响标志位测试
    ASRS{Rd,} Rm, <Rs|#imm>算术右移N,Z,Casrs r2, #1
    asrs r2, r3
    asrs r2, r2, #1
    asrs r2, r2, r3
    LSLS{Rd,} Rn, <Rs|#imm>逻辑左移N,Z,C同上
    LSRS{Rd,} Rn, <Rs|#imm>逻辑右移N,Z,C同上
    RORS{Rd,} Rn, Rs循环右移N,Z,Crors r2, r3
    rors r2, r2, r3
  • 5)比较与测试指令

    助记符操作数操作含义影响标志位测试
    CMPRn, <Rm|#imm>比较N,Z,C,Vcmp r2, #1
    cmp r2, r3
    CMNRn, Rm比较负值N,Z,C,V
    TST{S}Rn, Rm逻辑与测试N,Ztst r2, r3
    tsts r2, r3
  • 6)位域操作指令(无)

  • 7)跳转指令

    助记符操作数操作含义影响标志位测试
    B{cc}label跳转{有条件}跳转,
    BLlabel带链接的分支跳转跳转,且保存 PC 到 R14 中。
    BLXRm带链接的间接跳转跳转,并将处理器的工作状态在 ARM 状态和 Thumb 状态之前切换,且保存 PC 到 R14 中。
    BXRm间接跳转跳转,并将处理器的工作状态在 ARM 状态和 Thumb 状态之前切换。
    BEQRm间接跳转
    BNERm间接跳转

4.2 存储器访问指令

  • 1)存储器访问常用指令

    助记符操作数操作含义影响标志位测试
    ADRRd, label将基于PC相对偏移的地址读到寄存器
    LDRRt, label从基于PC相对偏移地址上加载寄存器
    LDRRt, [Rn, <Rm|#imm>]以字加载寄存器
    LDRBRt, [Rn, <Rm|#imm>]以字节加载寄存器
    LDRHRt, [Rn, <Rm|#imm>]以半字加载寄存器
    LDRSBRt, [Rn, <Rm|#imm>]以有符号字节加载寄存器
    LDRSHRt, [Rn, <Rm|#imm>]以有符号半字加载寄存器
    STRRt, [Rn, <Rm|#imm>]将寄存器作为字来存储
    STRBRt, [Rn, <Rm|#imm>]将寄存器作为字节来存储
    STRHRt, [Rn, <Rm|#imm>]将寄存器作为半字来存储
  • 2)批量加载/存储数据指令

    助记符操作数操作含义影响标志位测试
    LDMRn{!}, reglist加载多个寄存器,访问之后会递增地址
    STMRn!, reglist批量存储寄存器, Rn递减
  • 3)进栈/出栈指令

    助记符操作数操作含义影响标志位测试
    POPreglist寄存器出栈
    PUSHreglist寄存器压栈

4.3 其它指令

  • 1)
    助记符操作数操作含义影响标志位测试
    BKPT#imm断点
    NOP空操作
    REVRd, Rm按字节反转
    REV16Rd, Rm按半字反转
    REVSHRd, Rm按有符号半字反转
    WFE等待事件
    WFI等待中断

5 附录2:OpenOCD 命令

  • 1)probe 以及 info 命令:获取芯片的大致信息
> halt
[air001.cpu] halted due to debug-request, current mode: Thread
xPSR: 0x21000000 pc: 0x08000418 msp: 0x20000ff0
> flash probe 0
device id = 0x60001000
AIR001 flash size is 32kb, base address is 0x08000000
flash 'air001' found at 0x08000000

> flash info 0
#0 : air001 at 0x08000000, size 0x00008000, buswidth 0, chipwidth 0
        #  0: 0x00000000 (0x1000 4kB) protected
        #  1: 0x00001000 (0x1000 4kB) protected
        #  2: 0x00002000 (0x1000 4kB) protected
        #  3: 0x00003000 (0x1000 4kB) protected
        #  4: 0x00004000 (0x1000 4kB) protected
        #  5: 0x00005000 (0x1000 4kB) protected
        #  6: 0x00006000 (0x1000 4kB) protected
        #  7: 0x00007000 (0x1000 4kB) protected
AIR001 (Cat.1 - Low/Medium Density) - Rev: A

  • 2)除了可以通过 flash write_image erase {“/path/to/image.hex” | “/path/to/image.bin” address} 命令可以烧录镜像外,我们还可以使用以下命令来测试自已的驱动是否正常:
> flash erase_check 0
successfully checked erase state
        #  0: 0x00000000 (0x1000 4kB) not erased

> flash fillw 0x08003000 0xcafebaba 32
wrote 128 bytes to 0x08003000 in 0.602882s (0.207 KiB/s)

> flash mdw 0x08003000 48
0x08003000: cafebaba cafebaba cafebaba cafebaba cafebaba cafebaba cafebaba cafebaba
0x08003020: cafebaba cafebaba cafebaba cafebaba cafebaba cafebaba cafebaba cafebaba
0x08003040: cafebaba cafebaba cafebaba cafebaba cafebaba cafebaba cafebaba cafebaba
0x08003060: cafebaba cafebaba cafebaba cafebaba cafebaba cafebaba cafebaba cafebaba
0x08003080: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
0x080030a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff

> flash erase_sector 0 3 4
erased sectors 3 through 4 on flash bank 0 in 0.199937s

> flash mdw 0x08003000 48
0x08003000: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
0x08003020: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
0x08003040: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
0x08003060: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
0x08003080: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
0x080030a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff

  • 实际测试过程中,fillw 偶尔会出现失败的情况,未找到原因。

6 附录3:项目源码

  • 20
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenOCD是一个开源的软件调试和编程工具,它支持许多不同的硬件平台和芯片,包括第三方芯片。为了添加第三方芯片的支持,我们需要做下列工作: 1. 了解芯片的调试接口和协议:首先,我们需要获取第三方芯片的数据手册,了解它的调试接口和通信协议。这些细节通常包括调试端口的引脚定义、通信协议(如JTAG或SWD)和指令集。 2. 修改OpenOCD配置文件:OpenOCD使用配置文件来定义和配置支持的芯片。我们需要编辑配置文件,添加第三方芯片的定义和其他必要的参数。这些参数通常包括芯片的ID代码、调试接口类型、频率和通信速度等。 3. 编译和安装OpenOCD:在修改配置文件后,我们需要重新编译OpenOCD,并将其安装到我们的开发环境中。这通常涉及到使用工具链编译源代码、链接库文件,并将可执行文件复制到适当的目录中。 4. 测试和调试:一旦安装完成,我们可以使用OpenOCD来连接并调试我们的第三方芯片。通过适当的命令和选项,我们可以初始化和配置调试接口,并执行调试操作,如读写寄存器、设置断点和单步调试等。如果有任何问题,我们可以通过查看OpenOCD的输出日志、调试和修改配置文件来解决。 通过这些步骤,我们就能够将一个第三方芯片添加OpenOCD的支持列表中,并使用OpenOCD进行调试和编程操作。这为开发人员提供了更多的灵活性和工具选择,以便在开发过程中更好地支持各种类型的芯片和设备。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值