Keil-MDK 中 [WEAK] 的作用

本文探讨了FreeRTOS移植过程中遇到的问题,并详细解释了如何通过理解[WEAK]属性来解决SVC_Handler异常跳转的问题。通过定义宏来覆盖默认行为,实现了正确的系统调用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

移植后的代码戳这里: https://code.csdn.net/KISSMonX/freertos_f3discovery_test

在上一篇文章 ARM 汇编中的 "B ." 语句意义.时, 顺带介绍了 [WEAK] 的作用.
昨天再思考移植问题的时候(也就是执行第一个任务时直接跳到 SVC_Handler 里的 B . 处),
想到了这个问题, 然后在移植配置文件中添加了几个宏定义就解决了问题, 移植成功, 具体下文介绍.
这里再做一次解释. 看看自己是不是真正的理解了. :)

第一步明显是要贴代码装逼, 去启动文件里摘取出要介绍的部分. 然后记笔记的形式摘录下来.如下:

; Reset handler 这里才是启动文件的重点啊. 不过没见到为 C 程序建立栈空间操作啊??? 直接调用 main 大丈夫? MAN???
Reset_Handler    PROC
                 EXPORT  Reset_Handler             [WEAK]
        IMPORT  SystemInit
        IMPORT  __main

                 LDR     R0, =SystemInit
                 BLX     R0
                 LDR     R0, =__main
                 BX      R0
                 ENDP

; Dummy Exception Handlers (infinite loops which can be modified)

NMI_Handler     PROC
                EXPORT  NMI_Handler                [WEAK]
                B       .
                ENDP
HardFault_Handler\
                PROC
                EXPORT  HardFault_Handler          [WEAK]
                B       .
                ENDP
MemManage_Handler\
                PROC
                EXPORT  MemManage_Handler          [WEAK]
                B       .
                ENDP
BusFault_Handler\
                PROC
                EXPORT  BusFault_Handler           [WEAK]
                B       .
                ENDP
UsageFault_Handler\
                PROC
                EXPORT  UsageFault_Handler         [WEAK]
                B       .
                ENDP
SVC_Handler     PROC
                EXPORT  SVC_Handler                [WEAK]
                B       .
                ENDP
DebugMon_Handler\
                PROC
                EXPORT  DebugMon_Handler           [WEAK]
                B       .
                ENDP
PendSV_Handler  PROC
                EXPORT  PendSV_Handler             [WEAK]
                B       .
                ENDP
SysTick_Handler PROC
                EXPORT  SysTick_Handler            [WEAK]
                B       .
                ENDP

Default_Handler PROC

                EXPORT  WWDG_IRQHandler                   [WEAK]                                        
                EXPORT  PVD_IRQHandler                    [WEAK]                      
                EXPORT  TAMPER_STAMP_IRQHandler           [WEAK]         
                EXPORT  RTC_WKUP_IRQHandler               [WEAK]                     
                EXPORT  FLASH_IRQHandler                  [WEAK]                                         
                EXPORT  RCC_IRQHandler                    [WEAK]                                            
                EXPORT  EXTI0_IRQHandler                  [WEAK]                                            
                EXPORT  EXTI1_IRQHandler                  [WEAK]                                             
                EXPORT  EXTI2_TS_IRQHandler               [WEAK]                                            
                EXPORT  EXTI3_IRQHandler                  [WEAK]                                           
                EXPORT  EXTI4_IRQHandler                  [WEAK]                                            
                EXPORT  DMA1_Channel1_IRQHandler          [WEAK]                                
                EXPORT  DMA1_Channel2_IRQHandler          [WEAK]                                   
                EXPORT  DMA1_Channel3_IRQHandler          [WEAK]                                   
                EXPORT  DMA1_Channel4_IRQHandler          [WEAK]                                   
                EXPORT  DMA1_Channel5_IRQHandler          [WEAK]                                   
                EXPORT  DMA1_Channel6_IRQHandler          [WEAK]                                   
                EXPORT  DMA1_Channel7_IRQHandler          [WEAK]                                   
                EXPORT  ADC1_2_IRQHandler                 [WEAK]                         
                EXPORT  USB_HP_CAN1_TX_IRQHandler         [WEAK]                                                
                EXPORT  USB_LP_CAN1_RX0_IRQHandler        [WEAK]                                               
                EXPORT  CAN1_RX1_IRQHandler               [WEAK]                                                
                EXPORT  CAN1_SCE_IRQHandler               [WEAK]                                                
                EXPORT  EXTI9_5_IRQHandler                [WEAK]                                    
                EXPORT  TIM1_BRK_TIM15_IRQHandler         [WEAK]                  
                EXPORT  TIM1_UP_TIM16_IRQHandler          [WEAK]                
                EXPORT  TIM1_TRG_COM_TIM17_IRQHandler     [WEAK] 
                EXPORT  TIM1_CC_IRQHandler                [WEAK]                                   
                EXPORT  TIM2_IRQHandler                   [WEAK]                                            
                EXPORT  TIM3_IRQHandler                   [WEAK]                                            
                EXPORT  TIM4_IRQHandler                   [WEAK]                                            
                EXPORT  I2C1_EV_IRQHandler                [WEAK]                                             
                EXPORT  I2C1_ER_IRQHandler                [WEAK]                                             
                EXPORT  I2C2_EV_IRQHandler                [WEAK]                                            
                EXPORT  I2C2_ER_IRQHandler                [WEAK]                                               
                EXPORT  SPI1_IRQHandler                   [WEAK]                                           
                EXPORT  SPI2_IRQHandler                   [WEAK]                                            
                EXPORT  USART1_IRQHandler                 [WEAK]                                          
                EXPORT  USART2_IRQHandler                 [WEAK]                                          
                EXPORT  USART3_IRQHandler                 [WEAK]                                         
                EXPORT  EXTI15_10_IRQHandler              [WEAK]                                  
                EXPORT  RTC_Alarm_IRQHandler              [WEAK]                  
                EXPORT  USBWakeUp_IRQHandler              [WEAK]                        
                EXPORT  TIM8_BRK_IRQHandler               [WEAK]                 
                EXPORT  TIM8_UP_IRQHandler                [WEAK]                 
                EXPORT  TIM8_TRG_COM_IRQHandler           [WEAK] 
                EXPORT  TIM8_CC_IRQHandler                [WEAK]
                EXPORT  ADC3_IRQHandler                   [WEAK]                                   
                EXPORT  SPI3_IRQHandler                   [WEAK]                                             
                EXPORT  UART4_IRQHandler                  [WEAK]                                            
                EXPORT  UART5_IRQHandler                  [WEAK]                                            
                EXPORT  TIM6_DAC_IRQHandler               [WEAK]                   
                EXPORT  TIM7_IRQHandler                   [WEAK]                    
                EXPORT  DMA2_Channel1_IRQHandler          [WEAK]                                  
                EXPORT  DMA2_Channel2_IRQHandler          [WEAK]                                   
                EXPORT  DMA2_Channel3_IRQHandler          [WEAK]                                    
                EXPORT  DMA2_Channel4_IRQHandler          [WEAK]                                    
                EXPORT  DMA2_Channel5_IRQHandler          [WEAK]
                EXPORT  ADC4_IRQHandler                   [WEAK]                                 
                EXPORT  COMP1_2_3_IRQHandler              [WEAK]                                               
                EXPORT  COMP4_5_6_IRQHandler              [WEAK]                                               
                EXPORT  COMP7_IRQHandler                  [WEAK]                                               
                EXPORT  USB_HP_IRQHandler                 [WEAK]                      
                EXPORT  USB_LP_IRQHandler                 [WEAK]                      
                EXPORT  USBWakeUp_RMP_IRQHandler          [WEAK]                        
                EXPORT  FPU_IRQHandler                    [WEAK]                

然后到 keil 的帮助文档里找到这么一句话: 

/* WEAK : symbol is only imported into other sources if no other source exports an alternative symbol. 
If [WEAK] is used without symbol, all exported symbols are weak. */

紧接着下面就有这种介绍:


这里是针对汇编语言的, C 语言级别的别捉急. 英语好的可以直接移步:About weak references and definitions
比我介绍的详细准确多了.
英语不好的就算了吧. 大致意思就是:

// 意思就是告诉链接器: 
// "我略弱但我很绅士, 如果你在别处看到和我一样的符号实例.你就用它吧. 表管我, 求忽视! " 

所以......知道这个, 就可以解决为什么 FreeRTOS 在执行到下面这段代码老是跳转到 SVC_Handler 处了.

<乱入> SVC 作用:  SVCall  A supervisor call (SVC) is an exception that is triggered by the SVC instruction. In an OS environment, applications can use SVC instructions to 
access OS kernel functions and device drivers.

__asm void prvStartFirstTask( void )
{
	PRESERVE8

	/* Use the NVIC offset register to locate the stack. */
	ldr r0, =0xE000ED08
	ldr r0, [r0]
	ldr r0, [r0]
	/* Set the msp back to the start of the stack. */
	msr msp, r0
	/* Globally enable interrupts. */
	cpsie i
	dsb
	isb
	/* Call SVC to start the first task. */
	svc 0  // 0 号系统调用, 更多关于 SVC 可以参考 google 或者 ARM Cortex-M3 权威指南
	nop
}
因为各个开发工具厂家对这些启动文件的异常和中断只做了简单的处理. 基本都是死循环(也就是"B .").
而且特意加上了 [WEAK] 修饰. 这样用户可以根据自己的需要重新编写自己的处理函数, 而且只要命名一样就 OK 了.
那名字要是不一样怎么办? 然后, 我去找了 SVC_Handler 这个名字, 并没有找到, 但是在 port.c 中找到了
下面这个函数:

__asm void vPortSVCHandler( void )
{
	PRESERVE8

	/* Get the location of the current TCB. */
	ldr	r3, =pxCurrentTCB
	ldr r1, [r3]
	ldr r0, [r1]
	/* Pop the core registers. */
	ldmia r0!, {r4-r11, r14}
	msr psp, r0
	isb
	mov r0, #0
	msr	basepri, r0
	bx r14
}
这不就是披了马甲的 SVC_Handler 吗? 尼玛......显然里面的内容我不太明白, 就不解释了. 再学.
然后我当然没有那么聪明, 我找到了以前移植过的文件看了一下, 发现在 portmacro.h 中有下面三个宏定义:

#define vPortSVCHandler      SVC_Handler
#define xPortSysTickHandler  SysTick_Handler
#define xPortPendSVHandler   PendSV_Handler
扫噶. 原来宏名也比 WEAK 修饰过的强啊. 重新编译链接没错. 烧写, 各任务运行正常.

<think>好的,我需要帮用户修改论文中的“软件开发环境”章节,将原本提到的标准外设库改为HAL库,同时保持Keil MDK作为开发环境。首先,我得回顾用户之前提供的章节内容和之前的建议,确保修改后的内容准确且符合要求。用户之前的章节里详细描述了Keil uVision5的安装配置、外设驱动库集成和工程模板搭建,但错误地使用了标准库。现在需要调整为HAL库,但保留Keil作为IDE。根据用户提供的引用,Keil的Manage Run-Time Environment(RTE)功能可以管理HAL库组件,这点需要强调。首先,安装配置部分需要调整,不再手动下载标准库,而是通过Keil的RTE或STM32CubeMX来集成HAL库。用户之前的回答建议使用STM32CubeIDE,但用户现在希望保持Keil,所以需要找到在Keil中使用HAL库的方法。引用[2]提到HAL库是趋势,但和标准库不兼容,因此需要说明如何在Keil中配置HAL库组件。外设驱动库集成部分,原来的步骤是下载标准库并添加到工程,现在应改为通过RTE添加HAL库,或者使用CubeMX生成代码后导入Keil。需要具体说明如何通过ManageRTE选择HAL组件,或者结合CubeMX生成初始化代码。工程模板搭建部分,需要调整初始化代码的生成方式,可能涉及CubeMX生成的代码结构,比如使用HAL_Init()和SystemClock_Config(),主循环中使用HAL库的函数。同时,模块化接口可能需要调整以适应HAL的回调机制,比如中断处理使用HAL库的回调函数。文档资料部分,原来的标准库用户手册需要改为HAL库的文档,比如STM32CubeMX用户手册和HAL库的编程手册。开发工具方面,保持PuTTY、万用表等,但可能增加CubeMX的使用说明。需要注意引用用户提供的引用[1]和[2],特别是引用[1]提到的ManageRTE功能,用来管理HAL库组件。引用[2]指出HAL库的优势和趋势,需要融入修改后的内容中,强调HAL的可移植性和维护性。代码示例部分,原来的标准库函数如GPIO_SetBits需要改为HAL_GPIO_WritePin,并展示如何通过CubeMX生成的代码进行初始化。同时,时钟使能部分使用HAL库的宏,如__HAL_RCC_GPIOA_CLK_ENABLE()。 最后,确保修改后的内容流畅,保持章节结构,同时正确引用文献,添加相关的引用标识,如[^1]和[^2]。可能还需要生成相关问题,比如HAL库在Keil中的配置注意事项,性能对比等。总结步骤:1.修改安装配置部分,说明通过Keil的RTE或CubeMX集成HAL库。2.调整外设驱动集成步骤,使用HAL库函数和CubeMX生成的代码。 3.更新工程模板,体现HAL库的初始化和模块化设计。 4.更新文档和工具部分,引用HAL库相关文档和CubeMX。 5.替换代码示例,展示HAL库的用法。6.添加相关问题,引导进一步讨论。</think>根据您的要求,对"软件开发环境"章节进行修改如下(重点突出HAL库特性,同时保留Keil MDK开发环境描述): ### 二、开发环境配置 1. **Keil MDK5安装与配置** (1)安装Keil MDK5时,通过$Manage Run-Time Environment$(RTE)选择STM32HAL库组件,包含CMSIS核心包、HAL驱动库等必要模块[^1] (2)创建新工程时选择STM32F103C8T6芯片,通过RTE自动加载对应的HAL库文件 (3)配置工程选项时启用$Use MicroLIB$和$Use Floating Point Hardware$,优化HAL库运行效率 (4)调试设置中连接ST-Link调试器,在$Debug$选项卡启用$Trace Exceptions$以实现HAL库的错误跟踪 2. **HAL库集成方法** (1)通过STM32CubeMX生成初始化代码: ```c HAL_Init(); // HAL库全局初始化 SystemClock_Config(); // 自动生成的时钟配置函数 MX_GPIO_Init(); // 外设初始化函数 ``` (2)在Keil工程中引入生成的$Inc$和$Src$目录,保留用户代码与自动生成代码的分离结构 (3)使用HAL提供的抽象化接口替代寄存器操作,例如: ```c HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET); // GPIO控制 HAL_UART_Transmit(&huart1, buffer, length, timeout); // 串口通信 ``` 3. **工程模板优化** (1)创建包含HAL初始化层、硬件抽象层、应用逻辑层的分层架构 (2)通过$weak$函数机制实现回调函数重写,例如: ```c void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { // 用户自定义中断处理 } ``` (3)使用$\_\_HAL\_RCC\_$宏统一管理外设时钟,提升代码可读性: ```c __HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟 ``` ### 三、开发资源更新 1. **文档资料** (1)参考$STM32CubeMX User Manual$(UM1718)配置硬件初始化代码[^2] (2)查阅$STM32F1xx HAL Driver Description$(UM1850)理解HAL库的接口规范 2. **工具链整合** (1)使用STM32CubeMX生成初始化代码后,通过$Project > Import STM32Cube Project$导入Keil工程 (2)在Keil的$Options for Target > Output$中勾选$Create HEX File$,确保生成可烧录文件 ```mermaid graph TD A[STM32CubeMX配置] --> B[生成初始化代码] B --> C[Keil工程导入] C --> D[应用逻辑开发] D --> E[ST-Link调试] ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值