5. Debugging using Ozone
5.1. Introduction
This section will introduce Ozone, the J-Link debugger, and demonstrate how to use it within a DA1453x,DA1458x project. Ozone debugger is a full-featured graphical debugger for embedded applications. Using the Ozone Debugger it is possible to debug any embedded application on C source and assembly level. The Ozone Debugger can load applications built with any toolchain / IDE or debug the target’s resident application without any source. The Ozone Debugger includes all needed debug information windows and makes use of the best performance of J-Link debug probes
In order to download the Latest Release Version of The Ozone debugger, please visit the following ozone-j-link-debugger page.
5.2. Initial Project
We will use one of the sample projects contained within the SDK, empty_peripheral_template
, as the starting point. We will open this project and make a few modification.
Navigate to the location to which SDK6 has been downloaded and extracted, Open the folder .../projects/target_apps/template/empty_peripheral_template/Keil_5
Double click on the file empty_peripheral_template.uvprojx
Keil µVision should open the project at this point
At this time we will make a few quick modifications:
Add the advertising complete callback, when the timer expires, user_app_on_adv_undirect_complete()
is executed to terminate advertising and and as soon as the advertising is stopped it will stuck in the while (1) loop for few seconds (2.5 s) before the watchdog timer expires.
user_empty_peripheral_template.c
void user_on_connection(uint8_t connection_idx, struct gapc_connection_req_ind const *param)
{
default_app_on_connection(connection_idx, param);
}
void user_on_disconnect( struct gapc_disconnect_ind const *param )
{
default_app_on_disconnect(param);
}
void user_app_on_adv_undirect_complete(uint8_t status)
{
while(1);
}
user_empty_peripheral_template.h
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
void user_on_connection(uint8_t connection_idx, struct gapc_connection_req_ind const *param);
void user_on_disconnect( struct gapc_disconnect_ind const *param );
void user_app_on_adv_undirect_complete(uint8_t status);
user_callback_config.h
static const struct app_callbacks user_app_callbacks = {
.app_on_connection = user_on_connection,
.app_on_disconnect = user_on_disconnect,
.app_on_update_params_rejected = NULL,
.app_on_update_params_complete = NULL,
.app_on_set_dev_config_complete = default_app_on_set_dev_config_complete,
.app_on_adv_nonconn_complete = NULL,
.app_on_adv_undirect_complete = user_app_on_adv_undirect_complete,
.app_on_adv_direct_complete = NULL,
.app_on_db_init_complete = default_app_on_db_init_complete,
.app_on_scanning_completed = NULL,
.app_on_adv_report_ind = NULL,
.app_on_get_dev_name = default_app_on_get_dev_name,
.app_on_get_dev_appearance = default_app_on_get_dev_appearance,
.app_on_get_dev_slv_pref_params = default_app_on_get_dev_slv_pref_params,
.app_on_set_dev_info = default_app_on_set_dev_info,
.app_on_data_length_change = NULL,
.app_on_update_params_request = default_app_update_params_request,
.app_on_generate_static_random_addr = default_app_generate_static_random_addr,
.app_on_svc_changed_cfg_ind = NULL,
.app_on_get_peer_features = NULL,
The Advertisement time period is determined by the value set on .advertise_period = MS_TO_TIMERUNITS(18000)
Open the file user_config.h which is in the user_config
folder.
Change the default handlers configuration to advertise the device with a timeout, by configuring .adv_scenario to DEF_ADV_WITH_TIMEOUT
and changing the timeout value to 18000 for example, .advertise_period = MS_TO_TIMERUNITS(18000)
, as shown below:
static const struct default_handlers_configuration user_default_hnd_conf = {
// Configure the advertise operation used by the default handlers
// Possible values:
// - DEF_ADV_FOREVER
// - DEF_ADV_WITH_TIMEOUT
.adv_scenario = DEF_ADV_WITH_TIMEOUT,
// Configure the advertise period in case of DEF_ADV_WITH_TIMEOUT.
// It is measured in timer units (3 min). Use MS_TO_TIMERUNITS macro to convert
// from milliseconds (ms) to timer units.
.advertise_period = MS_TO_TIMERUNITS(18000),
// Configure the security start operation of the default handlers
// if the security is enabled (CFG_APP_SECURITY)
// Possible values:
// - DEF_SEC_REQ_NEVER
// - DEF_SEC_REQ_ON_CONNECT
.security_request_scenario = DEF_SEC_REQ_NEVER
};
5.2.1. Expected result after code modifications
The device start advertising and at some points it crashes. Next section will describes how to get to the root cause of this crashes with ozone debugger.
Sleep mode
The sleep mode was enabled in this project. In the
user_config.h
file the app_default_sleep_mode variable is set to ARCH_EXT_SLEEP_ONThe Power profile tool from the SmartSnippets™ Toolbox was used for data capturing. For more details you can refer to Power Profiler section in the UM-B-083.
/******************************************
* Default sleep mode. Possible values are:
*
* - ARCH_SLEEP_OFF
* - ARCH_EXT_SLEEP_ON
* - ARCH_EXT_SLEEP_OTP_COPY_ON
*
******************************************
*/
static const sleep_state_t app_default_sleep_mode = ARCH_EXT_SLEEP_ON;
5.3. Using the Ozone Debugger
Running the Ozone Debugger for the first time, there is a default user interface layout and the project wizard pops up. It will continue to do so, as soon as the first projected was created or opened.
5.3.1. Project Wizard
This is a graphical facility to specify the required settings needed to start a debug session.
Device User is asked to select the MCU to be debugged on. A complete list of MCU’s grouped by vendors is available under the browse button.
Peripheral File The user may optionally specify a peripheral register set description file that describes the memory-mapped register set of the selected MCU. If a valid description file is specified, peripheral registers will be observable and editable via the debugger’s Register Window.
Target Interface It specifies how the J-Link debug probe is connected to the MCU. The Ozone Debugger supports JTAG and SWD target interfaces. This must be compatible and in line with the Eclipse, Debug Configuration Settings.
Data File
This field allows the user to specify the program that wants to debug. The file has to contain symbol information, and only ELF or compatible program files getting accepted. A program file with no symbol information causes a limited functionality of the Ozone Debugger. in this case we will debug the .axf file. The .axf file is an object file format generated by ARM’s RealView compiler (also part of Keil’s ARM-MDK) and contains both object code and debug information. In the debugger, while just the object code is loaded on the target itself, both the code and the debug information are loaded in the development host’s memory.
Once you click on “Finish” you will have all the source code.
5.3.2. Running the Debugger
To attach the debugger to the application program click to Attach and Halt Program
Then it will shows you that it stucks to the NMI_HANDLER.
In order to check where exactly the issue happens you need to copy the STATUS_BASE
address from nmi_handler.c
file in the memory map in ozone.
Then you can check the PC (Program counter) address which is located in the 7th 32 word address.
From the Disassembly Window click to “Go To” then copy the PC address
Then when you click OK. It will go exactly to where the issue is happening.