Keil-MDK 中 [WEAK] 的作用

时间:2021-05-18 11:48:29

转自:http://blog.csdn.net/kissmonx/article/details/21622187

一句话:标记__weak 或 [weak]的函数 就是用在本文件占位的,如果别的文件重写的这个函数就用别文件的,否则使用本文件的。

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

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

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

[plain]  view plain  copy   Keil-MDK 中 [WEAK] 的作用 Keil-MDK 中 [WEAK] 的作用
  1. ; Reset handler 这里才是启动文件的重点啊. 不过没见到为 C 程序建立栈空间操作啊??? 直接调用 main 大丈夫? MAN???  
  2. Reset_Handler    PROC  
  3.                  EXPORT  Reset_Handler             [WEAK]  
  4.         IMPORT  SystemInit  
  5.         IMPORT  __main  
  6.   
  7.                  LDR     R0, =SystemInit  
  8.                  BLX     R0  
  9.                  LDR     R0, =__main  
  10.                  BX      R0  
  11.                  ENDP  
  12.   
  13. ; Dummy Exception Handlers (infinite loops which can be modified)  
  14.   
  15. NMI_Handler     PROC  
  16.                 EXPORT  NMI_Handler                [WEAK]  
  17.                 B       .  
  18.                 ENDP  
  19. HardFault_Handler\  
  20.                 PROC  
  21.                 EXPORT  HardFault_Handler          [WEAK]  
  22.                 B       .  
  23.                 ENDP  
  24. MemManage_Handler\  
  25.                 PROC  
  26.                 EXPORT  MemManage_Handler          [WEAK]  
  27.                 B       .  
  28.                 ENDP  
  29. BusFault_Handler\  
  30.                 PROC  
  31.                 EXPORT  BusFault_Handler           [WEAK]  
  32.                 B       .  
  33.                 ENDP  
  34. UsageFault_Handler\  
  35.                 PROC  
  36.                 EXPORT  UsageFault_Handler         [WEAK]  
  37.                 B       .  
  38.                 ENDP  
  39. SVC_Handler     PROC  
  40.                 EXPORT  SVC_Handler                [WEAK]  
  41.                 B       .  
  42.                 ENDP  
  43. DebugMon_Handler\  
  44.                 PROC  
  45.                 EXPORT  DebugMon_Handler           [WEAK]  
  46.                 B       .  
  47.                 ENDP  
  48. PendSV_Handler  PROC  
  49.                 EXPORT  PendSV_Handler             [WEAK]  
  50.                 B       .  
  51.                 ENDP  
  52. SysTick_Handler PROC  
  53.                 EXPORT  SysTick_Handler            [WEAK]  
  54.                 B       .  
  55.                 ENDP  
  56.   
  57. Default_Handler PROC  
  58.   
  59.                 EXPORT  WWDG_IRQHandler                   [WEAK]                                          
  60.                 EXPORT  PVD_IRQHandler                    [WEAK]                        
  61.                 EXPORT  TAMPER_STAMP_IRQHandler           [WEAK]           
  62.                 EXPORT  RTC_WKUP_IRQHandler               [WEAK]                       
  63.                 EXPORT  FLASH_IRQHandler                  [WEAK]                                           
  64.                 EXPORT  RCC_IRQHandler                    [WEAK]                                              
  65.                 EXPORT  EXTI0_IRQHandler                  [WEAK]                                              
  66.                 EXPORT  EXTI1_IRQHandler                  [WEAK]                                               
  67.                 EXPORT  EXTI2_TS_IRQHandler               [WEAK]                                              
  68.                 EXPORT  EXTI3_IRQHandler                  [WEAK]                                             
  69.                 EXPORT  EXTI4_IRQHandler                  [WEAK]                                              
  70.                 EXPORT  DMA1_Channel1_IRQHandler          [WEAK]                                  
  71.                 EXPORT  DMA1_Channel2_IRQHandler          [WEAK]                                     
  72.                 EXPORT  DMA1_Channel3_IRQHandler          [WEAK]                                     
  73.                 EXPORT  DMA1_Channel4_IRQHandler          [WEAK]                                     
  74.                 EXPORT  DMA1_Channel5_IRQHandler          [WEAK]                                     
  75.                 EXPORT  DMA1_Channel6_IRQHandler          [WEAK]                                     
  76.                 EXPORT  DMA1_Channel7_IRQHandler          [WEAK]                                     
  77.                 EXPORT  ADC1_2_IRQHandler                 [WEAK]                           
  78.                 EXPORT  USB_HP_CAN1_TX_IRQHandler         [WEAK]                                                  
  79.                 EXPORT  USB_LP_CAN1_RX0_IRQHandler        [WEAK]                                                 
  80.                 EXPORT  CAN1_RX1_IRQHandler               [WEAK]                                                  
  81.                 EXPORT  CAN1_SCE_IRQHandler               [WEAK]                                                  
  82.                 EXPORT  EXTI9_5_IRQHandler                [WEAK]                                      
  83.                 EXPORT  TIM1_BRK_TIM15_IRQHandler         [WEAK]                    
  84.                 EXPORT  TIM1_UP_TIM16_IRQHandler          [WEAK]                  
  85.                 EXPORT  TIM1_TRG_COM_TIM17_IRQHandler     [WEAK]   
  86.                 EXPORT  TIM1_CC_IRQHandler                [WEAK]                                     
  87.                 EXPORT  TIM2_IRQHandler                   [WEAK]                                              
  88.                 EXPORT  TIM3_IRQHandler                   [WEAK]                                              
  89.                 EXPORT  TIM4_IRQHandler                   [WEAK]                                              
  90.                 EXPORT  I2C1_EV_IRQHandler                [WEAK]                                               
  91.                 EXPORT  I2C1_ER_IRQHandler                [WEAK]                                               
  92.                 EXPORT  I2C2_EV_IRQHandler                [WEAK]                                              
  93.                 EXPORT  I2C2_ER_IRQHandler                [WEAK]                                                 
  94.                 EXPORT  SPI1_IRQHandler                   [WEAK]                                             
  95.                 EXPORT  SPI2_IRQHandler                   [WEAK]                                              
  96.                 EXPORT  USART1_IRQHandler                 [WEAK]                                            
  97.                 EXPORT  USART2_IRQHandler                 [WEAK]                                            
  98.                 EXPORT  USART3_IRQHandler                 [WEAK]                                           
  99.                 EXPORT  EXTI15_10_IRQHandler              [WEAK]                                    
  100.                 EXPORT  RTC_Alarm_IRQHandler              [WEAK]                    
  101.                 EXPORT  USBWakeUp_IRQHandler              [WEAK]                          
  102.                 EXPORT  TIM8_BRK_IRQHandler               [WEAK]                   
  103.                 EXPORT  TIM8_UP_IRQHandler                [WEAK]                   
  104.                 EXPORT  TIM8_TRG_COM_IRQHandler           [WEAK]   
  105.                 EXPORT  TIM8_CC_IRQHandler                [WEAK]  
  106.                 EXPORT  ADC3_IRQHandler                   [WEAK]                                     
  107.                 EXPORT  SPI3_IRQHandler                   [WEAK]                                               
  108.                 EXPORT  UART4_IRQHandler                  [WEAK]                                              
  109.                 EXPORT  UART5_IRQHandler                  [WEAK]                                              
  110.                 EXPORT  TIM6_DAC_IRQHandler               [WEAK]                     
  111.                 EXPORT  TIM7_IRQHandler                   [WEAK]                      
  112.                 EXPORT  DMA2_Channel1_IRQHandler          [WEAK]                                    
  113.                 EXPORT  DMA2_Channel2_IRQHandler          [WEAK]                                     
  114.                 EXPORT  DMA2_Channel3_IRQHandler          [WEAK]                                      
  115.                 EXPORT  DMA2_Channel4_IRQHandler          [WEAK]                                      
  116.                 EXPORT  DMA2_Channel5_IRQHandler          [WEAK]  
  117.                 EXPORT  ADC4_IRQHandler                   [WEAK]                                   
  118.                 EXPORT  COMP1_2_3_IRQHandler              [WEAK]                                                 
  119.                 EXPORT  COMP4_5_6_IRQHandler              [WEAK]                                                 
  120.                 EXPORT  COMP7_IRQHandler                  [WEAK]                                                 
  121.                 EXPORT  USB_HP_IRQHandler                 [WEAK]                        
  122.                 EXPORT  USB_LP_IRQHandler                 [WEAK]                        
  123.                 EXPORT  USBWakeUp_RMP_IRQHandler          [WEAK]                          
  124.                 EXPORT  FPU_IRQHandler                    [WEAK]                  

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

[cpp]  view plain  copy   Keil-MDK 中 [WEAK] 的作用 Keil-MDK 中 [WEAK] 的作用
  1. /* WEAK : symbol is only imported into other sources if no other source exports an alternative symbol.  
  2. If [WEAK] is used without symbol, all exported symbols are weak. */  

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

Keil-MDK 中 [WEAK] 的作用

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

[cpp]  view plain  copy   Keil-MDK 中 [WEAK] 的作用 Keil-MDK 中 [WEAK] 的作用
  1. // 意思就是告诉链接器:   
  2. // "我略弱但我很绅士, 如果你在别处看到和我一样的符号实例.你就用它吧. 表管我, 求忽视! "   

所以......知道这个, 就可以解决为什么 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.

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

[cpp]  view plain  copy   Keil-MDK 中 [WEAK] 的作用 Keil-MDK 中 [WEAK] 的作用
  1. __asm void vPortSVCHandler( void )  
  2. {  
  3.     PRESERVE8  
  4.   
  5.     /* Get the location of the current TCB. */  
  6.     ldr r3, =pxCurrentTCB  
  7.     ldr r1, [r3]  
  8.     ldr r0, [r1]  
  9.     /* Pop the core registers. */  
  10.     ldmia r0!, {r4-r11, r14}  
  11.     msr psp, r0  
  12.     isb  
  13.     mov r0, #0  
  14.     msr basepri, r0  
  15.     bx r14  
  16. }  
这不就是披了马甲的 SVC_Handler 吗? 尼玛......显然里面的内容我不太明白, 就不解释了. 再学.
然后我当然没有那么聪明, 我找到了以前移植过的文件看了一下, 发现在 portmacro.h 中有下面三个宏定义:

[cpp]  view plain  copy   Keil-MDK 中 [WEAK] 的作用 Keil-MDK 中 [WEAK] 的作用
  1. #define vPortSVCHandler      SVC_Handler  
  2. #define xPortSysTickHandler  SysTick_Handler  
  3. #define xPortPendSVHandler   PendSV_Handler  
扫噶. 原来宏名也比 WEAK 修饰过的强啊. 重新编译链接没错. 烧写, 各任务运行正常.