pulkin / micropython

MicroPython implementation on Ai-Thinker GPRS module A9 (RDA8955)
https://micropython.org
MIT License
103 stars 30 forks source link

FOTA module #88

Open arlucio opened 3 years ago

arlucio commented 3 years ago

I started making an OTA module that uses the FOTA API (https://ai-thinker-open.github.io/GPRS_C_SDK_DOC/en/c-sdk/function-api/fota.html) to update the firmware from a server. I would try running this from a micropython code or, if it doesn't work, use native code to check for updates and upgrade firmware before starting to run Micropython code.

I started to make the module but couldn't go further because I can't generate the .pack file to test at all, even using the FOTA example. Maybe I will come back to this later, but if anyone wants to give it a try. Would be something like this.

static void processFotaUpgradeData(const unsigned char *data, int len)
{
    if(len)
    {
        MEMBLOCK_Trace(1, (uint8_t*)data, (uint16_t)len, 16);
        if(!API_FotaInit(len))
            goto upgrade_failed;
        if(API_FotaReceiveData((unsigned char*)data, (int)len) == 0);
    }else{//error
        goto upgrade_failed;
    }
    return;

upgrade_failed:
    mp_printf(&mp_plat_print,"OTA upgrade failed");
    API_FotaClean();
}

STATIC mp_obj_t modota_update(size_t n_args, const mp_obj_t *args) {
    // ========================================
    // Get update from server and upgrade firmware.
    // Args:
    //     url (str): url from firmware server file on .pack format
    // ========================================
    if (n_args != 1) {
            mp_raise_ValueError("Unexpected number of argument: 1 is required");
    }

    const char* c_url = mp_obj_str_get_str(args[0]);
    if(API_FotaByServer((char*)c_url, processFotaUpgradeData) == 0)
        mp_printf(&mp_plat_print,"Starting OTA update");
    else
        mp_printf(&mp_plat_print,"OTA update failed");
    return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(modota_update_obj, modota_update);

STATIC const mp_map_elem_t mp_module_ota_globals_table[] = {
   { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_ota) },

   { MP_OBJ_NEW_QSTR(MP_QSTR_update),  (mp_obj_t)&modota_update_obj },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_ota_globals, mp_module_ota_globals_table);

const mp_obj_module_t ota_module = {
    .base = { &mp_type_module },
    .globals = (mp_obj_dict_t*)&mp_module_ota_globals,
};

There are already ways to just update .py/.mpy files like this one (https://medium.com/@ronald.dehuysser/micropython-ota-updates-and-github-a-match-made-in-heaven-45fde670d4eb). OTA updating entire firmware with all modules/main freezed seems better in terms of security and also update the freezed modules and bugs from the platform.

pulkin commented 3 years ago

upgrade firmware before starting to run Micropython code.

This is probably too intrusive.

What I learned from docs is that you need to build specific incremental images to make it work. Should be quite straightforward otherwise. Lod files are just addresses and text.