NXP JN5169滴答定时器中断回调函数
一、滴答定时器介绍
二、中断处理
1、中断回调函数
片上外设的中断由一组特定于外设的回调函数处理。 可以使用Integrated Peripherals API的适当回调注册功能来引入这些用户定义的功能。 例如,可以编写自己的UART0中断处理程序,然后注册使用vAHI_Uart0RegisterCallback()函数的回调函数。
下表提供了外设中断源的完整列表和相应的回调注册功能。
*包括DIO,比较器,唤醒定时器,脉冲计数器,随机数和掉电中断。
**用于SI主设备和SI从设备中断。
注:
① 回调函数在中断上下文中执行。 因此,必须确保函数及时返回主程序。
② 可以使用函数vAHI_InterruptSetPriority()设置来自各种中断源的中断的优先级。
③ 注册的回调函数仅在RAM保持供电的睡眠模式下保留。 如果在睡眠期间关闭RAM的电源并需要中断,则在唤醒时调用u32AHI_Init()之前必须重新注册所有回调函数。
2、 回调函数原型和参数
所有外围设备的用户定义回调函数必须按照以下原型设计:
void vHwDeviceIntCallback(uint32 u32DeviceId, uint32 u32ItemBitmap);
形参:u32DeviceId
标识产生中断的外设。 上面的表中列出了可能的来源。API中提供了这些来源的枚举,外设中断枚举(u32DeviceId)对此进行了详细说明。
形参:u32ItemBitmap
u32ItemBitmap是一个位图,用于标识通过上述u32DeviceId标识的外围模块内的中断的具体原因。 API中提供了掩码,允许检查特定的中断原因。 UART中断是一个例外,因为在这种情况下,枚举值是通过此参数而不是位图传递的。 掩码和枚举在外围中断源(u32ItemBitmap)详细介绍。
3、 回调行为
在调用其中一个回调函数之前,API会清除中断源,这样就不会存在相同中断的危险,从而不会导致处理器进入永久尝试处理同一中断的状态(由于回调函数编写不当)。 这也意味着可以使用NULL回调函数。
UART是该规则的例外。 当产生可用的接收数据或超时指示中断时,仅当从UART接收缓冲区读取数据后,UART才会清除该中断。 因此,至关重要的是,如果要启用UART中断,则回调函数通过在返回之前从UART读取数据来处理可用数据接收和超时指示中断。
如果正在使用Application Queue API,则该API将处理上述与UART中断有关的问题,因此应用程序无需对其进行处理。
处理唤醒中断本篇博客不涉及,不做展开介绍。
4、外设中断枚举(u32DeviceId)
5、外围中断源(u32ItemBitmap)
三、实现代码
使用BeyondStudio for NXP编写,SDK为JN-SW-4170,不带栈协议,仅外设功能实现。
1、宏定义
/* Value enumerations: Tick Timer */
#define E_AHI_TICK_TIMER_DISABLE (0x00) /* Disable tick timer */
#define E_AHI_TICK_TIMER_RESTART (0x01) /* Restart timer when match occurs */
#define E_AHI_TICK_TIMER_STOP (0x02) /* Stop timer when match occurs */
#define E_AHI_TICK_TIMER_CONT (0x03) /* Timer does not stop when match occurs */
#define TRUE (1) /* page 207 K+R 2nd Edition */
#define FALSE (0)
#define DELAY_TICK_TIME 16000000 /* 1s */
#define TICK_COUNT 16000 /* 1ms */
#define LED2 (1 << 0)
#define LED3 (1 << 1)
#define LED4 (1 << 2)
#define LED5 (1 << 3)
#define LED6 (1 << 4)
#define LED8 (1 << 5)
#define LED_DIO ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5))
#define LED_ON(Led) vAHI_DioSetOutput(0, Led)
#define LED_OFF(Led) vAHI_DioSetOutput(Led, 0)
2、全局变量
PRIVATE uint8 u8Tick; /*滴答定时器中断次数*/
PRIVATE uint32 u32Second; /*秒数*/
3、滴答定时器初始化函数
PRIVATE void vTickTimerInit (void)
{
vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_DISABLE);/* 关闭滴答定时器*/
vAHI_TickTimerWrite(0); /* 设置起始值*/
vAHI_TickTimerInterval(TICK_COUNT * 10); /* 设置参照值 10ms*/
vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_RESTART); /* 重新开始计数*/
vAHI_TickTimerRegisterCallback(vCbTickTimer); /* 注册中断回调*/
vAHI_TickTimerIntEnable(TRUE); /* 启动*/
}
4、中断回调函数
PRIVATE void vCbTickTimer(uint32 u32Device, uint32 u32ItemBitmap)
{
PRIVATE bool_t bLedStatus;
if (++u8Tick > 99) { /*满一秒*/
u8Tick = 0; /*重置计数次数*/
++u32Second; /*秒++*/
(bLedStatus = !bLedStatus) ? LED_ON(LED_DIO) : LED_OFF(LED_DIO);/* 每秒翻转一次输出*/
}
}
5、完整代码
PRIVATE uint8 u8Tick; /*滴答定时器中断次数*/
PRIVATE uint32 u32Second; /*秒数*/
/*初始化IO*/
PRIVATE void vLedsInit (void)
{
vAHI_DioSetDirection(0, LED_DIO);
vAHI_DioSetPullup(LED_DIO, 0);
}
/*滴答定时器初始化*/
PRIVATE void vTickTimerInit (void)
{
vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_DISABLE); /* 关闭滴答定时器 */
vAHI_TickTimerWrite(0); /* 设置起始值 */
vAHI_TickTimerInterval(TICK_COUNT); /* 设置参照值 */
vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_RESTART); /* 重新开始计数 */
vAHI_TickTimerRegisterCallback(vCbTickTimer); /* 注册中断回调 */
vAHI_TickTimerIntEnable(TRUE); /* 启动 */
}
/*中断回调函数*/
PRIVATE void vCbTickTimer (uint32 u32Device, uint32 u32ItemBitmap)
{
PRIVATE bool_t bLedStatus;
if (++u8Tick > 99) {
u8Tick = 0;
++u32Second;
(bLedStatus = !bLedStatus) ? LED_ON(LED_DIO) : LED_OFF(LED_DIO);/* 每秒翻转一次输出 */
}
}
/*主函数*/
PUBLIC void AppColdStart (void)
{
u8Tick = 0;
u32Second = 0;
vAHI_WatchdogStop();
(void)u32AHI_Init();
vLedsInit();
vTickTimerInit();
while (1) {
vAHI_CpuDoze(); /* Doze*/
}
}
/*热启动*/
PUBLIC void AppWarmStart (void)
{
AppColdStart();
}