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
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().