-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Description
Describe the bug
I have tied a simple interrupt to a pin on my nRF52833. This interrupt finally calls a small function that only gives an semaphore.
Another thread waits for this semaphore. This works just fine:
K_SEM_DEFINE(interrupt_sem, 0, 1);
void wait_for_sem() {
k_sem_take(&interrupt_sem, K_FOREVER);
}
void trigger_sem() {
k_sem_give(&interrupt_sem);
}However, after a period of time, calling k_sem_give(&interrupt_sem); causes an MPU Fault.
The exact location of the fault is in include/sys/dlist.h when calling sys_dlist_remove(sys_dnode_t). Rewinding the stack further, this is caused by thread->base.qnode_dlist only being NULL. This can be worked around by just setting next/prev to "it self":
K_SEM_DEFINE(interrupt_sem, 0, 1);
void wait_for_sem() {
k_sem_take(&interrupt_sem, K_FOREVER);
}
void trigger_sem() {
if (interrupt_sem.wait_q.waitq.next->next != NULL) {
k_sem_give(&interrupt_sem);
} else {
interrupt_sem.wait_q.waitq.next->next = interrupt_sem.wait_q.waitq.next;
interrupt_sem.wait_q.waitq.next->prev = interrupt_sem.wait_q.waitq.prev;
k_sem_give(&interrupt_sem);
}
}However, I don't understand why interrupt_sem.wait_q.waitq.next->next is NULL in the first place. This only happens after some amount of calling k_sem_give(). The first couple of times (multiple hundred) everything works as expected.
To Reproduce
Having an ISR call k_sem_give() a couple of times.
The thread waiting for the semaphore is an workqueue.
Expected behavior
Having k_sem_give() just increase the semaphore count without any MPU Faults.
Impact
Showstopper, its a critical routine to synchronize an external PHY.
Logs and console output
[00:00:07.941,162] <err> os: ***** MPU FAULT *****
[00:00:07.962,432] <err> os: Data Access Violation
[00:00:07.983,917] <err> os: MMFAR Address: 0x0
[00:00:08.005,096] <err> os: r0/a1: 0x20002828 r1/a2: 0x20002828 r2/a3: 0x00000000
[00:00:08.030,151] <err> os: r3/a4: 0x00000000 r12/ip: 0x80000000 r14/lr: 0x00024f31
[00:00:08.055,206] <err> os: xpsr: 0x81000016
[00:00:08.076,263] <err> os: Faulting instruction address (r15/pc): 0x00023008
[00:00:08.100,341] <err> os: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0
[00:00:08.124,298] <err> os: Fault during interrupt handling
[00:00:08.146,636] <err> os: Current thread: 0x20002828 (idle 00)
[00:00:08.189,300] <err> os: Halting system
Callstack:
mem_manage_fault fault.c:214
fault_handle fault.c:699
z_arm_fault fault.c:962
z_arm_usage_fault fault_s.S:102
<signal handler called> 0x00000000fffffff1
sys_dlist_remove dlist.h:497
z_priq_dumb_remove sched.c:929
unpend_thread_no_timeout sched.c:652
z_unpend_thread_no_timeout sched.c:660
z_unpend1_no_timeout ksched.h:304
z_unpend_first_thread sched.c:713
z_impl_k_sem_give sem.c:113
k_sem_give kernel.h:770
trigger_sem interrupt.c:22
if_int_handler pplc_nrf52_if.c:148
gpio_fire_callbacks gpio_utils.h:70
fire_callbacks gpio_nrfx.c:394
gpiote_event_handler gpio_nrfx.c:442
_isr_wrapper isr_wrapper.S:186
<signal handler called> 0x00000000fffffff1
get_num_regions arm_mpu.c:45
mpu_configure_dynamic_mpu_regions arm_mpu_v7_internal.h:344
arm_core_mpu_configure_dynamic_mpu_regions arm_mpu.c:287
z_arm_configure_dynamic_mpu_regions arm_core_mpu.c:305
z_arm_pendsv swap_helper.S:287
Environment:
- OS: Debian 11
- Zephyr SDK 2.4 (nRF Connect SDK v1.4.0)
- https://github.com/nrfconnect/sdk-zephyr e34b2f4 (HEAD, tag: v2.4.0-ncs2-rc1, tag: v2.4.0-ncs2, manifest-rev)