TEN MBED OS Course shell utility

shell.cpp

Committer:
uLipe
Date:
2017-01-29
Revision:
0:1e8461adc480

File content as of revision 0:1e8461adc480:

/**
 * @brief our first hello world threaded program with MBED OS
 */
#include "mbed.h"
#include "rtos.h"
#include "shell.h"

/* declare a thread reserved only for shell command handler */
const size_t shell_stk_size = 8192;
uint8_t shell_stk[shell_stk_size];
Thread shell_thread(osPriorityNormal, shell_stk_size, &shell_stk[0]);

/* reserve the debbuger uart to shell interface */
Serial pc_serial(SHELL_TXD,SHELL_RXD);

static shell_callback_t shell_handler = NULL;
static shell_usage_t shell_usage;
static int argc = 0;
static char *argv[16];    

/**
 * @brief show help menu 
 */
static void print_usage(void) 
{
    pc_serial.printf("## use with the syntax below:         \n\r");
    pc_serial.printf("## command <arg1> <arg2> ... <arg16>  \n\r");
    pc_serial.printf("## Available commands:                \n\r");
    if(shell_usage != NULL) {
        shell_usage((void *)&pc_serial);
    }
}

 
/**
 * @brief parse the command received via comport
 */
static void shell_parser (char *cmd, int size)
{
    int cmd_ptr = 0;
    int arg_ptr = 0;
    int cmd_size = 0;
    char command_buffer[256];
    
    
    /* copy to the root command */
    memset(&command_buffer, 0, sizeof(command_buffer)); 
    
    /* find the root command terminator (space) */
    while(cmd_ptr < size) {
        if(cmd[cmd_ptr] == ' ') break;
        cmd_ptr++;
    }
    cmd_size = size - cmd_ptr;
    
    
    /* extract command arguments */
    strncpy(&command_buffer[0], &cmd[cmd_ptr + 1], (size - cmd_ptr));    
    
    /* terminates the root command */
    cmd[cmd_ptr] = 0;
    arg_ptr = 0;
    
    //pc_serial.printf("## command: %s \n\r", cmd);
    //pc_serial.printf("## arguments: %s \n\r", command_buffer);

  
    /* extract the further arguments */
    while(arg_ptr < (cmd_size)) {
 
        argc++;
        *(argv + (argc- 1)) = &command_buffer[arg_ptr];
 
        /* find terminator */
        while(command_buffer[arg_ptr] != ' ') {
            arg_ptr++;
        }
        
        /* adds to argument list */
        command_buffer[arg_ptr] = 0;
        arg_ptr++;       
       // pc_serial.printf("## argument no: %d : %s \n\r", argc, argv[argc-1]);
    }



    /* finds and execute the command table */
    if(shell_handler != NULL){
        
        int ret = shell_handler(cmd, argc, argv, (void *)&pc_serial);
        if(ret < 0) {
            print_usage();        
        }
    }else {
        print_usage();
    }
}




/**
 * @brief shell commands processing thread 
 */
static void shell_task(void)
{
    char serial_buffer[1024] = {0};
    int read_ptr = 0;
 
    /* setup the serial as 115200 bps */
    pc_serial.baud(115200);
       
    /* prints a welcome message */
     
    pc_serial.printf("******************************************************************\n\r");    
    pc_serial.printf("***         Welcome to MbedOS  Simple Shell application      ****\n\r");
    pc_serial.printf("*** Type some commands or just Enter key to see the available ****\n\r");
    pc_serial.printf("******************************************************************\n\r");            
    pc_serial.printf(">>");
    
    for(;;Thread::wait(50)) {        
        /* check if we have character available */
        if(pc_serial.readable()) {
            bool new_cmd = false;
            
            /* get the incoming character */
            char c = pc_serial.getc();
                       
            if( (c == '\n') || (c == '\r')) {
                /* handle enter key */
                new_cmd = true;
                pc_serial.printf("\n\r");
                
            }else if( (c == 0x7F) || (c == 0x08)){
                /* handle backspace and del keys */
                pc_serial.printf("\033[1D");
                pc_serial.putc(' ');
                pc_serial.printf("\033[1D");
                
                read_ptr--;
                if(read_ptr < 0) read_ptr = 1023;
                serial_buffer[read_ptr] = ' ';

                
            } else {
                /* loopback the pressed key */
                pc_serial.putc(c);
                
                /* store the incoming character on command circular buffer */
                serial_buffer[read_ptr] = c;
                read_ptr = (read_ptr + 1) % 1024;
            }
            
            
            
            if(new_cmd != false) {
                /* command arrived, has other characters? */
                if(read_ptr != 0) {
                    shell_parser(&serial_buffer[0], read_ptr);
                } else {
                    print_usage();
                }
                /* reset the buffer command */
                memset(&serial_buffer, 0, sizeof(serial_buffer));
                read_ptr = 0;
                pc_serial.printf(">>");
            } 

        }        
    }
}

void shell_set_command_handler(shell_callback_t sh)
{
    shell_handler = sh;
}
void shell_set_cmd_list(shell_usage_t sh)
{
    shell_usage = sh;
}
void shell_start(void)
{
    shell_thread.start(shell_task);
}