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 Pierre, 

    We would need to have the logging from the bootloader to really tell what could be wrong. 

    Capturing a logic trace on the UART line when you do DFU with your GSM chip and when you do DFU with a PC would also help pointing out what's wrong. 

    My understanding is that: 

    - On SDK v12.1 your bootloader + GSM works perfectly fine

    - On SDK v15.3 you can do DFU using PC but can't do that with GSM ? 

    Is it correct ? 

    I would suggest to try with SDK v15.2 , we have some change in SDK v15.3 that may be the cause of the issue.  

  • Ok I think I found out. The GSM is sending chunk of data of 127 bytes whereas the bootloader seems to be expecting only chunks of 64 bytes.

    This brings me to another question, how can I change this value ? I tried to modify RX_BUF_SIZE (defined in nrf_dfu_serial_uart.c from (64) to (127), and also tried other values, but it didn't change anything from the fact that it will only accepts 64 bytes data packets.

  • Ok yes thank you debugging works with the SDK 15.2 bootloader.

    So with RX_BUF_SIZE = 127 and the GSM whip sending 127 bytes data packet (so the configuration for which I have this issue), the code get stuck in an infinite loop in an hardfault_handler in the startup file arm_startup_nrf52.s :

    I'll try to obtain some more information as to the source that provokes this hardfault.

    UPDATE: I used a code given by ARM in order to get the registers that provoked this HardFault:

    #include "RTE_Components.h"             // Component selection
    #include CMSIS_device_header            // Include device header file from
    #include "stdio.h"                      // include stdio library for printf output
    #include "project_configuration.h"      // Header file for test case configuration
    
    #if HARDFAULT_HANDLER == 1
    
    void HardFault_Handler_C(unsigned long * svc_args, unsigned int lr_value);
     
    // HardFault handler wrapper in assembly language.
    // It extracts the location of stack frame and passes it to the handler written
    // in C as a pointer. We also extract the LR value as second parameter.
    __asm void HardFault_Handler(void)
    {
    	TST    LR, #4
    	ITE    EQ
    	MRSEQ  R0, MSP
    	MRSNE  R0, PSP
    	MOV    R1, LR
    	B      __cpp(HardFault_Handler_C)
    }	
     
     
    // HardFault handler in C, with stack frame location and LR value extracted
    // from the assembly wrapper as input parameters
    void HardFault_Handler_C(unsigned long * hardfault_args, unsigned int lr_value)
    {
      unsigned long stacked_r0;
      unsigned long stacked_r1;
      unsigned long stacked_r2;
      unsigned long stacked_r3;
      unsigned long stacked_r12;
      unsigned long stacked_lr;
      unsigned long stacked_pc;
      unsigned long stacked_psr;
      unsigned long cfsr;
      unsigned long bus_fault_address;
      unsigned long memmanage_fault_address;
      
      bus_fault_address       = SCB->BFAR;
      memmanage_fault_address = SCB->MMFAR;
      cfsr                    = SCB->CFSR;
     
      stacked_r0  = ((unsigned long) hardfault_args[0]);
      stacked_r1  = ((unsigned long) hardfault_args[1]);
      stacked_r2  = ((unsigned long) hardfault_args[2]);
      stacked_r3  = ((unsigned long) hardfault_args[3]);
      stacked_r12 = ((unsigned long) hardfault_args[4]);
      stacked_lr  = ((unsigned long) hardfault_args[5]);
      stacked_pc  = ((unsigned long) hardfault_args[6]);
      stacked_psr = ((unsigned long) hardfault_args[7]);
     
      printf ("[HardFault]\n");
      printf ("- Stack frame:\n"); 
      printf (" R0  = %x\n", stacked_r0);
      printf (" R1  = %x\n", stacked_r1);
      printf (" R2  = %x\n", stacked_r2);
      printf (" R3  = %x\n", stacked_r3);
      printf (" R12 = %x\n", stacked_r12);
      printf (" LR  = %x\n", stacked_lr);
      printf (" PC  = %x\n", stacked_pc);
      printf (" PSR = %x\n", stacked_psr);
      printf ("- FSR/FAR:\n");  
      printf (" CFSR = %x\n", cfsr);
      printf (" HFSR = %x\n", SCB->HFSR);
      printf (" DFSR = %x\n", SCB->DFSR);
      printf (" AFSR = %x\n", SCB->AFSR);
    	if (cfsr & 0x0080) printf (" MMFAR = %x\n", memmanage_fault_address);
    	if (cfsr & 0x8000) printf (" BFAR = %x\n", bus_fault_address);
      printf ("- Misc\n"); 
      printf (" LR/EXC_RETURN= %x\n", lr_value);
     	
      while(1); // endless loop
    }
    #endif
    

    Results:

    SCB -> CFSR = 0x00008200 ("cfsr")

    PC = 0x00070240 ("stacked_pc")

    SCB -> BFAR = 0x00074031 ("bus_fault_address")

    So apparently this Hard Fault is forced and actually comes from a Bus Fault, generated at the address BFAR and where at this point PC was 0x0007024.

    This is precisely the moment the code enters write() function from nrf_fstorage_nvmc.c file:

  • That hardfault is more likely an softdevice assert. 

    Please try to test using the stock serial bootloader + MBR not serial bootloader + softdevice. 

  • I tried to do that, problem is I will have an error NRF_DFU_EXT_ERROR_SD_VERSION_FAILURE as the package generated that contains APP+SD (6.1.0) needs a --sd-req 0xXX parameter, even though there will be no SoftDevice programmed on my flash, only the MBR. So when comparing the required SD version and the one (not) installed, it throws this error.

    Is there a way to do a APP+SD DFU with only bootloader and MBR programmed ?

    UPDATE:

    It does work if my package only contains SD (6.1.0). So I programmed bootloader settings and MBR hex files on the flash memory using nrfjprog, than launched debug of the bootloader, and I still have the exact same Hard Fault with bootloader + MBR only.

  • Hi Pierre, 

    Shouldn't we focus on solving the 127 bytes byte issue first ? Could you try to test just updating the APP without the SD ? 

    I'm don't think we support updating SD+APP from a non-softdevice bootloader. You can merge the softdevice and app and then updating it as an app. But we can solve this after we solve the 127 bytes packet issue. 

  • Hi,

    I agree, hence my update. Serial bootloader + MBR gives me the same hard fault at the same point (second data packet received).

Reply Children
No Data
Related