OpenOCD 添加 AIR105(下)

2024-01-25 08:52
文章标签 openocd air105

本文主要是介绍OpenOCD 添加 AIR105(下),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 前言
    • 1 驱动实现方式的尝试
      • 1.1 第一次尝试
      • 1.2 第二次尝试
      • 1.3 第三次尝试
      • 1.4 第四次尝试
      • 1.5 第五次尝试
    • 2 测试
      • 2.1 汇编传参问题
      • 2.2 缓存
      • 2.3 header
        • 2.3.1 无法正常启动
        • 2.3.2 串口烧录程序
      • 2.4 烧录 .elf 文件
    • 3 优化
      • 3.1 DMA
      • 3.2 多扇区擦除
    • 4 附录1:调用 AIR105 FLM 算法的尝试
      • 4.1 关于 Keil FLM
      • 4.2 解析 FLM 文件

前言

  • 1)上一篇文章介绍了 Air105 OpenOCD 驱动编写的成果,这篇文章想着记录一下中间遇到的问题,一是防止和我一样的小白踩坑(你就当真的听),二是成功不吆喝,如锦衣夜行。

  • 2)ROM API 代码:

    // air105_rom_falsh_api @ 0x00008010UL :
    #define ROM_QSPI_Init                   (*((void     (*)(QSPI_InitTypeDef    *))             (*(uint32_t *)0x8010)))
    #define ROM_QSPI_ReadID                 (*((uint32_t (*)(QSPI_CommandTypeDef *))             (*(uint32_t *)0x8014)))
    #define ROM_QSPI_WriteParam             (*((uint8_t  (*)(QSPI_CommandTypeDef *, uint16_t))   (*(uint32_t *)0x8018)))
    #define ROM_QSPI_EraseSector            (*((uint8_t  (*)(QSPI_CommandTypeDef *, uint32_t))   (*(uint32_t *)0x801C)))
    #define ROM_QSPI_EraseChip			    (*((uint8_t  (*)(QSPI_CommandTypeDef *))             (*(uint32_t *)0x8020)))    // This's a reasonable guess.
    #define ROM_QSPI_ProgramPage            (*((uint8_t  (*)(QSPI_CommandTypeDef *, DMA_TypeDef *,   \uint32_t, uint32_t, uint8_t *))      (*(uint32_t *)0x8024)))
    #define ROM_QSPI_ReleaseDeepPowerDown   (*((uint8_t  (*)(QSPI_CommandTypeDef *))             (*(uint32_t *)0x802C)))

1 驱动实现方式的尝试

1.1 第一次尝试

  • 1)刚开始时,根据 Air001 时的经验,想通过 OpenOCD 模拟 QSPI API 的方式实现,结果烧录巨慢(几 KB 大小的文件烧录要一分多钟),且烧录后无法正常启动,放弃(第一次尝试)。
    • (1)现在想来,烧录慢应该是通过 OpenOCD 模拟寄存器操作只适合偶尔简单的操作,如解锁 FLASH,读取 FLASH SIZE 寄存器等操作。而烧录代码涉及到寄存器的频繁操作;
    • (2)无法正常启动应该是第一个扇区中未写入 header 所致。

1.2 第二次尝试

  • 1)既然操作 QSPI 寄存器不行,就考虑 ROM API 调用的方式。本来想参考 “为国产芯片增加OpenOCD Flash驱动----以AIC8800为例” 这篇文章,写完代码测试时发现运行算法的 target_run_algorithm() 函数一直报错。

  • 2)由于此时还不太明白 OpenOCD 驱动运行逻辑,因此让我一度怀疑官方的 ROM API 到底是否可用。(从这里开始走弯路。)

  • 3)上面提到的代码中的主要逻辑:

    struct aic8800_rom_api_call_code_t {uint16_t ldrn_r3;	// 0x4b01uint16_t blx_r3;	// 0x4798uint16_t bkpt;	    // 0xbe00uint16_t nop;	    // 0xbf00uint32_t api_addr;	// api addr
    };struct aic8800_rom_api_call_code_t aic8800_rom_api_call_code_example = {.ldrn_r3 = 0x4b01,			/* LDR.N R3, [PC, #0x4]*/.blx_r3 = 0x4798,			/* BLX R3 */.bkpt = 0xbe00,				/* bkpt */.nop = 0xbf00,				/* NOP */.api_addr = 0x12345678,
    };.......
    static int aic8800_probe(struct flash_bank *bank)
    {......    retval = target_read_buffer(target, AIC8800_ROM_APITBL_BASE, sizeof(rom_api_table), (uint8_t *)rom_api_table);if (retval != ERROR_OK)return retval;for (unsigned int i = 0; i < dimof(aic8800_bank->rom_api_call_code); i++) {init_rom_api_call_code(&aic8800_bank->rom_api_call_code[i], rom_api_table[i]);}......
    }
    
    • 上面通过 target_read_buffer() 函数,从 ROM API 的基地址读取出 ROM API 代码。

1.3 第三次尝试

  • 1)既然需要运行 ROM 代码,那么我是不是可以把官方 AIR105.FLM 中的算法代码(没有源码)提取出来,然后参考 1.2 中的形式实现来运行?(灵感来自 “利用MDK的FLM文件生成通用flash驱动”)

  • 2)说干就干,不过当我终于解析完 AIR105.FLM 文件,驱动写了一半时想到:AIR105.FLM 中的算法是通过 QSPI 实现的,里面有函数多层嵌套,OpenOCD 中该怎么实现呢?难度太大遂放弃,毕竟我是一个小白呢。

  • 3)解析 AIR105.FLM 文件见 “附录1:调用 AIR105.FLM 算法的尝试”。

1.4 第四次尝试

  • 1)再回头去仔细研究上面的大佬代码,这位大佬的情况好像是先从 FLASH 中读取出 ROM API 的代码,然后将代码写入到 SRAM 中运行的。再看一下 Air105 官方的 ROM API 地址间隔 4 个字节,不像是一个函数的大小啊。

  • 2)经过 “文心一言” 的解答,原来这个是函数指针。那我是不是可以把这个指针指向的地方的代码读取出来运行?好像不行,因为我不知道要读取多长的数据才是一个完整的 ROM API 代码。

    #define ROM_QSPI_ReadID (*((uint32_t (*)(QSPI_CommandTypeDef *))(*(uint32_t *)0x8014)))
    
  • 3)不过大佬的文章仍然给了我启发,那就是将一个地址赋值给一个寄存器,然后可以直接调用。可能官方 ROM API 是没问题的,只是我调用的方式有问题?

    LDR.N   R3, [PC,#0x4]   /* 将后面的入口地址载入 R3,已知的 ROM API 最多只需要用到 R0-R2 */
    BLX     R3              /* 调用 ROM API */
    
  • 4)那么就验证一下,当时想到如果有问题就放弃这个项目了(因为在 1.2 小节中,我尝试了各种办法结果都是报错)。通过在 Keil5 中调用 ROM_QSPI_ReadID() 成功获得芯片的 ID,然后通过调试找到对应的汇编代码(这也是我认为 Keil5 唯二可取的地方):

    0x01002424 F44F4000  MOV           r0,#0x8000
    0x01002428 6941      LDR           r1,[r0,#0x14]
    0x0100242A 2000      MOVS          r0,#0x00
    0x0100242C 4788      BLX           r1
    0x0100242E 4604      MOV           r4,r0
    
    • (2)通过 BLX r1 指令来调用 0x8014 处的函数,且参数 NULL 保存在 r0 寄存器中。结果成功获得 id,如下:

    • (3)再结合大佬文章中的 BLX 调用 API 代码,那么可以确定,确实可以这样来调用 ROM API 的函数指针,只要我们把参数设置完就好了(乐极生悲的伏笔)

1.5 第五次尝试

  • 1)当时想着先实现 ROM_QSPI_ReadID() ROM API 的调用,因为它参数少,且是 OpenOCD 烧录时最先调用的 .probe 中需要实现的。当看到程序输出下面的内容时,就差喜极而泣了:

    AIR105 flash base 0x01001000 device id = 0x005E4016
    
  • 2)路线选择完成,下面就把各个功能函数实现即可:

    const struct flash_driver air105_flash = {.name = "air105",.commands = air105_command_handlers,.flash_bank_command = air105_flash_bank_command,.erase = air105_erase,.write = air105_write,.read = default_flash_read,.probe = air105_probe,.auto_probe = air105_auto_probe,.erase_check = default_flash_blank_check,.info = air105_get_info,.free_driver_priv = default_flash_free_driver_priv,
    };
    
  • 3)其它情况:

    • (1)为了减少烧录时间,当然是采用异步烧录了
    • (2)驱动完成(见 air105.c),汇编算法完成(见 air105_write.S),编写过程中,通过 Keil5 测试 ROM API 时发现:
      • a. 扇区擦除函数 ROM_QSPI_EraseSector(),参数 uint16_t 为扇区所在地址,那么擦除实现时就需要循环擦除多个扇区了,原来还以为 API 擦除的是指定地址到 FLASH 尾地址呢
      • b. 页编程函数:ROM_QSPI_ProgramPage(),芯片的写入单位是页,那么就要除了实现异步烧录算法外,还要实现 ROM_QSPI_ProgramPage() 函数,防止不足页的情况

2 测试

2.1 汇编传参问题

  • 1)通过 “flash write_image erase” 烧录后,程序无法运行,于是通过 “flash read_bank 0 [filename]” 将整个 FLASH 读取出来,与 HEX 文件对比:发现异步烧录算法写入数据不对(而且有时在写的过程中会报错),折腾了几天,中间几乎一行一行地查代码感觉没有问题啊。

  • 2)最终在不经意间愤怒地质问 “文心一言”:“arm 汇编中 5 个参数的函数到底应该怎么传参?(概义如此)”,答:r0~r3 寄存器通常用于参数传递,多于 4 个参数就要放到栈里面去了。对不起,我是小白。下面是 QSPI API(与 ROM API 参数一致),有 5 个参数:

    uint8_t QSPI_ProgramPage(QSPI_CommandTypeDef *cmdParam,DMA_TypeDef *DMA_Channelx,uint32_t adr,uint32_t sz,uint8_t *buf
    );
    
    • (1)ARM 平台下,参数值传递按顺序存放在寄存器 r0,r1,r2,r3 里,超过 4 个参数值传递则放栈里。仔细想想也是,通用寄存器就那十几个,那我要是一个函数 20 个参数怎么办呢?
    • (2)页编程函数 QSPI_ProgramPage() 有 5 个参数,则第 5 个参数需要去 sp 指针指向的位置去取。
  • 3)同时中间想到,由于我们是异步烧录,那么我们需要几个寄存器来保存 FIFO 的起始、结束地址,烧录页数,读写指针等,这些寄存器在烧录过程中不能被外部改变。

    • (1)原来想着我从 R12~R0 开始往下用,BLX 指令调用函数时可能只用到前面的几个寄存器,不会覆盖我后面的寄存器。
    • (2)后来查看 AIR105.FLM 文件,以及《ARM Cortex-M3 权威指南》时发现,POP 和 PUSH 指令你值得拥有。

2.2 缓存

  • 1)每次烧录成功后,通过 flash mdw 查看发现内容不对。

    • mdw,Memory Display Word,显示内存字,即显示指定地址的一个 4 字节数据。
  • 2)然后就一直通过 “flash fillw [address] [value] [length]” 写入数据,“flash erase_sector [bank] [first] [last]” 擦除扇区,“flash erase_check [bank]” 查看扇区的标记情况,这三个命令来测试。

  • 3)偶然的机会发现,写入数据后,使用 “flash erase_check” 走一下,然后再通过 “flash mdw” 命令就可以看到正常值,然后就把 “flash erase_check” 对应的回调函数 “default_flash_blank_check” 添加到每次更新操作的后面,结果非常消耗时间。这样不行啊,再去翻 AIR105.FLM 解析内容,通过 “Cache_CleanAll()” 函数猜测可能是缓存问题。

  • 4)找到官方数据手册,把清除缓存的功能实现一下,再测试,终于正常烧录了。 通过 “flash read_bank 0 [filename]” 命令读取出来后,与镜像 HEX 文件一致。

2.3 header

2.3.1 无法正常启动
  • 1)程序已经烧录成功,校验也和镜像文件一致,但芯片无法正常启动。需要说明的是,此前的驱动中,我一直以为芯片的 FLASH 基地址为 0x01001000,且大小为 4092KB,因为官方文档这样说得,且 Link Script 中也如下指定(虽然心里也吐槽过,说好的 4MB FLASH 怎么少了 4KB 呢?)

    MEMORY
    {RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 640KFLASH    (rx)    : ORIGIN = 0x01001000,   LENGTH = 4092K
    }
    
  • 2)这里是耗时最长的部分,经过大概一周的折腾,包括一行一行检查汇编代码(怀疑自已),去查 SC300 文档(以为 SC300 安全核有啥特性),查看 Cortex-M3/M4 权威指南(想找找 FLASH 寄存器的说明),所有的路都走不能,再总结一下现象如下:

    • (1)先通过串口烧录一次,然后使用本驱动多次烧录相同的镜像,都可以正常运行
    • (2)通过 flash read_bank 命令读取出烧录的镜像文件,发现和正常运行的镜像一致
2.3.2 串口烧录程序
  • 1)OpenOCD 烧录无法正常运行,但串口烧录后却可以正常运行,观察下串口烧录的日志:

    PS D:\_Workspace\11_MCU\07_AirM2M\Air105\Demos\air105_mh1903s> .\air105-uploader.exe COM17 .\cmake-build-debug\air105_mh1903s.bin 
    >>> No signature key. Ignoring firmware signature
    >>> Port: COM17
    >>> Firmware: 4312 bytes
    >>> Starting bootloader
    >>> Received ChipSN Packet
    >>>  Boot Version: V1.3.0
    >>>  ChipID: 50790400
    >>>  ROM Version: Unknown
    >>>  Series: S030 (MH1903S)
    >>>  Serial: b'4131303551383854000000000000DAA9'
    >>> Initializing stage2
    >>> Erasing flash memory
    >>> Erasing flash from 00000000 to 00003000
    >>> Sending firmware
    >>> Writing @0x1001000
    >>> Writing @0x1002000
    >>> Upload finished
    >>> Resetting device
    
    • 没发现什么特殊的,烧录地址也是在 0x01001000。就死马当做活马医,看看它是怎么实现烧录的。“马生,你发现了华点!!!”
  • 2)发现了如下内容:

    def update(self):if self.Option == 2:hash = hashlib.sha256(self.Data).digest()else:hash = hashlib.sha512(self.Data).digest()self.Hash[:len(hash)] = hashself.header = struct.pack("<6I", 0x5555AAAA, 0, self.Start, self.Length, self.Version, self.Option)self.header += self.Hashcrc = self.c32.compute(self.header[4:])self.header += struct.pack("<I", crc)if self.rsaKey != NULL_KEY:signData = self.header[4:]signData += b"\x00" * (256 - len(signData))  # Pad to 256 bytessignData = int.from_bytes(signData, byteorder='big')signed = pow(signData, self.rsaKey.d, self.rsaKey.n)self.signed_header = self.header[:4] + signed.to_bytes(self.rsaKey.size_in_bytes(), byteorder='big')
    
    • 好像是对数据进行 SHA256 摘要,还有 CRC-32 签名的。
  • 3)与此同时,官方 SDK 里面竟然有如下定义:

    #define MHSCPU_FLASH_BASE                       (0x01000000UL)
    
  • 4)尝试将 OpenOCD 中 Air105 驱动程序中的 FLASH 基地址由 0x01001000 修改为 0x01000000,然后通过 “flash mdw 0x01000000 32” 读取内容,结果:

    > flash mdw 0x01000000 32
    AIR105 flash base 0x00000000 device id = 0x005E4016
    0x01000000: 5555aaaa 00000000 01001000 000010d8 00000000 00000002 5ac6ffb0 b06f56f2
    0x01000020: 756ff9bb 38a5f690 afbaf183 0c26b5cb d8008a24 d76168e3 00000000 00000000
    0x01000040: 00000000 00000000 00000000 00000000 00000000 00000000 2f91401d 00000000
    0x01000060: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
    
    • 从中可以发现,虽然后续内容不一致,但开始的 0x0x5555AAAA 与串口烧录代码中的一模一样。
  • 5)再仔细研究一下,终于发现,原来 FLASH 0x01000000 ~ 0x01001000 一个扇区 4KB 大小中,保存的是 0x0x5555AAAA 魔数、默认值0、app 地址、app 数据长度、版本、摘要算法等内容。接下来我们只需要一一实现这些内容即可。

  • 参考:sha256 C 语言实现:https://blog.csdn.net/qq_43176116/article/details/110388321

2.4 烧录 .elf 文件

  • 1)我的目标是在 CLion 中使用 OpenOCD 烧录程序,而 CLion 中烧录的是 .elf 文件。问题是,无论在 Link Script 文件怎么配置 FLASH 的起始地址 ORIGIN,结果在烧录时,OpenOCD 获取到的都是 0x01000000

    MEMORY
    {RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 640KFLASH    (rx)    : ORIGIN = 0x01001000,   LENGTH = 4092K
    }
    
  • 2)使用 “arm-none-eabi-readelf.exe -a .\air105_mh1903s.elf” 命令解析 .elf 文件,结果也是如此:

    Program Headers:Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg AlignLOAD           0x000000 0x01000000 0x01000000 0x01cac 0x01cac RWE 0x10000LOAD           0x008000 0x20008000 0x01001cac 0x0042c 0x0045c RW  0x10000LOAD           0x000000 0x20000000 0x20000000 0x00000 0x08000 RW  0x10000    
    
  • 3)晚上睡觉时,找了几篇类似的文件了解一下 Link Script 文件:

    • ARM Cortex-M文件那些事(6)- 可执行文件(.out/.elf):https://www.cnblogs.com/henjay724/p/8276677.html
    • ARM Cortex-M文件那些事(2)- 链接文件(.icf):https://www.cnblogs.com/henjay724/p/8191908.html
    • 链接脚本(Linker Scripts)语法和规则解析:https://www.cnblogs.com/jianhua1992/p/16852784.html
  • 4)早上起来文章还没看,先用 “flash mdw 0x01001000 32” 读取烧录后的头 32 个字节发现,虽然 .elf 文件的内容从地址 0x01000000 开始,但是它实际烧录的程序代码依然是从 0x01001000 开始写入的。那问题不就解决了,我只需要在计算 header 时,对传入 .write 函数中的 buffer 进行 1 个扇区 4KB 的偏移不就行了。

  • 5)结果不出所料,果然烧录成功。至此可以宣布,我的 OpenOCD 驱动终于可以支持 .elf、.hex、.bin 三种文件的烧录了。

3 优化

3.1 DMA

  • 1)可以正常烧录以后,当然就想优化一下烧录速度了。首先从参数类型我们可以看到烧录 ROM API 是支持 DMA 的,那就尝试一下吧。
#define ROM_QSPI_ProgramPage (*((uint8_t (*)(QSPI_CommandTypeDef *, DMA_TypeDef *, uint32_t, uint32_t, uint8_t *))(*(uint32_t *)0x8024)))#define DMA_Channel_0                           ((DMA_TypeDef *)DMA_BASE)
#define DMA_Channel_1                           ((DMA_TypeDef *)(DMA_BASE + 0x58))
  • 2)从 SDK 中可以看到 DMA 通道号的值,再使用 Keil5 进行 Debug 可以看到在 ROM_QSPI_ProgramPage() 调用时,r1 的值确实是 0x40008000,那么我们修改汇编代码:
    movs    r1, #0x4000     /* param of DMA_TypeDef         */
    lsls    r1, #16
    adds    r1, #0x800      /* DMA always failure           */// 还尝试了下面这种方式:
    ldr     r1, =#0x4000800
    
    • 还尝试了其它 DMA 通道号,结果发现:有时会出现死活烧录下进行的情况。此时测试不加 DMA 的情况下烧录,只比 Keil 慢 5~6 秒,就放弃了。

3.2 多扇区擦除

  • 1)为了对比 Keil 烧录速度,在擦除扇区和烧录分别加入了计时功能,结果发现擦除 150 个扇区都需要十几秒,就想到设置擦除的最后扇区,让擦除算法自已运行,这样可以节省每次擦除算法的初始化和释放过程时间。

    • 也就是由 OpenOCD 控制一个扇区一个扇区地擦除,修改为几十个扇区擦除一次。
  • 2)结果发现,当一次擦除 50 个以上扇区时,发现错误的概率大大提高。慢慢减少每次擦除的扇区数,直到等于 20 时,还会偶尔出现错误。没办法,设置成每次擦除 15 个扇区,并加入错误重试功能。

        /* erase sectors more than specified sectors will make ROM_QSPI_EraseSector() failed.* and there is a certain probability that the function returns successfully, but the* sector is not completely erased, this can lead to the program not running after being* burned.* The smaller the specified number of sectors, the better. it will always failed if more* than 60 sectors per erased.*/while (num_sectors > 0) {erase_last = erase_first + MIN(num_sectors, MAX_ERASE_SECTORS_ONCE);/* Loop over the selected sectors and erase them. */retval = ROM_QSPI_EraseSector(bank->target, erase_first, erase_last);if (retval != ERROR_OK) {LOG_WARNING("AIR105 erase sector from %d to %d error(retry):%d", erase_first, erase_last, retval);if (error_times++ > 5) {return retval;}continue;}erase_first = erase_last;num_sectors -= MAX_ERASE_SECTORS_ONCE;}
    
  • 3)至此,AIR105 驱动终于开发完成了。皇天不负有心人,CLion 给的惊喜太大了:

    • 命令行测试时,最高速度只有 40 KiB/s 左右,这一下提高了快 4 倍。

4 附录1:调用 AIR105 FLM 算法的尝试

4.1 关于 Keil FLM

  • 1)首先查看一下 FLASH 相关信息(这里显示了 15 MB 的大小,但手册上说只有 4MB):

  • 2)Keil 规定,一个 FLM 文件中要包含一些指定函数及结构:

    • (1)函数(FlashPrg.c):

      函数名是否必须描述
      Init初始化
      UnInit反初始化
      EraseSector扇擦除
      ProgramPage页擦除
      EraseChip片擦除。
      BlankCheckBlank 检查。
      Verify校验。
    • (2)FLASH 说明结构体(FlashDev.c):

    struct FlashDevice const FlashDevice  =  {FLASH_DRV_VERS,             // Driver Version, do not modify!"New Device 256kB Flash",   // Device Name ONCHIP,                     // Device Type0x00000000,                 // Device Start Address0x00040000,                 // Device Size in Bytes (256kB)1024,                       // Programming Page Size0,                          // Reserved, must be 00xFF,                       // Initial Content of Erased Memory100,                        // Program Page Timeout 100 mSec3000,                       // Erase Sector Timeout 3000 mSec// Specify Size and Address of Sectors0x002000, 0x000000,         // Sector Size  8kB (8 Sectors)0x010000, 0x010000,         // Sector Size 64kB (2 Sectors) 0x002000, 0x030000,         // Sector Size  8kB (8 Sectors)SECTOR_END
    };
    
    • (3)官方说明文档:
      • https://open-cmsis-pack.github.io/Open-CMSIS-Pack-Spec/main/html/flashAlgorithm.html
      • https://developer.arm.com/documentation/ka002873/latest
  • 3)函数说明:

    /*** FLASH 初始化,每次编程时调用** Keil 提供的示例代码中实现了三件事:* (1)设置 FLASH 读取间隔(LATENCY)* (2)解锁 FLASH* (3)增加独立看门狗(IWDG)喂狗时间(应该是防止程序烧录过程中喂狗时间到)** @param adr   Device base address* @param clk   Clock frequency(Hz)* @param fnc   Function code: 1, Erase; 2, Program; 3,Verify.* @return  status information: 0, on success; 1, on failure.*/
    int Init (unsigned long adr, unsigned long clk, unsigned long fnc);/*** FLASH 反初始化,在一次擦除、编程、或校验后调用。** Keil 提供的示例代码:重新锁定 FLASH** @param fnc   Function code: 1, Erase; 2, Program; 3, Verify.* @return status information: 0, on success; 1, on failure.*/
    int UnInit (unsigned long fnc);/*** 扇区擦除** Keil 提供的示例代码:重新锁定 FLASH** @param addr   Sector address* @return status information: 0, on success; 1, on failure.*/    
    int EraseSector (unsigned long adr);/*** 页编程** Keil 提供的示例代码为每次写半个字(即 2 个字节)** @param adr	Page start address* @param sz	Page size* @param buf	Data to be written* @return  status information: 0, on success; 1, on failure.*/
    int ProgramPage (unsigned long adr, unsigned long sz, unsigned char *buf);/*** 片擦除** @return  status information: 0, on success; 1, on failure.*/
    int EraseChip (void);/*** Blank 检查,检查指定块是否是指定内容 pat。** @param adr	Block start address* @param sz	Block size in bytes* @param pat	Pattern to compare* @return  status information: 0, block content == pattern pat; 1, block content != pattern pat.*/
    int BlankCheck (unsigned long adr, unsigned long sz, unsigned char pat);/*** 数据校验,校验 FLASH 数据是否和 buf 内容一致** @param adr	Start address* @param sz	Size in bytes* @param buf	Data to be compared* @return  success, sum of adr+sz; failure, other number represents the failing address.*/
    unsigned long Verify(unsigned long adr, unsigned long sz, unsigned char *buf);
    

4.2 解析 FLM 文件

  • 1)通过 arm-none-eabi-readelf 命令,找到 FLM 中定义的必要函数所在位置。

    $ arm-none-eabi-readelf.exe --helpUsage: readelf <option(s)> elf-file(s)
    Display information about the contents of ELF format files$ arm-none-eabi-readelf.exe -a Air105.FLMSymbol table '.symtab' contains 371 entries:
    Num:    Value  Size Type    Bind   Vis      Ndx Name
    297: 00000089    32 FUNC    GLOBAL HIDDEN     1 BlankCheck
    317: 00000d61    12 FUNC    GLOBAL HIDDEN     1 EraseChip
    318: 00000d6d    40 FUNC    GLOBAL HIDDEN     1 EraseSector
    319: 00000d95   332 FUNC    GLOBAL HIDDEN     1 Init
    320: 00000ffd    86 FUNC    GLOBAL HIDDEN     1 ProgramPage
    365: 00001f89    26 FUNC    GLOBAL HIDDEN     1 UnInit
    
  • 参考:https://blog.csdn.net/sinat_31039061/article/details/128350295

这篇关于OpenOCD 添加 AIR105(下)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/642749

相关文章

OpenOCD

http://openocd.org/getting-openocd/

下载软件 (二) openocd

简介 openocd 可用来在在linux上运行,做应用,打开相应的调试器对应文件,然后通过调试器控制stm32对应cmsis-dap 来说 不需要驱动,只需要应用openocd调试器对应文件为open("/dev/hidraw1", O_RDWR) = 3 strace 跟踪的openocd 下载过程 在 log.openocd log 地址 安装 sud

openocd riscv 对应的jtag动作解析

openocd 服务器开启时1.探测存在的核心2.halt住核心3.读misa4.resume核心5.循环查询dmstatus traget remote时1.halt住核心2.读了X0-X31和PC2.读各种CSR寄存器(TODO) disconnect 时1. resume request openocd 服务器 被ctrl-c 结束时1. resume req

ESP32S3在wsl环境的JTAG、openocd仿真调试

文章目录 一、准备工作二、添加 ESP-IDF 环境变量三、添加 udev 规则文件四、vscode 配置 一、准备工作 安装配置好 WSL、ubuntu, 参考连接: WSL2安装Ubuntu迁移到其他盘或者其他电脑_wsl ubuntu迁移-CSDN博客 WSL2 设置桥接模式_wsl2 桥接-CSDN博客 下载好 WSL-USB 参考连接 WSL2 Ubuntu装ESP

【教程】在Ubuntu下搭建ARM处理器 arm-linux-gcc 交叉编译环境以及OpenJTAG + openocd 烧写环境

在Ubuntu下搭建ARM处理器 arm-linux-gcc 交叉编译环境以及OpenJTAG + openocd 烧写环境 前言 本教程所用操作系统为Ubuntu 16.04,所用ARM处理器为Samsung S3C2440,在FriendlyARM Mini2440开发板上进行操作,使用OpenJTAG + openocd 烧录程序。 当然,道理是相通的,所以在不同平台下也只是稍微修

使用openocd + gdb 调试 imx6y芯片

使用openocd + gdb 调试 imx6y芯片 开发环境介绍 开发平台是正点原子的 imx6 mini开发板,核心板上的芯片不是imx6u而是imx6y,调试工具用的淘宝上买的jlink v11,感觉现在这个质量有点良莠不齐,换了三家店才买到一个能用openocd的,电脑上用的工具就是 windows 下的 openocd 和 windows子系统ubuntu 下的 arm-linux-

ubuntu下vscode+STM32CubeMX+openocd+stlinkv2搭建STM32开发调试下载环境

1、换源 清华源 # 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ ja

在ubuntu上使用vscode+gcc-arm-none-eabi+openocd工具开发STM32

文章目录 所需工具安装调试搭建过程中遇到的问题 写在前面   老大上周让我用vscode开发STM32,我爽快的答应了,心想大学四年装了这么多环境了这不简简单单,更何况vscode这两年还用过,然而现实总是令人不快的——我竟然花了差不多两周时间在这上面,并且不知道花费了多少流量😭😭😭。这玩意就给了所需要的主要工具,形象一点就如标题,问其他人他们也搞不定。因此,大家有空还是

Openocd 安装并在Eclipse环境下通过J-Link调试

一,安装前准备 1,软件安装平台:CentOS 5.5 2,开发板硬件环境:Mini2440 3,下载最新版http://sourceforge.net/projects/openocd/,当前版本oenocd-0.4.0 安装时参考文章http://www.eefocus.com/nl1031/blog/09-11/180036_21ebd.html 博主hy343说,很重要的一步是安

ubuntu10.04下使用insight(需要先装有openocd)

软件的安装 1. tar jxvf insight-6.8-1.tar.bz2 2. cd insight-6.8-1 3. ./configure --prefix=/opt/arm-linux-insight --target=arm-linux-gnu 4. make     编译很久产生错误     cc1: warnings being treated as errors