之前一篇文章:中断知识(重温)
搞BSP的同学,在Android/Linux 系统肯定很清楚中断处理方法,那么QNX 系统下中断又是怎么做的呢? 众所周知,QNX是RTOS,有些跟Linux不同的方法论。


其中中断有优先级,导致中断处理也具备了优先级.

如上图可以看出,taskB运行过程收到interrupt,并未立刻执行,而是等待TaskB执行完成之后再执行taskC。

如上图可以看出,taskB运行过程收到interrupt,立刻执行taskC,taskC执行完成后再调度执行之前任务taskB。
- extern int InterruptHookTrace(const struct sigevent *(*__handler)(int), unsigned __flags);
- extern int InterruptHookIdle(void (*__handler)(_Uint64t *, struct qtime_entry *), unsigned __flags);
- extern int InterruptHookIdle2(void (*__handler)(unsigned, struct syspage_entry *, struct _idle_hook *), unsigned __flags);
- extern int InterruptHookOverdriveEvent(const struct sigevent *__event, unsigned __flags);
- extern int InterruptAttachEvent(int __intr, const struct sigevent *__event, unsigned __flags);
- extern int InterruptAttachEvent_r(int __intr, const struct sigevent *__event, unsigned __flags);
- extern int InterruptAttach(int __intr, const struct sigevent *(*__handler)(void *__area, int __id), const void *__area, int __size, unsigned __flags);
- extern int InterruptAttach_r(int __intr, const struct sigevent *(*__handler)(void *__area, int __id), const void *__area, int __size, unsigned __flags);
- extern int InterruptAttachArray(int __intr, const struct sigevent * const *(*__handler)(void *__area, int __id), const void *__area, int __size, unsigned __flags);
- extern int InterruptAttachArray_r(int __intr, const struct sigevent * const *(*__handler)(void *__area, int __id), const void *__area, int __size, unsigned __flags);
- extern int InterruptDetach(int __id);
- extern int InterruptDetach_r(int __id);
- extern int InterruptWait(int __flags, const _Uint64t *__timeout);
- extern int InterruptWait_r(int __flags, const _Uint64t *__timeout);
- extern int InterruptCharacteristic(int __type, int __id, unsigned *__new, unsigned *__old);
- extern int InterruptCharacteristic_r(int __type, int __id, unsigned *__new, unsigned *__old);
-
- extern void InterruptEnable(void);
- extern void InterruptDisable(void);
- extern int InterruptMask(int __intr, int __id);
- extern int InterruptUnmask(int __intr, int __id);
- extern void InterruptLock(struct intrspin * __spin);
- extern void InterruptUnlock(struct intrspin * __spin);
- extern unsigned InterruptStatus(void);
常用配置接口:
- extern int ThreadCtl(int __cmd, void *__data);
- extern int InterruptAttachEvent(int __intr, const struct sigevent *__event, unsigned __flags);
- extern int InterruptWait_r(int __flags, const _Uint64t *__timeout);
- extern int InterruptUnmask(int __intr, int __id);
- extern int InterruptDetach(int __id);
- //get I/O privileges
- if (-1 == ThreadCtl(_NTO_TCTL_IO, 0)) {
- printf("Failed to get IO privileges!");
- goto exit_err;
- }
int32_t gpio_set_interrupt_cfg(int fd, uint32_t gpio, uint32_t trigger, void *event)
- // Set up edge detection of pin
- if(GPIO_FAIL == gpio_set_interrupt_cfg(fd,gpio_number,trigger,NULL))
- {
- printf("Failed to setup detect pin interrupt \n");
- goto exit_err;
- }
-
- if(GPIO_FAIL == (status = gpio_get_interrupt_cfg(fd,gpio_number,&irq)))
- {
- printf("Failed to get irq corresponding to gpio %d \n",gpio_number);
- goto exit_err;
- }
- else
- {
- if (irq == -1)
- {
- printf(" irq corresponding to gpio %d is %d status %d - exiting\n",gpio_number,irq, status);
- goto exit_err;
- }
- printf(" irq corresponding to gpio %d is %d status %d\n",gpio_number,irq, status);
- }
- // Attach Event ISR
- SIGEV_INTR_INIT(&int_event);
- interrupt_id = InterruptAttachEvent(irq, &int_event, _NTO_INTR_FLAGS_TRK_MSK);
-
- printf("Wakeup setup successfully completed and now wait for interrupt \n");
-
- while ( 1 ) {
- // Wait for interrupt
- status = InterruptWait_r(0, NULL );
- if (status != EOK)
- {
- printf("InterruptWait_r failed with error %d \n",status);
- break;
- }
-
- printf("Got GPIO%d interrupt\n", gpio_number );
- InterruptUnmask(irq, interrupt_id);
- }
-
- InterruptDetach(interrupt_id);
- SIGEV_INTR/InterruptWait()
- 最简单也最快速
- 必须在一个线程里
- 队列里元素只有有1个
- Pulse
- 可以在多线程下等待接收channel上的消息
- 可以队列化
- 最灵活
- Signal
- 如果使用signal handler,那将是开销最大的方案
- 可以队列化
- #define INTR_PULSE _PULSE_CODE_MINAVAIL
- struct sigevent event;
-
- const struct sigevent* handler(void *area,int id){
- // do work
- return (&event); // wake up main thread
- }
-
- int main(){
- chid = ChannelCreate(0);
- coid = ConnectAttach(ND_LOCAL_NODE,0,chid,_NTO_SIDE_CHANNEL,0);
- SIGEV_PULSE_INIT(&event,coid,MyPriority,INTR_PULSE,0);
- InterruptAttach(intnum, handler,NULL,0,_NTO_INTR_FLAGS_TRK_MSK);
- for(;;){
- rcvid = MsgReceive(chid,...);
- if(rcvid == 0){
- // got a pulse
- }
- }
- return 0;
- }
- if (-1 != (fd = open(“/dev/gpio/tlmm/38”, O_RDWR))) {
- chid = ChannelCreate( 0 );
- coid = ConnectAttach( 0, 0, chid, _NTO_SIDE_CHANNEL, 0 );
- SIGEV_PULSE_INIT(&event, coid, SIGEV_PULSE_PRIO_INHERIT,
- QCGPIO_TEST_CODE, 0);
- LOG("qcgpio_test : calling ionotify\n");
- rtn = ionotify(fd, _NOTIFY_ACTION_POLLARM, _NOTIFY_COND_INPUT, &event);
- rcvid = MsgReceive(chid, &msg, sizeof(msg), NULL);
- if (rcvid != 0) {
- LOG("qcgpio_test : invalid pulse received\n");
- } else {
- LOG("qcgpio_test : Hurray..! pulse received.\n");
- }
- }
测试demo:qnx_ap/AMSS\platform\services\applications\tlmm_gpio_interrupt_test.c