CH32V 系列 MCU IAP 使用函数形式通过传参形式灵活指定APP跳转地址

参考:
CH32V 系列 MCU IAP 升级跳转方法
CH32V103 的 IAP 问题(跳转及中断向量表重定位)

1. 沁恒的RISC-V内核MCU的IAP跳转示例程序简要分析

沁恒的RISC-V内核的MCU比如CH32V203、CH32V307等系列的EVT包中IAP升级的示例程序中都是通过使能软件中断之后,在 SW_Handler 函数中进行 APP 地址的跳转,如下图指定了 0x5000 的偏移地址去跳转,实际是为0x08000000 + 0x5000的地址,只不过在 LD 文件里设置了APP的 FLASH 起始地址后中断向量会自动偏移,IAP 不用管它。

这种方法是通过使能软件中断,使内核自动从用户模式进入机器模式后 ,进行的跳转,该方式无需配置工程在机器模式下,无需修改启动文件中 mstatus 寄存器的值。但是是写死的跳转地址,不够灵活 。参见**QingKeV4_Processor_Manual.PDF**中

1.1 mstatus描述

在默认的启动文件中可以看到mstatus寄存器值为0x6088,MPP位配置为了用户模式,MPIE和MIE使能。

2. 直接在 IAP 程序中需跳转位置直接进行跳转

重点参考: CH32V 系列 MCU IAP 升级跳转方法

但某些情况下,软件中断函数需用做他用,或用户不想通过中断进行跳转,可直接在 IAP 程序中需跳转位置直接进行跳转。当不通过中断直接进行跳转时,需要配置工程在机器模式下,需要修改 mstatus 寄存器的值。

mstatus 寄存器为机器模式状态寄存器,通过该寄存器可配置 MCU 运行在机器模式或用户模式下。此外,对于支持浮点运算的

MCU,通过该寄存器可开启或关闭浮点运算功能。关于该寄存器的具体介绍,可参考各 MCU 对应的青稞手册,具体可在沁恒官网搜索下载。

CH32V103 机器模式下配置 mstatus 的值为:0x1888

CH32V307 机器模式下配置 mstatus 的值为:0x7888

方式 1:

跳转函数按照下方式编写,注意此处一定要使用 a0,需要加__attribute__((noinline)),具体如下:

c 复制代码
__attribute__((noinline))
void jump_APP(uint32_t  addr)
{
    __asm("jr  a0");
    while(1);
}

入参addr实际保存在寄存器a0中,通过jr a0跳转到addr地址中。

方式2:

c 复制代码
void jump_APP(uint32_t  addr)
{
    __asm volatile("jr %0": :"r"(addr));

    while(1);
}

使用方法与方式 1 一致,直接在程序调用即可,这里同样注意,是相对的偏移地址,即 0x08000000 + addr 的地址

方式3:

c 复制代码
void jump_APP(uint8_t  value)
{
    if(value==1)
    {
        __asm("li  a6, 0x5000");
        __asm("jr  a6");
    }
    else if (value==2)
    {
        __asm("li  a6, 0x6000");
        __asm("jr  a6");
    }
    else if (value==3)
    {
        __asm("li  a6, 0x7000");
        __asm("jr  a6");
    }
    else
    {
        __asm("li  a6, 0x8000");
        __asm("jr  a6");
    }

    while(1);
}

这种其实和EVT中的IAP没啥区别,都是写死的地址跳转,不像方式2那种可以灵活制定地址进行跳转。

3. 利用软件中断+jump_APP(addr)使用

c 复制代码
/*********************************************************************
 * @fn      SW_Handler
 *
 * @brief   This function handles Software exception.
 *
 * @return  none
 */
// 这里的addr是相对0x08000000的偏移地址
void jump_APP(uint32_t addr)
{
    __asm volatile("jr %0": :"r"(addr));

    while(1);
}

void SW_Handler(void)
{
//    假设要跳转到的APP地址为 0x08005000
//    jump_app_address = 0x08005000 - 0x08000000 = 0x5000;
    jump_APP(jump_app_address);
}

如上所示,进入软件中断中,使用jump_APP(addr)就可以灵活指定要跳转到的APP入口地址了。

3.1. 简单测试

这里我使用了Ymodem协议通过串口发送APP固件给bootloader,固件接收保存在MCU中的flash后,更新APP入口地址这个全局变量 jump_app_address值为0x7800,实际为FLASH中的0x08000000+0x7800的地址,在软件中断中跳转到偏移地址0x7800即可。

不用像ARM单片机那样考虑中断向量表的重新映射,因为CH32V在默认的LD 文件里设置 FLASH 起始地址后中断向量会自动偏移,IAP 不用管它。

相关推荐
远望创客学堂6 小时前
【单片机毕业设计选题24047】-基于阿里云的工地环境监测系统
stm32·单片机·嵌入式硬件·阿里云·云计算·课程设计·arduino
极客小张6 小时前
利用 STM32 实现多协议物联网网关:Modbus/Zigbee 到以太网/Wi-Fi 的数据桥接
stm32·单片机·嵌入式硬件·物联网·网络协议·https·硬件工程
FPGAmaster创新者7 小时前
基于AGX ORIN与FPGA K7实现PCIE高速数据通信/Orin与FPGA高速数据传输/XDMA在linux系统使用教程
linux·嵌入式硬件·fpga开发
XD7429716367 小时前
【TB作品】电子琴,ATMEGA16单片机,Proteus仿真
单片机·proteus·电子琴·atmega
maybe_YX8 小时前
51单片机基础8——单片机控制超声波模块
c语言·单片机·嵌入式硬件·51单片机
@一二三四五8 小时前
STM32 看门狗 HAL
stm32·单片机·嵌入式硬件
北京迅为8 小时前
【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第一篇 嵌入式Linux入门篇-第四章 Ubuntu启用root用户
linux·嵌入式硬件
maybe_YX8 小时前
51单片机基础10——串口实验
c语言·单片机·嵌入式硬件·51单片机
Qingniu019 小时前
开关电源的电路组成原理
单片机·嵌入式硬件·新能源·电源模块·无刷电机
芯源义码10 小时前
嵌入式软件常用测试工具
单片机