drivers: mbox: nrf_bellboard: only clear events that raised the IRQ
The current implementation is such that if two or more events are generated in quick succession, only one is handled. This would have happened as follows. At the beginning of the ISR, the contents of INTPEND are read. Then, the ISR unconditionally clears all events that are set. When two (or more) events are generated in rapid succession, it may happen that by the time we enter the ISR, INTPEND is set only for one event, but while we process the ISR, EVENTS_TRIGGERED will be set for more than just that one event (more events are generated). By unconditionally clearing all events, we can potentially lose all events that are generated during ISR processing. This patch changes the ISR so that it only clears those events that have a corresponding bit set in INTPEND at the time it is read. Signed-off-by: Emanuele Di Santo <emdi@nordicsemi.no>
This commit is contained in:
parent
4ba5ad99cc
commit
271ef88e05
1 changed files with 14 additions and 4 deletions
|
|
@ -8,6 +8,7 @@
|
|||
#include <zephyr/devicetree.h>
|
||||
#include <zephyr/drivers/mbox.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
#include <zephyr/sys/__assert.h>
|
||||
|
||||
#include <hal/nrf_bellboard.h>
|
||||
|
||||
|
|
@ -47,11 +48,20 @@ static void bellboard_rx_isr(const void *parameter)
|
|||
for (uint8_t i = 0U; i < NRF_BELLBOARD_EVENTS_TRIGGERED_COUNT; i++) {
|
||||
nrf_bellboard_event_t event = nrf_bellboard_triggered_event_get(i);
|
||||
|
||||
if (nrf_bellboard_event_check(bellboard, event)) {
|
||||
nrf_bellboard_event_clear(bellboard, event);
|
||||
}
|
||||
|
||||
if ((int_pend & BIT(i)) != 0U) {
|
||||
/* Only clear those events that have their corresponding bit set
|
||||
* in INTPEND at the time we read it. Otherwise, if two (or more)
|
||||
* events are generated in quick succession, INTPEND may be set for
|
||||
* only one of events, but we clear the EVENTS_TRIGGERED bit for
|
||||
* all of them, thus losing them.
|
||||
*
|
||||
* Assume nrf_bellboard_event_check() is true for the event
|
||||
* that raised this interrupt.
|
||||
*/
|
||||
__ASSERT_NO_MSG(nrf_bellboard_event_check(bellboard, event));
|
||||
|
||||
nrf_bellboard_event_clear(bellboard, event);
|
||||
|
||||
if (cbs[i] != NULL) {
|
||||
cbs[i](DEVICE_DT_INST_GET(0), i, cbs_ctx[i], NULL);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue