nrf52zephyr-rtosnrf52840nrf-connect

nRF SDK: BLE GATT server and interrupts at the same time not working


I am trying to use nRF52DK as BLE GATT server and at the same time use interrupts to keep track of the current time in the device. Both work if only either ble or interrupts are enabled but at the same time I got fault at interrupt handling (see logs below).

I'm using nRF Connect SDK 2.4.1 and nrfx_rtc.h and bluetooth/gatt_dm.h libraries.

Does my timer interrupts cause conflicts with the ble library?

Code (GitHub):

/**
 * @file main.c
 * @brief Ajoittaja main
 * @author Kasperi Kiviluoma
 * @license MIT
 */

#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>

#include "bluetooth.h"
#include "timer.h"

LOG_MODULE_REGISTER(Ajoittaja, LOG_LEVEL_DBG);

Time now = {thursday, 21, 59, 50};

Schedule mon[] = {{7, 0, 0, 3600}, {20, 0, 0, 7200}};
Schedule tue[] = {{7, 0, 0, 3600}, {20, 0, 0, 7200}};
Schedule wed[] = {{7, 0, 0, 3600}, {20, 0, 0, 7200}};
Schedule thu[] = {{7, 0, 0, 3600}, {20, 0, 0, 7200}};
Schedule fri[] = {{7, 0, 0, 3600}, {20, 0, 0, 7200}};
Schedule sat[] = {{20, 0, 0, 7200}};
Schedule sun[] = {{20, 0, 0, 7200}};
Schedule *schedules[] = {mon, tue, wed, thu, fri, sat, sun};

int main(void) {
    int err;

    printk("Starting GATT Discovery Manager example\n");

    err = bluetooth_init();

    printk("Advertising successfully started\n");

    // Init GPIO
    if (gpio_init() != 0) {
        LOG_ERR("GPIO init failed");
        return -1;
    }

    // Init RTC0, 125ms counter period
    if (rtc_init(4095, time_rtc, time_handler, true) != NRFX_SUCCESS) {
        LOG_ERR("RTC0 init failed");
        return -1;
    }

    // Init RTC2
    if (rtc_init(4095, schedule_rtc, schedule_handler, false) != NRFX_SUCCESS) {
        LOG_ERR("RTC2 init failed");
        return -1;
    }

    // Init IRQs
    manual_isr_setup();

    // TODO: Low power sleep
    while (true) {
        k_sleep(K_MSEC(10));
    }

    return 0;   // Should never reach this
}

Log:

[00:00:02.520,111] <inf> bt_sdc_hci_driver: hci_driver_open: SoftDevice Controller build revision: 
                                            e0 7e 2e c1 5e 05 85 23  46 15 dc fa 8e 29 7d 70 |.~..^..# F....)}p
                                            10 93 a5 fc                                      |....             
[00:00:02.523,864] <inf> bt_hci_core: hci_vs_init: HW Platform: Nordic Semiconductor (0x0002)
[00:00:02.523,895] <inf> bt_hci_core: hci_vs_init: HW Variant: nRF52x (0x0002)
[00:00:02.523,925] <inf> bt_hci_core: hci_vs_init: Firmware: Standard Bluetooth controller (0x00) Version 224.11902 Build 2231721665
[00:00:02.525,390] <inf> bt_hci_core: bt_dev_show_info: Identity: EB:B6:AB:2B:10:65 (random)
[00:00:02.525,451] <inf> bt_hci_core: bt_dev_show_info: HCI: version 5.4 (0x0d) revision 0x1077, manufacturer 0x0059
[00:00:02.525,482] <inf> bt_hci_core: bt_dev_show_info: LMP: version 5.4 (0x0d) subver 0x1077
[00:00:03.458,618] <err> mpsl_init: m_assert_handler: MPSL ASSERT: 112, 2134
[00:00:03.458,648] <err> os: hard_fault: ***** HARD FAULT *****
[00:00:03.458,648] <err> os: hard_fault:   Fault escalation (see below)
[00:00:03.458,679] <err> os: hard_fault: ARCH_EXCEPT with reason 3

[00:00:03.458,709] <err> os: esf_dump: r0/a1:  0x00000003  r1/a2:  0x00000000  r2/a3:  0x00000009
[00:00:03.458,709] <err> os: esf_dump: r3/a4:  0x20001648 r12/ip:  0x20000ea0 r14/lr:  0x000138a5
[00:00:03.458,740] <err> os: esf_dump:  xpsr:  0x41000018
[00:00:03.458,770] <err> os: esf_dump: Faulting instruction address (r15/pc): 0x00020f04
[00:00:03.458,801] <err> os: z_fatal_error: >>> ZEPHYR FATAL ERROR 3: Kernel oops on CPU 0
[00:00:03.458,831] <err> os: z_fatal_error: Fault during interrupt handling

[00:00:03.458,862] <err> os: z_fatal_error: Current thread: 0x20002968 (unknown)
�00:00:09.921,539] <err> fatal_error: k_sys_fatal_error_handler: Resetting system

Solution

  • From MPSL docs:

    MPSL enables interrupts for RTC0, TIMER0, TIMER1 (only on nRF53 Series), POWER_CLOCK, and low_prio_irq. The application must enable and configure all the other interrupts.

    So you can not use those from your application. You can use other interrupts though.

    However, if your goal is to count time, see Zephyr Uptime docs:

    The kernel tracks a system uptime count on behalf of the application. This is available at all times via k_uptime_get(), which provides an uptime value in milliseconds since system boot. This is expected to be the utility used by most portable application code.

    The internal tracking, however, is as a 64 bit integer count of ticks. Apps with precise timing requirements (that are willing to do their own conversions to portable real time units) may access this with k_uptime_ticks().