你好,
I am using 3 GPIO as wakeup timer sources. Two sources trigger always on same level (one LOW and one HIGH) and the third source on both levels (during IRQ routine, I toggle the trigger of this GPIO). I have no debounce time (0 ms) and I am expecting an interrupt as soon as at least one source occurs (counter compare threshold is 1). Everything is working well. Two first sources always trigger on their expected levels and third source triggers on the both levels.
//init sequence:
hw_wkup_set_counter_threshold(1);
hw_wkup_set_debounce_time(0);
//等等
However, when at least two sources occur at the same time, the IRQ routine is never called; and for ever (I have observed the interrupt routine is never called only when two sources occur at same time). If I use a software watchdog which calls my IRQ routine, this call unlocks the system and the wakeup timer interrupt is thrown again (because, I think, the IRQ condition - GPIO level and/or trigger condition - is updated during watchdog call).
我已阅读文档:
事件计数器是边缘敏感。检测到A.
active edge a reverse edge must be detected first
before it goes back to the IDLE state and from there
starts waiting for a new active edge.
Is it my issue ? I cannot bypass this condition! I cannot change the source level (GPIO level) and I cannot change the trigger level (because I don't know if I am in the dead lock condition)...
Any reply will be greatly appreciated .
Regards,
Guillaume B.
你好gbmej,
I dont see any issues when the interrupts are issued at the same time, what might occur and the interrupts from the wake up controller will not trigger is when one of the interrupt sources is allready asserted, for example, if lets say for example that you have configured to wake up the device from 3 different gpios and the trigger pollarity is low for the first two and high for the remaining one. Now if one those interrupts is allready asserted (low for one of the sources of the first two or high for the later) then no interrupt will occur until the asserted pin will be de-asserted. So perhaps this is what you are experiencing and not when the interrupts are triggered at the same time.
Thanks MT_dialog
你好,
谢谢你的回答。我已经完成更多的我nvestigation to reduce my use case. I have now one GPIO interrupt on HIGH to LOW change and another one which toggles at every interrupt. I have observed when the GPIO 2 change occurs just after the GPIO 1 interrupt, there is no issue. But If the change occurs before the end of GPIO 1 interrupt but AFTER the GPIO 2 check, I have the lock
wakeuup_handler()
{
hw_wkup_reset_interrupt();
if (checkGPIO1COndition()) performGPIO1Job();
if (checkGPIO2COndition()) performGPIO2Job(); // toggle trigger
//如果gpio2条件在gpio1中断期间在这里发生变化(我们称为performgpio1job()但不是performgpio2job())我有问题(GPIO中断从不抛出GPIO2。如果GPIO2条件发生在IRQ常规之后,我没有问题。
}
With a watchdog, I have checked the GPIO states just after a lock (job1 performed but not job2): GPIO1 is HIGH and GPIO2 should throw the interrupt...
Regards,
Guillaume B.
你好gbmej,
我不确定我完全得到了这一点,你提到的部分当你锁定时让我感到困惑,试图复制你所提到的内容,我在HRP_Sensor中完成了以下测试,它已经实现了一个唤醒源。触发“静态”唤醒源触发低电平,默认引脚配置是上拉更改唤醒源(中断例程中的配置更改配置)具有最初相同的手机,以及执行更改的代码在下面连接。
//Global variables
__RETAINED HW_GPIO_MODE my_gpio_mode = HW_GPIO_MODE_INPUT_PULLUP;
__RETAINED HW_GPIO_FUNC my_gpio_function;
static void wkup_cb(void)
{
#if dg_configBLACK_ORCA_IC_REV == BLACK_ORCA_IC_REV_A
hw_wkup_reset_counter();
#endif
hw_wkup_reset_interrupt();
hw_gpio_get_pin_function(CFG_START_ADVERTISING_TRIGGER_1_GPIO_PORT, CFG_START_ADVERTISING_TRIGGER_1_GPIO_PIN, &my_gpio_mode, &my_gpio_function);
如果(my_gpio_mode = = HW_GPIO_MODE_INPUT_PULLDOWN) {
my_gpio_mode = hw_gpio_mode_input_pullup;
} else {
my_gpio_mode = HW_GPIO_MODE_INPUT_PULLDOWN;
}
hw_gpio_set_pin_function(cfg_start_advertising_trigger_1_gpio_port,cfg_start_advertising_trigger_1_gpio_pin,my_gpio_mode,hw_gpio_func_gpio);
hw_wkup_configure_pin(cfg_start_advertising_trigger_1_gpio_port,cfg_start_advertising_trigger_1_gpio_pin,true,
my_gpio_mode!=HW_GPIO_MODE_INPUT_PULLDOWN?HW_WKUP_PIN_STATE_LOW:HW_WKUP_PIN_STATE_HIGH);
hw_cpm_trigger_sw_cursor(); //this will help identify the interrupt in the power profiler with a thin red line each time the interrupt triggers
hrp_wkup_cb();
}
In the periph_init():
hw_gpio_set_pin_function(cfg_start_advertising_trigger_1_gpio_port,cfg_start_advertising_trigger_1_gpio_pin,my_gpio_mode,hw_gpio_func_gpio);
只要触发中断,然后从触发状态释放行,都会出现在触发状态,因此应该检查上面的片段上的更改以及引脚的唤醒状态如何基于该中断用于检查默认引脚配置HW_GPIO_SET_PIN_FUNCTION()的默认引脚,HW_GPIO_GET_PIN_FUNCTION()用于设置正确的默认PIN状态(与先前中断命中相反)。
Thanks MT_dialog
你好,
Thanks a lot for your answer but I have no issue with the trigger toggle. I have an issue when a GPIO interrupt occur during another GPIO interrupt. This is my pseudo code (see attached file).
- GPIOA中断每40毫秒发生一次。GPIOA任务责任GPIOA水平从低到高(它是清除传感器中断的传感器读数)。
- GPIOB interrupt occurs every 200ms. The first interrupt is thrown when level goes from HIGH to LOW. We toggle the trigger to check now LOW to HIGH. The task GPIOB forces the GPIOB to return from LOW to HIGH (the source which drives the GPIOB signal). Then the second interrupt is thrown and we toggle again. It is like as a button to get press/release events but source cannot release until press event is taken in consideration.
Everything works well, except this use case:
[interrupt 1 at t +0ms ]
- GPIOA go to LOW
- interrupt is thrown
- valid GPIOA condition: we wakeup GPIOA task
- 无效的gpiob条件:我们不会切换gpiob触发器,我们不会唤醒gpiob任务
- we leave the interrupt
[task GPIOA at t +1ms]
- we read the sensor
- the GPIOA level return to HIGH
[interrupt 2 at t +33ms]
- GPIOB go to LOW
- interrupt is thrown
- 无效的GPIOA条件:我们不唤醒GPIOA任务
- 有效的GPIOB条件:我们切换GPIOB触发器,我们唤醒GPIOB任务
- we leave the interrupt
[T + 34MS的任务GPIOB]
- 我们确认GPIOB级别让源工作(大约6到8毫秒)
[interrupt 3 at t +40ms]
- GPIOA go to LOW
- interrupt is thrown
- we wakeup GPIOA task (valid GPIOA condition)
- we don't wakeup GPIOB task (invalid GPIOB condition)
- we leave the interrupt
[T = + 41ms的任务GPIOA]
- we read the sensor
- the GPIOA level return to HIGH
If the GPIOB LOW to HIGH level is updated just AFTER interrupt 3 (we have left interrupt vector routine), there is no error. If this update occurs just after the check of GPIOB interrupt condition but before leaving the interrupt vector routine, no more interrupt is thrown. This is the lock. I think the internal wakeup state machine stays in the KEY_RELEASE state because key_hit of GPIOA back to zero but at same time, key_hit of GPIOB go to 1...
Thank you again for your help
Guillaume
你好gbmej,
你的意思是,M0正在执行一个按钮按下的ISR时没有中断?那是对的吗 ?这与唤醒控制器无关,而是M0和NVIC如何运行,如果处理器在执行中断处理程序时进行中断,因为两个中断都具有相同的优先级,因此挂起的中断标志将是相同的设置为1,一旦上一个ISR被执行,它将再次调用它来服务挂起的中断,并且就我测试了这正是68倍的所做中断。
Now in your case i see that your pins are configured with the internal resistors in pulldown and pullup, i can imagine that this is the reason for the interrupts to lock, perhaps in case that the external device is not properly driving the line in a specific state the pullups will take place and keep the interrupt signal for the wake up controller asserted for at least one pin source which i suppose is the one that toggles its state, and this is enough for no interrupts to occur and the wake up controller to wait for the interrupt to be asserted before reporting another interrupt. So you can try to either not to use the internal pull ups in case you are certain that the external sensor is driving the lines properly, or if you would like to use the internal resistors you should alter the default state of the resistor to the opposite of the state that will trigger the wake up, something like i have mentioned in my previous post, using the hw_gpio_set_pin_function() in order to change the default pin configuration.
Thanks MT_dialog
你好,
I have a lock on wakeup timer interrupt, not on the other interrupts. As soon as I have a lock (after several seconds; my code works well during several seconds), the wakeup timer interrupt is never thrown again. When I am in the wakeup timer interrupt function due to GPIOA level change AND the conditions of GPIOB becomes valid just after the check of GPIOB conditions but before the end of the interrupt, I have the lock.
I have tried with gpio pin reconfiguration (input pull up then down then up etc.) + udpate of trigger level, no more result.
GPIOA task is waked up on GPIOA interrup (using freertos binary semaphore). Just after the GPIOA task wakeup, I store the GPIOB state in RAM (level, trigger). When I encounter the lock (watchdog), I print the GPIOB state: the interrupt conditions are satisfied but no interrupt (wakeup timer interrupt) is thrown. If I compare this GPIOB state with the GPIOB state during the GPIOA interrupt (just before leaving the wakeup timer interrupt, I store in RAM GPIOB state too), I can see the GPIOB conditions were not satisfied before the end of ISR (wakeup timer interrupt) but satisfied after the ISR. After 40ms after the lock, the conditions of GPIOA are satisfied again too but the interrupt (wakeup timer interrupt) is not thrown.
If during my watchdog callback I call the wakeup interrupt function, this unlocks the lock and then the interrupt keep working...
Thanlks for your help
Guillaume
你好gbmej,
唤醒定时器中断是我所讨论的,源可能是许多引脚,但唤醒定时器的中断是一个。如果有一个唤醒中断和ISR执行,然后在ISR执行期间又一次击中相同的中断,则将设置待处理的位(WKUP_GPIO_IRQN),并且只要ISR提供服务即可重新调用以服务待处理打断。
也许发生了以下情况,GPIOA变低(及其低触发),因此ISR运行,并且您提到任务正在读取传感器的状态以释放中断,因此瞬间有一个句点xGPIOA中断发生在断开中断的那一刻,即唤醒控制器不会接受来自其他源(包括GPIOB)的中断,因为GPIOA的状态仍然被断言,它与...不一定GPIOB中断的条件,如果仍然追随GPIOA,因此仍然触发GPIOB。
Try to check with an analyser the signals and make sure that when the interrupts occur there is no overlapping in the assertion of the signals, meaning that when one interrupt occurs the other is not allready asserted, since this is the only condition that can stall the wake up controller.
Thanks MT_dialog
你好
我更新了我的代码要使用latch mode(chapter 4.3). The results are better. However, I have a question about clearing the interrupt: The function
hw_wkup_reset_interrupt
在具有多个中断源的示例中永远不会调用。这是一个错误吗?Regards,
Guillaume B.
你好gbmej,
The hw_wkup_reset_interrupt() is an API function and not a callback function, so it must be called by any user-specified interrupt callback, to clear the interrupt flag. If you don’t call this function, it will never be called by the application, so this isn’t an error. For more information, please read the Step #2 in 3.2. Key Points of the Initialization Function chapter, of Starting a Project tutorial from our support page.
Thanks, PM_Dialog