ftf mbedos threads lab

Dependencies:   ST7567

Revision:
0:ead5ee0a33fa
Child:
1:e7266223f1fa
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Nov 05 02:46:29 2016 +0000
@@ -0,0 +1,305 @@
+/**
+ *  @brief NXP FTF LAB3 - Mbed OS Threads control each thread execution
+ */
+
+
+#include "mbed.h"
+#include "ST7567.h"
+#include "rtos.h"
+
+/* LCD screen dimensions */
+#define LCD_HEIGHT          64
+#define LCD_WIDTH           128
+
+/* LCD font dimensions */
+#define FONT_HEIGHT         10
+#define FONT_WIDTH          5
+
+
+/** Instance a on board GLCD object */
+ ST7567 glcd(D11, D13, D12, D9, D10);
+ 
+ 
+ /* allocate statically stacks for the three threads */
+unsigned char app1_stk[1024];
+unsigned char app2_stk[1024];
+unsigned char app3_stk[1024];
+unsigned char shell_stk[4096];
+
+/* creates three tread objects with different priorities */
+Thread app1_thread(osPriorityNormal, 1024, &app1_stk[0]);
+Thread app2_thread(osPriorityHigh, 1024, &app2_stk[0]);
+Thread app3_thread(osPriorityNormal, 1024, &app3_stk[0]);
+Thread shell_thread(osPriorityRealtime, 4096, &shell_stk[0]);
+ 
+ 
+ /** Instance a UART class to communicate with pc */
+Serial pc_serial(USBTX,USBRX);
+
+
+/**
+ * @brief application demo task 
+ */
+void app1_task(void) {
+    const char thread_message[] = {"app1_task now running! \0"};
+    for(;;) {
+        app1_thread.signal_wait(1);
+        app1_thread.signal_set(1);
+        glcd.locate((LCD_WIDTH - (FONT_WIDTH * sizeof(thread_message)))/2,
+                        (LCD_HEIGHT - FONT_HEIGHT) / 2);
+        glcd.printf(thread_message);
+    }
+}
+
+/**
+ * @brief application demo task 
+ */
+void app2_task(void) {
+    const char thread_message[] = {"app2_task now running! \0"};
+
+    for(;;) {
+        app2_thread.signal_wait(1);
+        app2_thread.signal_set(1);
+        glcd.locate((LCD_WIDTH - (FONT_WIDTH * sizeof(thread_message)))/2,
+                        (LCD_HEIGHT - FONT_HEIGHT) / 2);
+        glcd.printf(thread_message);
+    }
+}
+
+
+
+/**
+ * @brief application demo task 
+ */
+void app3_task(void) {
+    const char thread_message[] = {"app3_task now running! \0"};
+
+    for(;;) {
+        app3_thread.signal_wait(1);
+        app3_thread.signal_set(1);        
+        glcd.locate((LCD_WIDTH - (FONT_WIDTH * sizeof(thread_message)))/2,
+                       (LCD_HEIGHT - FONT_HEIGHT) / 2);
+        glcd.printf(thread_message);
+    }
+}
+
+
+/**
+ * @brief thread_command interpreter
+ */
+void shell_thread_execute_command(int argc, char **argv){
+    
+    Thread *ptr;
+    
+    /* check the argument number */
+    if(argc < 2) {
+        pc_serial.printf("## thread: too few arguments, exiting \n\r");
+        return;
+    }
+    
+    /* check which thread the shell command is claiming */
+    if(strcmp("app1", argv[0])== 0) {
+        ptr = &app1_thread;
+    }else if (strcmp("app2", argv[0])==0) {
+        ptr = &app2_thread;
+    } else if (strcmp("app3", argv[0])==0) {
+        ptr = &app3_thread;       
+    }else {
+        /* oops! invalid thread  */
+        pc_serial.printf("## thread: invalid thread argument, exiting! \n\r");
+        return;
+    }   
+    
+    
+    /* select which command */
+    if(strcmp("resume", argv[1])== 0) {
+        glcd.cls();
+        ptr->signal_set(1);
+        pc_serial.printf("## thread: Resuming the %s task! \n\r", argv[0]);           
+    }else if (strcmp("suspend", argv[1]) == 0) {
+        glcd.cls();
+        ptr->signal_clr(1);
+        pc_serial.printf("## thread: Suspending the %s task! \n\r", argv[0]);   
+    }else{    
+        /* oops! invalid thread  */
+        pc_serial.printf("## thread: invalid option argument, exiting! \n\r");
+        return;
+    }   
+    
+}
+
+
+/**
+ * @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");
+    pc_serial.printf("## thread  <app1/2/3>  <suspend|resume>   : control thread execution \n\r");
+    pc_serial.printf("##          app1/2/3:         name of desired thread\n\r");
+    pc_serial.printf("##          suspend:          suspend selected thread from execution \n\r");
+    pc_serial.printf("##          resume:           resume  selected thread execution \n\r");        
+}
+
+ 
+/**
+ * @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];
+    
+    int argc = 0;
+    char *argv[16];    
+    
+    /* 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(strcmp("thread", cmd) == 0) { 
+        shell_thread_execute_command(argc, argv);
+    } else {
+        print_usage();
+    }    
+
+}
+
+
+
+
+/**
+ * @brief shell commands processing thread 
+ */
+static void shell_task(void)
+{
+    char serial_buffer[1024] = {0};
+    int read_ptr = 0;
+    const char msg[] = {"Welcome to NXP FTF !\0"};
+ 
+    /* setup the serial as 115200 bps */
+    pc_serial.baud(115200);
+
+/* setup our on-board glcd */
+    glcd.set_contrast(0x35);
+    glcd.cls();
+
+   /* Center the LCD cursor based on message size*/
+    glcd.locate(LCD_WIDTH - (sizeof(msg) * FONT_WIDTH), 
+                    (LCD_HEIGHT - FONT_HEIGHT) / 2);
+
+    
+    /* prints a welcome message */
+    glcd.printf(msg);
+    
+    glcd.cls();
+    Thread::wait(1000);
+    
+  
+    pc_serial.printf("******************************************************************\n\r");    
+    pc_serial.printf("***         Welcome to NXP FTF 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();
+            pc_serial.putc(c);
+            
+            
+            /* is a enter ? */
+            if( (c == '\n') || (c == '\r')) {
+                new_cmd = true;
+                pc_serial.getc();
+                
+            } else {
+                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(">>");
+            } 
+
+        }        
+    }
+}
+
+static void idle_hook(void) {
+        const char thread_message[] = {"No thread running! \0"};        
+        glcd.locate((LCD_WIDTH - (FONT_WIDTH * sizeof(thread_message)))/2, 
+                    (LCD_HEIGHT - FONT_HEIGHT) / 2);
+        glcd.printf(thread_message);   
+}
+
+/**
+ * @brief main application loop
+ */
+int main(void) 
+{   
+
+    glcd.cls();
+
+    /* starts the shell task and applications task*/
+    shell_thread.attach_idle_hook(idle_hook);
+    shell_thread.start(shell_task);   
+    app1_thread.start(app1_task);
+    app2_thread.start(app2_task);
+    app3_thread.start(app3_task); 
+    return 0;
+}