nRF52832: MPU FAULT (Instruction Access Violation in RAM) when using custom bare-metal TWIM0 ISR in Zephyr

Environment:

  • Chip: nRF52832

  • NCS Version: v2.8.0 (Zephyr OS v3.7.99)

  • Language: C++ (main.cpp)

Issue Description: I am trying to implement a custom bare-metal I2C (TWIM0) application by bypassing the default Zephyr I2C driver to directly control the hardware registers. However, as soon as NRF_TWIM0->TASKS_STARTTX = 1; is called and the interrupt triggers, the system immediately crashes with an MPU FAULT (Instruction Access Violation).

The strangest part is that the faulting PC address is always pointing to a RAM address (e.g., 0x200010d0), which is located immediately after my RX/TX static arrays (rxd, txd). It seems the CPU is jumping to RAM to execute the ISR instead of the Flash memory, triggering the eXecute-Never (XN) violation.

What I have tried (Always with Pristine Builds):

  1. Disabled i2c0 and spi0 in app.overlay (status = "disabled";) to prevent Zephyr from taking the IRQ 3.

  2. Set CONFIG_I2C=n in prj.conf.

  3. Tried standard IRQ_CONNECT with void TWIM0_IRQHandler(const void *args).

  4. Tried irq_connect_dynamic() with CONFIG_DYNAMIC_INTERRUPTS=y.

  5. Currently using ISR_DIRECT_DECLARE and IRQ_DIRECT_CONNECT.

Despite all these attempts to take over the interrupt cleanly, the exact same MPU FAULT occurs pointing to a RAM address.

Error log:

*** Booting nRF Connect SDK v2.8.0-a2386bfc8401 ***
*** Using Zephyr OS v3.7.99-0bc3393fb112 ***
Rxd addr: 0x200010b4, Txd addr: 0x200010a0

[00:00:00.405,792] <err> os: ***** MPU FAULT *****
[00:00:00.405,822] <err> os:   Instruction Access Violation
[00:00:00.405,822] <err> os: r0/a1:  0x00007cd8  r1/a2:  0x000000c0  r2/a3:  0xe000e100
[00:00:00.405,853] <err> os: r3/a4:  0x00000001 r12/ip:  0x00000004 r14/lr:  0xfffffffd
[00:00:00.405,853] <err> os:  xpsr:  0x00000013
[00:00:00.405,853] <err> os: Faulting instruction address (r15/pc): 0x200010d0
[00:00:00.405,914] <err> os: >>> ZEPHYR FATAL ERROR 20: Unknown error on CPU 0
[00:00:00.405,914] <err> os: Fault during interrupt handling

[00:00:00.405,944] <err> os: Current thread: 0x20000f20 (main)
[00:00:00.700,561] <err> os: Halting system

Source: main.cpp

#include <Configure.h>
#include <setup.h>
#include <zephyr/irq.h>

static uint8_t rxd[20] = {0};
static uint8_t txd[20] = {0};

static void TWIM0_IRQHandler();

int main(void){
    NRF_TWIM0->PSEL.SDA = TWIM_PIN_SDA;
    NRF_TWIM0->PSEL.SCL = TWIM_PIN_SCL;
    NRF_TWIM0->FREQUENCY = 0x06400000;
    NRF_TWIM0->RXD.PTR = (uint32_t)rxd;
    NRF_TWIM0->RXD.MAXCNT = sizeof(rxd);
    NRF_TWIM0->TXD.PTR = (uint32_t)txd;
    NRF_TWIM0->TXD.MAXCNT = sizeof(txd);
    NRF_TWIM0->INTENSET = (1 << 23) | (1 << 24) | (1 << 20);
    printk("Rxd addr: %p, Txd addr: %p\r\n", rxd, txd);
    //IRQ_DIRECT_CONNECT(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn, 5, TWIM0_IRQHandler, 0);
    IRQ_CONNECT(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn, 5, TWIM0_IRQHandler, NULL, 0);
    irq_enable(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn);
    NRF_TWIM0->ENABLE = 0x06;
    NRF_TWIM0->SHORTS = (1 << 9);
    NRF_TWIM0->ADDRESS = ICM42670_ADDR0;
    txd[0] = ICM42670_PWR_MGMT0;
    txd[1] = 0x9F;
    NRF_TWIM0->TXD.MAXCNT = 2;
    NRF_TWIM0->TASKS_STARTTX = 1;

    while(true){
        printk("TEST\r\n");
        k_msleep(1000);
    }
    return 0;
}

void TWIM0_IRQHandler(){
    //printk("tESTTEST\r\n");
    if(NRF_TWIM0->EVENTS_TXSTARTED == 1){
        NRF_TWIM0->EVENTS_TXSTARTED = 0;
        //printk("EVENTS_STOPPED\r\n");
    }
    if(NRF_TWIM0->EVENTS_LASTRX == 1){
        NRF_TWIM0->EVENTS_LASTRX = 0;
        //printk("EVENTS_LASTRX\r\n");
    }
    if(NRF_TWIM0->EVENTS_LASTTX == 1){
        NRF_TWIM0->EVENTS_LASTTX = 0;
        //printk("EVENTS_LASTTX\r\n");
    }
}

prj.conf

# General Configuration
CONFIG_CPP=y
CONFIG_STD_CPP17=y
CONFIG_MAIN_STACK_SIZE=2048
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
CONFIG_HEAP_MEM_POOL_SIZE=4096

# Logging Configuration
CONFIG_CONSOLE=y
CONFIG_LOG=y
CONFIG_LOG_PROCESS_THREAD_STACK_SIZE=2048
CONFIG_LOG_BUFFER_SIZE=2048
CONFIG_LOG_DEFAULT_LEVEL=2
CONFIG_RTT_CONSOLE=y
CONFIG_USE_SEGGER_RTT=y
CONFIG_NO_OPTIMIZATIONS=y

CONFIG_I2C=n

Parents Reply Children
No Data
Related