ftf mbedos threads lab

Dependencies:   ST7567

Committer:
uLipe
Date:
Sat Nov 05 23:27:09 2016 +0000
Revision:
1:e7266223f1fa
Parent:
0:ead5ee0a33fa
added backspace support

Who changed what in which revision?

UserRevisionLine numberNew contents of line
uLipe 0:ead5ee0a33fa 1 /**
uLipe 0:ead5ee0a33fa 2 * @brief NXP FTF LAB3 - Mbed OS Threads control each thread execution
uLipe 0:ead5ee0a33fa 3 */
uLipe 0:ead5ee0a33fa 4
uLipe 0:ead5ee0a33fa 5
uLipe 0:ead5ee0a33fa 6 #include "mbed.h"
uLipe 0:ead5ee0a33fa 7 #include "ST7567.h"
uLipe 0:ead5ee0a33fa 8 #include "rtos.h"
uLipe 0:ead5ee0a33fa 9
uLipe 0:ead5ee0a33fa 10 /* LCD screen dimensions */
uLipe 0:ead5ee0a33fa 11 #define LCD_HEIGHT 64
uLipe 0:ead5ee0a33fa 12 #define LCD_WIDTH 128
uLipe 0:ead5ee0a33fa 13
uLipe 0:ead5ee0a33fa 14 /* LCD font dimensions */
uLipe 0:ead5ee0a33fa 15 #define FONT_HEIGHT 10
uLipe 0:ead5ee0a33fa 16 #define FONT_WIDTH 5
uLipe 0:ead5ee0a33fa 17
uLipe 0:ead5ee0a33fa 18
uLipe 0:ead5ee0a33fa 19 /** Instance a on board GLCD object */
uLipe 0:ead5ee0a33fa 20 ST7567 glcd(D11, D13, D12, D9, D10);
uLipe 0:ead5ee0a33fa 21
uLipe 0:ead5ee0a33fa 22
uLipe 0:ead5ee0a33fa 23 /* allocate statically stacks for the three threads */
uLipe 0:ead5ee0a33fa 24 unsigned char app1_stk[1024];
uLipe 0:ead5ee0a33fa 25 unsigned char app2_stk[1024];
uLipe 0:ead5ee0a33fa 26 unsigned char app3_stk[1024];
uLipe 0:ead5ee0a33fa 27 unsigned char shell_stk[4096];
uLipe 0:ead5ee0a33fa 28
uLipe 0:ead5ee0a33fa 29 /* creates three tread objects with different priorities */
uLipe 0:ead5ee0a33fa 30 Thread app1_thread(osPriorityNormal, 1024, &app1_stk[0]);
uLipe 0:ead5ee0a33fa 31 Thread app2_thread(osPriorityHigh, 1024, &app2_stk[0]);
uLipe 0:ead5ee0a33fa 32 Thread app3_thread(osPriorityNormal, 1024, &app3_stk[0]);
uLipe 0:ead5ee0a33fa 33 Thread shell_thread(osPriorityRealtime, 4096, &shell_stk[0]);
uLipe 0:ead5ee0a33fa 34
uLipe 0:ead5ee0a33fa 35
uLipe 0:ead5ee0a33fa 36 /** Instance a UART class to communicate with pc */
uLipe 0:ead5ee0a33fa 37 Serial pc_serial(USBTX,USBRX);
uLipe 0:ead5ee0a33fa 38
uLipe 0:ead5ee0a33fa 39
uLipe 0:ead5ee0a33fa 40 /**
uLipe 0:ead5ee0a33fa 41 * @brief application demo task
uLipe 0:ead5ee0a33fa 42 */
uLipe 0:ead5ee0a33fa 43 void app1_task(void) {
uLipe 0:ead5ee0a33fa 44 const char thread_message[] = {"app1_task now running! \0"};
uLipe 0:ead5ee0a33fa 45 for(;;) {
uLipe 1:e7266223f1fa 46 /* each thread has the same behavior
uLipe 1:e7266223f1fa 47 * waits for a signal and when it asserted
uLipe 1:e7266223f1fa 48 * executes and keep sending a signal_set
uLipe 1:e7266223f1fa 49 * in order to suspend only when requested via
uLipe 1:e7266223f1fa 50 * terminal
uLipe 1:e7266223f1fa 51 */
uLipe 0:ead5ee0a33fa 52 app1_thread.signal_wait(1);
uLipe 0:ead5ee0a33fa 53 app1_thread.signal_set(1);
uLipe 0:ead5ee0a33fa 54 glcd.locate((LCD_WIDTH - (FONT_WIDTH * sizeof(thread_message)))/2,
uLipe 0:ead5ee0a33fa 55 (LCD_HEIGHT - FONT_HEIGHT) / 2);
uLipe 0:ead5ee0a33fa 56 glcd.printf(thread_message);
uLipe 0:ead5ee0a33fa 57 }
uLipe 0:ead5ee0a33fa 58 }
uLipe 0:ead5ee0a33fa 59
uLipe 0:ead5ee0a33fa 60 /**
uLipe 0:ead5ee0a33fa 61 * @brief application demo task
uLipe 0:ead5ee0a33fa 62 */
uLipe 0:ead5ee0a33fa 63 void app2_task(void) {
uLipe 0:ead5ee0a33fa 64 const char thread_message[] = {"app2_task now running! \0"};
uLipe 0:ead5ee0a33fa 65
uLipe 0:ead5ee0a33fa 66 for(;;) {
uLipe 0:ead5ee0a33fa 67 app2_thread.signal_wait(1);
uLipe 0:ead5ee0a33fa 68 app2_thread.signal_set(1);
uLipe 0:ead5ee0a33fa 69 glcd.locate((LCD_WIDTH - (FONT_WIDTH * sizeof(thread_message)))/2,
uLipe 0:ead5ee0a33fa 70 (LCD_HEIGHT - FONT_HEIGHT) / 2);
uLipe 0:ead5ee0a33fa 71 glcd.printf(thread_message);
uLipe 0:ead5ee0a33fa 72 }
uLipe 0:ead5ee0a33fa 73 }
uLipe 0:ead5ee0a33fa 74
uLipe 0:ead5ee0a33fa 75
uLipe 0:ead5ee0a33fa 76
uLipe 0:ead5ee0a33fa 77 /**
uLipe 0:ead5ee0a33fa 78 * @brief application demo task
uLipe 0:ead5ee0a33fa 79 */
uLipe 0:ead5ee0a33fa 80 void app3_task(void) {
uLipe 0:ead5ee0a33fa 81 const char thread_message[] = {"app3_task now running! \0"};
uLipe 0:ead5ee0a33fa 82
uLipe 0:ead5ee0a33fa 83 for(;;) {
uLipe 0:ead5ee0a33fa 84 app3_thread.signal_wait(1);
uLipe 0:ead5ee0a33fa 85 app3_thread.signal_set(1);
uLipe 0:ead5ee0a33fa 86 glcd.locate((LCD_WIDTH - (FONT_WIDTH * sizeof(thread_message)))/2,
uLipe 0:ead5ee0a33fa 87 (LCD_HEIGHT - FONT_HEIGHT) / 2);
uLipe 0:ead5ee0a33fa 88 glcd.printf(thread_message);
uLipe 0:ead5ee0a33fa 89 }
uLipe 0:ead5ee0a33fa 90 }
uLipe 0:ead5ee0a33fa 91
uLipe 0:ead5ee0a33fa 92
uLipe 0:ead5ee0a33fa 93 /**
uLipe 0:ead5ee0a33fa 94 * @brief thread_command interpreter
uLipe 0:ead5ee0a33fa 95 */
uLipe 0:ead5ee0a33fa 96 void shell_thread_execute_command(int argc, char **argv){
uLipe 0:ead5ee0a33fa 97
uLipe 0:ead5ee0a33fa 98 Thread *ptr;
uLipe 0:ead5ee0a33fa 99
uLipe 0:ead5ee0a33fa 100 /* check the argument number */
uLipe 0:ead5ee0a33fa 101 if(argc < 2) {
uLipe 0:ead5ee0a33fa 102 pc_serial.printf("## thread: too few arguments, exiting \n\r");
uLipe 0:ead5ee0a33fa 103 return;
uLipe 0:ead5ee0a33fa 104 }
uLipe 0:ead5ee0a33fa 105
uLipe 0:ead5ee0a33fa 106 /* check which thread the shell command is claiming */
uLipe 0:ead5ee0a33fa 107 if(strcmp("app1", argv[0])== 0) {
uLipe 0:ead5ee0a33fa 108 ptr = &app1_thread;
uLipe 0:ead5ee0a33fa 109 }else if (strcmp("app2", argv[0])==0) {
uLipe 0:ead5ee0a33fa 110 ptr = &app2_thread;
uLipe 0:ead5ee0a33fa 111 } else if (strcmp("app3", argv[0])==0) {
uLipe 0:ead5ee0a33fa 112 ptr = &app3_thread;
uLipe 0:ead5ee0a33fa 113 }else {
uLipe 0:ead5ee0a33fa 114 /* oops! invalid thread */
uLipe 0:ead5ee0a33fa 115 pc_serial.printf("## thread: invalid thread argument, exiting! \n\r");
uLipe 0:ead5ee0a33fa 116 return;
uLipe 0:ead5ee0a33fa 117 }
uLipe 0:ead5ee0a33fa 118
uLipe 0:ead5ee0a33fa 119
uLipe 0:ead5ee0a33fa 120 /* select which command */
uLipe 0:ead5ee0a33fa 121 if(strcmp("resume", argv[1])== 0) {
uLipe 0:ead5ee0a33fa 122 glcd.cls();
uLipe 0:ead5ee0a33fa 123 ptr->signal_set(1);
uLipe 0:ead5ee0a33fa 124 pc_serial.printf("## thread: Resuming the %s task! \n\r", argv[0]);
uLipe 0:ead5ee0a33fa 125 }else if (strcmp("suspend", argv[1]) == 0) {
uLipe 0:ead5ee0a33fa 126 glcd.cls();
uLipe 0:ead5ee0a33fa 127 ptr->signal_clr(1);
uLipe 0:ead5ee0a33fa 128 pc_serial.printf("## thread: Suspending the %s task! \n\r", argv[0]);
uLipe 0:ead5ee0a33fa 129 }else{
uLipe 0:ead5ee0a33fa 130 /* oops! invalid thread */
uLipe 0:ead5ee0a33fa 131 pc_serial.printf("## thread: invalid option argument, exiting! \n\r");
uLipe 0:ead5ee0a33fa 132 return;
uLipe 0:ead5ee0a33fa 133 }
uLipe 0:ead5ee0a33fa 134
uLipe 0:ead5ee0a33fa 135 }
uLipe 0:ead5ee0a33fa 136
uLipe 0:ead5ee0a33fa 137
uLipe 0:ead5ee0a33fa 138 /**
uLipe 0:ead5ee0a33fa 139 * @brief show help menu
uLipe 0:ead5ee0a33fa 140 */
uLipe 0:ead5ee0a33fa 141 static void print_usage(void) {
uLipe 0:ead5ee0a33fa 142 pc_serial.printf("## use with the syntax below: \n\r");
uLipe 0:ead5ee0a33fa 143 pc_serial.printf("## command <arg1> <arg2> ... <arg16> \n\r");
uLipe 0:ead5ee0a33fa 144 pc_serial.printf("## Available commands: \n\r");
uLipe 0:ead5ee0a33fa 145 pc_serial.printf("## thread <app1/2/3> <suspend|resume> : control thread execution \n\r");
uLipe 0:ead5ee0a33fa 146 pc_serial.printf("## app1/2/3: name of desired thread\n\r");
uLipe 0:ead5ee0a33fa 147 pc_serial.printf("## suspend: suspend selected thread from execution \n\r");
uLipe 0:ead5ee0a33fa 148 pc_serial.printf("## resume: resume selected thread execution \n\r");
uLipe 0:ead5ee0a33fa 149 }
uLipe 0:ead5ee0a33fa 150
uLipe 0:ead5ee0a33fa 151
uLipe 0:ead5ee0a33fa 152 /**
uLipe 0:ead5ee0a33fa 153 * @brief parse the command received via comport
uLipe 0:ead5ee0a33fa 154 */
uLipe 0:ead5ee0a33fa 155 static void shell_parser (char *cmd, int size) {
uLipe 0:ead5ee0a33fa 156 int cmd_ptr = 0;
uLipe 0:ead5ee0a33fa 157 int arg_ptr = 0;
uLipe 0:ead5ee0a33fa 158 int cmd_size = 0;
uLipe 0:ead5ee0a33fa 159 char command_buffer[256];
uLipe 0:ead5ee0a33fa 160
uLipe 0:ead5ee0a33fa 161 int argc = 0;
uLipe 0:ead5ee0a33fa 162 char *argv[16];
uLipe 0:ead5ee0a33fa 163
uLipe 0:ead5ee0a33fa 164 /* copy to the root command */
uLipe 0:ead5ee0a33fa 165 memset(&command_buffer, 0, sizeof(command_buffer));
uLipe 0:ead5ee0a33fa 166
uLipe 0:ead5ee0a33fa 167 /* find the root command terminator (space) */
uLipe 0:ead5ee0a33fa 168 while(cmd_ptr < size) {
uLipe 0:ead5ee0a33fa 169 if(cmd[cmd_ptr] == ' ') break;
uLipe 0:ead5ee0a33fa 170 cmd_ptr++;
uLipe 0:ead5ee0a33fa 171 }
uLipe 0:ead5ee0a33fa 172 cmd_size = size - cmd_ptr;
uLipe 0:ead5ee0a33fa 173
uLipe 0:ead5ee0a33fa 174
uLipe 0:ead5ee0a33fa 175 /* extract command arguments */
uLipe 0:ead5ee0a33fa 176 strncpy(&command_buffer[0], &cmd[cmd_ptr + 1], (size - cmd_ptr));
uLipe 0:ead5ee0a33fa 177
uLipe 0:ead5ee0a33fa 178 /* terminates the root command */
uLipe 0:ead5ee0a33fa 179 cmd[cmd_ptr] = 0;
uLipe 0:ead5ee0a33fa 180 arg_ptr = 0;
uLipe 0:ead5ee0a33fa 181
uLipe 0:ead5ee0a33fa 182 //pc_serial.printf("## command: %s \n\r", cmd);
uLipe 0:ead5ee0a33fa 183 //pc_serial.printf("## arguments: %s \n\r", command_buffer);
uLipe 0:ead5ee0a33fa 184
uLipe 0:ead5ee0a33fa 185
uLipe 0:ead5ee0a33fa 186 /* extract the further arguments */
uLipe 0:ead5ee0a33fa 187 while(arg_ptr < (cmd_size)) {
uLipe 0:ead5ee0a33fa 188
uLipe 0:ead5ee0a33fa 189 argc++;
uLipe 0:ead5ee0a33fa 190 *(argv + (argc- 1)) = &command_buffer[arg_ptr];
uLipe 0:ead5ee0a33fa 191
uLipe 0:ead5ee0a33fa 192 /* find terminator */
uLipe 0:ead5ee0a33fa 193 while(command_buffer[arg_ptr] != ' ') {
uLipe 0:ead5ee0a33fa 194 arg_ptr++;
uLipe 0:ead5ee0a33fa 195 }
uLipe 0:ead5ee0a33fa 196
uLipe 0:ead5ee0a33fa 197 /* adds to argument list */
uLipe 0:ead5ee0a33fa 198 command_buffer[arg_ptr] = 0;
uLipe 0:ead5ee0a33fa 199 arg_ptr++;
uLipe 0:ead5ee0a33fa 200 // pc_serial.printf("## argument no: %d : %s \n\r", argc, argv[argc-1]);
uLipe 0:ead5ee0a33fa 201 }
uLipe 0:ead5ee0a33fa 202
uLipe 0:ead5ee0a33fa 203
uLipe 0:ead5ee0a33fa 204
uLipe 0:ead5ee0a33fa 205 /* finds and execute the command table */
uLipe 0:ead5ee0a33fa 206 if(strcmp("thread", cmd) == 0) {
uLipe 0:ead5ee0a33fa 207 shell_thread_execute_command(argc, argv);
uLipe 0:ead5ee0a33fa 208 } else {
uLipe 0:ead5ee0a33fa 209 print_usage();
uLipe 0:ead5ee0a33fa 210 }
uLipe 0:ead5ee0a33fa 211
uLipe 0:ead5ee0a33fa 212 }
uLipe 0:ead5ee0a33fa 213
uLipe 0:ead5ee0a33fa 214
uLipe 0:ead5ee0a33fa 215
uLipe 0:ead5ee0a33fa 216
uLipe 0:ead5ee0a33fa 217 /**
uLipe 0:ead5ee0a33fa 218 * @brief shell commands processing thread
uLipe 0:ead5ee0a33fa 219 */
uLipe 0:ead5ee0a33fa 220 static void shell_task(void)
uLipe 0:ead5ee0a33fa 221 {
uLipe 0:ead5ee0a33fa 222 char serial_buffer[1024] = {0};
uLipe 0:ead5ee0a33fa 223 int read_ptr = 0;
uLipe 0:ead5ee0a33fa 224 const char msg[] = {"Welcome to NXP FTF !\0"};
uLipe 0:ead5ee0a33fa 225
uLipe 0:ead5ee0a33fa 226 /* setup the serial as 115200 bps */
uLipe 0:ead5ee0a33fa 227 pc_serial.baud(115200);
uLipe 0:ead5ee0a33fa 228
uLipe 0:ead5ee0a33fa 229 /* setup our on-board glcd */
uLipe 0:ead5ee0a33fa 230 glcd.set_contrast(0x35);
uLipe 0:ead5ee0a33fa 231 glcd.cls();
uLipe 0:ead5ee0a33fa 232
uLipe 0:ead5ee0a33fa 233 /* Center the LCD cursor based on message size*/
uLipe 0:ead5ee0a33fa 234 glcd.locate(LCD_WIDTH - (sizeof(msg) * FONT_WIDTH),
uLipe 0:ead5ee0a33fa 235 (LCD_HEIGHT - FONT_HEIGHT) / 2);
uLipe 0:ead5ee0a33fa 236
uLipe 0:ead5ee0a33fa 237
uLipe 0:ead5ee0a33fa 238 /* prints a welcome message */
uLipe 0:ead5ee0a33fa 239 glcd.printf(msg);
uLipe 0:ead5ee0a33fa 240
uLipe 0:ead5ee0a33fa 241 glcd.cls();
uLipe 0:ead5ee0a33fa 242 Thread::wait(1000);
uLipe 0:ead5ee0a33fa 243
uLipe 0:ead5ee0a33fa 244
uLipe 0:ead5ee0a33fa 245 pc_serial.printf("******************************************************************\n\r");
uLipe 0:ead5ee0a33fa 246 pc_serial.printf("*** Welcome to NXP FTF Simple Shell application ****\n\r");
uLipe 0:ead5ee0a33fa 247 pc_serial.printf("*** Type some commands or just Enter key to see the available ****\n\r");
uLipe 0:ead5ee0a33fa 248 pc_serial.printf("******************************************************************\n\r");
uLipe 0:ead5ee0a33fa 249 pc_serial.printf(">>");
uLipe 0:ead5ee0a33fa 250
uLipe 0:ead5ee0a33fa 251 for(;;Thread::wait(50)) {
uLipe 0:ead5ee0a33fa 252 /* check if we have character available */
uLipe 0:ead5ee0a33fa 253 if(pc_serial.readable()) {
uLipe 0:ead5ee0a33fa 254 bool new_cmd = false;
uLipe 0:ead5ee0a33fa 255
uLipe 0:ead5ee0a33fa 256 /* get the incoming character */
uLipe 0:ead5ee0a33fa 257 char c = pc_serial.getc();
uLipe 1:e7266223f1fa 258
uLipe 0:ead5ee0a33fa 259 if( (c == '\n') || (c == '\r')) {
uLipe 1:e7266223f1fa 260 /* handle enter key */
uLipe 0:ead5ee0a33fa 261 new_cmd = true;
uLipe 1:e7266223f1fa 262 pc_serial.printf("\n\r");
uLipe 1:e7266223f1fa 263
uLipe 1:e7266223f1fa 264 }else if( (c == 0x7F) || (c == 0x08)){
uLipe 1:e7266223f1fa 265 /* handle backspace and del keys */
uLipe 1:e7266223f1fa 266 pc_serial.printf("\033[1D");
uLipe 1:e7266223f1fa 267 pc_serial.putc(' ');
uLipe 1:e7266223f1fa 268 pc_serial.printf("\033[1D");
uLipe 1:e7266223f1fa 269
uLipe 1:e7266223f1fa 270 read_ptr--;
uLipe 1:e7266223f1fa 271 if(read_ptr < -1) read_ptr = 1023;
uLipe 1:e7266223f1fa 272 serial_buffer[read_ptr] = ' ';
uLipe 1:e7266223f1fa 273
uLipe 0:ead5ee0a33fa 274
uLipe 0:ead5ee0a33fa 275 } else {
uLipe 1:e7266223f1fa 276 /* loopback the pressed key */
uLipe 1:e7266223f1fa 277 pc_serial.putc(c);
uLipe 1:e7266223f1fa 278
uLipe 1:e7266223f1fa 279 /* store the incoming character on command circular buffer */
uLipe 0:ead5ee0a33fa 280 serial_buffer[read_ptr] = c;
uLipe 0:ead5ee0a33fa 281 read_ptr = (read_ptr + 1) % 1024;
uLipe 0:ead5ee0a33fa 282 }
uLipe 0:ead5ee0a33fa 283
uLipe 1:e7266223f1fa 284
uLipe 1:e7266223f1fa 285
uLipe 0:ead5ee0a33fa 286 if(new_cmd != false) {
uLipe 0:ead5ee0a33fa 287 /* command arrived, has other characters? */
uLipe 0:ead5ee0a33fa 288 if(read_ptr != 0) {
uLipe 0:ead5ee0a33fa 289 shell_parser(&serial_buffer[0], read_ptr);
uLipe 0:ead5ee0a33fa 290 } else {
uLipe 0:ead5ee0a33fa 291 print_usage();
uLipe 0:ead5ee0a33fa 292 }
uLipe 0:ead5ee0a33fa 293 /* reset the buffer command */
uLipe 0:ead5ee0a33fa 294 memset(&serial_buffer, 0, sizeof(serial_buffer));
uLipe 0:ead5ee0a33fa 295 read_ptr = 0;
uLipe 0:ead5ee0a33fa 296 pc_serial.printf(">>");
uLipe 0:ead5ee0a33fa 297 }
uLipe 0:ead5ee0a33fa 298
uLipe 0:ead5ee0a33fa 299 }
uLipe 0:ead5ee0a33fa 300 }
uLipe 0:ead5ee0a33fa 301 }
uLipe 0:ead5ee0a33fa 302
uLipe 0:ead5ee0a33fa 303 static void idle_hook(void) {
uLipe 1:e7266223f1fa 304 const char thread_message[] = {"No thread running!"};
uLipe 0:ead5ee0a33fa 305 glcd.locate((LCD_WIDTH - (FONT_WIDTH * sizeof(thread_message)))/2,
uLipe 0:ead5ee0a33fa 306 (LCD_HEIGHT - FONT_HEIGHT) / 2);
uLipe 0:ead5ee0a33fa 307 glcd.printf(thread_message);
uLipe 0:ead5ee0a33fa 308 }
uLipe 0:ead5ee0a33fa 309
uLipe 0:ead5ee0a33fa 310 /**
uLipe 0:ead5ee0a33fa 311 * @brief main application loop
uLipe 0:ead5ee0a33fa 312 */
uLipe 0:ead5ee0a33fa 313 int main(void)
uLipe 0:ead5ee0a33fa 314 {
uLipe 0:ead5ee0a33fa 315
uLipe 0:ead5ee0a33fa 316 glcd.cls();
uLipe 0:ead5ee0a33fa 317
uLipe 0:ead5ee0a33fa 318 /* starts the shell task and applications task*/
uLipe 0:ead5ee0a33fa 319 shell_thread.attach_idle_hook(idle_hook);
uLipe 0:ead5ee0a33fa 320 shell_thread.start(shell_task);
uLipe 0:ead5ee0a33fa 321 app1_thread.start(app1_task);
uLipe 0:ead5ee0a33fa 322 app2_thread.start(app2_task);
uLipe 0:ead5ee0a33fa 323 app3_thread.start(app3_task);
uLipe 0:ead5ee0a33fa 324 return 0;
uLipe 0:ead5ee0a33fa 325 }