|
为国产芯片增加OpenOCD Flash驱动----以AIC8800为例
[复制链接]
一般而言,在上手一个新芯片时,如果其架构已被OpenOCD支持,那么可以直接访问其寄存器及RAM。但对于Flash部分,往往需要写一个几百行的Flash驱动文件。
Flash操作的基本套路
显而易见的,调试器可以控制CPU、可以改写寄存器和RAM,最直接的方式就是通过访问Flash控制器的相关寄存器来完成对Flash的擦除及写入。但在这颗芯片上,原厂并没有提供Flash控制器的资料,而是提供了一个ROM API表,如下:
- struct aic8800_rom_falsh_api_t {
- void (*undefined_api_0)(void);
- void (*undefined_api_1)(void);
- uint32_t (*ChipSizeGet)(void);
- void (*ChipErase)(void);
- int32_t (*Erase)(uint32_t addr_4k, uint32_t len);
- int32_t (*Write)(uint32_t addr_256, uint32_t len, uint32_t buf);
- int32_t (*Read)(uint32_t addr_256, uint32_t len, uint32_t buf);
- void (*CacheInvalidAll)(void);
- void (*CacheInvalidRange)(uint32_t addr, uint32_t len);
- } aic8800_rom_falsh_api @ 0x00000180UL;
就是说,我们需要让调试器调用这些API来完成对应功能。
构造API调用
需要注意的是这些API是普通的C函数,在调用前,需要配置好传入参数及栈。同时,为了让所运行的程序能自动暂停,也需要增加一个特殊汇编指令 ,完整的汇编代码如下:
- LDR.N R3, [PC, #0x4]
- BLX R3
- BKPT #0x0
- NOP
- DC32 0x12345678
部分代码解析
以擦除为例,请看下列代码中的中文注释
- static uint32_t romapi_Erase(struct flash_bank *bank, uint32_t addr, uint32_t len)
- {
- int retval;
- struct working_area *algorithm;
- struct target *target = bank->target;
- struct aic8800_flash_bank *aic8800_bank = bank->driver_priv;
- struct reg_param reg_params[3];
-
- /*
- 在脚本指定的work-area(即部分SRAM区域)中,分配一块RAM用于放入汇编代码及栈
- */
- retval = target_alloc_working_area(target, sizeof(struct aic8800_rom_api_call_code_t) + STACK_DEFAULT, &algorithm);
- if (retval != ERROR_OK) {
- LOG_ERROR("Insufficient working area to initialize. You must allocate at least %zdB of working "
- "area in order to use this driver.", sizeof(struct aic8800_rom_api_call_code_t) + STACK_DEFAULT);
- return retval;
- }
-
- /*
- 将调用Erase API的汇编代码写入这块SRAM的头部
- */
- retval = target_write_buffer(target, algorithm->address, sizeof(struct aic8800_rom_api_call_code_t),
- (const uint8_t *)&aic8800_bank->rom_api_call_code[4]);
- if (retval != ERROR_OK) {
- target_free_working_area(target, algorithm);
- return retval;
- }
-
- /*
- 配置R0 R1 SP寄存器
- */
- init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT);
- init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
- init_reg_param(®_params[2], "sp", 32, PARAM_OUT);
- buf_set_u32(reg_params[0].value, 0, 32, addr);
- buf_set_u32(reg_params[1].value, 0, 32, len);
- buf_set_u32(reg_params[2].value, 0, 32, algorithm->address + algorithm->size);
-
- /*
- #define CALL_CODE_BKPT_ADDR(enter_addr) ((enter_addr) + 4)
- 调用汇编,指定了汇编代码的入口地址及自动断点地址,并根据擦除块的数量粗略计算了一个超时时间
- */
- LOG_DEBUG("Running AIC8800 Erase algorithm");
- retval = target_run_algorithm(target, 0, NULL, dimof(reg_params), reg_params,
- algorithm->address, CALL_CODE_BKPT_ADDR(algorithm->address),
- TIMEROUT_ERASE_4K * (len / 4096), &aic8800_bank->armv7m_info);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error executing Erase algorithm");
- }
-
- /*
- 释放资源
- */
- target_free_working_area(target, algorithm);
- destroy_reg_param(®_params[0]);
- destroy_reg_param(®_params[1]);
- destroy_reg_param(®_params[2]);
-
- return retval;
- }
其他代码及编译过程不再赘述
脚本调用
AIC8800的调试脚本与其他Cortex-M4基本相同,需要修改的有两点:
- 指定一个RAM区域,用于运行Flash操作代码
- $_TARGETNAME configure -work-area-phys 0x00160000 -work-area-size $_WORKAREASIZE -work-area-backup 0
- 指定Flash起始地址
- flash bank $_FLASHNAME aic8800 0x08000000 0 0 0 $_TARGETNAME
测试
- 运行
- .openocd.exe -f .cmsis-dap_v2_aic8800m.cfg
- Open On-Chip Debugger 0.11.0+dev-gce5ddd7f7 (2022-02-20-08:04)
- Licensed under GNU GPL v2
- For bug reports, read
- http://openocd.org/doc/doxygen/bugs.html
- Info : Listening on port 6666 for tcl connections
- Info : Listening on port 4444 for telnet connections
- Info : Using CMSIS-DAPv2 interface with VID:PID=0x1209:0x6666, serial=Vllink.Basic.0123456789A
- Info : CMSIS-DAP: SWD supported
- Info : CMSIS-DAP: JTAG supported
- Info : CMSIS-DAP: SWO-UART supported
- Info : CMSIS-DAP: Atomic commands supported
- Info : CMSIS-DAP: Test domain timer supported
- Info : CMSIS-DAP: FW Version = 0254
- Info : CMSIS-DAP: Serial
- Info : CMSIS-DAP: Interface Initialised (SWD)
- Info : SWCLK/TCK = 0 SWDIO/TMS = 0 TDI = 0 TDO = 0 nTRST = 0 nRESET = 1
- Info : CMSIS-DAP: Interface ready
- Info : clock speed 8000 kHz
- Info : SWD DPIDR 0x2ba01477
- Info : aic8800m.cpu: Cortex-M4 r0p1 processor detected
- Info : aic8800m.cpu: target has 2 breakpoints, 1 watchpoints
- Info : starting gdb server for aic8800m.cpu on 3333
- Info : Listening on port 3333 for gdb connections
-
连接Telnet ,执行如下命令完成测试
- Open On-Chip Debugger
- > halt
- target halted due to debug-request, current mode: Thread
- xPSR: 0x21000000 pc: 0x00002272 msp: 0x0019ff88
- > flash probe 0
- Flash Size = 2048kbytes
- flash 'aic8800' found at 0x08000000
-
- > flash write_image erase ./host_wb.bin 0x08000000 bin
- Padding image section 0 at 0x08063c18 with 232 bytes (bank write end alignment)
- Adding extra erase range, 0x08063d00 .. 0x08063fff
- auto erase enabled
- wrote 408832 bytes from file ./host_wb.bin in 4.843174s (82.436 KiB/s)
-
- > flash verify_image ./host_wb.bin 0x08000000 bin
- Padding image section 0 at 0x08063c18 with 232 bytes (bank write end alignment)
- verified 408832 bytes from file ./host_wb.bin in 0.732257s (545.232 KiB/s)
-
- > flash erase_check 0
- successfully checked erase state
- # 0: 0x00000000 (0x1000 4kB) not erased
- # 1: 0x00001000 (0x1000 4kB) not erased
- # 2: ...
- ...
- # 97: ...
- # 98: 0x00062000 (0x1000 4kB) not erased
- # 99: 0x00063000 (0x1000 4kB) not erased
- #511: 0x001ff000 (0x1000 4kB) not erased
-
- > flash erase_sector 0 0 510
- erased sectors 0 through 510 on flash bank 0 in 0.679665s
-
- > flash erase_check 0
- successfully checked erase state
- #511: 0x001ff000 (0x1000 4kB) not erased
-
- >
总结
在增加Flash驱动后,可以在调试过程中直接一键完成程序的下载,非常方便。
几个链接
|
|