Skip to content

Calling k_sem_give causes MPU Fault on nRF52833 #31778

@bamkrs

Description

@bamkrs

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:

Metadata

Metadata

Assignees

Labels

Waiting for responseWaiting for author's responsebugThe issue is a bug, or the PR is fixing a bugpriority: lowLow impact/importance bug

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions