参考链接:
https://blog.csdn.net/pilihuo182175954/article/details/124856479
https://blog.csdn.net/qq_58099085/article/details/131813593
https://bbs.21ic.com/icview-3214976-1-1.html
https://blog.csdn.net/weixin_38848977/article/details/72523561
https://shatang.github.io/2020/08/12/M0%E7%9A%84%E4%B8%AD%E6%96%AD%E5%90%91%E9%87%8F%E8%A1%A8%E9%87%8D%E6%98%A0%E5%B0%84/
方法一,华大M0内核的CPU内核为M0+,支持中断向量偏移寄存器。根据华大官方IAP例程,修改SCB->VTOR寄存器即可
方法二、直接在Boot程序的中断向量函数跳转到APP的中断函数。参考链接1、2
方法三、参考STM32F0把中断向量表映射到内存上华大MCU不支持此方法
下面具体说一下方法二的实现:
实现原理,在boot和app程序同时定义一个变量irq_jump_flag在内存0x2000000位置
#define FLAG_JUMP_BOOTLOADER 0x5A5A5A5A
#define FLAG_JUMP_APP 0xA0A0A0A0
//static uint32_t irq_jump_flag __attribute__ ((at(0x20000000)));//AC5编译
__IO uint32_t irq_jump_flag __attribute__((section(".ARM.__at_0x20000000")));//AC6编译
在Boot程序里面此变量赋值为FLAG_JUMP_BOOTLOADER,在APP程序此变量赋值为FLAG_JUMP_APP。
boot里面的所有中断函数,对变量irq_jump_flag进行判断,根据irq_jump_flag内容选择执行Boot的中断函数,还是跳转到app的中断函数
代码片段
startup_hc32.s文件中
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset
DCD NMI_Handler ; NMI
DCD HardFault_Handler ; Hard Fault
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV
DCD SysTick_Handler ; SysTick
DCD IRQ000_Handler ;
DCD IRQ001_Handler ;
DCD IRQ002_Handler ;
DCD IRQ003_Handler ;
DCD IRQ004_Handler ;
DCD IRQ005_Handler ;
DCD IRQ006_Handler ;
DCD IRQ007_Handler ;
DCD IRQ008_Handler ;
DCD IRQ009_Handler ;
DCD IRQ010_Handler ;
DCD IRQ011_Handler ;
DCD IRQ012_Handler ;
DCD IRQ013_Handler ;
DCD IRQ014_Handler ;
DCD IRQ015_Handler ;
DCD IRQ016_Handler ;
DCD IRQ017_Handler ;
DCD IRQ018_Handler ;
DCD IRQ019_Handler ;
DCD IRQ020_Handler ;
DCD IRQ021_Handler ;
DCD IRQ022_Handler ;
DCD IRQ023_Handler ;
DCD IRQ024_Handler ;
DCD IRQ025_Handler ;
DCD IRQ026_Handler ;
DCD IRQ027_Handler ;
DCD IRQ028_Handler ;
DCD IRQ029_Handler ;
DCD IRQ030_Handler ;
DCD IRQ031_Handler ;
Boot程序的main.c文件中
/* Flash相关宏定义 */
#define FLASH_SECTOR_SIZE 0x200ul //一个sector的尺寸
#define FLASH_BASE ((uint32_t)0x00000000) //flash基地址
#define FLASH_SIZE (128u * FLASH_SECTOR_SIZE) //flash尺寸
/* BootLoader flash相关宏定义 */
#define BOOT_SIZE (8*FLASH_SECTOR_SIZE) //BootLoader flash尺寸
#define BOOT_PARA_ADDRESS (FLASH_BASE + BOOT_SIZE - 0x100u) //BootLoader para存储地址
/* APP flash相关宏定义 */
#define APP_FLAG ((uint32_t)0x67890123) //从BootLoader para区读到此值,表示APP需要更新
#define APP_ADDRESS (FLASH_BASE + BOOT_SIZE) //APP程序存储基地址
#define FLAG_JUMP_BOOTLOADER 0x5A5A5A5A
#define FLAG_JUMP_APP 0xA0A0A0A0
//static uint32_t irq_jump_flag __attribute__ ((at(0x20000000)));//AC5编译
__IO uint32_t irq_jump_flag __attribute__((section(".ARM.__at_0x20000000")));//AC6编译
__WEAK void __SVC_Handler(void);
__WEAK void __PendSV_Handler(void);
__WEAK void __SysTick_Handler(void);
__WEAK void PORTA_IRQHandler(void);
__WEAK void PORTB_IRQHandler(void);
__WEAK void PORTC_IRQHandler(void);
__WEAK void PORTD_IRQHandler(void);
__WEAK void DMAC_IRQHandler(void);
__WEAK void TIM3_IRQHandler(void);
__WEAK void UART0_IRQHandler(void);
__WEAK void UART1_IRQHandler(void);
__WEAK void LPUART0_IRQHandler(void);
__WEAK void LPUART1_IRQHandler(void);
__WEAK void SPI0_IRQHandler(void);
__WEAK void SPI1_IRQHandler(void);
__WEAK void I2C0_IRQHandler(void);
__WEAK void I2C1_IRQHandler(void);
__WEAK void TIM0_IRQHandler(void);
__WEAK void TIM1_IRQHandler(void);
__WEAK void TIM2_IRQHandler(void);
__WEAK void LPTIM_IRQHandler(void);
__WEAK void TIM4_IRQHandler(void);
__WEAK void TIM5_IRQHandler(void);
__WEAK void TIM6_IRQHandler(void);
__WEAK void PCA_IRQHandler(void);
__WEAK void WDT_IRQHandler(void);
__WEAK void RTC_IRQHandler(void);
__WEAK void ADC_IRQHandler(void);
__WEAK void PCNT_IRQHandler(void);
__WEAK void VC0_IRQHandler(void);
__WEAK void VC1_IRQHandler(void);
__WEAK void LVD_IRQHandler(void);
__WEAK void LCD_IRQHandler(void);
__WEAK void FLASH_RAM_IRQHandler(void);
__WEAK void CLK_TRIM_IRQHandler(void);
typedef uint32_t( *pImageTaskFn)( void );
static uint32_t JumpNext(void)
{
return APP_ADDRESS;
}
static void GotoVector(uint32_t IRQn)
{
((pImageTaskFn *)JumpNext())[IRQn + 16]();
}
void SVC_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
__SVC_Handler();
}
else
{
GotoVector(SVC_IRQn);
}
}
void PendSV_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
__PendSV_Handler();
}
else
{
GotoVector(PendSV_IRQn);
}
}
void SysTick_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
__SysTick_Handler();
}
else
{
GotoVector(SysTick_IRQn);
}
}
void IRQ000_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
PORTA_IRQHandler();
}
else
{
GotoVector(PORTA_IRQn);
}
}
void IRQ001_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
PORTB_IRQHandler();
}
else
{
GotoVector(PORTB_IRQn);
}
}
void IRQ002_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
PORTC_IRQHandler();
}
else
{
GotoVector(PORTC_IRQn);
}
}
void IRQ003_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
PORTD_IRQHandler();
}
else
{
GotoVector(PORTD_IRQn);
}
}
void IRQ004_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
DMAC_IRQHandler();
}
else
{
GotoVector(DMAC_IRQn);
}
}
void IRQ005_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
TIM3_IRQHandler();
}
else
{
GotoVector(TIM3_IRQn);
}
}
void IRQ006_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
UART0_IRQHandler();
}
else
{
GotoVector(UART0_IRQn);
}
}
void IRQ007_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
UART1_IRQHandler();
}
else
{
GotoVector(UART1_IRQn);
}
}
void IRQ008_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
LPUART0_IRQHandler();
}
else
{
GotoVector(LPUART0_IRQn);
}
}
void IRQ009_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
LPUART1_IRQHandler();
}
else
{
GotoVector(LPUART1_IRQn);
}
}
void IRQ010_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
SPI0_IRQHandler();
}
else
{
GotoVector(SPI0_IRQn);
}
}
void IRQ011_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
SPI1_IRQHandler();
}
else
{
GotoVector(SPI1_IRQn);
}
}
void IRQ012_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
I2C0_IRQHandler();
}
else
{
GotoVector(I2C0_IRQn);
}
}
void IRQ013_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
I2C1_IRQHandler();
}
else
{
GotoVector(I2C1_IRQn);
}
}
void IRQ014_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
TIM0_IRQHandler();
}
else
{
GotoVector(TIM0_IRQn);
}
}
void IRQ015_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
TIM1_IRQHandler();
}
else
{
GotoVector(TIM1_IRQn);
}
}
void IRQ016_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
TIM2_IRQHandler();
}
else
{
GotoVector(TIM2_IRQn);
}
}
void IRQ017_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
LPTIM_IRQHandler();
}
else
{
GotoVector(LPTIM_IRQn);
}
}
void IRQ018_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
TIM4_IRQHandler();
}
else
{
GotoVector(ADTIM4_IRQn);
}
}
void IRQ019_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
TIM5_IRQHandler();
}
else
{
GotoVector(ADTIM5_IRQn);
}
}
void IRQ020_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
TIM6_IRQHandler();
}
else
{
GotoVector(ADTIM6_IRQn);
}
}
void IRQ021_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
PCA_IRQHandler();
}
else
{
GotoVector(PCA_IRQn);
}
}
void IRQ022_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
WDT_IRQHandler();
}
else
{
GotoVector(WDT_IRQn);
}
}
void IRQ023_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
RTC_IRQHandler();
}
else
{
GotoVector(RTC_IRQn);
}
}
void IRQ024_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
ADC_IRQHandler();
}
else
{
GotoVector(ADC_IRQn);
}
}
void IRQ025_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
PCNT_IRQHandler();
}
else
{
GotoVector(PCNT_IRQn);
}
}
void IRQ026_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
VC0_IRQHandler();
}
else
{
GotoVector(VC0_IRQn);
}
}
void IRQ027_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
VC1_IRQHandler();
}
else
{
GotoVector(VC1_IRQn);
}
}
void IRQ028_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
LVD_IRQHandler();
}
else
{
GotoVector(LVD_IRQn);
}
}
void IRQ029_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
LCD_IRQHandler();
}
else
{
GotoVector(LCD_IRQn);
}
}
void IRQ030_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
FLASH_RAM_IRQHandler();
}
else
{
GotoVector(FLASH_RAM_IRQn);
}
}
void IRQ031_Handler(void)
{
if(FLAG_JUMP_BOOTLOADER==irq_jump_flag)
{
CLK_TRIM_IRQHandler();
}
else
{
GotoVector(CLKTRIM_IRQn);
}
}
/**
*******************************************************************************
** \brief IAP 主函数
**
** \param None
**
** \retval int32_t Return value, if needed
**
******************************************************************************/
int32_t main(void)
{
irq_jump_flag=FLAG_JUMP_BOOTLOADER;
IAP_UpdateCheck();
IAP_Init();
IAP_Main();
}
app程序的main.c文件
#define FLAG_JUMP_BOOTLOADER 0x5A5A5A5A
#define FLAG_JUMP_APP 0xA0A0A0A0
//static uint32_t irq_jump_flag __attribute__ ((at(0x20000000)));//AC5编译
__IO uint32_t irq_jump_flag __attribute__((section(".ARM.__at_0x20000000")));//AC6编译
int32_t main(void)
{
irq_jump_flag=FLAG_JUMP_APP;
//时钟配置
App_ClkCfg();
//串口引脚配置
App_PortInit();
//串口配置
App_UartCfg();
//flash擦写初始化
Flash_Init(6, TRUE);
while(1)
{
///< LED点亮
Gpio_SetIO(STK_LED_PORT, STK_LED_PIN);
delay1ms(1000);
///< LED关闭
Gpio_ClrIO(STK_LED_PORT, STK_LED_PIN);
delay1ms(1000);
}
}