[STM32F1] stm32——ucos的中断使用

[复制链接]
1571|3
 楼主| Jessicakjdsl 发表于 2016-4-20 17:54 | 显示全部楼层 |阅读模式
uCosII移植到stm32上的**和demo已经很多了,细节上建议大家可以看官方的移植文档(当然是E文的)。网上流传的各种移植版本基本都是基于官方的移植版本做了小改进。这些改进基本都限制在更适合自己的项目或自己的使用习惯上。当然我也一样,我的改进是为了搭建一个平台,只要stm32+ucos平台都使用这个版本,无论是我使用或是一起开发者,能更快上手。          uCosII V2.86版本在cortex-m3的移植上面有bug,具体可以自己google一下。我目前使用的是V2.91版本,建立在stm32 V3.40的库基本上。我是强烈要求(或是强制要求)协同开发者使用库函数,除非在速度要求高的情况下或中断里需要直接操作寄存器,也必须使用库的地址定义,并要求在后面注明对应的库函数。因为程序不是你一个人看的……例如:

                                                [cpp]
  1. *
  2. *********************************************************************************************************
  3. *                                             INCLUDE FILES
  4. *********************************************************************************************************
  5. */  
  6.   
  7. #define  BSP_INTERRUPT_MODULE  
  8.   
  9. #include   
  10. #include  //STM32芯片内部寄存器定议  
  11.   
  12. #include   
  13.   
  14. #include   
  15.   
  16. /*
  17. *********************************************************************************************************
  18. *                                            LOCAL DEFINES
  19. *********************************************************************************************************
  20. */  
  21. #define  BSP_INT_SRC_NBR                                 60  
  22.   
  23.   
  24. /*
  25. *********************************************************************************************************
  26. *                                            LOCAL TABLES
  27. *********************************************************************************************************
  28. */  
  29.   
  30. static  CPU_FNCT_VOID  BSP_IntVectTbl[BSP_INT_SRC_NBR];  
  31.   
  32.   
  33. /*
  34. *********************************************************************************************************
  35. *                                      LOCAL FUNCTION PROTOTYPES
  36. *********************************************************************************************************
  37. */  
  38.   
  39. static  void  BSP_IntHandler(u16  int_id);  
  40. static  void  BSP_IntHandlerDummy(void);  
  41.   
  42.   
  43. /*
  44. *********************************************************************************************************
  45. *                                            BSP_IntVectSet()
  46. *
  47. * Description : Assign ISR handler.
  48. *
  49. * Argument(s) : int_id      Interrupt for which vector will be set.
  50. *
  51. *               isr         Handler to assign
  52. *
  53. * Return(s)   : none.
  54. *
  55. * Caller(s)   : Application.
  56. *
  57. * Note(s)     : none.
  58. *********************************************************************************************************
  59. */  
  60.   
  61. void  BSP_IntVectSet (u16       int_id,  
  62.                       CPU_FNCT_VOID  isr)  
  63. {  
  64.   
  65. #if OS_CRITICAL_METHOD == 3u                            /* Allocate storage for CPU status register    */  
  66.     OS_CPU_SR     cpu_sr = 0u;  
  67. #endif  
  68.       
  69.   
  70.     if(int_id < BSP_INT_SRC_NBR){  
  71.         OS_ENTER_CRITICAL();  
  72.         BSP_IntVectTbl[int_id] = isr;  
  73.         OS_EXIT_CRITICAL();  
  74.     }  
  75. }   

                       
               
       
       
  •                         /* Clear the selected DMA interrupt pending bits */
  •                         DMA1->IFCR = DMA1_IT_TC4;  //DMA_ClearITPendingBit(DMA1_IT_TC4);
  •                         /* Disable the selected DMAy Channelx */
  •                         DMA1_Channel4->CCR &= (u16)(~DMA_CCR1_EN);//DMA_Cmd(DMA1_Channel4, DISABLE);


好了,进入正题。uCos在stm32上的移植官方的版本是默认不支持中断嵌套的(个人理解),因为其没有调用NVIC_PriorityGroupConfig这一函数或使用相同的功能语句。stm32在复位的状态下默认进去NVIC_PriorityGroup_0,即只要子优先级没有主优先级,即先到先处理,同时到达再按优先级处理。 官方在这上面也是留有空间,因为NVIC_PriorityGroupConfig只能调用一次,采用默认状态,开发者可以加入并完善使用中断嵌套。
        官方的移植把所有的应用中断入口都指向了BSP_IntHandler这个函数,并定义了一个函数数组static  CPU_FNCT_VOID  BSP_IntVectTbl[BSP_INT_SRC_NBR];因此,如果要加入自己的中断函数的话,只需把自己写的中断函数的指针存入这个数组就OK了,在初始化中断前调用这函数BSP_IntVectSet。官方的中断优先级设置方式,我全删除了,使用库函数来设置将更直接,但这种中断方式保存下来,这样中断函数更自由,写中断函数时也不用考虑太多东西,只负责自己要做的东西。

 楼主| Jessicakjdsl 发表于 2016-4-20 17:55 | 显示全部楼层
  1. /*
  2. *********************************************************************************************************
  3. *********************************************************************************************************
  4. *                                           INTERNAL FUNCTIONS
  5. *********************************************************************************************************
  6. *********************************************************************************************************
  7. */  
  8.   
  9. /*
  10. *********************************************************************************************************
  11. *                                              BSP_IntInit()
  12. *
  13. * Description : Initialize interrupts:
  14. *
  15. * Argument(s) : none.
  16. *
  17. * Return(s)   : none.
  18. *
  19. * Caller(s)   : BSP_Init().
  20. *
  21. * Note(s)     : none.
  22. *********************************************************************************************************
  23. */  
  24.   
  25. void  BSP_IntInit (void)  
  26. {  
  27.     u16  int_id;  
  28.     OS_CPU_SR  cpu_sr;  
  29.   
  30.   
  31.     OS_ENTER_CRITICAL();                         /* Tell uC/OS-II that we are starting an ISR          */  
  32.     OSIntNeedSW = OSIntSW_Disable;               // 需退出中断时进行任务调度切换  
  33.     OS_EXIT_CRITICAL();  
  34.   
  35.     for (int_id = 0; int_id < BSP_INT_SRC_NBR; int_id++) {  
  36.         BSP_IntVectSet(int_id, BSP_IntHandlerDummy);  
  37.     }  
  38. }  
  39.   
  40.   
  41. /*
  42. *********************************************************************************************************
  43. *                                        BSP_IntHandler####()
  44. *
  45. * Description : Handle an interrupt.
  46. *
  47. * Argument(s) : none.
  48. *
  49. * Return(s)   : none.
  50. *
  51. * Caller(s)   : This is an ISR.
  52. *
  53. * Note(s)     : none.
  54. *********************************************************************************************************
  55. */  
  56. void  BSP_IntHandlerWWDG          (void)  { BSP_IntHandler(WWDG_IRQn);            }  
  57. void  BSP_IntHandlerPVD           (void)  { BSP_IntHandler(PVD_IRQn);             }  
  58. void  BSP_IntHandlerTAMPER        (void)  { BSP_IntHandler(TAMPER_IRQn);          }  
  59. void  BSP_IntHandlerRTC           (void)  { BSP_IntHandler(RTC_IRQn);             }  
  60. void  BSP_IntHandlerFLASH         (void)  { BSP_IntHandler(FLASH_IRQn);           }  
  61. void  BSP_IntHandlerRCC           (void)  { BSP_IntHandler(RCC_IRQn);             }  
  62. void  BSP_IntHandlerEXTI0         (void)  { BSP_IntHandler(EXTI0_IRQn);           }  
  63. void  BSP_IntHandlerEXTI1         (void)  { BSP_IntHandler(EXTI1_IRQn);           }  
  64. void  BSP_IntHandlerEXTI2         (void)  { BSP_IntHandler(EXTI2_IRQn);           }  
  65. void  BSP_IntHandlerEXTI3         (void)  { BSP_IntHandler(EXTI3_IRQn);           }  
  66. void  BSP_IntHandlerEXTI4         (void)  { BSP_IntHandler(EXTI4_IRQn);           }  
  67. void  BSP_IntHandlerDMA1_CH1      (void)  { BSP_IntHandler(DMA1_Channel1_IRQn);        }  
  68. void  BSP_IntHandlerDMA1_CH2      (void)  { BSP_IntHandler(DMA1_Channel2_IRQn);        }  
  69. void  BSP_IntHandlerDMA1_CH3      (void)  { BSP_IntHandler(DMA1_Channel3_IRQn);        }  
  70. void  BSP_IntHandlerDMA1_CH4      (void)  { BSP_IntHandler(DMA1_Channel4_IRQn);        }  
  71. void  BSP_IntHandlerDMA1_CH5      (void)  { BSP_IntHandler(DMA1_Channel5_IRQn);        }  
  72. void  BSP_IntHandlerDMA1_CH6      (void)  { BSP_IntHandler(DMA1_Channel6_IRQn);        }  
  73. void  BSP_IntHandlerDMA1_CH7      (void)  { BSP_IntHandler(DMA1_Channel7_IRQn);        }  
  74. void  BSP_IntHandlerADC1_2        (void)  { BSP_IntHandler(ADC1_2_IRQn);          }  
  75. void  BSP_IntHandlerUSB_HP_CAN_TX (void)  { BSP_IntHandler(USB_HP_CAN1_TX_IRQn);   }  
  76. void  BSP_IntHandlerUSB_LP_CAN_RX0(void)  { BSP_IntHandler(USB_LP_CAN1_RX0_IRQn);  }  
  77. void  BSP_IntHandlerCAN_RX1       (void)  { BSP_IntHandler(CAN1_RX1_IRQn);         }  
  78. void  BSP_IntHandlerCAN_SCE       (void)  { BSP_IntHandler(CAN1_SCE_IRQn);         }  
  79. void  BSP_IntHandlerEXTI9_5       (void)  { BSP_IntHandler(EXTI9_5_IRQn);         }  
  80. void  BSP_IntHandlerTIM1_BRK      (void)  { BSP_IntHandler(TIM1_BRK_IRQn);        }  
  81. void  BSP_IntHandlerTIM1_UP       (void)  { BSP_IntHandler(TIM1_UP_IRQn);         }  
  82. void  BSP_IntHandlerTIM1_TRG_COM  (void)  { BSP_IntHandler(TIM1_TRG_COM_IRQn);    }  
  83. void  BSP_IntHandlerTIM1_CC       (void)  { BSP_IntHandler(TIM1_CC_IRQn);         }  
  84. void  BSP_IntHandlerTIM2          (void)  { BSP_IntHandler(TIM2_IRQn);            }  
  85. void  BSP_IntHandlerTIM3          (void)  { BSP_IntHandler(TIM3_IRQn);            }  
  86. void  BSP_IntHandlerTIM4          (void)  { BSP_IntHandler(TIM4_IRQn);            }  
  87. void  BSP_IntHandlerI2C1_EV       (void)  { BSP_IntHandler(I2C1_EV_IRQn);         }  
  88. void  BSP_IntHandlerI2C1_ER       (void)  { BSP_IntHandler(I2C1_ER_IRQn);         }  
  89. void  BSP_IntHandlerI2C2_EV       (void)  { BSP_IntHandler(I2C2_EV_IRQn);         }  
  90. void  BSP_IntHandlerI2C2_ER       (void)  { BSP_IntHandler(I2C2_ER_IRQn);         }  
  91. void  BSP_IntHandlerSPI1          (void)  { BSP_IntHandler(SPI1_IRQn);            }  
  92. void  BSP_IntHandlerSPI2          (void)  { BSP_IntHandler(SPI2_IRQn);            }  
  93. void  BSP_IntHandlerUSART1        (void)  { BSP_IntHandler(USART1_IRQn);          }  
  94. void  BSP_IntHandlerUSART2        (void)  { BSP_IntHandler(USART2_IRQn);          }  
  95. void  BSP_IntHandlerUSART3        (void)  { BSP_IntHandler(USART3_IRQn);          }  
  96. void  BSP_IntHandlerEXTI15_10     (void)  { BSP_IntHandler(EXTI15_10_IRQn);       }  
  97. void  BSP_IntHandlerRTCAlarm      (void)  { BSP_IntHandler(RTCAlarm_IRQn);        }  
  98. void  BSP_IntHandlerUSBWakeUp     (void)  { BSP_IntHandler(USBWakeUp_IRQn);       }  
  99. void  BSP_IntHandlerTIM8_BRK      (void)  { BSP_IntHandler(TIM8_BRK_IRQn);        }  
  100. void  BSP_IntHandlerTIM8_UP       (void)  { BSP_IntHandler(TIM8_UP_IRQn);         }  
  101. void  BSP_IntHandlerTIM8_TRG_COM  (void)  { BSP_IntHandler(TIM8_TRG_COM_IRQn);    }  
  102. void  BSP_IntHandlerTIM8_CC       (void)  { BSP_IntHandler(TIM8_CC_IRQn);         }  
  103. void  BSP_IntHandlerADC3          (void)  { BSP_IntHandler(ADC3_IRQn);            }  
  104. void  BSP_IntHandlerFSMC          (void)  { BSP_IntHandler(FSMC_IRQn);            }  
  105. void  BSP_IntHandlerSDIO          (void)  { BSP_IntHandler(SDIO_IRQn);            }  
  106. void  BSP_IntHandlerTIM5          (void)  { BSP_IntHandler(TIM5_IRQn);            }  
  107. void  BSP_IntHandlerSPI3          (void)  { BSP_IntHandler(SPI3_IRQn);            }  
  108. void  BSP_IntHandlerUART4         (void)  { BSP_IntHandler(UART4_IRQn);           }  
  109. void  BSP_IntHandlerUART5         (void)  { BSP_IntHandler(UART5_IRQn);           }  
  110. void  BSP_IntHandlerTIM6          (void)  { BSP_IntHandler(TIM6_IRQn);            }  
  111. void  BSP_IntHandlerTIM7          (void)  { BSP_IntHandler(TIM7_IRQn);            }  
  112. void  BSP_IntHandlerDMA2_CH1      (void)  { BSP_IntHandler(DMA2_Channel1_IRQn);        }  
  113. void  BSP_IntHandlerDMA2_CH2      (void)  { BSP_IntHandler(DMA2_Channel2_IRQn);        }  
  114. void  BSP_IntHandlerDMA2_CH3      (void)  { BSP_IntHandler(DMA2_Channel3_IRQn);        }  
  115. void  BSP_IntHandlerDMA2_CH4_5    (void)  { BSP_IntHandler(DMA2_Channel4_5_IRQn);      }  
  116.   
  117.   
  118. /*
  119. *********************************************************************************************************
  120. *********************************************************************************************************
  121. *                                           LOCAL FUNCTIONS
  122. *********************************************************************************************************
  123. *********************************************************************************************************
  124. */  
  125.   
  126. /*
  127. *********************************************************************************************************
  128. *                                          BSP_IntHandler()
  129. *
  130. * Description : Central interrupt handler.
  131. *
  132. * Argument(s) : int_id          Interrupt that will be handled.
  133. *
  134. * Return(s)   : none.
  135. *
  136. * Caller(s)   : ISR handlers.
  137. *
  138. * Note(s)     : none.
  139. *********************************************************************************************************
  140. */  
  141.   
  142. static  void  BSP_IntHandler (u16  int_id)  
  143. {  
  144.   
  145. #if OS_CRITICAL_METHOD == 3u                            /* Allocate storage for CPU status register    */  
  146.     OS_CPU_SR     cpu_sr = 0u;  
  147. #endif  
  148.   
  149.     OS_ENTER_CRITICAL();                                      /* 不支持中断嵌套,无需关中断    */  
  150.     OSIntNesting++;  
  151.     OS_EXIT_CRITICAL();  
  152.   
  153.     if (int_id < BSP_INT_SRC_NBR) {  
  154.         BSP_IntVectTbl[int_id]();  
  155.     }  
  156.     OSIntExit();  
  157. }  
  158.   
  159.   
  160. /*  
  1. /*
  2. *********************************************************************************************************
  3. *                                        BSP_IntHandlerDummy()
  4. *
  5. * Description : Dummy interrupt handler.
  6. *
  7. * Argument(s) : none.
  8. *
  9. * Return(s)   : none.
  10. *
  11. * Caller(s)   : BSP_IntHandler().
  12. *
  13. * Note(s)     : none.
  14. *********************************************************************************************************
  15. */  
  16.   
  17. static  void  BSP_IntHandlerDummy (void)  
  18. {  
  19.   
  20. }   


 楼主| Jessicakjdsl 发表于 2016-4-20 17:55 | 显示全部楼层
从上代码可以看到,增加了一个全局变量OSIntNeedSW。这个变量的使用是判断退出中断的时候需不需要任务调度,因为你在中断里没有做改变任务优先级的事,在退出的时候就无需重新调试,如需调度,只需加一个语句 OSIntNeedSW =OSIntSW_Enable;  当然这是临界代码,需关中断。                                                [cpp] view plaincopy                       
               
       
       
  •                         void  BSP_IntInit (void)

        这一函数必须在开中断前调用一次,初始化必要的变量。
        还有两个系统函数必须改动,以实现这功能。在滴答时钟中断中,
                                                [cpp] view plaincopy                       
               
       
       
  •                         void  OS_CPU_SysTickHandler (void)


  1.     {  
  2.         OS_CPU_SR  cpu_sr;  
  3.       
  4.       
  5.         OS_ENTER_CRITICAL();                         /* Tell uC/OS-II that we are starting an ISR          */  
  6.         OSIntNesting++;  
  7.         OSIntNeedSW = OSIntSW_Enable;               // 需退出中断时进行任务调度切换  
  8.         OS_EXIT_CRITICAL();  
  9.       
  10.         OSTimeTick();                                /* Call uC/OS-II's OSTimeTick()                       */  
  11.       
  12.         OSIntExit();                                 /* Tell uC/OS-II that we are leaving the ISR          */  
  13.     }  

  14. 最后需改动的一个函数是OSIntExit(),




  15. [cpp] view plaincopy

  16.     void  OSIntExit (void)  
  17.     {  
  18.     #if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */  
  19.         OS_CPU_SR  cpu_sr = 0u;  
  20.     #endif  
  21.       
  22.         if (OSRunning == OS_TRUE) {  
  23.             OS_ENTER_CRITICAL();  
  24.             if (OSIntNesting > 0u) {                           /* Prevent OSIntNesting from wrapping       */  
  25.                 OSIntNesting--;  
  26.             }  
  27.             if (OSIntNesting == 0u) {                          /* Reschedule only if all ISRs complete ... */  
  28.                 if(OSIntNeedSW == OSIntSW_Enable){            // 在这判断是否需要任务切换调试  
  29.                     OSIntNeedSW = OSIntSW_Disable;  
  30.                     if (OSLockNesting == 0u) {                     /* ... and not locked.                      */  
  31.                         OS_SchedNew();  
  32.                         OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];  
  33.                         if (OSPrioHighRdy != OSPrioCur) {          /* No Ctx Sw if current task is highest rdy */  
  34.     #if OS_TASK_PROFILE_EN > 0u  
  35.                             OSTCBHighRdy->OSTCBCtxSwCtr++;         /* Inc. # of context switches to this task  */  
  36.     #endif  
  37.                             OSCtxSwCtr++;                          /* Keep track of the number of ctx switches */  
  38.                             OSIntCtxSw();                          /* Perform interrupt level ctx switch       */  
  39.                         }                     
  40.                     }                  
  41.                 }  
  42.             }  
  43.             OS_EXIT_CRITICAL();  
  44.         }  
  45.     }  



 楼主| Jessicakjdsl 发表于 2016-4-20 17:56 | 显示全部楼层
最终目的,通过增加一个OSIntNeedSW全局变量,来判断退出中断时是否需要进行任务调试切换。这样的话,在一般的中断处理函数处理的退出过程更快,缩短无改变任务优先级中断的处理时间。其实这功能在新的版本ucos III中已经实现了。


        之前使用的版本我还按网上一些人的做法更改了ucos的移植文件,如下图,这是任务切换的时候,如果不使用OSTaskSwHook可以屏蔽下面四行汇编。,省四条语句。
  1. point, entire context of process has been saved  
  2. PU_PendSVHandler_nosave  
  3. ;PUSH    {R14}                                               ; Save LR exc_return value  
  4. ;LDR     R0, =OSTaskSwHook                                   ; OSTaskSwHook();  
  5. ;BLX     R0  
  6. ;POP     {R14}  
  7.   
  8. LDR     R0, =OSPrioCur                                      ; OSPrioCur = OSPrioHighRdy;  
  9. LDR     R1, =OSPrioHighRdy  
  10. LDRB    R2, [R1]  
  11. STRB    R2, [R0]  
  12.   
  13. LDR     R0, =OSTCBCur                                       ; OSTCBCur  = OSTCBHighRdy;  
  14. LDR     R1, =OSTCBHighRdy  
  15. LDR     R2, [R1]  
  16. STR     R2, [R0]  
  17.   
  18. LDR     R0, [R2]                                            ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;  
  19. LDM     R0, {R4-R11}                                        ; Restore r4-11 from new process stack  
  20. ADDS    R0, R0, #0x20  
  21. MSR     PSP, R0                                             ; Load PSP with new process SP  
  22. ORR     LR, LR, #0x04                                       ; Ensure exception return uses process stack  
  23. CPSIE   I  
  24. BX      LR                                                  ; Exception return will restore   
强烈推荐在调试阶段加入,并开启这宏定义

  1.     #ifdef USE_FULL_ASSERT  
  2.     /******************************************************************************
  3.     *
  4.     * Function Name  : assert_failed
  5.     * Description    : Reports the name of the source file and the source line  
  6.     number
  7.     *                  where the assert_param error has occurred.
  8.     * Input          : - file: pointer to the source file name
  9.     *                  - line: assert_param error line source number
  10.     * Output         : None
  11.     * Return         : None
  12.     *******************************************************************************/  
  13.     void assert_failed(uint8_t* file, uint32_t line)  
  14.     {  
  15.       /* User can add his own implementation to report the file name and line number,
  16.          ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line)  
  17.     */  
  18.       
  19.       /* Infinite loop */  
  20.         while (1)  
  21.         {}  
  22.     }  
  23.     #endif  


您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

116

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部