如果在开发过程中遇到如下报错,你就可以继续往下看:
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
描述
在调用外设blocking数据传输接口时(比如LPSPI_DRV_MasterTransferBlocking),需要在外设中断产生时调用操作系统的信号量接口来传递传输状态,这里面其实存在一个中断优先级的问题。
在不设置该外设的中断优先级情况下,系统默认将其外设的中断优先级设置为0x00,可使用INT_SYS_GetPriority 接口进行查看。
此时,假如FreeRTOS配置中(FreeRTOSConfig.h),你的配置为:
configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY = 0x01
configPRIO_BITS = 4
configMAX_SYSCALL_INTERRUPT_PRIORITY = 0x01 << (8-configPRIO_BITS)
那么,就表示操作系统内核中断优先级为0x10。
处于以上情况时,就会出现一种现象:当外设中断产生,在中断服务函数中去调用操作系统内核接口(如OSIF_SemaPost)就会出现系统内核无法抢占当前中断的情况,从而导致系统出错。因为按照数字越小,优先级越高的规则,外设中断优先级(0x00) 高于 操作系统内核中断优先级 (0x10),低优先级无法抢占高优先级。
解决方法
在初始化外设驱动之前,设置该外设的中断优先级,使得该外设中断优先级低于(数字大于)操作系统内核中断优先级。
在S32K中,使用接口 INT_SYS_SetPriority(IRQn_Type irqNumber, uint8_t priority) 来设置外设的中断优先级,设置值与配置FEATURE_NVIC_PRIO_BITS有关。
比如SDK\platform\devices\S32K148\include\S32K148_features.h FEATURE_NVIC_PRIO_BITS = 4,则设置:
INT_SYS_SetPriority(LPSPI2_IRQn, 0x02);
表示设置SPI2的中断优先级为:(0x02 << FEATURE_NVIC_PRIO_BITS) = (0x02 << 4) = 0x20。
此时SPI2的外设中断优先级(0x20) 低于 操作系统内核中断优先级 (0x10),中断抢占问题得以解决,调用操作系统内核接口(如OSIF_SemaPost)成功,外设blocking数据传输接口得以正常使用。
推荐默认将外设中断优先级设置为支持的最低优先级,然后按需地逐步增加其优先级。