Program to update the D7A modem's firmware.

Dependencies:   modem_ref_helper DebouncedInterrupt

cup.cpp

Committer:
Jeej
Date:
2016-10-26
Revision:
3:a59c8d77006b
Parent:
2:e0cdfa7d2a8b
Child:
4:23cb73bb11b3

File content as of revision 3:a59c8d77006b:

#include "mbed.h"
#include "cup.h"
#include "bin.h"
#include "crc.h"
#include "d7a.h"
#include "dbg.h"

#define FLASH_PAGE_SIZE (256)
#define TU_LOCAL        (220)


CUP_Archive::CUP_Archive(void) :
data(cup_data),
data_size(CUP_DATA_SIZE),
signature(CUP_SIGNATURE),
nb_archives(CUP_NB_ARCHIVES),
word_size(CUP_WORD_SIZE),
fw_id(0),
fw_major(CUP_FW_MAJOR),
fw_minor(CUP_FW_MINOR),
fw_patch(CUP_FW_PATCH),
fw_hash(CUP_FW_HASH),
hw_version(PLATFORM_HW_VERSION)
{}

void CUP_Archive::start_update(uint32_t src_offset, uint32_t max_size)
{
    cup_cfg_t cfg = {
        .cmd = 0x10AD,
        .arch_nb = 100,
    };
    
    uint32_t fof = 0;
    int32_t rem = this->data_size;
    uint8_t percent = 0;
    uint8_t percent_old = 255;
    Timer tim;
    
    // get archive address
    uint32_t addr = *((uint32_t*)&this->data[4]);
    // get uncompressed size
    uint32_t dsize = *((uint32_t*)&this->data[9]);
    // End address
    uint32_t eaddr = addr + dsize;
    
    uint32_t offset = 0;
    
    if (eaddr > src_offset)
    {
        // Calculate offset if needed
        PRINT("/!\\ CUP process will overwrite Archive: 0x%08X + %d > 0x%08X /!\\\r\n", addr, dsize, src_offset);
        eaddr = ((eaddr / FLASH_PAGE_SIZE) + 1) * FLASH_PAGE_SIZE;
        offset = eaddr - src_offset;
        PRINT("/!\\ CUP Shifting archive storage to 0x%08X (Offset 0x%X) /!\\\r\n", eaddr, offset);
    }
    
    max_size -= offset;
    int32_t slack = max_size - this->data_size;
    ASSERT(slack >= 0, "Not enough space to store archive! (%d bytes short)\r\n", slack);
    
    D7A_WRITE((uint8_t*)&cfg, CUP_CFG_FID, 0, 4, root_key);
    
    // Upload file
    PRINT("Uploading %d bytes at address 0x%08X (%d bytes slack)\r\n", this->data_size, src_offset + offset, slack);
    
    tim.start();
    
    while (rem > 0)
    {
        D7A_WRITE(&(this->data[fof]), CUP_CODE_FID, fof + offset, TU_LOCAL, NULL);
        rem -= TU_LOCAL;
        fof += TU_LOCAL;
        
        percent = (100*fof)/this->data_size;
        if (percent != percent_old)
        {
            PRINT("UPLOADING CUP FILE %3d percent\r\n", percent);
            percent_old = percent;
        }
        
        // Wait to avoid COM faillure
        Thread::wait(1);
    }
    
    float time_s = tim.read();
    PRINT("File[%d] %d bytes written in %.2f sec (%.2f kB/s)\r\n", CUP_CODE_FID, this->data_size, time_s, (this->data_size/time_s)/1024.0);
    
    // Force PFLASH-cache flushing
    D7A_FLUSH(CUP_CODE_FID, root_key);
        
    // Send Upgrade command
    cfg.cmd = 0xC0D5;
    cfg.arch_nb = this->nb_archives;
    cfg.src_offset = offset;
    cfg.signature = this->signature;
        
    D7A_WRITE((uint8_t*)&cfg, CUP_CFG_FID, 0, 12, root_key);
    
    PRINT("CUP Done.\r\nPlease wait for reboot...\r\n");
}