华大hc32f460移植FreeRTOS中断优先级管理

  • Post author:
  • Post category:其他


使用环境:

hc32f460 _ddl_rev3.1.0

FreeRTOSv202212.00

中断优先级配置异常,会导致FreeRtos卡死在以下俩个断言.

 void vPortValidateInterruptPriority( void )
    {
        uint32_t ulCurrentInterrupt;
        uint8_t ucCurrentPriority;

        /* Obtain the number of the currently executing interrupt. */
        ulCurrentInterrupt = vPortGetIPSR();

        /* Is the interrupt number a user defined interrupt? */
        if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
        {
            /* Look up the interrupt's priority. */
            ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];

            /* The following assertion will fail if a service routine (ISR) for
             * an interrupt that has been assigned a priority above
             * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
             * function.  ISR safe FreeRTOS API functions must *only* be called
             * from interrupts that have been assigned a priority at or below
             * configMAX_SYSCALL_INTERRUPT_PRIORITY.
             *
             * Numerically low interrupt priority numbers represent logically high
             * interrupt priorities, therefore the priority of the interrupt must
             * be set to a value equal to or numerically *higher* than
             * configMAX_SYSCALL_INTERRUPT_PRIORITY.
             *
             * Interrupts that use the FreeRTOS API must not be left at their
             * default priority of zero as that is the highest possible priority,
             * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
             * and therefore also guaranteed to be invalid.
             *
             * FreeRTOS maintains separate thread and ISR API functions to ensure
             * interrupt entry is as fast and simple as possible.
             *
             * The following links provide detailed information:
             * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
             * https://www.FreeRTOS.org/FAQHelp.html */
            configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
        }

        /* Priority grouping:  The interrupt controller (NVIC) allows the bits
         * that define each interrupt's priority to be split between bits that
         * define the interrupt's pre-emption priority bits and bits that define
         * the interrupt's sub-priority.  For simplicity all bits must be defined
         * to be pre-emption priority bits.  The following assertion will fail if
         * this is not the case (if some bits represent a sub-priority).
         *
         * If the application only uses CMSIS libraries for interrupt
         * configuration then the correct setting can be achieved on all Cortex-M
         * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
         * scheduler.  Note however that some vendor specific peripheral libraries
         * assume a non-zero priority group setting, in which cases using a value
         * of zero will result in unpredictable behaviour. */
        configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
    }

由于HC63F460使用的是Cortex-M4内核,中断优先级于STM32是相同的,所以配置相同情况下不会出问题.

优先级配置在FreeRTOSconfig.c中

/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
	/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
	#define configPRIO_BITS       		__NVIC_PRIO_BITS
#else
	#define configPRIO_BITS       		4        /* 15 priority levels */
#endif

/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY			0xf

/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY	5

/* Interrupt priorities used by the kernel port layer itself.  These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY 		( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

Cortex-M4 中断占用高4位,需要注意的是configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY这个宏决定哪些中断归FreeRTOS管理,在设置中断优先级时如需要RTOS管理则需要大于这个宏定义即可.

另外在进入程序时,一定要调用NVIC_SetPriorityGrouping()此函数设置优先级组,一般情况下设置为Group4,即NVIC_SetPriorityGrouping(3);*参数对应为0,1,2,3

配置完成即可正常运行.

以下配置一个外部中断来说明.

1.优先组设定(进入程序第一件事设置)

int32_t main(void)
{
			SystemClkInit();
			NVIC_SetPriorityGrouping(3);
			CLK_SetSysClockSrc(CLK_SYSCLK_SRC_PLL);
			LL_PERIPH_WE(LL_PERIPH_GPIO);
			app_led_PortInit1();
			xTaskCreate((TaskFunction_t)start_task,
								(const char*)"start_task",
								(uint16_t)START_STK_SIZE,
								(void*)NULL,
								(UBaseType_t)START_TASK_PRIO,
								(TaskHandle_t*) &StartTask_Handler);
								
		vTaskStartScheduler();			
	
}

2.配置外部中断,NVIC_SetPriority(stcIrqSignConfig.enIRQn, DDL_IRQ_PRIO_07);这里的优先级数字一定是要比config中的   configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY大.

数字越小优先级越高.

void Bsp_FT5446_CTP_Init(void)
{
	uint8_t i=0;
	uint8_t lvalue;

	stc_extint_init_t stcExtIntInit;
  stc_irq_signin_config_t stcIrqSignConfig;
	//----------------RESET---------
	stc_gpio_init_t stcGpioInit;
	
	(void)GPIO_StructInit(&stcGpioInit);

	stcGpioInit.u16PinState = PIN_STAT_SET;
  stcGpioInit.u16PinDir  = PIN_DIR_OUT;
	stcGpioInit.u16PullUp =PIN_PU_OFF;
	
	(void)GPIO_Init(CTP_RST_PORT, CTP_RST_PIN, &stcGpioInit);
	
	RST_LOW();
	DDL_DelayMS(20);
	RST_HIGH();
	//---------------IIC init-------
	drv_i2c_Init(CTP_SDA_PORT,CTP_SDA_PIN,CTP_SCK_PORT,CTP_SCL_PIN);
	
	//---------------INT init-------
    /* configuration structure initialization */
		(void)EXTINT_StructInit(&stcExtIntInit); 		// MEM_ZERO_STRUCT(stcExtiConfig);
    				
																								// MEM_ZERO_STRUCT(stcPortInit);

    /**************************************************************************/
    /* External Int Ch.9                                                      */
    /**************************************************************************/
		stcExtIntInit.u32Edge=EXTINT_TRIG_FALLING;
	 (void)EXTINT_Init(EXTINT_CH09, &stcExtIntInit);
	 
		stcIrqSignConfig.enIntSrc=INT_SRC_PORT_EIRQ9;
    stcIrqSignConfig.enIRQn=INT000_IRQn;
		stcIrqSignConfig.pfnCallback=&ExtInt09_Callback;
		(void)INTC_IrqSignIn(&stcIrqSignConfig);
   

    /* Set PA09 as External Int Ch.9 input */
    (void)GPIO_StructInit(&stcGpioInit);
    stcGpioInit.u16ExtInt = PIN_EXTINT_ON;
		stcGpioInit.u16PullUp=PIN_PU_ON;
		stcGpioInit.u16PinDir=PIN_DIR_IN;
    (void)GPIO_Init(CTP_INT_PORT, CTP_INT_PIN, &stcGpioInit);

     NVIC_ClearPendingIRQ(stcIrqSignConfig.enIRQn);
     NVIC_SetPriority(stcIrqSignConfig.enIRQn, DDL_IRQ_PRIO_07);
     NVIC_EnableIRQ(stcIrqSignConfig.enIRQn);
		
	//------------------------------------------------------------
	do{
		 CTP_I2C_READ(0xa3, &lvalue, 1);
		 i++;
		 DDL_DelayMS(50);
		 if((lvalue==0x06)||(lvalue==0x36)||(lvalue==0x64))
		 	break;
	  }
	while(i<20);
	if((lvalue==0x06)||(lvalue==0x36)||(lvalue==0x64))
	{

	}
	DDL_DelayMS(10);
}

3.中断回调函数

void ExtInt09_Callback(void)
{
	BaseType_t pxHigherPriorityTaskWoken=pdFALSE; 
	uint32_t ulReturn;
	uint16_t event;
	ulReturn = taskENTER_CRITICAL_FROM_ISR();
	
  if (SET == EXTINT_GetExtIntStatus(EXTINT_CH09))
  {   
				//Touch_Int();
				//vTaskNotifyGiveFromISR();
			EXTINT_ClearExtIntStatus(EXTINT_CH09);
			// 发送事件请求		
			pxHigherPriorityTaskWoken=pdFALSE;
			event=EVENT7;
			xEventGroupSetBitsFromISR(myxEventGroupHandle_t,event,
			&pxHigherPriorityTaskWoken);
		
			/// 如果需要就切换任务
			portYIELD_FROM_ISR(pxHigherPriorityTaskWoken);

      
  }
	taskEXIT_CRITICAL_FROM_ISR( ulReturn ); 
}



版权声明:本文为hwf236521原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。