使用官方给的例程没问题。
然后我在keil新建一个工程,简单的初始化
/********************************************************************************** \brief Main function of project**** \return uint32_t return value, if needed********************************************************************************/
int32_t main(void)
{uint32_t TickNew=0;uint32_t TickOld=0;Sysctrl_SetRCHTrim(SysctrlRchFreq24MHz);SystemCoreClockUpdate();SysTick_Config(SystemCoreClock/1000);//systick 1ms///< 端口初始化App_GpioInit();while(1){}
}//systick中断函数
void SysTick_IRQHandler(void)
{ SysTick1MS++;// 1ms
}
运行结果,怎么都不进入,重新写的SysTick_IRQHandler函数,仿真查看
已经进入中断
/*********************************************************************************** \brief NVIC SysTick 中断实现**** \retval******************************************************************************/
void SysTick_Handler(void)
{SysTick_IRQHandler();
}
我把代码拷贝到官方工程里面 运行 一点问题都没有
查看map,发现重新写的SysTick_IRQHandler被移除,被编译器优化了,好奇怪
Removing main.o(i.SysTick_IRQHandler), (44 bytes).
然后我强制修改interrupts_hc32l17x.c里面的函数声明 去掉__weak
__WEAK void SysTick_IRQHandler(void);
改成
void SysTick_IRQHandler(void);
又没被优化了,运行也正常。
最后和官方例程对比Option发现少下面的设置。加上就好了
--keep=*Handler
gpt-4的解释
在Keil的链接器设置中使用--keep=*Handler
选项通常用于确保链接器保留特定的符号或函数,即使它们看起来未被引用。在你的情况中,使用--keep=*Handler
指令是为了确保所有包含"Handler"的函数都不会因为优化而被移除。这对于中断处理函数尤其重要,因为它们通常不会被代码中的其他部分直接引用,而是由硬件或操作系统的特定事件触发。
解释--keep=*Handler
选项:
--keep
选项:这是一个链接器指令,用于告诉链接器保持列表中的特定符号,即使在优化过程中认为这些符号未被使用。*Handler
:这是一个通配符表达式,匹配所有包含"Handler"的符号名。这意味着所有如SysTick_Handler
、USART_Handler
等通常用于中断服务例程(ISR)的函数都被保留。
这种设置的好处是确保所有重要的中断处理和事件处理函数在最终生成的二进制文件中保持完整,即使编译器的静态分析可能认为这些函数从未被调用。这在嵌入式系统开发中是常见的情况,因为许多函数(特别是中断服务例程)是由硬件事件直接触发的,而不是通过常规的函数调用路径。
因此,如果之前你遇到了SysTick_IRQHandler
被优化掉的问题,添加--keep=*Handler
确实是一个解决这类问题的有效方法。
记录一下 跳出的这个坑吧