Program to update the D7A modem's firmware.

Dependencies:   modem_ref_helper DebouncedInterrupt

main.cpp

Committer:
Jeej
Date:
2016-10-26
Revision:
0:82a60d86ab2e
Child:
1:765933092750

File content as of revision 0:82a60d86ab2e:

#include "mbed.h"
#include "rtos.h"
#include "d7a.h"
#include "dbg.h"
#include "cup.h"
#include "DebouncedInterrupt.h"

// File IDs
#define D7A_FID_FIRMWARE_VERSION        (2)


// callbacks structure
const d7a_callbacks_t callbacks = {
    .write_file = NULL,
    .read_file = NULL,
    .notif_done = NULL,
    .unsolicited_msg = NULL,
};

// Com configuration for the DASH7 shield
const d7a_com_config_t shield_config = {
    .tx  = D10,
    .rx  = D2,
    .rts = D13,
    .cts = D9,
    .rx_buffer_size = 1024,
};

// Semaphore for notifiying button presses
Semaphore button_user(0);

// Interrupt Service Routine on button press.
void button_push_isr( void )
{
    button_user.release();
}

int main()
{
    d7a_revision_t rev;
    
    // Start & initialize
    DBG_OPEN();
    PRINT("\r\n--- D7A WM Updater ---\r\n");

    DebouncedInterrupt user_interrupt(USER_BUTTON);
    user_interrupt.attach(button_push_isr, IRQ_FALL, 200, true);

    d7a_open(&shield_config, A3, &callbacks);

    // Check modem revision
    D7A_READ(&rev, D7A_FID_FIRMWARE_VERSION, 0, sizeof(d7a_revision_t), NULL);
    
    PRINT("-----------------------------------\r\n");
    PRINT("--------- D7A Modem infos ---------\r\n");
    PRINT("Manufacturer ID:  0x%08X\r\n", rev.manufacturer_id);
    PRINT("Device ID:        0x%08X\r\n", rev.device_id);
    PRINT("Hardware version: 0x%08X\r\n", rev.hw_version);
    PRINT("Firmware version: v%d.%d.%d\r\n", rev.fw_version.major, rev.fw_version.minor, rev.fw_version.patch);
    PRINT("Firmware hash:    0x%08x\r\n", rev.fw_version.hash);
    PRINT("File system CRC:  0x%08x\r\n", rev.fs_crc);
    PRINT("-----------------------------------\r\n");
    
    // Check package infos
    CUP_Archive cup_pkg;
    
    PRINT("-------- CUP Archive infos --------\r\n");
    PRINT("Firmware version: v%d.%d.%d\r\n", cup_pkg.fw_major, cup_pkg.fw_minor, cup_pkg.fw_patch);
    PRINT("Size:             %d\r\n", cup_pkg.data_size);
    PRINT("Nb archives:      %d\r\n", cup_pkg.nb_archives);
    PRINT("Signature:        0x%08X\r\n", cup_pkg.signature);
    PRINT("-----------------------------------\r\n");
    
    // Read CUP config with root permissions
    cup_cfg_t cup_cfg;
    D7A_READ(&cup_cfg, CUP_CFG_FID, 0, sizeof(cup_cfg_t), root_key);
    
    PRINT("----- CUP Configuration infos -----\r\n");
    PRINT("Src offset:       0x%08X\r\n", cup_cfg.src_offset);
    PRINT("Signature:        0x%08X\r\n", cup_cfg.signature);
    PRINT("File max size:    %d\r\n", cup_cfg.key);
    PRINT("Dbg config:       0x%08X\r\n", cup_cfg.dbg_cfg);
    PRINT("-----------------------------------\r\n");
    
    uint32_t version_old = (rev.fw_version.major << 24) | (rev.fw_version.minor << 16) | rev.fw_version.patch;
    uint32_t version_new = (cup_pkg.fw_major << 24) | (cup_pkg.fw_minor << 16) | cup_pkg.fw_patch;
    
    if (rev.hw_version != cup_pkg.hw_version)
    {
        PRINT("Please select the right Hardware in bin.h\r\n");
    }
    else if((cup_pkg.data_size % cup_pkg.word_size) != 0)
    {
        PRINT("Size %d should be multiple of %d.\r\n", cup_pkg.data_size, cup_pkg.word_size);
    }
    else if (cup_pkg.data_size > cup_cfg.key)
    {
        PRINT("CUP File too big for upgrade. Available %d needs %d.\r\n", cup_cfg.key, cup_pkg.data_size);
    }
    else if (version_old == version_new)
    {
        PRINT("Your modem is already up to date!\r\n");
    }
    else
    {
        if (version_old > version_new)
        {
            PRINT("/!\\ Your modem is at a more recent version /!\\\r\n/!\\ Are you sure you want to downgrade?    /!\\\r\n");
            PRINT("PRESS USER BUTTON TO CONFIRM...\r\n");
            button_user.wait();
            PRINT("Downgrading firmware: v%d.%d.%d --> v%d.%d.%d\r\n", 
                    rev.fw_version.major, rev.fw_version.minor, rev.fw_version.patch,
                    cup_pkg.fw_major, cup_pkg.fw_minor, cup_pkg.fw_patch);
            PRINT("PRESS USER BUTTON TO START DOWNGRADE...\r\n");
        }
        else
        {
            PRINT("Upgrading firmware: v%d.%d.%d --> v%d.%d.%d\r\n", 
                    rev.fw_version.major, rev.fw_version.minor, rev.fw_version.patch,
                    cup_pkg.fw_major, cup_pkg.fw_minor, cup_pkg.fw_patch);
            PRINT("PRESS USER BUTTON TO START UPGRADE...\r\n");
        }
        
        button_user.wait();
        cup_pkg.start_update(cup_cfg.src_offset);
    }
    
    // Set main task to lowest priority
    osThreadSetPriority(osThreadGetId(), osPriorityIdle);
    while(true)
    {
        // Wait to avoid beeing stuck in loop
        Thread::wait(200);
    }
}