This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

app_error_fault_handler() called with PC at 0x128A0

Given this error handler function...

void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info)
{
	error_info_t * i = (error_info_t *)info;

	NRF_LOG_ERROR("%d, %s line %d\n", (int)i->err_code, (int)i->p_file_name, (int)i->line_num);
	NRF_LOG_ERROR("ID: %d, PC: %d\n", (int)id, (int)pc);
	
	// Omitted: more logging.
	
	NRF_LOG_FINAL_FLUSH();
	
	// Omitted: reset.
}

and this logging from it with the Segger attached...

E error 1405, KGJ`h??@h line 1024

E error ID: 1, PC: 75936

how do I debug this?

I presume the info passed in is bogus and just points to some random part of memory.

75936 is 0x128A0 and that's in the soft device.

My code is not doing anything in particular when it hits this. It tends to happen out of the blue. The nRF52832 is not in a BLE connection at the time but it is advertising. It's listening to a GPS module over SPI, running a bunch of timers, and that's about it.

Also, NRF_LOG_FINAL_FLUSH() doesn't appear to work, because I frequently see this while the Segger is attached, testing on the desk, but I never see it logged to my in-memory log in field testing.

[Edit]

Here are three log "files" to demonstrate my logging problem.

This one is a Segger RTT log taken from desk testing with the debugger attached. I get the error logging for the assert that stops execution just fine.

------
I state RESET
D state Reset reasons:
D state   wake from system off from GPIO
I pwr_mgmt Init
D power Charge state: CHARGE_STATE_NOT_CHARGING
D power Started
D acc Programming for phase 2
D acc Now programmed for state ACC_STATE_PHASE_2
D acc Resting state from last sys off: -9, 4, 62
D acc   0,  0
D acc  11,  0
D acc  28,  0
D acc  48,  0
D acc  62,  0
D acc  62,  0
D acc  62, 28
D acc  62,108
D acc  62,189
D acc  62,226
D acc  72,226
D acc 105,226
D acc 147,250
D acc 189,274
D acc 217,274
D acc 223,274
D acc 223,292
D acc 223,341
D acc 223,370
D acc 223,370
D acc 231,370
D acc 252,386
D acc Threshold crossed
D main Got device ID from retained RAM
I state STATE_RESET -> BONDED
D power Battery ADC value: 1547/4096
I power Bat: 4.06V
$AL 12
D gps Powered off
D util Bike Tracker firmware r00.01 on device 00228892
D util BUILD_FIELD_TEST
D ble_periph C7:56:60:F0:56:58 of type RANDOM_STATIC
I state BONDED -> BONDED_ADVERTISING_ON_MOTION
pm_whitelist_get() returned address: D ble_periph AC:37:43:8A:34:6C of type PUBLIC
pm_whitelist_get() returned IRK: 2000DDD0
D main Ready
D main Bonded
D gps Powered on
I state BONDED_ADVERTISING_ON_MOTION -> BONDED_AWAITING_MODEM_BEFORE_ALERT
D modem Powering on
D state Event: modem on
I state BONDED_AWAITING_MODEM_BEFORE_ALERT -> BONDED_ALERTING
pm_whitelist_get() returned address: D ble_periph AC:37:43:8A:34:6C of type PUBLIC
pm_whitelist_get() returned IRK: 2000DDB8
$AM 1
D acc Now programmed for state ACC_STATE_TRACKING
D gps Time since power on: 79ms
D gps Time since power on: 466ms
D gps Time since power on: 856ms
D gps Time since power on: 1244ms
D gps Time since power on: 1633ms
D gps Time since power on: 2023ms
D gps Time since power on: 2414ms
D gps > $PUBX,41,4,0002,0002,19200,0*24


D gps > $PUBX,40,GSA,0,0,0,0,0,0*4E


D gps > $PUBX,40,VTG,0,0,0,0,0,0*5E


D gps > $PUBX,40,RMC,0,0,0,0,0,0*47


D gps > $PUBX,40,GLL,0,0,0,0,0,0*5C


D gps > $PUBX,40,GGA,0,0,0,0,1,0*5B


D gps > $PUBX,40,GSV,0,0,0,0,1,0*58


D gps NMEA output set for no fix yet. Starting 1 Hz timer.
$SV 0
D gps Started
$AM 0
I tracking No forward motion
I tracking Alert attempt #1
D modem > AT$SB=1,1
$AM 1
D modem < OK

D modem Response time: 38614 ms
D modem < RX=80 30 36 33 32 34 36 00

D modem Response time: 29 ms
D modem Downlink message: ?063246
I tracking Alert attempt #1: SUCCESS
I state BONDED_ALERTING -> BONDED_TRACKING
$AM 0
$TM 01
$AM 1
$AM 0
$TM 02
E error 1405, KGJ`h??@h line 1024

E error ID: 1, PC: 75936

This one is taken from my in-RAM log generated during field testing, but read back once I'm back at the desk with a tiny pynrfjprog Python script that just converts a RAM region to ASCII. I'm not worried about the PANIC at the end - that's just the panic function in my log backend being called as the Nordic goes into sys off. This is an example of a "good" in-RAM log for me - I can see everything up to the last sys off or assert.

I pwr_mgmt Init
D power Charge state: CHARGE_STATE_NOT_CHARGING
D power Started
D acc Programming for phase 2
D acc Now programmed for state ACC_STATE_PHASE_2
D acc Resting state from last sys off: 18472, 19048, -25106
D acc  67,188
D acc 140,373
D acc 203,555
D acc 264,738
D acc Threshold crossed
D modem Powering on
D state Event: modem on
D modem > AT$I=10
D modem < 00228892

D modem Response time: 19 ms
D modem Powered off
I state STATE_RESET -> BONDED
D power Battery ADC value: 1491/4096
I power Bat: 3.91V
$AL 12
D gps Powered off
D util Bike Tracker firmware r00.01 on device 00228892
D util BUILD_FIELD_TEST
D ble_periph C7:56:60:F0:56:58 of type RANDOM_STATIC
I state BONDED -> BONDED_ADVERTISING_ON_MOTION
pm_whitelist_get() returned address: D ble_periph AC:37:43:8A:34:6C of type PUBLIC
pm_whitelist_get() returned IRK: 2000DDD0
D main Ready
D main Bonded
D gps Powered on
I state BONDED_ADVERTISING_ON_MOTION -> BONDED_AWAITING_MODEM_BEFORE_ALERT
D modem Powering on
D state Event: modem on
I state BONDED_AWAITING_MODEM_BEFORE_ALERT -> BONDED_ALERTING
pm_whitelist_get() returned address: D ble_periph AC:37:43:8A:34:6C of type PUBLIC
pm_whitelist_get() returned IRK: 2000DDB8
$AM 1
D acc Now programmed for state ACC_STATE_TRACKING
D gps Time since power on: 81ms
D gps Time since power on: 470ms
D gps Time since power on: 863ms
D gps Time since power on: 1251ms
D gps Time since power on: 1640ms
D gps Time since power on: 2029ms
D gps Time since power on: 2419ms
D gps > $PUBX,41,4,0002,0002,19200,0*24


D gps > $PUBX,40,GSA,0,0,0,0,0,0*4E


D gps > $PUBX,40,VTG,0,0,0,0,0,0*5E


D gps > $PUBX,40,RMC,0,0,0,0,0,0*47


D gps > $PUBX,40,GLL,0,0,0,0,0,0*5C


D gps > $PUBX,40,GGA,0,0,0,0,1,0*5B


D gps > $PUBX,40,GSV,0,0,0,0,1,0*58


D gps NMEA output set for no fix yet. Starting 1 Hz timer.
$SV 0
D gps Started
$AM 0
I tracking No forward motion
I tracking Alert attempt #1
D modem > AT$SB=1,1
$AM 1
I ble_periph Connected.
Connection from: D ble_periph AC:37:43:8A:34:6C of type PUBLIC
I ble_periph connection from address type: 0
D ble_gatt Requesting to update ATT MTU to 247 bytes on connection 0x0.
D ble_gatt Requesting to update data length to 251 on connection 0x0.
E ble_gatt sd_ble_gap_data_length_update() (request) on connection 0x0 returned unexpected value 0x13.
I state STATE_BONDED_ALERTING -> BONDED_CONNECTED
D state Field test build, tracking when connected
E modem Busy
D acc Already programmed for state ACC_STATE_TRACKING
D gps Time since power on: 18437ms
D ble_gatt ATT MTU updated to 247 bytes on connection 0x0 (response).
I ble_periph GATT ATT MTU on connection 0x0 changed to 247.
D ble_gatt Peer on connection 0x0 requested a data length of 123 bytes.
D ble_gatt Updating data length to 123 bytes on connection 0x0.
D gps > $PUBX,41,4,0002,0002,19200,0*24


D gps > $PUBX,40,GSA,0,0,0,0,0,0*4E


D gps > $PUBX,40,VTG,0,0,0,0,0,0*5E


D gps > $PUBX,40,RMC,0,0,0,0,0,0*47


D gps > $PUBX,40,GLL,0,0,0,0,0,0*5C


D gps > $PUBX,40,GGA,0,0,0,0,1,0*5B


D gps > $PUBX,40,GSV,0,0,0,0,1,0*58


D gps NMEA output set for no fix yet. Starting 1 Hz timer.
$SV 0
D gps Started
D ble_gatt Data length updated to 123 on connection 0x0.
D ble_gatt max_rx_octets: 123
D ble_gatt max_tx_octets: 123
D ble_gatt max_rx_time: 1096
D ble_gatt max_tx_time: 1096
D gps > $PUBX,40,GSV,0,0,0,0,1,0*58


D gps Lost fix. Sentence types changed.
D ble_gatt Peer on connection 0x0 requested an ATT MTU of 247 bytes.
D ble_gatt Updating ATT MTU to 247 bytes (desired: 247) on connection 0x0.
I ble_periph GATT ATT MTU on connection 0x0 changed to 247.
D bts Log CCCD write
D modem < OK

D modem Response time: 37434 ms
D modem < RX=80 32 31 30 30 35 33 00

D modem Response time: 29 ms
E modem Unhandled downlink message ID: 56
I tracking Alert attempt #1: SUCCESS
I state STATE_BONDED_CONNECTED -> BONDED_TRACKING
$AM 0
$TM 01
I ble_periph Disconnected.
pm_whitelist_get() returned address: D ble_periph AC:37:43:8A:34:6C of type PUBLIC
pm_whitelist_get() returned IRK: 2000DBD0
I state STATE_BONDED_CONNECTED -> BONDED_DISCONNECTED
D state Field test build, stopping tracking when disconnected
D modem Powered off
D gps Powered off
D state Storing new resting state
D acc Now programmed for state ACC_STATE_PHASE_2
D acc Resting state: 9, 0, 63.
D state Programming accelerometer for phase 1
D acc Now programmed for state ACC_STATE_PHASE_1
D power pwr_charger_power_on_toggle(): low: 0
D power Charge state: CHARGE_STATE_NOT_CHARGING
D power pwr_charger_charge_toggle(): low: 0
D power Charge state: CHARGE_STATE_NOT_CHARGING
I state STATE_BONDED_DISCONNECTED -> SYS_OFF
D state Good night
I pwr_mgmt Shutdown request 0
I pwr_mgmt Shutdown started. Type 0
I pwr_mgmt Shutdown complete.
PANIC

And this one is taken from my in-RAM log again, same as the second one, but this one is "bad" because there's no sys off at the end and no assert. I have some normal debug logging from my GPS driver and then a lot of memory that looks like it never got zero'ed out when the in-RAM log was initialised. I can't tell what the software died from here. I suspect an error, because the device isn't doing anything, but I can't tell what's happened.

Note that my in-RAM log is a circular buffer so it'll wrap around to the beginning, which is why this one doesn't start with the same init stuff.

D gps > $PUBX,40,GSA,0,0,0,0,0,0*4E


D gps > $PUBX,40,VTG,0,0,0,0,0,0*5E


D gps > $PUBX,40,RMC,0,0,0,0,0,0*47


D gps > $PUBX,40,GLL,0,0,0,0,0,0*5C


D gps > $PUBX,40,GGA,0,0,0,0,1,0*5B


D gps > $PUBX,40,GSV,0,0,0,0,1,0*58


D gps NMEA output set for no fix yet. Starting 1 Hz timer.
$SV 0
D gps Started
$AM 0
D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D ble_gatt Peer on connection 0x0 requested an ATT MTU of 247 bytes.
D ble_gatt Updating ATT MTU to 247 bytes (desired: 247) on connection 0x0.
I ble_periph GATT ATT MTU on connection 0x0 changed to 247.
D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D gps Dropping unwanted sentence: $GP

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D gps Dropping unwanted sentence: $GP

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D bts Log CCCD write
D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D gps Dropping unwanted sentence: $GP

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D gps Dropping unwanted sentence: $GP

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D nmea SNR ___ ___ ___ ___

D gps Dropping unwanted sentence: $GP

G 2I	h	G 0I	h	G -I	h	G +I	h	G (I	h	G &I	h	G #I	h	G !I	h	G I	h	G I	h	G I	h	G I	h	G I  G I	h	G I	h	G 
B B O0R ;KKC"BBpGpGpGO) h	G_pI	h	GHIJKpG h	h	@*

                       +
_|$++H+pGOFFF 9"
                P
                 P 	(
                         PH
                           ](@pGH +O+pGKhG 	H
IpG KGJ`@hGh	h	 
                        	i8x(JGJh,2hGKJXG X	 ////i//////////////////////////////////////////// 

DDE 	CG<
DO
  [dkdK
       	mXkkmBpG#$%&:(xR(0H
                           `pG=
                              	JGo.iIaODpGF@FIFRF[F0HGFFFFFpG	 RpLF	  p_Y )F Fp@p
                                                                                     FI	x)`U `(i(C
                                                                                                   
NP$n(FG `p p  LF! ;!
 /! +! '!C#! ! F !pGHpGJhK3`
                            H`pGpGI	( pG pGB@H!`A`pG-CFF@h@`h `x(  NMF0rHF[ )F )(%BPOP@"(F(BPO(P@GF!hF @ 0 xaxaB@
@ 02p`4
       `h
hF( 0BPB    04
hF( p1HF3(BPB @!hF 4P @  
 @DP@
G0PhFJ(  >>   >!F `( `
~HjF!) >F 
          Fb oHOp) !a _HjF@!) !! RHjFAOp) KLFF zF
                                                   -
                                                     0F (0x (@	 iF	P ;FB |F 
                                                                                F(F  |PjFOp!|
F!  @ 0  @  F B D <`>@B                                                                       |0F 
F(                      (( 0{FF
   0: 8(z(({( `-GF
F
 !{.F((3!
@F2L`B4 !HC0,`HF  s'A
!ii@"
0 `BGA
@F2-GF

      7
        
        O
>g
  L1*	U%! VpCFqi 
HF
4m
  L2*	HFkCFqi!y`bb	bB	bE	b!q	`q "F
4my
  5#
    *Up2qicb-OF

FF*`zp

      'O
(s(08FUjsss!FHFy {((70 

 {F(71 ( {F(72  {F(73  {F(4 (/
 {F(5 (/@F
 {F(( 06 (/x {F(77 *OO8(x

(
 (	
 {      (
  ( 
(  {( 8smkp
           FFv x" pCp!(F  p p-G'FFF0
@ (PF(S{%h	((E%HhI{BqCB8:F4
                                 -(+!0

F)FP:F0@F
(

 & $   C 
         #Fp*FPF5WA{@hqC
                        -OFFFFI^@F'2F&)F;FI #FPJFQF@F    F#0R
 x 	
F!6)Fp@ #jF!F( p
FF&F(x({zTT<5V22222	22222(y((5!@F{((
                                        ((&W(y( P(y@(((y(!9!@F@F	,*F!F@F\+!@F&$!@FiF	)"
,J`$ -G0F@  DpGP$O
       F
       

[Edit]

Here's my error handling code.

/* Copyright (C) Bike Tracker Ltd - All Rights Reserved
 * Unauthorized copying of this file, via any medium is strictly prohibited.
 * Proprietary and confidential.
 * Written by Eliot Stock, [email protected]
 */
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>

#include "app_error.h"
#include "ble_err.h"
#include "nrf_delay.h"
#include "nrf_nvic.h"
#include "nrf_soc.h"

#include "boards.h"
#include "util.h"
#include "error.h"

#define NRF_LOG_MODULE_NAME error
#include "nrf_log.h"
NRF_LOG_MODULE_REGISTER();
#include "nrf_log_ctrl.h"

#define ERROR_SD_SCHEDULER_BLOCKED (209)

// We have three types of errors we need to handle in our application:
//   1. Asserts. These are when a call to an SDK or application function returns something other than NRF_SUCCESS (0) and we catch that using APP_ERROR_CHECK().
//   2. Soft device faults. These are probably caused by us misusing the soft device and indicate a bug in our application code. These come through here as well.
//   3. Hardfaults. If these are caused by our code, eg. dividing by zero, we should be able to fix them. But they may also be caused by electromagnetic interference near the device or glitches on power lines. We must handle them in production. We use the SDK's implementation of the hardfault handler, which simply resets on a hardfault. See <SDK>/components/libraries/hardfault/nrf52/handler/hardfault_handler_gcc.c

// Reset, but set the general purpose retention register first. Don't do any logging or debug LED operations in this function, since we need this to work even when those functions are broken. Don't do any APP_ERROR_CHECK()s either.
void app_reset(void)
{
	// We should only have to do this once, but just in case, sit in a loop calling it repeatedly.
	while (true)
	{
		// Note that if the error being handled is a soft device fault, we may not be able to call any more sd_* functions and sd_power_gpregret_set() will just block. Therefore, don't use the general purpose retention register to remember the reason for the reset. Instead, just log the reset reason early in main().

		// Strictly speaking we should be calling sd_nvic_SystemReset() here if the soft device is enabled, but if the error being handled is a soft device fault, that may not work. All that does is call NVIC_SystemReset() anyway, so just go straight there.
		NVIC_SystemReset();

		__WFE();
	}
}

// See <SDK>/components/libraries/util/app_error.c. The implementations of app_error_handler() and app_error_handler_bare() there will call this function when DEBUG is defined. softdevice_fault_handler() in softdevice_handler.c also calls this on soft device faults.
void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info)
{
	error_info_t * i = (error_info_t *)info;

	// Regardless of which build we're in, log the error.
	NRF_LOG_ERROR("%d, %s line %d\n", (int)i->err_code, (int)i->p_file_name, (int)i->line_num);
	NRF_LOG_ERROR("ID: %d, PC: %d\n", (int)id, (int)pc);

	// Note: If we ever see an SD fault here again, get the stack trace, clear steps to repro, and reopen this case with Nordic: https://www.nordicsemi.com/eng/supportcase/view/36380

	// Copied in from:
	//   error.h
	//   <SDK>/components/softdevice/s130/headers/nrf_error.h
	//   <SDK>/components/softdevice/s130/headers/ble_error.h
	//   <SDK>/components/libraries/util/sdk_errors.h
	//   error.h
	// Update this list on each SDK release.
	switch (i->err_code)
	{
		case NRF_ERROR_SVC_HANDLER_MISSING:
			NRF_LOG_ERROR("NRF_ERROR_SVC_HANDLER_MISSING");
			break;
		case NRF_ERROR_SOFTDEVICE_NOT_ENABLED:
			NRF_LOG_ERROR("NRF_ERROR_SOFTDEVICE_NOT_ENABLED");
			break;
		case NRF_ERROR_INTERNAL:
			NRF_LOG_ERROR("NRF_ERROR_INTERNAL");
			break;
		case NRF_ERROR_NO_MEM:
			NRF_LOG_ERROR("NRF_ERROR_NO_MEM");
			break;
		case NRF_ERROR_NOT_FOUND:
			NRF_LOG_ERROR("NRF_ERROR_NOT_FOUND");
			break;
		case NRF_ERROR_NOT_SUPPORTED:
			NRF_LOG_ERROR("NRF_ERROR_NOT_SUPPORTED");
			break;
		case NRF_ERROR_INVALID_PARAM:
			NRF_LOG_ERROR("NRF_ERROR_INVALID_PARAM");
			break;
		case NRF_ERROR_INVALID_STATE:
			NRF_LOG_ERROR("NRF_ERROR_INVALID_STATE");
			break;
		case NRF_ERROR_INVALID_LENGTH:
			NRF_LOG_ERROR("NRF_ERROR_INVALID_LENGTH");
			break;
		case NRF_ERROR_INVALID_FLAGS:
			NRF_LOG_ERROR("NRF_ERROR_INVALID_FLAGS");
			break;
		case NRF_ERROR_INVALID_DATA:
			NRF_LOG_ERROR("NRF_ERROR_INVALID_DATA");
			break;
		case NRF_ERROR_DATA_SIZE:
			NRF_LOG_ERROR("NRF_ERROR_DATA_SIZE");
			break;
		case NRF_ERROR_TIMEOUT:
			NRF_LOG_ERROR("NRF_ERROR_TIMEOUT");
			break;
		case NRF_ERROR_NULL:
			NRF_LOG_ERROR("NRF_ERROR_NULL");
			break;
		case NRF_ERROR_FORBIDDEN:
			NRF_LOG_ERROR("NRF_ERROR_FORBIDDEN");
			break;
		case NRF_ERROR_INVALID_ADDR:
			NRF_LOG_ERROR("NRF_ERROR_INVALID_ADDR");
			break;
		case NRF_ERROR_BUSY:
			NRF_LOG_ERROR("NRF_ERROR_BUSY");
			break;
		case NRF_ERROR_CONN_COUNT:
			NRF_LOG_ERROR("NRF_ERROR_CONN_COUNT");
			break;
		case NRF_ERROR_RESOURCES:
			NRF_LOG_ERROR("NRF_ERROR_RESOURCES");
			break;
		case BLE_ERROR_NOT_ENABLED:
			NRF_LOG_ERROR("BLE_ERROR_NOT_ENABLED");
			break;
		case BLE_ERROR_INVALID_CONN_HANDLE:
			NRF_LOG_ERROR("BLE_ERROR_INVALID_CONN_HANDLE");
			break;
		case BLE_ERROR_INVALID_ATTR_HANDLE:
			NRF_LOG_ERROR("BLE_ERROR_INVALID_ATTR_HANDLE");
			break;
		// Missing from SD 132 v4:
		// case BLE_ERROR_NO_TX_PACKETS:
		// 	NRF_LOG_ERROR("BLE_ERROR_NO_TX_PACKETS");
		// 	break;
		case BLE_ERROR_INVALID_ROLE:
			NRF_LOG_ERROR("BLE_ERROR_INVALID_ROLE");
			break;
		case NRF_ERROR_MODULE_NOT_INITIALZED:
			NRF_LOG_ERROR("NRF_ERROR_MODULE_NOT_INITIALZED");
			break;
		case NRF_ERROR_MUTEX_INIT_FAILED:
			NRF_LOG_ERROR("NRF_ERROR_MUTEX_INIT_FAILED");
			break;
		case NRF_ERROR_MUTEX_LOCK_FAILED:
			NRF_LOG_ERROR("NRF_ERROR_MUTEX_LOCK_FAILED");
			break;
		case NRF_ERROR_MUTEX_UNLOCK_FAILED:
			NRF_LOG_ERROR("NRF_ERROR_MUTEX_UNLOCK_FAILED");
			break;
		case NRF_ERROR_MUTEX_COND_INIT_FAILED:
			NRF_LOG_ERROR("NRF_ERROR_MUTEX_COND_INIT_FAILED");
			break;
		case NRF_ERROR_MODULE_ALREADY_INITIALIZED:
			NRF_LOG_ERROR("NRF_ERROR_MODULE_ALREADY_INITIALIZED");
			break;
		case NRF_ERROR_API_NOT_IMPLEMENTED:
			NRF_LOG_ERROR("NRF_ERROR_API_NOT_IMPLEMENTED");
			break;
		case NRF_ERROR_FEATURE_NOT_ENABLED:
			NRF_LOG_ERROR("NRF_ERROR_FEATURE_NOT_ENABLED");
			break;
		case NRF_ERROR_DRV_TWI_ERR_OVERRUN:
			NRF_LOG_ERROR("NRF_ERROR_DRV_TWI_ERR_OVERRUN");
			break;
		case NRF_ERROR_DRV_TWI_ERR_ANACK:
			NRF_LOG_ERROR("NRF_ERROR_DRV_TWI_ERR_ANACK");
			break;
		case NRF_ERROR_DRV_TWI_ERR_DNACK:
			NRF_LOG_ERROR("NRF_ERROR_DRV_TWI_ERR_DNACK");
			break;
		// Bike Tracker application errors.
		case BIKE_TRACKER_ACC_ERROR_INVALID_STATE:
			NRF_LOG_ERROR("BIKE_TRACKER_ACC_ERROR_INVALID_STATE");
			break;
		case BIKE_TRACKER_ACC_ERROR_NO_COMMS:
			NRF_LOG_ERROR("BIKE_TRACKER_ACC_ERROR_NO_COMMS");
			break;
		case BIKE_TRACKER_MODEM_ERROR_NO_DEVICE_ID:
			NRF_LOG_ERROR("BIKE_TRACKER_MODEM_ERROR_NO_DEVICE_ID");
			break;
		case BIKE_TRACKER_MODEM_ERROR_INVALID_STATE:
			NRF_LOG_ERROR("BIKE_TRACKER_MODEM_ERROR_INVALID_STATE");
			break;
		case BIKE_TRACKER_MODEM_IDENTITY_CRISIS:
			NRF_LOG_ERROR("BIKE_TRACKER_MODEM_IDENTITY_CRISIS");
			break;
		case BIKE_TRACKER_GPS_ERROR_INVALID_STATE:
			NRF_LOG_ERROR("BIKE_TRACKER_GPS_ERROR_INVALID_STATE");
			break;
		case BIKE_TRACKER_GPS_TIMEOUT:
			NRF_LOG_ERROR("BIKE_TRACKER_GPS_TIMEOUT");
			break;
		case BIKE_TRACKER_UNHANDLED_STATE_CHANGE:
			NRF_LOG_ERROR("BIKE_TRACKER_UNHANDLED_STATE_CHANGE");
			break;
		case ERROR_SD_SCHEDULER_BLOCKED:
			// See Nordic case: https://www.nordicsemi.com/eng/supportcase/view/36380
			NRF_LOG_ERROR("Soft device scheduler blocked");
			break;
	}

	// Flush the log before we reset. This won't help getting the above log messages out over BLE when we're running a field test build, but it might help getting them out to the console when we're running a desk test build.
	NRF_LOG_FINAL_FLUSH();

#ifdef BUILD_PROD
	// Reset immediately on all errors. This function doesn't return.
	app_reset();
#endif

#ifdef BUILD_FIELD_TEST
	// Reset immediately on all errors. This function doesn't return.
	app_reset();
#endif

#ifdef BUILD_DESK_TEST
	// Ideally, break here in gdb. Use a BUILD_DESK_TEST build when running "make test".

	if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk)
	{
		// Generate breakpoint if debugger is connected
		NRF_BREAKPOINT;
	}

	// In case the above breakpoint isn't reached, wait here.
	while (true) {};
#endif
}

The build I'm testing with is a BUILD_FIELD_TEST.

Parents
  • Hi,

    That is pretty strange. If you give me the version number of your Softdevice I can take a look under the hood and see what goes on at that specific address. 

    How frequently does it occur?

    And what SDK are you using?

  • Thanks.

    NORDIC_SDK_ROOT := $(HOME)/dev/nRF5_SDK_14.0.0_3bcc1f7
    
    SOFTDEVICE = $(NORDIC_SDK_ROOT)/components/softdevice/s132/hex/s132_nrf52_5.0.0_softdevice.hex
    

    I've seen it about four times in the last month, but I can't reliably repro it. Happy to send the hex file if it helps.

  • Hi,

    Thanks. I found the source of the assert. The Softdevice includes what we call a Radio Event Manager (REM), and an assert at 0x128A0 is the REM warning you that a radio event has overstayed its planned duration. This is more likely to happen in complex applications where you have multiple concurrent BLE links, have multiple radio protocols running concurrently, or are using the Timeslot API to allocate time slots to time sensitive peripheral operations. You say that you are not in a connection and just advertising, but do you use the timeslot API? Any other time sensitive things going on at the time?

    Another possibility is that your clock is not accurate enough. If you are not doing anything timecritical as discussed above this possibility might be more likely. It could e.g. be that your crystal is incorrectly loaded. Are you using a custom device or a development kit?

     

  • In that case I may be wrong about not being in a connection. I'm only ever in one connection at a time but I do a lot of logging stuff over a characteristic a bit like the Nordic UART service's RX characteristic (notify only). I don't know if that would have the radio busy enough to hit this, but I guess it's possible. I don't use the timeslot API.

    I'm using a module from Wisol so I haven't chosen the crystal myself. I could ask them what they used.

    It would help if I could get reliable logging in my app_error_fault_handler() function. At the moment I really only know this is happening on the desk because the debugger breaks in the error handler. In the field, I'd expect to see the same error logging in my in-memory log as I do in the gdb client, but instead the log just stops. My in-memory log is in retained RAM, so it survives a reset.

Reply
  • In that case I may be wrong about not being in a connection. I'm only ever in one connection at a time but I do a lot of logging stuff over a characteristic a bit like the Nordic UART service's RX characteristic (notify only). I don't know if that would have the radio busy enough to hit this, but I guess it's possible. I don't use the timeslot API.

    I'm using a module from Wisol so I haven't chosen the crystal myself. I could ask them what they used.

    It would help if I could get reliable logging in my app_error_fault_handler() function. At the moment I really only know this is happening on the desk because the debugger breaks in the error handler. In the field, I'd expect to see the same error logging in my in-memory log as I do in the gdb client, but instead the log just stops. My in-memory log is in retained RAM, so it survives a reset.

Children
Related