uCosII V2.86版本在cortex-m3的移植上面有bug,具体可以自己google一下。我目前使用的是V2.91版本,建立在stm32 V3.40的库基本上。我是强烈要求(或是强制要求)协同开发者使用库函数,除非在速度要求高的情况下或中断里需要直接操作寄存器,也必须使用库的地址定义,并要求在后面注明对应的库函数。因为程序不是你一个人看的……例如:
/* 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);
官方的移植把所有的应用中断入口都指向了BSP_IntHandler这个函数,并定义了一个函数数组static CPU_FNCT_VOID BSP_IntVectTbl[BSP_INT_SRC_NBR];因此,如果要加入自己的中断函数的话,只需把自己写的中断函数的指针存入这个数组就OK了,在初始化中断前调用这函数BSP_IntVectSet。官方的中断优先级设置方式,我全删除了,使用库函数来设置将更直接,但这种中断方式保存下来,这样中断函数更自由,写中断函数时也不用考虑太多东西,只负责自己要做的东西。
/*
*********************************************************************************************************
* INCLUDE FILES
*********************************************************************************************************
*/
#define BSP_INTERRUPT_MODULE
#include
#include //STM32芯片内部寄存器定议
#include
#include
/*
*********************************************************************************************************
* LOCAL DEFINES
*********************************************************************************************************
*/
#define BSP_INT_SRC_NBR 60
/*
*********************************************************************************************************
* LOCAL TABLES
*********************************************************************************************************
*/
static CPU_FNCT_VOID BSP_IntVectTbl[BSP_INT_SRC_NBR];
/*
*********************************************************************************************************
* LOCAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/
static void BSP_IntHandler(u16 int_id);
static void BSP_IntHandlerDummy(void);
/*
*********************************************************************************************************
* BSP_IntVectSet()
*
* Description : Assign ISR handler.
*
* Argument(s) : int_id Interrupt for which vector will be set.
*
* isr Handler to assign
*
* Return(s) : none.
*
* Caller(s) : Application.
*
* Note(s) : none.
*********************************************************************************************************
*/
void BSP_IntVectSet (u16 int_id,
CPU_FNCT_VOID isr)
{
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
if(int_id < BSP_INT_SRC_NBR){
OS_ENTER_CRITICAL();
BSP_IntVectTbl[int_id] = isr;
OS_EXIT_CRITICAL();
}
}
/*
*********************************************************************************************************
*********************************************************************************************************
* INTERNAL FUNCTIONS
*********************************************************************************************************
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* BSP_IntInit()
*
* Description : Initialize interrupts:
*
* Argument(s) : none.
*
* Return(s) : none.
*
* Caller(s) : BSP_Init().
*
* Note(s) : none.
*********************************************************************************************************
*/
void BSP_IntInit (void)
{
u16 int_id;
OS_CPU_SR cpu_sr;
OS_ENTER_CRITICAL(); /* Tell uC/OS-II that we are starting an ISR */
OSIntNeedSW = OSIntSW_Disable; // 需退出中断时进行任务调度切换
OS_EXIT_CRITICAL();
for (int_id = 0; int_id < BSP_INT_SRC_NBR; int_id++) {
BSP_IntVectSet(int_id, BSP_IntHandlerDummy);
}
}
/*
*********************************************************************************************************
* BSP_IntHandler####()
*
* Description : Handle an interrupt.
*
* Argument(s) : none.
*
* Return(s) : none.
*
* Caller(s) : This is an ISR.
*
* Note(s) : none.
*********************************************************************************************************
*/
void BSP_IntHandlerWWDG (void) { BSP_IntHandler(WWDG_IRQn); }
void BSP_IntHandlerPVD (void) { BSP_IntHandler(PVD_IRQn); }
void BSP_IntHandlerTAMPER (void) { BSP_IntHandler(TAMPER_IRQn); }
void BSP_IntHandlerRTC (void) { BSP_IntHandler(RTC_IRQn); }
void BSP_IntHandlerFLASH (void) { BSP_IntHandler(FLASH_IRQn); }
void BSP_IntHandlerRCC (void) { BSP_IntHandler(RCC_IRQn); }
void BSP_IntHandlerEXTI0 (void) { BSP_IntHandler(EXTI0_IRQn); }
void BSP_IntHandlerEXTI1 (void) { BSP_IntHandler(EXTI1_IRQn); }
void BSP_IntHandlerEXTI2 (void) { BSP_IntHandler(EXTI2_IRQn); }
void BSP_IntHandlerEXTI3 (void) { BSP_IntHandler(EXTI3_IRQn); }
void BSP_IntHandlerEXTI4 (void) { BSP_IntHandler(EXTI4_IRQn); }
void BSP_IntHandlerDMA1_CH1 (void) { BSP_IntHandler(DMA1_Channel1_IRQn); }
void BSP_IntHandlerDMA1_CH2 (void) { BSP_IntHandler(DMA1_Channel2_IRQn); }
void BSP_IntHandlerDMA1_CH3 (void) { BSP_IntHandler(DMA1_Channel3_IRQn); }
void BSP_IntHandlerDMA1_CH4 (void) { BSP_IntHandler(DMA1_Channel4_IRQn); }
void BSP_IntHandlerDMA1_CH5 (void) { BSP_IntHandler(DMA1_Channel5_IRQn); }
void BSP_IntHandlerDMA1_CH6 (void) { BSP_IntHandler(DMA1_Channel6_IRQn); }
void BSP_IntHandlerDMA1_CH7 (void) { BSP_IntHandler(DMA1_Channel7_IRQn); }
void BSP_IntHandlerADC1_2 (void) { BSP_IntHandler(ADC1_2_IRQn); }
void BSP_IntHandlerUSB_HP_CAN_TX (void) { BSP_IntHandler(USB_HP_CAN1_TX_IRQn); }
void BSP_IntHandlerUSB_LP_CAN_RX0(void) { BSP_IntHandler(USB_LP_CAN1_RX0_IRQn); }
void BSP_IntHandlerCAN_RX1 (void) { BSP_IntHandler(CAN1_RX1_IRQn); }
void BSP_IntHandlerCAN_SCE (void) { BSP_IntHandler(CAN1_SCE_IRQn); }
void BSP_IntHandlerEXTI9_5 (void) { BSP_IntHandler(EXTI9_5_IRQn); }
void BSP_IntHandlerTIM1_BRK (void) { BSP_IntHandler(TIM1_BRK_IRQn); }
void BSP_IntHandlerTIM1_UP (void) { BSP_IntHandler(TIM1_UP_IRQn); }
void BSP_IntHandlerTIM1_TRG_COM (void) { BSP_IntHandler(TIM1_TRG_COM_IRQn); }
void BSP_IntHandlerTIM1_CC (void) { BSP_IntHandler(TIM1_CC_IRQn); }
void BSP_IntHandlerTIM2 (void) { BSP_IntHandler(TIM2_IRQn); }
void BSP_IntHandlerTIM3 (void) { BSP_IntHandler(TIM3_IRQn); }
void BSP_IntHandlerTIM4 (void) { BSP_IntHandler(TIM4_IRQn); }
void BSP_IntHandlerI2C1_EV (void) { BSP_IntHandler(I2C1_EV_IRQn); }
void BSP_IntHandlerI2C1_ER (void) { BSP_IntHandler(I2C1_ER_IRQn); }
void BSP_IntHandlerI2C2_EV (void) { BSP_IntHandler(I2C2_EV_IRQn); }
void BSP_IntHandlerI2C2_ER (void) { BSP_IntHandler(I2C2_ER_IRQn); }
void BSP_IntHandlerSPI1 (void) { BSP_IntHandler(SPI1_IRQn); }
void BSP_IntHandlerSPI2 (void) { BSP_IntHandler(SPI2_IRQn); }
void BSP_IntHandlerUSART1 (void) { BSP_IntHandler(USART1_IRQn); }
void BSP_IntHandlerUSART2 (void) { BSP_IntHandler(USART2_IRQn); }
void BSP_IntHandlerUSART3 (void) { BSP_IntHandler(USART3_IRQn); }
void BSP_IntHandlerEXTI15_10 (void) { BSP_IntHandler(EXTI15_10_IRQn); }
void BSP_IntHandlerRTCAlarm (void) { BSP_IntHandler(RTCAlarm_IRQn); }
void BSP_IntHandlerUSBWakeUp (void) { BSP_IntHandler(USBWakeUp_IRQn); }
void BSP_IntHandlerTIM8_BRK (void) { BSP_IntHandler(TIM8_BRK_IRQn); }
void BSP_IntHandlerTIM8_UP (void) { BSP_IntHandler(TIM8_UP_IRQn); }
void BSP_IntHandlerTIM8_TRG_COM (void) { BSP_IntHandler(TIM8_TRG_COM_IRQn); }
void BSP_IntHandlerTIM8_CC (void) { BSP_IntHandler(TIM8_CC_IRQn); }
void BSP_IntHandlerADC3 (void) { BSP_IntHandler(ADC3_IRQn); }
void BSP_IntHandlerFSMC (void) { BSP_IntHandler(FSMC_IRQn); }
void BSP_IntHandlerSDIO (void) { BSP_IntHandler(SDIO_IRQn); }
void BSP_IntHandlerTIM5 (void) { BSP_IntHandler(TIM5_IRQn); }
void BSP_IntHandlerSPI3 (void) { BSP_IntHandler(SPI3_IRQn); }
void BSP_IntHandlerUART4 (void) { BSP_IntHandler(UART4_IRQn); }
void BSP_IntHandlerUART5 (void) { BSP_IntHandler(UART5_IRQn); }
void BSP_IntHandlerTIM6 (void) { BSP_IntHandler(TIM6_IRQn); }
void BSP_IntHandlerTIM7 (void) { BSP_IntHandler(TIM7_IRQn); }
void BSP_IntHandlerDMA2_CH1 (void) { BSP_IntHandler(DMA2_Channel1_IRQn); }
void BSP_IntHandlerDMA2_CH2 (void) { BSP_IntHandler(DMA2_Channel2_IRQn); }
void BSP_IntHandlerDMA2_CH3 (void) { BSP_IntHandler(DMA2_Channel3_IRQn); }
void BSP_IntHandlerDMA2_CH4_5 (void) { BSP_IntHandler(DMA2_Channel4_5_IRQn); }
/*
*********************************************************************************************************
*********************************************************************************************************
* LOCAL FUNCTIONS
*********************************************************************************************************
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* BSP_IntHandler()
*
* Description : Central interrupt handler.
*
* Argument(s) : int_id Interrupt that will be handled.
*
* Return(s) : none.
*
* Caller(s) : ISR handlers.
*
* Note(s) : none.
*********************************************************************************************************
*/
static void BSP_IntHandler (u16 int_id)
{
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
OS_ENTER_CRITICAL(); /* 不支持中断嵌套,无需关中断 */
OSIntNesting++;
OS_EXIT_CRITICAL();
if (int_id < BSP_INT_SRC_NBR) {
BSP_IntVectTbl[int_id]();
}
OSIntExit();
}
/*
*********************************************************************************************************
* BSP_IntHandlerDummy()
*
* Description : Dummy interrupt handler.
*
* Argument(s) : none.
*
* Return(s) : none.
*
* Caller(s) : BSP_IntHandler().
*
* Note(s) : none.
*********************************************************************************************************
*/
static void BSP_IntHandlerDummy (void)
{
}
void BSP_IntInit (void)
这一函数必须在开中断前调用一次,初始化必要的变量。
还有两个系统函数必须改动,以实现这功能。在滴答时钟中断中,
void OS_CPU_SysTickHandler (void)
{
OS_CPU_SR cpu_sr;
OS_ENTER_CRITICAL(); /* Tell uC/OS-II that we are starting an ISR */
OSIntNesting++;
OSIntNeedSW = OSIntSW_Enable; // 需退出中断时进行任务调度切换
OS_EXIT_CRITICAL();
OSTimeTick(); /* Call uC/OS-II's OSTimeTick() */
OSIntExit(); /* Tell uC/OS-II that we are leaving the ISR */
}
最后需改动的一个函数是OSIntExit(),
void OSIntExit (void)
{
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
if (OSRunning == OS_TRUE) {
OS_ENTER_CRITICAL();
if (OSIntNesting > 0u) { /* Prevent OSIntNesting from wrapping */
OSIntNesting--;
}
if (OSIntNesting == 0u) { /* Reschedule only if all ISRs complete ... */
if(OSIntNeedSW == OSIntSW_Enable){ // 在这判断是否需要任务切换调试
OSIntNeedSW = OSIntSW_Disable;
if (OSLockNesting == 0u) { /* ... and not locked. */
OS_SchedNew();
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */
#if OS_TASK_PROFILE_EN > 0u
OSTCBHighRdy->OSTCBCtxSwCtr++; /* Inc. # of context switches to this task */
#endif
OSCtxSwCtr++; /* Keep track of the number of ctx switches */
OSIntCtxSw(); /* Perform interrupt level ctx switch */
}
}
}
}
OS_EXIT_CRITICAL();
}
}
最终目的,通过增加一个OSIntNeedSW全局变量,来判断退出中断时是否需要进行任务调试切换。这样的话,在一般的中断处理函数处理的退出过程更快,缩短无改变任务优先级中断的处理时间。
其实这功能在新的版本ucos III中已经实现了。
之前使用的版本我还按网上一些人的做法更改了ucos的移植文件,如下图,这是任务切换的时候,如果不使用OSTaskSwHook可以屏蔽下面四行汇编。,省四条语句。
; At this point, entire context of process has been saved
OS_CPU_PendSVHandler_nosave
;PUSH {R14} ; Save LR exc_return value
;LDR R0, =OSTaskSwHook ; OSTaskSwHook();
;BLX R0
;POP {R14}
LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy;
LDR R1, =OSPrioHighRdy
LDRB R2, [R1]
STRB R2, [R0]
LDR R0, =OSTCBCur ; OSTCBCur = OSTCBHighRdy;
LDR R1, =OSTCBHighRdy
LDR R2, [R1]
STR R2, [R0]
LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
LDM R0, {R4-R11} ; Restore r4-11 from new process stack
ADDS R0, R0, #0x20
MSR PSP, R0 ; Load PSP with new process SP
ORR LR, LR, #0x04 ; Ensure exception return uses process stack
CPSIE I
BX LR ; Exception return will restore
强烈推荐在调试阶段加入,并开启这宏定义
#ifdef USE_FULL_ASSERT
/******************************************************************************
*
* Function Name : assert_failed
* Description : Reports the name of the source file and the source line
number
* where the assert_param error has occurred.
* Input : - file: pointer to the source file name
* - line: assert_param error line source number
* Output : None
* Return : None
*******************************************************************************/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line)
*/
/* Infinite loop */
while (1)
{}
}
#endif
如转载请注明出处:spark 更多交流请加QQ群: 291636736