本帖最后由 N32BLE 于 2022-9-8 11:36 编辑
由来: 在平时工作过程中,遇到不少工程师反馈在蓝牙协议栈开启后,原本运行正常的外设/内部定时器中断就不响应了,好像与蓝牙功能有冲突,到底谁影响了谁,下面就来讲解一下:
简介:
此文档的目的在于让使用者能够快速熟悉N32WB03x系列蓝牙SOC芯片的中断服务函数的使用方式,以减少开发前期的准备时间,降低开发难度。
内容:
1、中断号:
N32WB03X芯片的中断定义在n32wb03x.h文件里,具体代码如下
2、中断服务函数
中断的配置和开启在使用和不使用蓝牙协议栈这两种情况下,方法是一致的,一般为开启外设的中断功能,配置中断源,使用NVIC函数启用具体的中断 号。中断服务函数的使用在使用蓝牙协议栈和不使用蓝牙协议栈时的用法不同,现在我们分别介绍这两种情况的用法。
2.1、不使用蓝牙协议栈程序 不使用蓝牙协议栈的话,我们直接使用flash代码里面的中断向量表(PWR->VTOR_REG= 0x81000000;),用户直接重新实现如下中断服务函数即可。
2.2、使用蓝牙协议栈
蓝牙协议栈的话,我们必须使用ROM代码里面的中断向量表(PWR->VTOR_REG = 0;),我们在初始化协议栈时,把中断向量表配置配ROM的
中断向量表地址。用户的中断服务函数需要按如下两种方式配置。
2.2.1、中断号为0~31的中断服务函数
先使用ModuleIrqRemoval函数清除当前中断号的回调函数,然后使用ModuleIrqRegister注册新中断服务函数。(注意中断号8(EXTI4_12_IRQn) 需要特殊处理如下节介绍)
1) ModuleIrqRemoval
功能:移除指定中断号的中断响应回调函数 语法:void ModuleIrqRemoval(IRQn_Type irqn);
参数:[in] irqn:需要移除注册函数的中断号
返回值:无
示例: ModuleIrqRegister(DMA_Channel5_IRQn);
2) ModuleIrqRegister
功能:注册指定中断号的中断响应回调函数 语法:uint32_t ModuleIrqRegister(IRQn_Type irqn,IRQ_HANNDLE_FUN fun);
参数:[in] irqn:需要注册的函数的中断号。[in] fun:被注册的中断响应回调函数
返回值:1:注册成功。0:注册失败
示例: ModuleIrqRegister(DMA_Channel5_IRQn, DmaCh5_irq_callback);
2.2.2、EXTI4_12_IRQn特殊处理
由于在协议栈初始化时将覆盖EXTI4_12_IRQn的中断服务函数,所以用户必须在app_ble_msg_handler函数下APP_BLE_OS_READY事件处理里注册用户
的的中断服务函数注册中断服务函数EXTI4_12_IRQn_callback 如下:
ModuleIrqRemoval(EXTI4_12_IRQn);
ModuleIrqRegister(EXTI4_12_IRQn, EXTI4_12_IRQn_callback);
另外在用户的这个中断服务函数里面加上EXTI_11的处理如下:
if ( EXTI_GetITStatus(EXTI_LINE11)!= RESET)
{
EXTI_ClrITPendBit(EXTI_LINE11);
}
2.2.3、M0内核自带的中断服务函数
M0内核自带的中断服务函数,其中断号为负数(-1至-13),包括SysTick_IRQn,PendSV_IRQn,SVCall_IRQn和HardFault_IRQn ,应该使用
如下的方式注册中断服务函数 , 把函数 User_PortSysTickHandler ,User_PortPendSVHandler,User_PortSVCHandler和User_PortHardFaultHandler注册
为相应的中断服务函数。
3、中断优先级
我们的n32wb03x这款芯片的中断优先级有4个等级,为0~3。不使用蓝牙协议栈的话,完全只需要用户代码需要设置中断优先级为0~3任意一个值。
使用蓝牙协议栈的话,蓝牙协议栈相关的中断使用了0和1两个优先级,用户代码应尽可能使用中断优先级2和3,不建议使用优先级0和1。
4、注意事项
1、如果使用中断从SLEEP模式唤醒,注意中断服务函数里面先开启需要操作硬件的时钟,特别是GPIO的时钟。SLEEP模式下可以保持GPIO的状态但没有没 有保持时钟的使能。
2、蓝牙项目里,SLEEP 唤醒之后必须经过一个LP cycle(约32us)之后再调用ke_timer_set函数。
|