Run multiple binaries on your mbed.

Dependencies:   mbed

main.cpp

Committer:
paulg
Date:
2013-05-29
Revision:
0:4ea2252690b9
Child:
1:68f8899ed1ea

File content as of revision 0:4ea2252690b9:

/******************************************************************************
 * File:      main.cpp
 * Author:    Paul Griffith
 * Created:   27 May 2013
 * Last Edit: see below
 * Version:   see below
 *
 * Description:
 * Test program to demonstrate application switching.
 
 * This program loads and runs one of several different binaries.
 * The binaries are all present on the local filesystem, but are renamed to
 * app1.mbd, app2.mbd and so on. The filenames must conform to the local
 * filesystem's 8+3 filename rule and have an extension other then .bin.
 * This ensures that the files can be accessed by the local filesystem library
 * and that the interface chip does not act upon the binaries.
 * Another requirement is that all other .bin files must be deleted from the
 * local filesystem. This is necessary because downloaded files will always
 * have more recent timestamps than ones created by the local filesystem.
 * To switch applications, the current .bin file is deleted, the chosen app
 * file is copied to a .bin and the nR pin is driven low. The interface chip
 * then loads the .bin file into mbed's Flash.
 *
 * To use this program:
 * 1. From the PC, remove all .bin files from the mbed local filesystem,
 * 2. Compile as is, download to mbed and Flash it into mbed.
 * 3. From the PC, rename the binary to app1.mbd.
 * 4. Edit the MYNAME string to app2.bin
 * 5. Save, recompile and download to mbed. Do NOT Flash into mbed.
 * 6. From the PC, rename the binary to app2.mbd.
 * 7. Edit the MYNAME string to app3.bin
 * 8. Save, recompile and download to mbed. Do NOT Flash into mbed.
 * 9. From the PC, rename the binary to app3.mbd.
 * 10 Fit a wire jumper between mbed pin 9 (rstOut) and mbed pin 4 (nR).
 *    Another mbed I/O pin can be used if you change the RSTPIN definition.
 *    (If you don't fit a jumper you will have to press the Reset button
 *    when the Resetting mbed module... prompt appears).
 *
 * The program can now be run. It uses the virtual serial port at 9600 baud
 * and has a simple command interpreter. All commands end with <Enter>.
 * Use the 1, 2 and 3 commands to switch applications.
 *
 * Copyright (c) 2013 Paul Griffith.
 * Released under the MIT License: http://mbed.org/license/mit
 *
 * Modifications:
 * Ver  Date    By  Details
 * 0.00 27May13 PG  File created.
 * 1.00 29May13 PG  Initial release.
 *
 ******************************************************************************/

#define VERSION "1.00"
#define MYNAME "app1.bin"   //edit to desired name before compiling & downloading
#define RSTPIN p9

#include "mbed.h"

void printHelps(void);
void badArgs(void);
void nyi(void);
void pause(void);
void usage(void);
int getVal();
int exist(char *);
int copyFile(char*, char*);
void listDir(char*);
int renameFile(char*, char*);
void resetMbed(void);

Serial pc(USBTX, USBRX);
LocalFileSystem local("local");

int main() {
    char buf[120], *cp;
    char arg0[50], arg1[50], arg2[50];
    int argc, i;

    printf("\nApplication Switcher Demo (Version %s, %s %s)\n",
        VERSION, __DATE__, __TIME__);
    printf("I am application %s\n", MYNAME);
    printf("Type ? for help\n");

    strcpy(arg1, "/local/");    //build file name
    strcpy(arg2, "/local/");    //build file name            

    while (1) {
        printf("> ");
        cp = buf;
        while ( (*cp++ = putchar(getchar())) != '\r') ;   //get a line of input
        *cp = '\0';                                       //terminate buffer
        printf("\n");
        argc = sscanf(buf, "%s%s%s", arg0, &arg1[7], &arg2[7]);   //extract cmd & args
        if (argc < 1)
            continue;
        switch (arg0[0]) {

            case '1':        //load Application app1.bin
                if (strcmp(MYNAME, "app1.bin") == 0) {
                    printf("Application app1.bin is already running!\n");
                }
                else {
                    sprintf(&arg1[7], MYNAME);
                    remove(arg1);
                    copyFile("/local/app1.mbd", "/local/app1.bin");
                    resetMbed();
                }
                break; 

            case '2':        //load Application app2.bin
                if (strcmp(MYNAME, "app2.bin") == 0) {
                    printf("Application app2.bin is already running!\n");
                }
                else {
                    sprintf(&arg1[7], MYNAME);
                    remove(arg1);
                    copyFile("/local/app2.mbd", "/local/app2.bin");
                    resetMbed();
                }
                break; 

            case '3':        //load Application app3.bin
                if (strcmp(MYNAME, "app3.bin") == 0) {
                    printf("Application app3.bin is already running!\n");
                }
                else {
                    sprintf(&arg1[7], MYNAME);
                    remove(arg1);
                    copyFile("/local/app3.mbd", "/local/app3.bin");
                    resetMbed();
                }
                break; 

            case 'c':        //copy file
                if (argc != 3) {
                    usage();
                    break;
                }
                i = copyFile(arg1, arg2);
                printf("Copy %s to %s returned %d\n", arg1, arg2, i);
                break;

            case 'd':        //delete file
                if (argc != 2) {
                    usage();
                    break;
                }
                if (exist(arg1) == 0)
                    printf("File does not exist\n");
                else {
                    remove(arg1);
                    printf("File deleted\n");
                }
                break;

            case 'e':        //check if file exists
                if (argc != 2) {
                    usage();
                    break;
                }
                if (exist(arg1) != 0)
                    printf("File exists\n");
                else
                    printf("File does not exist\n");
                break;

            case 'i':        //identify self
                printf("I am application %s\n", MYNAME);
                break;

            case 'l':        //list files on local filesystem
                listDir("/local");
                break;

            case 'r':        //rename file on local filesystem
                if (argc != 3) {
                    usage();
                    break;
                }
                i = renameFile(arg1, arg2);
                printf("Rename %s to %s returned %d\n", arg1, arg2, i);
                break;

             case 'x':        //reset mbed module
                resetMbed();
                break;

            case '?':        //print help
                printHelps();
                break;
                
            default:
                printf("?? Unknown command\n");
                break;
        }
    }
}

//************************
// Display command summary
//************************

void printHelps(void) {
    printf("Command summary:\n");
    printf("1 - 3      load specified application\n");
    printf("c old new  copy file on local filesystem\n");
    printf("d filename delete file on local filesystem\n");
    printf("e filename check if file exists on local filesystem\n");
    printf("i          identification\n");
    printf("l          list files on local filesystem\n");
    printf("r old new  rename file on local filesystem\n");
    printf("x          reset mbed module\n");
}

//************************
// Miscellaneous functions
//************************

void badArgs(void) {
    pc.printf("?? Bad arguments\n");
}

void nyi(void) {
    pc.printf("!! Not yet implemented\n");
}

void pause(void)
{
    pc.printf("Press any key to continue . . .\n");
    pc.getc();
}

void usage(void) {
    printf("Invalid command usage\n");
}

// Get integer value from user. Used in enter functions

int getVal() {
    char buf[10];
    char* cp;
    int v;

    cp = buf;
    while ( (*cp++ = putchar(getchar())) != '\r') ; 
    *cp = '\0';
    printf("\n");
    v = 0;
    sscanf(buf, "%d", &v);
    return v; 
}

int exist(char *name) {
    FILE *fp;
    
    fp = fopen(name, "r");
    if (fp != NULL)
        fclose(fp);
    return ((fp == NULL) ? 0 : 1);
}

//*******************
// Command processing
//*******************

// Copy file

int copyFile(char *srcfile, char *destfile)
{
    char buf[512];
    int end, r, w;
    long length, size = 0;
    FILE *fp, *fp2;
    Timer timer;
    
    fp = fopen(srcfile, "r");
    if (fp == NULL)
    {
        printf("Source file does not exist\n");
        return(-1);
    }
    if (exist(destfile) == 1)
    {
        printf("Destination file already exists\n");
        fclose(fp);
        return(-2);
    }
    fp2 = fopen(destfile, "w");
    if (fp2 == NULL)
    {
        printf("Unable to create file\n");
        fclose(fp);
        return(-3);
    }
    fseek(fp, 0L, SEEK_END);
    length = ftell(fp);
    fseek(fp, 0L, SEEK_SET);

    printf("copy %s to %s\n", srcfile, destfile);
        
    printf("file length = %ld\n", length);
    timer.start();
    while (size < length)
    {
        r = fread(buf, 1, 512, fp);     //read a sector
        w = fwrite(buf, 1, r, fp2);     //write a sector
        if (w != r)
        {
            printf("file write error\n");
            fclose(fp);
            fclose(fp2);
            return(-4);
        }
        if (r < 512)    //reached end
            break;
        size += r;
    }
    end = timer.read_ms();
    fclose(fp);
    fclose(fp2);
    printf("%ld bytes copied in %d.%03ds\n", size, end/1000, end%1000);
    return(0);
}


// List directory

void listDir(char *drive) {
    DIR *d;
    struct dirent *p;

    d = opendir(drive);
    if (d != NULL) {
        while ((p = readdir(d)) != NULL) {
            printf(" - %s\n", p->d_name);
        }
    }
    else {
        printf("Could not open directory!\n");
    }
    closedir(d);
}

// Rename file
// this does not seem to work, perhaps rename() is broken?

int renameFile(char* srcfile, char* destfile) {
    if (exist(srcfile) == 0)
    {
        printf("Source file does not exist\n");
        return(-2);
    }
    if (exist(destfile) == 1)
    {
        printf("Destination file already exists\n");
        return(-3);
    }
    return( rename(srcfile, destfile) );
}

// Reset mbded module
// Requires a wire jumper between an I/O pin and pin 4

void resetMbed(void) {
    DigitalOut rst(RSTPIN);
    
    printf("Resetting mbed module...\n");
    rst = 0;
}

// END of main.cpp