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

Hard fault SD132 with timers and ble rwauth

Hi,

i'm testing an application on nRF52, with nRF5_SDK_11.0.0-2.alpha and SoftDevice 132.

I took the ble_uart example and added a custom service with some characteristics with various permissions. Everything seems to work well, i then decided to add a timer for system tick tracking and i'm stuck in a hard fault i get when performing SD calls.

In main.c i defined a timer for system tick management

APP_TIMER_DEF(system_timer);
volatile uint32_t systemTick;
...
int main(int)
{ 
    ...
    services_init();
    ... 
    err_code = app_timer_create(&system_timer, APP_TIMER_MODE_REPEATED , systemtimer_timeout_callback);
    err_code = app_timer_start(system_timer, APP_TIMER_TICKS(1, 0), NULL);
    ...
    for(;;){
    }
}

void systemtimer_timeout_callback(void *p_context)
{
	systemTick++;
	return;
}

What happens it that, if i perform authorized read on my characteristic, the system crashes without recovering. For example if i do authorized read from nRF Master tool, the system enters BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST, but when i perform sd_ble_gatts_rw_authorize_reply, it doesn't exit from the function. If i debug and pause after that i can see

HardFault_Handler() at 0x24022
<signal handler called>() at 0xfffffff1	
on_rwauth() at ble_myservice.c:575 0x21444	
ble_myservice_on_ble_evt() at ble_myservice.c:672 0x21614
...

on the call stack.

If i comment timer section, everything works. Do you have any idea what could be the issue?

Thank you

EDIT 1:

This is a snippet of the function on_rwauth() i call inside BLE_GATT_RW_AUTHORIZE_REQUEST:

static void on_rwauth(ble_gate_t * p_gate, ble_evt_t * p_ble_evt){
	uint8_t result;
	uint8_t ledstate;
	uint32_t err_code;
	ble_gatts_rw_authorize_reply_params_t    reply_params;
	if (p_ble_evt->evt.gatts_evt.params.authorize_request.type == BLE_GATTS_AUTHORIZE_TYPE_READ){
		//Authorized Read
		if(p_ble_evt->evt.gatts_evt.params.authorize_request.request.read.handle == p_myservice->state_handle.value_handle){
			SEGGER_RTT_WriteString(0, "READ AUTH IN\r\n");
			//retrieve global state of myservice
			result = p_myservice->mysrv_globalstate_handler(p_myservice);
			if(result == INIT_STATE){
				strncpy((char *)user_data, "HELLO", sizeof(user_data) -1);
			}
			else{
				//return state of LED
				ledstate = mysrv_ledstate_handler(p_myservice);
				if(ledstate == LED_ON){
					strncpy((char *)user_data, "ON", sizeof(user_data) -1);
				}
				else if(ledstate == LED_OFF){
					strncpy((char *)user_data, "OFF", sizeof(user_data) -1);
				}
			}

			memset(&reply_params, 0, sizeof(reply_params));

			reply_params.type                       = BLE_GATTS_AUTHORIZE_TYPE_READ;
			reply_params.params.read.p_data 		= (uint8_t *)&user_data[0];
			reply_params.params.read.len        	= strlen((char *)user_data);
			reply_params.params.read.offset 		= 0;
			reply_params.params.read.update 		= 1;

			SEGGER_RTT_WriteString(0, "ENTER SD_BLE_GATTS:....\r\n");
			
			err_code = sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gattc_evt.conn_handle, &reply_params);
			APP_ERROR_CHECK(err_code);
			
			SEGGER_RTT_WriteString(0, "READ AUTH OUT\r\n");
		}
	}
  • Not sure to be honest, but have you made sure you don't enter the block at all? Also can you verify if you are hitting the app_error_fault_handler() function, which will be called if APP_ERROR_CHECK() fails?

  • Yes i'm sure and app_error_fault_handler is not hit. Here is something more, this behaviour is seen in Eclipse GCC. I tried to compile with Keils 5 and i don't see HardFault anymore. One thing i noted in GCC is that sd debug info says:

    RAM START ADDR 0x20001F00 should be adjusted to 0x20001E00
    RAM SIZE should be adjusted to 0xE200 
    sd_ble_enable: RAM START at 0x20001F00
    sd_ble_enable: app_ram_base should be adjusted to 0x20001E10
    ram size should be adjusted to 0xE1F0 
    

    I read that this shouldn't bother anyway.

  • Yeah that's not a problem, it just means you're wasting some RAM between the SD and the app areas.

    I assume you have a breakpoint in HardFault_Handler in arm_startup_nrf2.s. Can you check the value of the R0 register when that breakpoint hits?

  • In gcc makefile i can see that ASM_SOURCE_FILE included is gcc_startup_nrf52.s not arm_startup_nrf52.s. Is it correct? I did open gcc_startup_nrf52.s anyway in Eclipse and set a breakpoint at line after HardFault_Handler: line (394) but it doesn't hit. But if i pause i can see the last call in the stack is

    HardFault_Handler() at 0x2431a	
    

    The R0 here is 0x21744, which is the line inside on_rwauth() function just before rw_auth_reply()

  • Could you add a screen dump of the disassemble view at 0x21744 together with the core registers when the exception has occurred?

    To be able to set breakpoints in the startup file you need to do the following:

    • change the file extension from .s to capital .S in /components/toolchain/gcc
    • Add the -g3 option to the assembler flags.

    As a side note, have experienced problems with debugging after updating to the 5.0 release of arm-none-eabi. I'd suggest to downgrade to 4.9 if you are using this one.

Related