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

SDK 15.3 Secure Serial UART Bootloader does not handle NRF_DFU_OP_OBJECT_WRITE (data)

Hi,

I am currently trying to use SDK 15.3 secure serial UART bootloader (from the example in nRF5_SDK_15.3.0_59ac345\examples\dfu\secure_bootloader\pca10040_uart) on a custom chip embedding an nRF52832 and a GSM chip, communicating between themselves via UART. In order to adapt the given example to my particular case, I just added in nrf_dfu_init() function the power-on of the GSM chip. I also modified UART configuration (pinout, HWFC activated, baudrate = 57600).

After calling this function, the bootloader then loops forever (loop_forever() function), and waits for commands, via UART, from the GSM chip. The GSM chip basically connects to server, downloads new firmware, checks if a firmware upgrade is needed, and "if true" starts to transfer said firmware to nRF52832.

Here is the detailed communication between GSM and nRF52832, from the GSM chip point of view:

<--Sent CMD: 02, len: 4-->
Received 0x02 0x01

<--Sent CMD: 07, len: 2-->
Received 0x07 0x01

<--Sent CMD: 06, len: 3-->
Received 0x06 0x01

<--Sent CMD: 01, len: 7-->
Received 0x01 0x01

<--Sent CMD: 08, len: 130--> (command)
<--Sent CMD: 08, len: 16-->  (command)
<--Sent CMD: 03, len: 2-->
Received 0x03 0x01
<-- Received CALC CRC message response -->
<-- Received CRC: 912423956 (36627C14), local CRC: 912423956(36627C14) -->
<-- Received offset: 141, local offset: 141 -->

<--Sent CMD: 04, len: 2-->
Received 0x04 0x01

<--Sent CMD: 06, len: 3-->
Received 0x06 0x01

<--Sent CMD: 01, len: 7-->
Received 0x01 0x01

<--Sent CMD: 08, len: 129-->	(data)
<-- Sent 127 bytes, local CRC: -1046533821(C19F2943) -->
<--Sent CMD: 08, len: 129-->	(data)
<-- Sent 254 bytes, local CRC: -340869425(EBAEBECF) -->
<--Sent CMD: 08, len: 129-->	(data)
<-- Sent 381 bytes, local CRC: -793576822(D0B2FA8A) -->
<--Sent CMD: 08, len: 129-->	(data)
<-- Sent 508 bytes, local CRC: 143380219(088BCEFB) -->

...


<--Sent CMD: 08, len: 34-->	(data)
<-- Sent 4096 bytes, local CRC: 1943765718(73DB82D6) -->

<--Sent CMD: 03, len: 2-->

This command sequence is right and was working perfectly fine with a secure serial UART bootloader I used with SDK 12.1. The problem here is that after having received and handled successfully the 2 first chunks of data (lines 30 and 32), so 254 bytes, the nRF52832 seems to stop receiving the data, or at least handling it: it does not go into the case NRF_DFU_OP_OBJECT_WRITE from the nrf_dfu_serial_on_packet_received() function anymore. As so of course it doesn't reply to the CRC command (0x03, line 45) sent by the GSM chip, which is waiting for a CRC answer before proceeding with sending next data packet.

Now I am having trouble understanding the source of this issue. I thought at first that it could be a full buffer issue, but it is supposed to be freed asynchronously. I then thought the GSM chip was sending chunks of data too quickly for the nRF52832 to handle, but even after adding a 500ms delay between each chunks (originally 100ms), the issue is still there.

Also, for some reason the logs are not working properly, which does not help debugging... Some of them seems to be missing on the viewer, and they appear very slowly, like they are flushed 30 seconds after being called (and again, not all of them...). So for now my only way of debugging, which is also how I know of this issue, is a buzzer embedded on the board.

Thank you in advance for any help !

Parents
  • Hi,

    Hung asked me to follow up on this case as he's out of office this week. There has been a while since the last update, have you had any progress in the meantime?

    As a test, I think it would be interesting if you could try adding a delay between every packet on the controller side and see if that makes a difference (w 127 byte MTU). Also, the stack frame from the hardfault handler appears to be incorrect. The LR value is not pointing to a valid address but is a typical value for xPSR. It might be worth trying the hardfault handler included in the SDK, I'm not familiar with the ARM version, but this implementation will detect stack overflow as well. 

    Do the following to use the SDK Hardfault handler:

    Add  "\nRF5_SDK_15.2.0_9412b96\components\libraries\hardfault\nrf52\handler\hardfault_handler_keil.c" and "\nRF5_SDK_15.2.0_9412b96\components\libraries\hardfault\hardfault_implementation.c" to the project and build with HARDFAULT_HANDLER_ENABLED=1

    Best regards,

    Vidar

  • Hi Vidar, thank you for your help.

    No progress in the meantime no, I used 100 bytes data packet to continue my project, but it can't be a final solution...

    By default, a delay of 100 ms is present between every data packet sent by the GSM chip to the NRF52, and I tried increasing this delay (up to 1000ms), but it doesn't change anything.

    Here are the results shown by the SDK 15.2 Hardfault Handler (I am still going into HardFault when handling, so writing, the second 127 bytes data packet received whith RX_BUF_SIZE = 127):

    <error> hardfault: HARD FAULT at 0x00076F90
    <error> hardfault:   R0:  0x0263DB00  R1:  0x4001E504  R2:  0x0000001F  R3:  0x00000001
    <error> hardfault:   R12: 0x0007AD89  LR:  0x0007ADB9  PSR: 0x81000000
    <error> hardfault: Cause: Data bus error (PC value stacked for the exception return points to the instruction that caused the fault).
    <error> hardfault: Bus Fault Address: 0x0002607F

    The PC value points to this line in the code:

    The LR value points to this line in the code:

    And BFAR value, which I'm guessing represents the address where the value should be written:

    More precisely, the HardFault PC points to the "STR" assembly instruction, that is supposed to store (at the address r5+(r4<<2)) the data and that causes the fault here:

    I checked the assembly code for the same C instruction in my SDK 12.1 Serial Bootloader, that works with 127 bytes packets, and I see no difference in the assembly code, except for the registers used:

    UPDATE:

    After running some tests, it seems that this issue may have to do with the size of sent data packets, in bytes, being a multiple of 4. It actually works for 124 bytes data packets with RX_BUF_SIZE >= 124. It also works with 128 bytes data packets with RX_BUF_SIZE = 128, but for this precise case I get a NRF_DRV_UART_EVT_ERROR when trying to send CRC via UART after the reception of the first 4096 bytes of data.

    Any reason for a non divisible per 4 size not working ? Could it come from the fact that the packet length is at some point divided by 4 to equal the number of words ?

  • Hi,

    Thanks for the update. This stack frame looks more correct. I will try to replicate then debug this on my side to see if I can find the root cause. I'll keep you posted.

Reply Children
  • Hi,

    All right thank you, still working on it on my side also.

  • Hi,

    I have tested Softdevice and app update with different MTU sizes but not been able to replicate the hardfault:

    Setup:

    - nrfutil 5.2.0

    - sdk 15.3.0

    - UART Serial bootloader - debug version

    I did, however, observe that the RX_BUF_SIZE is passed as length to nrf_fstorage_write() so the size must be a multiple of 4, the  NRF_FSTORAGE_PARAM_CHECK(!(len % p_fs->p_flash_info->program_unit), NRF_ERROR_INVALID_LENGTH); check will fail otherwise. Didn't this check fail on your side when you set the RX_BUF_SIZE to 127?

  • Hi,

    Thank you for your answer, I did find out about RX_BUF_SIZE having to be a multiple of 4 (UPDATE of my previous post), and then I also found this PARAM_CHECK line you are talking about, and I was surprised that it does not do anything when RX_BUF_SIZE = 127, because as you said it should have failed there...

    I have two questions from there:

    - Did it work on your side with RX_BUF_SIZE = 128 ? Because in this case I have a NRF_DRV_UART_EVT_ERROR when trying to send CRC via UART after the reception of the first 4096 bytes of data.

    - Is there any way to modify the write function so it can work with non-multiple of 4 values for RX_BUF_SIZE and so data packets size (such as 127) ? It was the case in the SDK 12.1 example bootloader.

    Thank you !

  • Did it work on your side with RX_BUF_SIZE = 128 ? Because in this case I have a NRF_DRV_UART_EVT_ERROR when trying to send CRC via UART after the reception of the first 4096 bytes of data.

    Yes, 128 worked for me. I'm using flow control, are you? When waiting for the CRC, does the GSM controller wait for the CRC and validate it before proceeding with the execute command? NRF_DRV_UART_EVT_ERROR indicate that you received invalid data (framing error,etc)

    Is there any way to modify the write function so it can work with non-multiple of 4 values for RX_BUF_SIZE and so data packets size (such as 127) ? It was the case in the SDK 12.1 example bootloader.

    Not the write function itself. The length must be a multiple of 4. But you could create a new buffer for immediate storage of the data, then make sure the data length passed to nrf_fstorage_write is always a multiple of 4. 

  • I am using flow control yes. The GSM chip waits for the CRC reception and validation before proceeding with the next step (execute command) also yes, that is how I first detected this issue.

    Ok I will try that and update the results, though I am not sure how to implement this without a zero-padding like solution which would mess with the data.

Related