ftf mbedos threads lab

Dependencies:   ST7567

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /**
00002  *  @brief NXP FTF LAB3 - Mbed OS Threads control each thread execution
00003  */
00004 
00005 
00006 #include "mbed.h"
00007 #include "ST7567.h"
00008 #include "rtos.h"
00009 
00010 /* LCD screen dimensions */
00011 #define LCD_HEIGHT          64
00012 #define LCD_WIDTH           128
00013 
00014 /* LCD font dimensions */
00015 #define FONT_HEIGHT         10
00016 #define FONT_WIDTH          5
00017 
00018 
00019 /** Instance a on board GLCD object */
00020  ST7567 glcd(D11, D13, D12, D9, D10);
00021  
00022  
00023  /* allocate statically stacks for the three threads */
00024 unsigned char app1_stk[1024];
00025 unsigned char app2_stk[1024];
00026 unsigned char app3_stk[1024];
00027 unsigned char shell_stk[4096];
00028 
00029 /* creates three tread objects with different priorities */
00030 Thread app1_thread(osPriorityNormal, 1024, &app1_stk[0]);
00031 Thread app2_thread(osPriorityHigh, 1024, &app2_stk[0]);
00032 Thread app3_thread(osPriorityNormal, 1024, &app3_stk[0]);
00033 Thread shell_thread(osPriorityRealtime, 4096, &shell_stk[0]);
00034  
00035  
00036  /** Instance a UART class to communicate with pc */
00037 Serial pc_serial(USBTX,USBRX);
00038 
00039 
00040 /**
00041  * @brief application demo task 
00042  */
00043 void app1_task(void) {
00044     const char thread_message[] = {"app1_task now running! \0"};
00045     for(;;) {
00046         /* each thread has the same behavior
00047          * waits for a signal and when it asserted
00048          * executes and keep sending a signal_set
00049          * in order to suspend only when requested via
00050          * terminal
00051          */
00052         app1_thread.signal_wait(1);
00053         app1_thread.signal_set(1);
00054         glcd.locate((LCD_WIDTH - (FONT_WIDTH * sizeof(thread_message)))/2,
00055                         (LCD_HEIGHT - FONT_HEIGHT) / 2);
00056         glcd.printf(thread_message);
00057     }
00058 }
00059 
00060 /**
00061  * @brief application demo task 
00062  */
00063 void app2_task(void) {
00064     const char thread_message[] = {"app2_task now running! \0"};
00065 
00066     for(;;) {
00067         app2_thread.signal_wait(1);
00068         app2_thread.signal_set(1);
00069         glcd.locate((LCD_WIDTH - (FONT_WIDTH * sizeof(thread_message)))/2,
00070                         (LCD_HEIGHT - FONT_HEIGHT) / 2);
00071         glcd.printf(thread_message);
00072     }
00073 }
00074 
00075 
00076 
00077 /**
00078  * @brief application demo task 
00079  */
00080 void app3_task(void) {
00081     const char thread_message[] = {"app3_task now running! \0"};
00082 
00083     for(;;) {
00084         app3_thread.signal_wait(1);
00085         app3_thread.signal_set(1);        
00086         glcd.locate((LCD_WIDTH - (FONT_WIDTH * sizeof(thread_message)))/2,
00087                        (LCD_HEIGHT - FONT_HEIGHT) / 2);
00088         glcd.printf(thread_message);
00089     }
00090 }
00091 
00092 
00093 /**
00094  * @brief thread_command interpreter
00095  */
00096 void shell_thread_execute_command(int argc, char **argv){
00097     
00098     Thread *ptr;
00099     
00100     /* check the argument number */
00101     if(argc < 2) {
00102         pc_serial.printf("## thread: too few arguments, exiting \n\r");
00103         return;
00104     }
00105     
00106     /* check which thread the shell command is claiming */
00107     if(strcmp("app1", argv[0])== 0) {
00108         ptr = &app1_thread;
00109     }else if (strcmp("app2", argv[0])==0) {
00110         ptr = &app2_thread;
00111     } else if (strcmp("app3", argv[0])==0) {
00112         ptr = &app3_thread;       
00113     }else {
00114         /* oops! invalid thread  */
00115         pc_serial.printf("## thread: invalid thread argument, exiting! \n\r");
00116         return;
00117     }   
00118     
00119     
00120     /* select which command */
00121     if(strcmp("resume", argv[1])== 0) {
00122         glcd.cls();
00123         ptr->signal_set(1);
00124         pc_serial.printf("## thread: Resuming the %s task! \n\r", argv[0]);           
00125     }else if (strcmp("suspend", argv[1]) == 0) {
00126         glcd.cls();
00127         ptr->signal_clr(1);
00128         pc_serial.printf("## thread: Suspending the %s task! \n\r", argv[0]);   
00129     }else{    
00130         /* oops! invalid thread  */
00131         pc_serial.printf("## thread: invalid option argument, exiting! \n\r");
00132         return;
00133     }   
00134     
00135 }
00136 
00137 
00138 /**
00139  * @brief show help menu 
00140  */
00141 static void print_usage(void) {
00142     pc_serial.printf("## use with the syntax below:         \n\r");
00143     pc_serial.printf("## command <arg1> <arg2> ... <arg16>  \n\r");
00144     pc_serial.printf("## Available commands:                \n\r");
00145     pc_serial.printf("## thread  <app1/2/3>  <suspend|resume>   : control thread execution \n\r");
00146     pc_serial.printf("##          app1/2/3:         name of desired thread\n\r");
00147     pc_serial.printf("##          suspend:          suspend selected thread from execution \n\r");
00148     pc_serial.printf("##          resume:           resume  selected thread execution \n\r");        
00149 }
00150 
00151  
00152 /**
00153  * @brief parse the command received via comport
00154  */
00155 static void shell_parser (char *cmd, int size) {
00156     int cmd_ptr = 0;
00157     int arg_ptr = 0;
00158     int cmd_size = 0;
00159     char command_buffer[256];
00160     
00161     int argc = 0;
00162     char *argv[16];    
00163     
00164     /* copy to the root command */
00165     memset(&command_buffer, 0, sizeof(command_buffer)); 
00166     
00167     /* find the root command terminator (space) */
00168     while(cmd_ptr < size) {
00169         if(cmd[cmd_ptr] == ' ') break;
00170         cmd_ptr++;
00171     }
00172     cmd_size = size - cmd_ptr;
00173     
00174     
00175     /* extract command arguments */
00176     strncpy(&command_buffer[0], &cmd[cmd_ptr + 1], (size - cmd_ptr));    
00177     
00178     /* terminates the root command */
00179     cmd[cmd_ptr] = 0;
00180     arg_ptr = 0;
00181     
00182     //pc_serial.printf("## command: %s \n\r", cmd);
00183     //pc_serial.printf("## arguments: %s \n\r", command_buffer);
00184 
00185   
00186     /* extract the further arguments */
00187     while(arg_ptr < (cmd_size)) {
00188  
00189         argc++;
00190         *(argv + (argc- 1)) = &command_buffer[arg_ptr];
00191  
00192         /* find terminator */
00193         while(command_buffer[arg_ptr] != ' ') {
00194             arg_ptr++;
00195         }
00196         
00197         /* adds to argument list */
00198         command_buffer[arg_ptr] = 0;
00199         arg_ptr++;       
00200        // pc_serial.printf("## argument no: %d : %s \n\r", argc, argv[argc-1]);
00201     }
00202 
00203 
00204 
00205     /* finds and execute the command table */
00206     if(strcmp("thread", cmd) == 0) { 
00207         shell_thread_execute_command(argc, argv);
00208     } else {
00209         print_usage();
00210     }    
00211 
00212 }
00213 
00214 
00215 
00216 
00217 /**
00218  * @brief shell commands processing thread 
00219  */
00220 static void shell_task(void)
00221 {
00222     char serial_buffer[1024] = {0};
00223     int read_ptr = 0;
00224     const char msg[] = {"Welcome to NXP FTF !\0"};
00225  
00226     /* setup the serial as 115200 bps */
00227     pc_serial.baud(115200);
00228 
00229 /* setup our on-board glcd */
00230     glcd.set_contrast(0x35);
00231     glcd.cls();
00232 
00233    /* Center the LCD cursor based on message size*/
00234     glcd.locate(LCD_WIDTH - (sizeof(msg) * FONT_WIDTH), 
00235                     (LCD_HEIGHT - FONT_HEIGHT) / 2);
00236 
00237     
00238     /* prints a welcome message */
00239     glcd.printf(msg);
00240     
00241     glcd.cls();
00242     Thread::wait(1000);
00243     
00244   
00245     pc_serial.printf("******************************************************************\n\r");    
00246     pc_serial.printf("***         Welcome to NXP FTF Simple Shell application      ****\n\r");
00247     pc_serial.printf("*** Type some commands or just Enter key to see the available ****\n\r");
00248     pc_serial.printf("******************************************************************\n\r");            
00249     pc_serial.printf(">>");
00250     
00251     for(;;Thread::wait(50)) {        
00252         /* check if we have character available */
00253         if(pc_serial.readable()) {
00254             bool new_cmd = false;
00255             
00256             /* get the incoming character */
00257             char c = pc_serial.getc();
00258                        
00259             if( (c == '\n') || (c == '\r')) {
00260                 /* handle enter key */
00261                 new_cmd = true;
00262                 pc_serial.printf("\n\r");
00263                 
00264             }else if( (c == 0x7F) || (c == 0x08)){
00265                 /* handle backspace and del keys */
00266                 pc_serial.printf("\033[1D");
00267                 pc_serial.putc(' ');
00268                 pc_serial.printf("\033[1D");
00269                 
00270                 read_ptr--;
00271                 if(read_ptr < -1) read_ptr = 1023;
00272                 serial_buffer[read_ptr] = ' ';
00273 
00274                 
00275             } else {
00276                 /* loopback the pressed key */
00277                 pc_serial.putc(c);
00278                 
00279                 /* store the incoming character on command circular buffer */
00280                 serial_buffer[read_ptr] = c;
00281                 read_ptr = (read_ptr + 1) % 1024;
00282             }
00283             
00284             
00285             
00286             if(new_cmd != false) {
00287                 /* command arrived, has other characters? */
00288                 if(read_ptr != 0) {
00289                     shell_parser(&serial_buffer[0], read_ptr);
00290                 } else {
00291                     print_usage();
00292                 }
00293                 /* reset the buffer command */
00294                 memset(&serial_buffer, 0, sizeof(serial_buffer));
00295                 read_ptr = 0;
00296                 pc_serial.printf(">>");
00297             } 
00298 
00299         }        
00300     }
00301 }
00302 
00303 static void idle_hook(void) {
00304         const char thread_message[] = {"No thread running!"};        
00305         glcd.locate((LCD_WIDTH - (FONT_WIDTH * sizeof(thread_message)))/2, 
00306                     (LCD_HEIGHT - FONT_HEIGHT) / 2);
00307         glcd.printf(thread_message);   
00308 }
00309 
00310 /**
00311  * @brief main application loop
00312  */
00313 int main(void) 
00314 {   
00315 
00316     glcd.cls();
00317 
00318     /* starts the shell task and applications task*/
00319     shell_thread.attach_idle_hook(idle_hook);
00320     shell_thread.start(shell_task);   
00321     app1_thread.start(app1_task);
00322     app2_thread.start(app2_task);
00323     app3_thread.start(app3_task); 
00324     return 0;
00325 }