10. Appendix A - Debugging FAQ

This Appendix’ purpose is to provide some ideas as to why something might not be working as expected or to help the audience identify where the problem might be lying. Some frequently encountered problems are covered which will hopefully assist driver developers fulfilling their task.


Question: My Firmware fails to boot. Where do I even start with debugging?

The first place to start looking at when a firmware fails to be uploaded, should always be uartboot secondary loader. Even though uartboot is automatically downloaded to the device as part of cli_programmer whenever it is invoked, keep in mind that it will only be uploaded if uartboot is not already running in the device.

  1. Start by importing project uartboot into the workspace.

  2. Compile the debug version and add the desired breakpoints(e.g in automode.c qspi_automode_init() or qspi_read_flash_jedec_id() function).

  3. Additionally compile cli_programmer anew as well.

  4. Initiate a DEBUG session and pick as target, RAM. This should trigger any autodetection phase breakpoints if any.

  5. When the execution halts at the start of main, make sure the execution is continued(not halted by any breakpoint)

  6. Try burning the target firmware to the device. Since uartboot is already in the RAM it will not be redownloaded and no RESET will be required. Any breakpoints that are bound to occur after requesting a read or write will fire properly.


Question: I am unable to write my firmware to the device but I am unsure as to which instruction fails. How can I tell ?

The short answer would be by elimination.

  1. Import projects uartboot, libprogrammer and cli_programmer to the workspace if they are not already there.

  2. Compile the debug version of uartboot and the debug static version of cli_programmer.

  3. (Optional) Start a uartboot debug session and place any desired breakpoints to the code.

  4. Navigate to folder {SDK_root)/binaries and initiate terminal with admin privileges(e.g. for windows type cmd to the explorer bar).

  5. (Optional) Type cli_programmer -help to see the options offered by cli_programmer.

  6. If a uartboot debug session is running in the background no option that involves gdbserver should be picked as the gdbserver is utilized for the debugging session. Otherwise you can use it instead of COM.

  7. Type cli_programmer COMX chip_erase_qspi to erase the entire chip, where COMX is the COM port that DA1469x is connected to. Follow the instructions printed on the console window and keep track of the status returned.

  8. Type cli_programmer COMX read_qspi 0x00000000 – 256 to read 256 bytes starting from address 0x00000000 (start of Flash). The read values should be 0xFF if the erase chip command succeeded.

  9. Type cli_programmer COMX write_qspi_bytes 0x00000000 0xDE 0xAD 0xBE 0xEF to write the sequence 0xDE 0xAD 0xBE 0xEF at 0x0000 0000 (start of Flash).

  10. Read the first 256 bytes to verify that the sequence is written.

  11. Type cli_programmer COMX erase_qspi 0x00000000 256 to erase the first sector of the Flash (basically the sectors that contain the address 0x0000 0000 and all the sectors up to the one containing the address 0x0000 0000 + 256Bytes - 1).

  12. Read the first 256 bytes again to verify that the data were erased.

Depending on which operation failed, it is possible to deduct where to put breakpoints in order to capture the failed operation.


Question: Okay, I am still unable to tell what is wrong with my driver. Any ideas?

Debugging the code can only get one so far. If after debugging the code it is still not clear where something is failing, it is always good practice to capture the signals with a logic analyzer. Perhaps something is expected to be sent in Single SPI Mode but is instead sent in Quad and vice versa or there is a timing error. Such errors are harder to catch without signal capturing as they will be executed and return result, just not the one expected.


Question: I am capturing the signals. I see commands passing through the bus but they do not have the proper programmed opcodes. What to check ?

This might be something as simple as a wrong setting in the way the logic analyzer translates the signals (e.g. using mode 3 while the command was sent in mode 0) to a timing issue.

The ROM Booter initially uses mode 3 and once the SDK sets up the QSPI Controller in automode.c file found under {SDK_root}/sdk/bsp/memory/src, in function init_hw_qspi() the mode is set to mode 0 by default.

However, certain devices do not operate as well in both modes.


Question: I wrote my instruction issuing commands in a similar fashion to the SDK but when I capture the signals I do not see them being sent through the bus. What to do ?

For starters, the status of Chip Select signal (CE#) should be checked. If it does not change status from High to Low no Clock signal will be passed to the QSPI Memory.

If it is explicitly requested of the device to change the status of CE# signal but the command is ignored one of the things to check should be under what context the command is being sent. If the device is using Auto Mode at this point then it will simply ignore any API calls that specifically request signal status changes as Auto Mode handles all of the signals automatically. Such API calls require Manual Mode.

Using functions qspi_int_activate_command_entry_mode() and qspi_int_deactivate_command_entry_mode() will cover any need but in case only Manual/Auto mode needs to configured, flash_set_automode() is the API to be called.


Question: What tests would you advise me to perform in order to have a robust driver?

For the device operation itself, a good benchmark would be burning a firmware and performing SUOTA™.

  1. Import project pxp_reporter to the workspace.

  2. Set the system clock to PLL96, set dg_configFLASH_POWER_DOWN to 1 in the corresponding custom_config_ file and compile the DA1469x-00-Debug_QSPI_SUOTA version and burn it to the device.

  3. Reset the device and verify that the pxp_reporter boots properly.

  4. Download Dialog |suota| application on your Android or IOS mobile phone.

  5. Compile a DA1469x-00-Debug_QSPI_SUOTA modified version of the pxp_reporter (e.g. different device BDAddress) and download the SUOTA™ image onto the mobile phone.

  6. Start the application and once the DA1469x is found, perform SUOTA™.

  7. Once DA1469x is finished with the update it should restart and now appear to be using the modified firmware.

  8. Since a few QSPI Flash devices occasionally have bad response to program/erase suspend and resume, it might be benefficial to leave the firmware running for a couple of hours and performing SUOTA™ again.

  9. Repeat the above steps for system clock XTAL32M.

  10. (Optional) Measure the power consumption.


Question: While testing my firmware, I noticed excessive power consumption. What can I do?

The most probable QSPI Flash Related reason is configuration directive …

#define dg_configFLASH_POWER_DOWN               ( 0 )

… which can be found in the custom_config_ files under {SDK_root}/config. It is set by default to zero which does not put the QSPI Flash in Deep Power Down mode when DA1469x goes to sleep. Make sure its value is changed to 1 to enable this feature.

A rare case had been a certain QSPI Flash device would remain in Active Read state while Performance Mode was activated in Burst Read Mode resulting in unreasonably high power consumption. In that particular case, performance mode had to be set to never be activated by setting field .send_once of the driver to false. The trade-off of this approach is the loss of speed under certain circumstances.

For more information about Power Consumption, there is a tutorial about this subject in the Tutorials section of the support portal.


Question: If I opt not to use Performance Mode in Burst Read, how will the product be affected?

This depends a lot on several factors, one of which is how optimized is the code of the firmware in regards to locality of data in cache.

When performance mode is not activated, initially the burst read instructions issued to the Flash will add a significant overhead to the execution of the code. After the first burst read command, every subsequent read will have to spend 8 system clock cycles extra to issue the burst read command again since all opcodes are sent in Single Mode.

However, after a while, unless the code is written in a fashion that totally disregards the locality of data in memory, the Cache should reach a balance point in which the most frequently used commands will be living in cache and thus be executed without causing a read request from the QSPI Flash. After that point is reached, the impact of not using performance mode should be minimal.