Helper library to use modem_ref driver.
Dependencies: WizziCom WizziDebug ram_fs modem_ref
Dependents: D7A_Localisation D7A_1x_demo_send_file_data_and_forget D7A_1x_demo_CodeUpgradeProtocol D7A_1x_demo_LoRaWAN ... more
modem_cup/modem_cup.cpp
- Committer:
- Jeej
- Date:
- 2022-03-10
- Revision:
- 87:ae859849b6b4
- Parent:
- 75:dad2f09cb870
File content as of revision 87:ae859849b6b4:
#include "DebouncedInterrupt.h" #include "modem_cup.h" // Semaphore for notifiying button presses static Semaphore button_user(0); static Semaphore boot(0); uint8_t const modem_data[CUP_DATA_SIZE] = CUP_DATA; uint8_t const libex_data[LIBEX_DATA_SIZE] = LIBEX_DATA; uint8_t const bootloader_data[BOOTLOADER_DATA_SIZE] = BOOTLOADER_DATA; // Interrupt Service Routine on button press. static void button_push_isr( void ) { button_user.release(); } static void cup_boot(u8 cause, u16 number) { PRINT("Modem BOOT[%c] #%d\r\n", cause, number); boot.release(); } cup_param_t const cup_modem = { .data = (uint8_t*)modem_data, .cfg_fid = CUP_CFG_FID, .code_fid = CUP_CODE_FID, .code_size = CUP_CODE_SIZE, .data_size = CUP_DATA_SIZE, .local_mtu = CUP_LOCAL_MTU, .nb_archives = CUP_NB_ARCHIVES, .signature = CUP_SIGNATURE, .mfg_id = CUP_MFG_ID, .dev_id = CUP_DEV_ID, .hw_id = CUP_HW_ID, .fw_major = CUP_FW_MAJOR, .fw_minor = CUP_FW_MINOR, .fw_patch = CUP_FW_PATCH, .fw_hash = CUP_FW_HASH, .target_fw_major = CUP_TARGET_FW_MAJOR, .target_fw_minor = CUP_TARGET_FW_MINOR, .target_fw_patch = 0, .target_fw_hash = 0, }; cup_param_t const cup_libex = { .data = (uint8_t*)libex_data, .cfg_fid = CUP_CFG_FID, .code_fid = CUP_CODE_FID, .code_size = CUP_CODE_SIZE, .data_size = LIBEX_DATA_SIZE, .local_mtu = CUP_LOCAL_MTU, .nb_archives = 1, .signature = LIBEX_SIGNATURE, .mfg_id = CUP_MFG_ID, .dev_id = CUP_DEV_ID, .hw_id = CUP_HW_ID, .fw_major = CUP_FW_MAJOR, .fw_minor = CUP_FW_MINOR, .fw_patch = CUP_FW_PATCH, .fw_hash = CUP_FW_HASH, .target_fw_major = CUP_FW_MAJOR, .target_fw_minor = CUP_FW_MINOR, .target_fw_patch = CUP_FW_PATCH, .target_fw_hash = CUP_FW_HASH, }; cup_param_t const cup_bootloader = { .data = (uint8_t*)bootloader_data, .cfg_fid = BOOTLOADER_CFG_FID, .code_fid = BOOTLOADER_CODE_FID, .code_size = BOOTLOADER_CODE_SIZE, .data_size = BOOTLOADER_DATA_SIZE, .local_mtu = BOOTLOADER_LOCAL_MTU, .nb_archives = BOOTLOADER_NB_ARCHIVES, .signature = BOOTLOADER_SIGNATURE, .mfg_id = BOOTLOADER_MFG_ID, .dev_id = BOOTLOADER_DEV_ID, .hw_id = BOOTLOADER_HW_ID, .fw_major = BOOTLOADER_FW_MAJOR, .fw_minor = BOOTLOADER_FW_MINOR, .fw_patch = BOOTLOADER_FW_PATCH, .fw_hash = BOOTLOADER_FW_HASH, .target_fw_major = BOOTLOADER_TARGET_FW_MAJOR, .target_fw_minor = BOOTLOADER_TARGET_FW_MINOR, }; static void modem_cup_start_update(uint32_t offset, cup_param_t* cup) { cup_cfg_t cfg = { .cmd = 0x10AD, .arch_nb = 20, }; uint32_t fof = 0; uint8_t percent = 0; uint8_t percent_old = 255; Timer tim; int32_t rem; float now = 0; float speed_before = 0; float speed = 0; int speed_data = 0; float time_before = 0; float time_left = 0; float print_before = 0; rem = cup->data_size; // Start CUP modem_write_file(cup->cfg_fid, (uint8_t*)&cfg, 0, 4); // Upload file PRINT("Uploading %d bytes to CUP file. (offset %d)\r\n", cup->data_size, offset); tim.start(); while (rem > 0) { int32_t chunk = (rem > cup->local_mtu)? cup->local_mtu : rem; modem_write_file(cup->code_fid, &(cup->data[fof]), fof + offset, chunk); rem -= chunk; fof += chunk; now = tim.read(); speed_data += chunk; // Update speed if (now - speed_before > 1.0 || speed_before == 0) { speed = (speed_data/(now - speed_before))/1024.0; speed_before = now; speed_data = 0; } // Update time left if (now - time_before > 0.2 || time_before == 0 || rem == 0) { time_before = now; time_left = (rem / speed) / 1024.0; } // Print if (now - print_before > 0.1 || print_before == 0 || rem == 0) { percent = (100*fof)/cup->data_size; print_before = now; PRINT("\rUPLOADING NEW FIRMWARE %d/%d (%3d%%) %.2f kB/s %.0fs ", fof, cup->data_size, percent, speed, time_left); } } PRINT("\n"); float time_s = tim.read(); PRINT("CUP: %d bytes written in %.2f sec (%.2f kB/s)\r\n", cup->data_size, time_s, (cup->data_size/time_s)/1024.0); // Force PFLASH-cache flushing modem_flush_file(cup->code_fid); // Send Upgrade command cfg.cmd = 0xC0D5; cfg.arch_nb = cup->nb_archives; cfg.src_offset = offset; cfg.signature = cup->signature; modem_write_file(cup->cfg_fid, (uint8_t*)&cfg, 0, 12); PRINT("Waiting self reboot...\r\n"); boot.acquire(); } static uint8_t check_parameter(const char* str, uint32_t param1, uint32_t param2) { PRINT("Checking %s ", str); if (param1 != param2) { PRINT("Failed. (0x%08X != 0x%08X)\r\n", param1, param2); return 1; } else { PRINT("OK. (0x%08X)\r\n", param1); return 0; } } static void print_check_rev(void) { PRINT("\r\n" "/!\\ Please, check that you are at the right commit in the mbed revision tree /!\\\r\n" ); } static void print_check_hardware(void) { PRINT("Please, check that you chose the right Hardware in bin.h\r\n"); } static int32_t check_slack(uint32_t cup_max_size, uint32_t cup_data_size) { //PRINT("key: %d data: %d code: %d src: %d\r\n", cup_cfg->key, cup->data_size, cup->code_size, cup_cfg->src_offset); PRINT("Checking CUP Slack... "); //int32_t data_size = (((cup->data_size/256)+1)*256); int32_t cup_slack = cup_max_size - cup_data_size; cup_slack = ((cup_slack/256)*256); if (cup_slack < 0) { PRINT("Failed. (%d bytes short)\r\n", -cup_slack); } else { PRINT("OK. (%d bytes)\r\n", cup_slack); } return cup_slack; } static int modem_cup_check(revision_t* rev, cup_param_t* cup) { int cup_slack = -1; do { // Check modem revision if (check_parameter("Manufacturer ID... ", rev->manufacturer_id, cup->mfg_id)) { print_check_rev(); break; } if (check_parameter("Hardware version... ", rev->hw_version, cup->hw_id)) { print_check_hardware(); break; } if (rev->device_id != cup->dev_id) { // Update bootloader PRINT("\r\n" "/!\\ Not a modem firmware. /!\\\r\n" ); break; } else { // Update modem if (check_parameter("Device ID... ", rev->device_id, cup->dev_id)) { print_check_rev(); break; } if (&cup_libex != cup) { PRINT("Checking Firmware version major... "); if (rev->fw_version.major < cup->target_fw_major) { PRINT("Failed. (0x%08X != 0x%08X)\r\n", rev->fw_version.major, cup->target_fw_major); print_check_rev(); break; } else { PRINT("OK. (0x%08X)\r\n", rev->fw_version.major); } PRINT("Checking Firmware version minor... "); if (rev->fw_version.minor < cup->target_fw_minor && rev->fw_version.major == cup->target_fw_major) { PRINT("Failed. (0x%08X != 0x%08X)\r\n", rev->fw_version.minor, cup->target_fw_minor); print_check_rev(); break; } else { PRINT("OK. (0x%08X)\r\n", rev->fw_version.minor); } } else { if (check_parameter("Firmware version major...", rev->fw_version.major, cup->target_fw_major)) { print_check_rev(); break; } if (check_parameter("Firmware version minor...", rev->fw_version.minor, cup->target_fw_minor)) { print_check_rev(); break; } if (check_parameter("Firmware version patch...", rev->fw_version.patch, cup->target_fw_patch)) { print_check_rev(); break; } if (check_parameter("Firmware version hash... ", rev->fw_version.hash, cup->target_fw_hash)) { print_check_rev(); break; } } cup_slack = check_slack(rev->cup_max_size, cup->data_size); if (cup_slack < 0) { PRINT("\r\n" "/!\\ Not enough space for modem firmware binary. /!\\\r\n" "\r\n" ); break; } } return cup_slack; } while (0); FLUSH(); while(true) { ThisThread::sleep_for(500); } } void modem_cup_update(revision_t* rev) { bool bootloader; cup_param_t* cup = (cup_param_t*)&cup_modem; int32_t cup_slack = 0; uint32_t version_old = (rev->fw_version.major << 24) | (rev->fw_version.minor << 16) | rev->fw_version.patch; uint32_t version_new = (cup->fw_major << 24) | (cup->fw_minor << 16) | cup->fw_patch; if (version_old < version_new) { #ifdef DEBUG_BUTTON DebouncedInterrupt user_interrupt(DEBUG_BUTTON); user_interrupt.attach(button_push_isr, IRQ_FALL, 200, true); #endif modem_ref_set_boot_cb(cup_boot); cup_slack = modem_cup_check(rev, cup); PRINT("\r\nYour modem version is behind the recommended version for this driver."); PRINT("\r\nUpgrading modem firmware: v%d.%d.%d --> v%d.%d.%d\r\n", rev->fw_version.major, rev->fw_version.minor, rev->fw_version.patch, cup->fw_major, cup->fw_minor, cup->fw_patch); #ifdef DEBUG_BUTTON PRINT("PRESS USER BUTTON TO START UPGRADE...\r\n"); button_user.acquire(); #endif modem_cup_start_update(cup_slack, cup); if (LIBEX_NB_ARCHIVES) { ThisThread::sleep_for(500); PRINT("Updating Libex...\r\n"); modem_read_file(D7A_FID_FIRMWARE_VERSION, (uint8_t*)rev, 0, sizeof(revision_t)); cup = (cup_param_t*)&cup_libex; cup_slack = modem_cup_check(rev, cup); modem_cup_start_update(cup_slack, cup); } PRINT("Restarting application...\r\n"); FLUSH(); NVIC_SystemReset(); } }