Felipe Neves
/
ftf_mbed_lab3
ftf mbedos threads lab
Embed:
(wiki syntax)
Show/hide line numbers
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 }
Generated on Sat Jul 16 2022 20:37:39 by 1.7.2