FOTA over wifi

I try to download FOTA from http server to nrf7002 over WIFI

i use fota download library and initialized it ,then call API fota_download_start()
then the fota_callback_handler respond with   "FOTA_DOWNLOAD_EVT_FINISHED" , but when i call  sys_reboot(SYS_REBOOT_COLD) the system doesn't jump to the new firmware and reset to the old firmware

so where's the problem ?

  • Hi,

    Do you have any logs? Preferably including from MCUBoot.

    How different is the new image you are downloading from the old one? Is it a different application, or different SDK version?

    Do you have a static partition configuration?

    Best regards,

    Didrik

  • I found out that there's no download happened
    Although that handler is "FOTA_DOWNLOAD_EVT_FINISHED" , there's no file downloaded
     
    After i enabled the logs the response was error : Donload socket error -109

    Logs :
    I: Connection requested
    I: Waiting to connect to Wi-Fi
    I: Network connected
    I: Downloading: xxx.xxxxx.com/merged.bin [0]
    I: Connecting to xxx.xxxx.com:80
    W: Failed to set socket timeout, errno 109
    E: Error in recv(), errno 109
    W: Download socket error

    that's my main.c

    /*
     * Copyright (c) 2023 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */

    #include <errno.h>
    #include <stddef.h>
    #include <string.h>
    #include <stdio.h>
    #include <zephyr/device.h>
    #include <zephyr/kernel.h>
    #include <zephyr/types.h>
    #include <zephyr/logging/log.h>

    #include <zephyr/sys/printk.h>

    #include <dk_buttons_and_leds.h>

    #include <zephyr/drivers/flash.h>
    #include <zephyr/storage/flash_map.h>
    #include <zephyr/devicetree.h>

    #include <zephyr/net/wifi.h>
    #include <zephyr/net/wifi_mgmt.h>
    #include <zephyr/net/net_mgmt.h>
    #include <net/wifi_mgmt_ext.h>
    #include <net/wifi_credentials.h>
    #include <zephyr/net/socket.h>

    #include <zephyr/dfu/mcuboot.h>

    #include <net/download_client.h>
    #include <net/fota_download.h>

    #include <zephyr/sys/reboot.h>

    // #include <_timeval.h>
    /*--------------------------------------------------------------------------*/
    #ifdef CONFIG_TRUSTED_EXECUTION_NONSECURE
    #define TEST_PARTITION  storage_partition
    #else
    #define TEST_PARTITION  storage_partition
    #endif

    #define TEST_PARTITION_OFFSET   FIXED_PARTITION_OFFSET(TEST_PARTITION)
    // #define TEST_PARTITION_OFFSET        0x00080000

    #define TEST_PARTITION_DEVICE   FIXED_PARTITION_DEVICE(TEST_PARTITION)

    #define FLASH_PAGE_SIZE   4096
    #define TEST_DATA_WORD_0  0x1122
    #define TEST_DATA_WORD_1  0xaabb
    #define TEST_DATA_WORD_2  0xabcd
    #define TEST_DATA_WORD_3  0x1234

    #define FLASH_TEST_OFFSET2 0x41234
    #define FLASH_TEST_PAGE_IDX 37
    /*--------------------------------------------------------------------------*/



    /* STEP 1.2 - Include the header file of the HTTP client library */
    #include <zephyr/net/http/client.h>



    LOG_MODULE_REGISTER(Lesson5_Exercise1, LOG_LEVEL_INF);

    #define EVENT_MASK (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED)
    #define FOTA_EVENT_MASK     (FOTA_DOWNLOAD_EVT_PROGRESS|FOTA_DOWNLOAD_EVT_FINISHED|FOTA_DOWNLOAD_EVT_CANCELLED|FOTA_DOWNLOAD_EVT_ERROR|FOTA_DOWNLOAD_EVT_ERASE_DONE|FOTA_DOWNLOAD_EVT_ERASE_PENDING)
    #define CLIENT_MASK             (DOWNLOAD_CLIENT_EVT_DONE | DOWNLOAD_CLIENT_EVT_FRAGMENT | DOWNLOAD_CLIENT_EVT_ERROR)
    /* STEP 2 - Define the macros for the HTTP server hostname and port */
    #define HTTP_HOSTNAME "xxx.xxxx.com"
    #define HTTP_PORT     80

    /* STEP 3 - Declare the necessary buffers for receiving messages */
    #define RECV_BUF_SIZE  4096
    #define CLIENT_ID_SIZE 36

    static char recv_buf[RECV_BUF_SIZE];
    static char client_id_buf[CLIENT_ID_SIZE + 2];

    /* STEP 4 - Define the variable for the counter as 0 */
    static int counter = 0;

    static int sock;
    static struct sockaddr_storage server;

    static struct net_mgmt_event_callback mgmt_cb;
    static struct net_mgmt_event_callback mgmt_cb2;
    static struct net_mgmt_event_callback mgmt_cb3;


    static bool connected;
    static K_SEM_DEFINE(run_app, 0, 1);

    static void net_mgmt_event_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_event,
                       struct net_if *iface)
    {
        if ((mgmt_event & EVENT_MASK) != mgmt_event) {
            return;
        }
        if (mgmt_event == NET_EVENT_L4_CONNECTED) {
            LOG_INF("Network connected");
            connected = true;
            dk_set_led_on(DK_LED1);
            k_sem_give(&run_app);
            return;
        }
        if (mgmt_event == NET_EVENT_L4_DISCONNECTED) {
            if (connected == false) {
                LOG_INF("Waiting for network to be connected");
            } else {
                dk_set_led_off(DK_LED1);
                LOG_INF("Network disconnected");
                connected = false;
            }
            k_sem_reset(&run_app);
            return;
        }
    }




     
    volatile uint8_t binary[5000];
    volatile uint8_t RXbuff[5000];


    void fota_download_callback(const struct fota_download_evt *event) {
        switch (event->id) {
            case FOTA_DOWNLOAD_EVT_PROGRESS:
                // Handle fragment download event
               
                int x= event->progress;
                __NOP();    
                break;
            case FOTA_DOWNLOAD_EVT_FINISHED:
                // Handle finished download event
                // Issue reboot command to apply the upgrade
                sys_reboot(SYS_REBOOT_COLD); // or SYS_REBOOT_WARM
                break;
            case FOTA_DOWNLOAD_EVT_ERASE_PENDING:
                // Handle finished download event
                // Issue reboot command to apply the upgrade
                break;
            case FOTA_DOWNLOAD_EVT_ERASE_DONE:
                // Handle finished download event
                // Issue reboot command to apply the upgrade
                break;
            case FOTA_DOWNLOAD_EVT_ERROR:
                // Handle finished download event
                // Issue reboot command to apply the upgrade
                break;
            case FOTA_DOWNLOAD_EVT_CANCELLED:
                // Handle finished download event
                // Issue reboot command to apply the upgrade
                break;
            default : break ;
            // More cases can be added as per specific requirements
        }
    }

    void fota_download_handler(const struct download_client_evt *event) {
        __NOP();
        switch (event->id) {
            case DOWNLOAD_CLIENT_EVT_DONE:
                printf("Firmware download finished. Issuing reboot command for upgrade.\n");
                // Issue reboot command to apply the upgrade
                break;
            case DOWNLOAD_CLIENT_EVT_ERROR :
                break;
            case DOWNLOAD_CLIENT_EVT_FRAGMENT :
                break;
            // Handle other download client events as needed
            default:
                break;
        }
    }


    static struct k_work fota_work;

    #define FOTA_IMAGE_URL "xxx.xxxxx.com"
    static void fota_work_cb(struct k_work *work);
    static int wait_for_download(void);
    static K_SEM_DEFINE(fota_download_sem, 0, 1);

    int main(void)
    {

        /*--------------------------------------------------------------------------------------------------*/
        const struct device *flash_dev = TEST_PARTITION_DEVICE;

        uint32_t buf_array_1[4] = { TEST_DATA_WORD_0, TEST_DATA_WORD_1,
                        TEST_DATA_WORD_2, TEST_DATA_WORD_3 };

        uint32_t buf_array_2[4] = { TEST_DATA_WORD_3, TEST_DATA_WORD_1,
                        TEST_DATA_WORD_2, TEST_DATA_WORD_0 };

        uint32_t buf_array_3[8] = { TEST_DATA_WORD_0, TEST_DATA_WORD_1,
                        TEST_DATA_WORD_2, TEST_DATA_WORD_3,
                        TEST_DATA_WORD_0, TEST_DATA_WORD_1,
                        TEST_DATA_WORD_2, TEST_DATA_WORD_3 };

        uint32_t buf_word = 0U;
        uint32_t i, offset;

        /*--------------------------------------------------------------------------------------------------*/

        if (dk_leds_init() != 0) {
            LOG_ERR("Failed to initialize the LED library");
        }


        if(!device_is_ready(flash_dev)) {
            printf("Flash device not ready\n");
            return 0;
        }

       

        // k_work_init(&fota_work , fota_work_cb);

        offset = TEST_PARTITION_OFFSET;

        /* Sleep to allow initialization of Wi-Fi driver */
        k_sleep(K_SECONDS(1));

        net_mgmt_init_event_callback(&mgmt_cb, net_mgmt_event_handler, EVENT_MASK);
        net_mgmt_add_event_callback(&mgmt_cb);

        net_mgmt_init_event_callback(&mgmt_cb2, fota_download_callback, FOTA_EVENT_MASK);
        net_mgmt_add_event_callback(&mgmt_cb2);

        net_mgmt_init_event_callback(&mgmt_cb3, fota_download_handler, CLIENT_MASK);
        net_mgmt_add_event_callback(&mgmt_cb3);

        printf("System starts ...\r\n");

        LOG_INF("Waiting to connect to Wi-Fi");
        k_sem_take(&run_app, K_FOREVER);

        /********************************************************************************************************/
       
        /********************************************************************************************************/

        /********************************************************************************************************/
       
        //Initialize FOTA download client
       fota_download_callback_t fota_cfg = fota_download_callback ;

       /* This is needed so that MCUBoot won't revert the update */
       

        int err = fota_download_init(fota_download_callback);
        if (err != 0) {
            printk("fota_download_init() failed, err %d\n", err);
            return err;
        }  

        /* Functions for getting the host and file */
        err = fota_download_start("xxx.xxxx.com:80" ,"xxxx.xxxx.com/merged.bin" , -1 , 0 , 0);
        if (err != 0) {
            printk("fota_download_start() failed, err %d\n", err);
            return err;
        }

        k_msleep(1);

       
        return 0;
    }

    static void fota_work_cb(struct k_work *work)
    {
        int err;

        ARG_UNUSED(work);

        err = fota_download_init(fota_download_callback);
        if (err != 0) {
            printk("fota_download_init() failed, err %d\n", err);
            return err;
        }  

        /* Functions for getting the host and file */
        err = fota_download_start("xxx.xxxxx.com:8090" ,""xxx.xxxx.com/tfm_s.bin" , -1 , 0 , 0);
        if (err != 0) {
            printk("fota_download_start() failed, err %d\n", err);
            return err;
        }

        wait_for_download();

    }

    static int wait_for_download(void)
    {
        int err = k_sem_take(&fota_download_sem,
                K_MINUTES(10));
        if (err == -EAGAIN) {
            fota_download_cancel();
            return -ETIMEDOUT;
        } else if (err != 0) {
            LOG_ERR("k_sem_take error: %d", err);
            return -ENOLCK;
        }

        return 0;
    }
  • Hi,

    Can you confirm that this is how you have formatted the URL in your code? Or is the "> part just an artifact of your copying (on this note, please use the code formatting option in the future)?

    err = fota_download_start("">lucca.quanttronix.com:80" ,"">lucca.quanttronix.com/merged.bin" , -1 , 0 , 0);

    The host should be just the hostname, though you can include the scheme and/or port, e.g. lucca.qanttronix.com:80.

    Then, the file is just the path part of the URL, i.e. merged.bin.

    Also, the sec_tag_list parameter should be NULL to disable TLS, not -1.

Related