博客專欄

EEPW首頁 > 博客 > 分享一個OTA升級相關(guān)的應(yīng)用實踐!(2)

分享一個OTA升級相關(guān)的應(yīng)用實踐?。?)

發(fā)布人:魚鷹談單片機 時間:2023-04-23 來源:工程師 發(fā)布文章

各升級情況的統(tǒng)一處理如:

左右滑動查看全部代碼>>>

static ota_update_case_e s_ota_update_case = UPDATE_SELECTED_NULL;        // 升級情況
static ota_update_case_e s_not_yet_update_case = UPDATE_SELECTED_NULL;    // 還未升級的情況

// 啟動固件安裝
void start_firmware_install(void)
{
    app_install_result_t install_board2_result = {0};
    app_install_result_t install_board3_result = {0};

    memset(&s_install_info, 0sizeof(app_install_info_t));
    send_install_info_to_app(&s_install_info);
    memset(&install_board2_result, 0sizeof(app_install_result_t));
    memset(&install_board3_result, 0sizeof(app_install_result_t));
    send_board2_install_result_to_app(&install_board2_result);
    send_board3_install_result_to_app(&install_board3_result);

    s_ota_update_case = get_ota_update_case();
    s_install_info.install_case = s_ota_update_case;

    switch (s_ota_update_case)
    {
        // 固件包相同,不升級
        case UPDATE_NON_DEV:
        {
            LOG_D("UPDATE_INSTALL_SUCCESS --- UPDATE_NON_DEV");

            s_install_info.total_install_status = UPDATE_INSTALL_SUCCESS;
            send_install_info_to_app(&s_install_info);
            storage_write_file(APP_OTA_INSTALL_RESULT_FILE, &s_install_info.total_install_status, sizeof(install_status_e));
            break;
        }
        // 只升級board1設(shè)備
        case UPDATE_BOARD1_DEV:
        {
            LOG_D("UPDATE_BOARD1_DEV");
            // 保存新的md5值
            md5sum_t calc_board1_img_md5 = {0};
            read_ota_md5_list_from_file(&s_flash_ota_file_md5_list, sizeof(s_flash_ota_file_md5_list)); 
            calc_file_md5(OTA_BOARD1_DEV_IMG_FILE, &calc_board1_img_md5);
            memcpy(s_flash_ota_file_md5_list[OTA_IMG_INDEX_BOARD1_DEV].md5, &calc_board1_img_md5, sizeof(md5sum_t));   
            write_ota_md5_list_to_file(&s_flash_ota_file_md5_list, sizeof(s_flash_ota_file_md5_list));

            start_board1_ota_install();
            break;
        }
        // 只升級board2設(shè)備
        case UPDATE_BOARD2_DEV:
        {
            LOG_D("UPDATE_BOARD2_DEV");
            start_board2_ota_install();
            s_not_yet_update_case = UPDATE_BOARD2_DEV;
            break;
        }
        // 只升級board3設(shè)備
        case UPDATE_BOARD3_DEV:
        {
            LOG_D("UPDATE_BOARD3_DEV");
            start_board3_ota_install();
            s_not_yet_update_case = UPDATE_BOARD3_DEV;
            break;
        }
        // 升級board1與board2設(shè)備
        case UPDATE_BOARD1_AND_BOARD2_DEV:
        {
            LOG_D("UPDATE_BOARD1_AND_BOARD2_DEV");
            start_board2_ota_install();
            s_not_yet_update_case = UPDATE_BOARD1_AND_BOARD2_DEV;
            break;
        }
        // 升級board1與board3設(shè)備
        case UPDATE_BOARD1_AND_BOARD3_DEV:
        {
            LOG_D("UPDATE_BOARD1_AND_BOARD3_DEV");
            start_board3_ota_install();
            s_not_yet_update_case = UPDATE_BOARD1_AND_BOARD3_DEV;
            break;
        }
        // 升級board2設(shè)備與board3設(shè)備
        case UPDATE_BOARD2_AND_BOARD3_DEV:
        {
            LOG_D("UPDATE_BOARD2_AND_BOARD3_DEV");
            start_board2_ota_install();
            start_board3_ota_install();
            s_not_yet_update_case = UPDATE_BOARD2_AND_BOARD3_DEV;
            break;
        }
        // 升級所有設(shè)備
        case UPDATE_ALL_DEV:
        {
            LOG_D("UPDATE_ALL_DEV");
            start_board2_ota_install();
            start_board3_ota_install();
            s_not_yet_update_case = UPDATE_ALL_DEV;
            break;
        }
        default:
            break;
    }
}
4、安裝進(jìn)度只有一個,如何處理三塊板子的安裝進(jìn)度?

手機APP上并不會去區(qū)分各個板子的安裝進(jìn)度,即安裝進(jìn)度只有一個。因為用戶并不會關(guān)注設(shè)備里有幾塊板子的固件在安裝。所以這個安裝進(jìn)度需要表明以上各種情況的安裝。

需要明確的是:

  • 安裝進(jìn)度總是以board2、board3中的較大固件為主。

  • 安裝某個板子異常則表明這個安裝過程算是失敗。為了防止這類情況:假如需要升級board1與board2,正好本次更新是增加了之間的一些協(xié)議數(shù)據(jù),如果單單升級成功其中一塊,另一塊沒升級成功,這種情況下也要去使用的話,就有可能會出現(xiàn)問題,協(xié)議數(shù)據(jù)對不上,輕則某些數(shù)據(jù)錯誤,程序中防錯機制設(shè)計得不好的話重則可能程序會崩潰。

  • 雖然board2與board3的安裝進(jìn)度不直接顯示在手機APP上,但無論是給手機APP做邏輯使用還是供我們調(diào)試實用,都有必要創(chuàng)建他們各自的屬性數(shù)據(jù)。比如會往云端上報各種情況的board2與board3的安裝信息屬性數(shù)據(jù),如:

typedef struct app_install_result
{

    uint8_t install_status;     // 安裝狀態(tài)
    uint8_t install_progress;   // 安裝進(jìn)度
}app_install_result_t;

app_install_result_t install_board2_result = {0};
app_install_result_t install_board3_result = {0};
send_board2_install_result_to_app(&install_board2_result);
send_board3_install_result_to_app(&install_board3_result);
5、安裝結(jié)束的檢測?

安裝過程包含如下幾種情況,挨個進(jìn)行處理即可:

圖片

對應(yīng)代碼如(注:以下為了方便說明全都寫在一塊,實際中可以進(jìn)行拆分):

// 檢測是否升級結(jié)束
void check_whether_update_end(void)
{
    app_install_result_t install_board2_result = {0};
    app_install_result_t install_board3_result = {0};

    // 包含board1的升級情況(board1+board2、board1+board3、board1+board2+board3)。board1最后安裝
    if (UPDATE_BOARD1_AND_BOARD2_DEV == s_ota_update_case || 
        UPDATE_BOARD1_AND_BOARD3_DEV == s_ota_update_case || 
        UPDATE_ALL_DEV == s_ota_update_case)
    {
        // 正常安裝且剩下board1沒安裝了,開始安裝board1
        if (UPDATE_BOARD1_DEV == s_not_yet_update_case)
        {
            s_ota_update_case = UPDATE_SELECTED_NULL;
            s_not_yet_update_case = UPDATE_SELECTED_NULL;
            // 1. 記錄新的版本號
            // 2. 保存新的md5值至本地文件
            // 3.重啟之前上報安裝成功給手機APP
            // 4.重啟進(jìn)行安裝board1
        }
        // 升級安裝失敗
        else
        {
            // 只升級board1與board2的情況
            if (UPDATE_BOARD1_AND_BOARD2_DEV == s_ota_update_case && UPDATE_BOARD1_AND_BOARD2_DEV == s_not_yet_update_case)
            {
                if (UPDATE_STATUS_BOARD2_DATA_ACK_ERR == s_board2_update_status)
                {
                    s_ota_update_case = UPDATE_SELECTED_NULL;
                    s_not_yet_update_case = UPDATE_SELECTED_NULL;
                    // 1. 上報board2安裝失敗
                    // 2. board2安裝失敗 -> 上報總的安裝失敗
                }
            }
            // 只升級board1與board3的情況
            else if (UPDATE_BOARD1_AND_BOARD3_DEV == s_ota_update_case && UPDATE_BOARD1_AND_BOARD3_DEV == s_not_yet_update_case)
            {
                if (UPDATE_STATUS_BOARD3_DATA_ACK_ERR == s_board3_update_status)
                {
                    s_ota_update_case = UPDATE_SELECTED_NULL;
                    s_not_yet_update_case = UPDATE_SELECTED_NULL;
                    // 1. 上報board3安裝失敗
                    // 2. board3安裝失敗 -> 上報總的安裝失敗
                }
            }
            // 升級全部設(shè)備
            else
            {
                // board2安裝失敗,board3安裝成功
                if (UPDATE_STATUS_BOARD2_DATA_ACK_ERR == s_board2_update_status && 
                    UPDATE_STATUS_BOARD3_DATA_FINISH_ACK_OK == s_board3_update_status)
                {
                    s_ota_update_case = UPDATE_SELECTED_NULL;
                    s_not_yet_update_case = UPDATE_SELECTED_NULL;                    
                    // 1. 上報board2安裝失敗
                    // 2. 上報board3安裝成功
                    // 3. board2安裝失敗 -> 上報總的安裝失敗
                }

                // board2安裝成功,board3安裝失敗
                if (UPDATE_STATUS_BOARD2_DATA_FINISH_ACK_OK == s_board2_update_status && UPDATE_STATUS_BOARD3_DATA_ACK_ERR == s_board3_update_status)
                {
                    s_ota_update_case = UPDATE_SELECTED_NULL;
                    s_not_yet_update_case = UPDATE_SELECTED_NULL;
                    // 1. 上報board2安裝成功
                    // 2. 上報board3安裝失敗
                    // 3. board3安裝失敗 -> 上報總的安裝失敗
                }

                // board2與board3都安裝失敗
                if (UPDATE_STATUS_BOARD2_DATA_ACK_ERR == s_board2_update_status && UPDATE_STATUS_BOARD3_DATA_ACK_ERR == s_board3_update_status)
                {
                    s_ota_update_case = UPDATE_SELECTED_NULL;
                    s_not_yet_update_case = UPDATE_SELECTED_NULL;
                    // 1. 上報board2安裝失敗
                    // 2. 上報board3安裝失敗
                    // 3. board2、board3安裝失敗 -> 上報總的安裝失敗
                }
            }
        }
    }
    
    // 只升級board2及board3的情況。如果數(shù)據(jù)都已經(jīng)傳輸數(shù)據(jù)完成,則上報安裝完成
    if (UPDATE_BOARD2_AND_BOARD3_DEV == s_ota_update_case) 
    {
        // 升級安裝成功
        if (UPDATE_NON_DEV == s_not_yet_update_case)
        {
            s_ota_update_case = UPDATE_SELECTED_NULL;
            s_not_yet_update_case = UPDATE_SELECTED_NULL;
            // 1. 上報board2安裝成功
            // 2. 上報board3安裝成功
            // 3. board2、board3安裝成功 -> 上報總的安裝成功
        }
        // 升級安裝失敗
        else
        {
            // board2安裝失敗,board3安裝成功
            if (UPDATE_STATUS_BOARD2_DATA_ACK_ERR == s_board2_update_status && UPDATE_STATUS_BOARD3_DATA_FINISH_ACK_OK == s_board3_update_status)
            {
                s_ota_update_case = UPDATE_SELECTED_NULL;
                s_not_yet_update_case = UPDATE_SELECTED_NULL;
                // 1. 上報board2安裝失敗
                // 2. 上報board3安裝成功
                // 3. board2安裝失敗 -> 上報總的安裝失敗
            }

            // board2安裝成功,board3安裝失敗
            if (UPDATE_STATUS_BOARD2_DATA_FINISH_ACK_OK == s_board2_update_status && UPDATE_STATUS_BOARD3_DATA_ACK_ERR == s_board3_update_status)
            {
                s_ota_update_case = UPDATE_SELECTED_NULL;
                s_not_yet_update_case = UPDATE_SELECTED_NULL;
                // 1. 上報board2安裝成功
                // 2. 上報board3安裝失敗
                // 3. board3安裝失敗 -> 上報總的安裝失敗
            }

            // board2與board3都安裝失敗
            if (UPDATE_STATUS_BOARD2_DATA_ACK_ERR == s_board2_update_status && UPDATE_STATUS_BOARD3_DATA_ACK_ERR == s_board3_update_status)
            {
                s_ota_update_case = UPDATE_SELECTED_NULL;
                s_not_yet_update_case = UPDATE_SELECTED_NULL;
                // 1. 上報board2安裝失敗
                // 2. 上報board3安裝失敗
                // 3. board2、board3安裝失敗 -> 上報總的安裝失敗
            }
        }
    }

    // 只升級board2的情況
    if (UPDATE_BOARD2_DEV == s_ota_update_case)
    {
        if (UPDATE_NON_DEV == s_not_yet_update_case)
        {
            s_ota_update_case = UPDATE_SELECTED_NULL;
            s_not_yet_update_case = UPDATE_SELECTED_NULL;
            // 1. 上報board2安裝成功
            // 2. board2安裝成功 -> 上報總的安裝成功
        }
        else
        {
            if (UPDATE_STATUS_BOARD2_DATA_ACK_ERR == s_board2_update_status)
            {
                s_ota_update_case = UPDATE_SELECTED_NULL;
                s_not_yet_update_case = UPDATE_SELECTED_NULL;
                // 1. 上報board2安裝失敗
                // 2. board2安裝失敗 -> 上報總的安裝失敗
            }
        }
    }

    // 只升級board3的情況
    if (UPDATE_BOARD3_DEV == s_ota_update_case)
    {
        if (UPDATE_NON_DEV == s_not_yet_update_case)
        {
            s_ota_update_case = UPDATE_SELECTED_NULL;
            s_not_yet_update_case = UPDATE_SELECTED_NULL;
            // 1. 上報board3安裝成功
            // 2. board3安裝成功 -> 上報總的安裝成功
        }
        else
        {
            if (UPDATE_STATUS_BOARD3_DATA_ACK_ERR == s_board3_update_status)
            {
                s_ota_update_case = UPDATE_SELECTED_NULL;
                s_not_yet_update_case = UPDATE_SELECTED_NULL;
                // 1. 上報board3安裝失敗
                // 2. board3安裝失敗 -> 上報總的安裝失敗
            }
        }
    } 
}

前面我們的升級情況進(jìn)行加法的組合,比如:

升級所有設(shè)備 = BOARD1 + BOARD2 + BOARD3 = 1 + 2 + 4

那么,我們每安裝完一個設(shè)備,可以減掉對應(yīng)的值,這樣可以區(qū)分當(dāng)前的安裝處于哪個階段。

以上就是本次的分享,大家還有什么其它思路嗎?


*博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權(quán)請聯(lián)系工作人員刪除。



關(guān)鍵詞: AI

相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉