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

SPI DFU Bootloader Protocol

Hi,

I am currently working on SDK 15.2.0 on my NRF52840 DK to program a bootloader that can do DFUs over SPI. I have been following the protocol found in this link. I have been able to get a DFU_Master to talk to the Slave_bootloader, however, when it gets to the execute command, I am getting a "NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED" error from the bootloader. The log error says that it is running "execute with faulty offset", which lead me to believe that I there is something wrong with how I am executing the DFU protocol. I believe that it has something to do with how I am using the offset and the crc values given from the bootloader. I am also especially confused as to how to write the if statement shown in the picture below:

Currently I have the if statement set in my spi_send_object() function as you can see in the code below. I also included the functions for the corresponding protocols that are I think are supposed to occur in the if statement.

uint32_t MAX_OBJECT_SIZE, OFFSET,CRC, SEL_OFFSET, SEL_CRC;

static void spi_send_object(uint8_t type, uint8_t *data, uint32_t length, int size)
{
    uint8_t payload[127];
    length = 256;

      select_object(type,data,payload);//select the current object
      if (SEL_OFFSET==0 || SEL_OFFSET>length || SEL_CRC != CRC)
        create_object(type,data,length,payload);
      else if (OFFSET==length || CRC == SEL_CRC)
        execute_object(payload);
      
    write_object(type,data,length,payload);//transfer write data
    calculate_crc(payload);//calculate crc 
    execute_object(payload);
}

static void create_object(uint8_t type, uint8_t *data, uint32_t length, uint8_t* payload)
{
    //Create Object
    printf("In create object\n");
    payload[0]=0x01;
    payload[1]=type;//Command or Data Object
    payload[2]=length;
    payload[3]=length>>8;
    payload[4]=length>>16;
    payload[5]=length>>24;
    APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, payload, 6, NULL, 0));
    spi_response_polling(m_rx_buf,3,5);
    check_response(NRF_DFU_OP_OBJECT_CREATE,type,data,length,payload);
    //for(int loop = 0; loop < 10; loop++)
        //printf("Create Response m_rx_buf[%i]: 0x%X \r\n",loop, m_rx_buf[loop]);
}

static void select_object(uint8_t type, uint8_t *data, uint8_t* payload)
{
    //string temp;
    //int j = 0;
    //Select Object
    printf("In select object\n");
    payload[0] = 0x06;
    payload[1] = type;
    APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, payload, 2, NULL, 0));
    spi_response_polling(m_rx_buf,11,15);
    check_response(NRF_DFU_OP_OBJECT_SELECT,type,data,NULL,payload);
    
    MAX_OBJECT_SIZE = m_rx_buf[3] | (m_rx_buf[4] << 8)| (m_rx_buf[5] << 16);
    SEL_OFFSET = m_rx_buf[6] | (m_rx_buf[7] << 8) | (m_rx_buf[8] << 16);
    SEL_CRC = m_rx_buf[9] | (m_rx_buf[10] << 8);
    //if(m_rx_buf[1]!=0x06)
      //select_object(type,data,length);
}

static void calculate_crc(uint8_t* payload)
{
     //Ask for CRC
     printf("In calculate crc\n");
     payload[0]=0x03;
     APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, payload, 1, NULL, 0));
     nrf_delay_ms(5);
     spi_response_polling(m_rx_buf,11,5);
     check_response(NRF_DFU_OP_CRC_GET,NULL,NULL,NULL,payload);
     
     OFFSET = m_rx_buf[3] | (m_rx_buf[4] << 8)| (m_rx_buf[5] << 16);
     CRC = m_rx_buf[7] | (m_rx_buf[8] << 8) | (m_rx_buf[9] << 16) | (m_rx_buf[10] << 24);

If someone can please help me understand how I should be using the offset and crc values, I would greatly appreciate it!

  • Hello,

    Since we don't support SPI bootloaders, I assume you have done some of this implementation yourself. You say that the error says: execute with faulty offset. What offset do you send from the SPI command, and what does it expect? Try setting a breakpoint in nrf_dfu_validation_init_cmd_execute() and check what the s_dfu_settings.progress.command_offset and s_dfu_settings.progress.command_size is.

    Best regards,

    Edvin

Related