当前位置: 首页 > article >正文

DAPLINK 源码学习(1)BL 之 main() 函数

文章目录

    • bootloader 主函数
    • 1 sdk_init()
    • 2 gpio_init()
    • 3 config_init()
    • 4 board_bootloader_init()
    • 5 运行 IF 还是 BL?
    • 6 main_task()
    • 7 总结

bootloader 主函数

1)我们以 stm32f103xb_bl 为例,从 bootloader 项目的 main() 函数开始:

  • (1)sdk_init():MCU 初始化
  • (2)gpio_init():USB 相关引脚配置
  • (3)config_init():RAM 中配置初始化
  • (4)board_bootloader_init():nothing
  • (5)reset_button_pressed() 和 modify_stack_pointer_and_start_app():运行 BL or IF
  • (6)OS 和 main task 配置:
    • osKernelInitialize():初始化
    • osThreadNew(main_task):主任务回调函数 main_task()
    • osKernelStart():启动主任务

1 sdk_init()

1)sdk_init() 是 DAPLINK 提供的 厂商 sdk 初始化 接口函数。移植时可实现该函数,以进行时钟等外设上电初始化:

// 在 /source/hic_hal/sdk.h 文件中声明
void sdk_init(void);

// 在 /source/daplink/sdk_stub.c 文件中提供默认实现
__WEAK void sdk_init()
{
    // Do nothing
}

2)在 stm32f103xb_bl 项目中,该函数的调用逻辑如下:

2 gpio_init()

1)gpio_init() 是 DAPLINK 提供的 LED、按键初始化接口函数。移植时可实现该函数,用来来指示 USB 状态、等

2)在 stm32f103xb_bl 项目中,该函数的调用逻辑如下:

3 config_init()

config_init() 用来进行配置初始化。其创建 static cfg_ram_t 结构体的两个实例:config_ram 和 config_ram_copy。

可以用来对配置进行备份:比如我们在程序运行过程中(非上电)调用 config_init() 函数,则当前配置将保存到 config_ram_copy 中;此时我们可以对配置进行临时修改,修改完成后如果我们想恢复,只需要将 config_ram.key 修改一下后再次调用 config_init() 函数即可。

2)在 stm32f103xb_bl 项目中,该函数的调用逻辑如下:

4 board_bootloader_init()

board_bootloader_init() 是 DAPLINK 提供的板级 bootloader 初始化接口函数。移植时可实现该函数,用来对开发板进行初始化(DAPLINK 中,除了 nrf52820 芯片对 bootloader 所在的 flash 进行锁定外,没有其它厂商实现该函数)。

// 定义在 source/daplink/bootloader/main_bootloader.c 文件中
__WEAK void board_bootloader_init()
{
    return;
}

5 运行 IF 还是 BL?

BL 表示 bootloader,用来升级 IF;IF 则表示 interface,是 DAPLINK 实现烧录的执行代码。

该部分代码逻辑如下:

if (!reset_button_pressed()
    && g_board_info.target_cfg
    && validate_bin_nvic((uint8_t *)g_board_info.target_cfg->flash_regions[0].start)
    && !config_ram_get_initial_hold_in_bl()) {
    
    // change to the new vector table
    SCB->VTOR = g_board_info.target_cfg->flash_regions[0].start; //bootloaders should only have one flash region for interface
    
    // modify stack pointer and start app
    modify_stack_pointer_and_start_app((*(uint32_t *)(g_board_info.target_cfg->flash_regions[0].start)),
            (*(uint32_t *)(g_board_info.target_cfg->flash_regions[0].start + 4)));
}
  • 1)首先是 reset_button_pressed() 函数,该函数主要用来判断当前是否是复位状态。以 stm32f103xb_bl 为例来看,当 MCU 低电平复位时,该函数返回 1,无法进入 if 逻辑内。

  • 2)然后是 validate_bin_nvic() 函数,该函数有两个判断:

    • (1)判断 SP 指针。即 IF 在 FLASH 起始地址存储的内容是否在 RAM 的地址范围内。

      当我们没有烧录 IF 时,该地址上存储值为 0xFFFFFFFF,不在 RAM 范围内。将无法进入到该 if 判断内部执行。

    • (2)判断 Reset_Handler、NMI_Handler、HardFault_Handler 指针。即 IF 在 FLASH 起始地址偏移 4、8、12 位置存储的内容是否在超出 FLASH 区域

  • 3)最后是 config_ram_get_initial_hold_in_bl() 函数,该函数用来判断是否 hold in bootloader。
    cfg_ram_t config_ram 结构体持有的 uint8_t 类型的 hold_in_bl 变量,该变量只有在虚拟文件系统 vfs 改变时才会通过调用 config_ram_set_hold_in_bl() 函数来修改。

  • 4)modify_stack_pointer_and_start_app() 函数,从 FLASH 中 IF 所在位置开始运行。

6 main_task()

  • 1)OsKernelInitialize():初始化 OS 内核
  • 2)osThreadNew():将 main_task() 函数赋值给到 OS 的主函数回调上。
  • 3)osKernelStart():回调 main_task() 函数

7 总结

关于 main() 函数,我们来总结一下移植时需要修改的地方:

移植点描述
sdk_init()厂商 sdk 初始化。主要用来进行时钟 RCC 的初始化
gpio_init()led、button 初始化。USB 状态指示灯、复位按钮初始化
board_bootloader_init()缺省。bootloader flash
board_info_t g_board_info板子信息定义。包括 daplink 名称、mcu flash/ram 信息等

http://www.kler.cn/news/360211.html

相关文章:

  • typescript 的类型注解和类型断言
  • C#学习笔记(十)
  • 拥抱“新市民” ,数字银行的“谋与变”
  • jetson agx orin 的pytorch、torchvision安装
  • el-table表格数据处理,列表将变更前数据放置在前面,变更后数据放在表格后面
  • 第1篇:计算机网络概述与基础
  • 【小白学机器学习15】 概率论的世界观
  • Web,RESTful API 在微服务中的作用是什么?
  • 【修订中】ffmpeg 知识点
  • 从传统到智能,从被动监控到主动预警,解锁视频安防平台EasyCVR视频监控智能化升级的关键密钥
  • 【小程序】-基础语法(二)
  • Netty初体验-1-NIO基础补漏
  • 域渗透之 内网穿透 隧道技术聊聊看 环境搭建 regeorg技术 proxifier联合使用 一步步让你明白如何玩转隧道技术 含对应软件下载
  • Yolo目标检测:实时性与准确性的完美结合
  • 一文2500字从0到1实现压测自动化!
  • 宠物用品电商网站:SpringBoot框架设计与开发
  • 回忆Web编程的岁月变迁
  • Anchor DETR论文笔记
  • Docker私有仓库部署与管理
  • 【含开题报告+文档+PPT+源码】基于SpringBoot电脑DIY装机教程网站的设计与实现