/************************************************************************* This file is part of aOS. aOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. aOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with aOS; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Copyright 2001, 2002 Anssi Ylätalo ================================== March 2005 Modified by Bruce Land to include: A command line interface **************************************************************************/ #include #include #include #include "aos.h" #include "user_tasks.h" #include "aos_core.c" #include "aos_task.c" #include "aos_semaphore.c" //omit if no semaphores or mail used #include "aos_mbox.c" //omit if no mailboxes (needs semaphore) #include "aos_uart.c" //omit if you don't need UART (needs mbox & cmd) //global variables for all tasks //force the data to be in RAM using pragma #pragma regalloc- aos_mailbox *task23_pipe ; /*string from task2 to task3*/ //temps for the cmd process ; //MUST BE global so asm can find them unsigned char temp, temp1, temp2, temp4 ; UWORD temp3; char store_demo @0x7d0; //allow register vars again #pragma regalloc+ //******************************************************** // This command shell task must run at highest priority // so that it can stomp on all other processes void cmd( void ) { unsigned char cmd1str[32], current_char, in_count; unsigned char t0temp, t1temp, t2temp; char i; //array of task control block pointers for the cmd process ; aos_tcb *t[AOS_TASK_MAX]; aos_scb *s[AOS_SEM_MAX]; //aos_mcb *m[AOS_MBOX_MAX] //start 3 tasks and retrun control block pointers t[2]=aos_task_create( task2, hw_stack2, data_stack2, 100 ); t[3]=aos_task_create( task3, hw_stack3, data_stack3, 150 ); t[4]=aos_task_create( task4, hw_stack4, data_stack4, 200 ); //allocate UART structures, turn on UART //parameter is baud rate given as an integer //This routine uses the clock value set in the //Project...Config dialog!! aos_init_uart(9600); //This is a test to make sure the system does not fail //and reboot itself printf("\r\r\n aOS 18Sept2005\r\n"); // while (PINC.0==1){}; //init portB to output DDRB = 0xff ; PORTB = 0xff; //init portC to input DDRC = 0x00; while(1) { //wait for an external event to wake up cmd shell aos_suspend_task(cmd_tcb); //clear interrupts and freeze the timers #asm("cli") t0temp = TCCR0; t1temp = TCCR1B; t2temp = TCCR2; TCCR0 = 0; TCCR1B = 0; TCCR2 = 0; //print break source: 255 is printf("Break ID:%d\r\n",aos_break_id); cmd1str[0]=0; /* command list -- all commands are terminated by an -- stop tasks and enter cmd shell with BreakID=255 break(char BreakID) -- enters the shell from running code g -- exit cmd shell and run tasks x -- reboot mcu i ioreg -- read i/o register, register# in hex I ioreg data -- write i/o register, register# and data in hex t tasknumber query -- tasknumber assigned at beginning of cmd as the index of t[tasknumber] -- query -- t total execution time since RESET -- s status: see aos.h for status values -- x suspend -- r resume -- d data stack free -- h hardware stack free -- w remaining wait time r tasknumber datareg -- read task data register: datareg number in decimal: output in hex R tasknumber datareg data -- write task data register m addr -- read memory M addr dat -- write memory s semaphore -- c count -- q next qued task h -- help */ //loop until a go command exits to main program while(cmd1str[0]!='g') { //get the next shell command //handles backspace, printf("aOS>"); in_count=0; while ( (current_char=getchar()) != '\r' ) // { putchar(current_char); if (current_char == 0x08) //backspace --in_count; else cmd1str[in_count++]=current_char; } cmd1str[in_count] = 0; //terminate the string putchar('\r'); //emit carriage return putchar('\n'); //line feed makes output nicer //execute the shell command //printf("%s\r\n", cmd1str); //reset -- this forces a reboot!!! if (cmd1str[0]=='x') { while(!UCSRA.5); //allows last char to send before UART is reset #asm jmp 0 ;reset vector #endasm } //read an i/o register if (cmd1str[0]=='i') { sscanf(cmd1str,"%c%x", &temp, &temp1); //check to see if ioreg is timer control //(which were saved when cmd was entered) if (temp1==0x33) temp = t0temp; else if (temp1==0x2e) temp = t1temp; else if (temp1==0x25) temp = t2temp; else { #asm push r26 push r27 push r16 lds r26, _temp1 ;address of ioregister ldi r27, 0 ;always zero when ioreg adiw r27:r26, 0x20 ;ioreg 0 position in memory ld r16, x ;get the ioreg contents sts _temp, r16 ;and store ioreg contents pop r16 pop r27 pop r26 #endasm } printf("ioport %x= %x\n\r",temp1,temp) ; } //write an i/o register if (cmd1str[0]=='I') { sscanf(cmd1str,"%c%x%x", &temp,&temp1, &temp2); //check to see if ioreg is timer control //(which were saved when cmd was entered) if (temp1==0x33) t0temp = temp2; else if (temp1==0x2e) t1temp = temp2; else if (temp1==0x25) t2temp = temp2; else { #asm push r26 push r27 push r16 lds r16, _temp2 ;data to be put in ioreg lds r26, _temp1 ;address of ioregister ldi r27, 0 ;always zero when ioreg adiw r27:r26, 0x20 ;ioreg 0 position in memory st x, r16 ;set the ioreg contents pop r16 pop r27 pop r26 #endasm } } //all task operations if(cmd1str[0]=='t') { sscanf(cmd1str,"%c%d%c", &temp, &temp1, &temp2); if (t[temp1]!=0) { if (temp2=='t' && AOS_CHCK==1) printf("Task %d time = %ld\n\r", temp1, aos_task_gettime(t[temp1])) ; if (temp2=='s') printf("Task %d status = %d\n\r", temp1, aos_task_getstatus(t[temp1])) ; if (temp2=='x') aos_suspend_task(t[temp1]); if (temp2=='r') aos_resume_task(t[temp1]); if (temp2=='d') printf("Task %d dstk free = %ld\n\r", temp1, aos_task_dstk_chck(t[temp1])); if (temp2=='h') printf("Task %d hstk free = %ld\n\r", temp1, aos_task_hstk_chck(t[temp1])); if (temp2=='w') printf("Task %d wait time = %d\n\r", temp1, t[temp1]->delay); } } //read a data register //This is tricky because each task has its own registers //so you have to retreive the registers from the right stack if(cmd1str[0]=='r') { sscanf(cmd1str,"%c%d%d", &temp,&temp1, &temp2); if (t[temp1]!=0) { //get the task stack pointer from the tcb temp3 = t[temp1]->hwstk ; #asm push r26 push r27 push r18 push r16 push r17 lds r26, _temp3 ;address of stack lds r27, _temp3+1 adiw r27:r26, 31 ;reg 0 position ( 35 bytes of state) lds r16, _temp2 ;reg number ldi r17, 0 sub r26, r16 ;subtact the actual reg number sbc r27, r17 ld r18, x ;get the reg contents sts _temp, r18 ;and store reg contents pop r17 pop r16 pop r18 pop r27 pop r26 #endasm printf("Task %d reg %d= %x\n\r",temp1, temp2, temp); } } //WRITE a data register //This is tricky because each task has its own registers //so you have to retreive the registers from the right stack if(cmd1str[0]=='R') { sscanf(cmd1str,"%c%d%d%x", &temp,&temp1, &temp2, &temp4); if (t[temp1]!=0) { //get the task stack pointer from the tcb temp3 = t[temp1]->hwstk ; #asm push r26 push r27 push r18 push r16 push r17 lds r26, _temp3 ;address of stack lds r27, _temp3+1 adiw r27:r26, 31 ;reg 0 position ( 35 bytes of state) lds r16, _temp2 ;reg number ldi r17, 0 sub r26, r16 ;subtact the actual reg number sbc r27, r17 lds r18, _temp4 ;get the data to write st x, r18 ;and write it pop r17 pop r16 pop r18 pop r27 pop r26 #endasm printf("Task %d reg %d> %x\n\r",temp1, temp2, temp4); } } //read an memory location if (cmd1str[0]=='m') { sscanf(cmd1str,"%c%x", &temp, &temp3); #asm push r26 push r27 push r16 lds r26, _temp3 ;low address of memory lds r27, _temp3+1 ;high address of memory ld r16, x ;get the memory contents sts _temp, r16 ;and save memory contents pop r16 pop r27 pop r26 #endasm printf("memory %x= %x\n\r",temp3,temp) ; } //WRITE an memory location if (cmd1str[0]=='M') { sscanf(cmd1str,"%c%x%x", &temp, &temp3, &temp4); #asm push r26 push r27 push r16 lds r26, _temp3 ;low address of memory lds r27, _temp3+1 ;high address of memory lds r16, _temp4 ;get the data st x, r16 ;put it in memory pop r16 pop r27 pop r26 #endasm printf("memory %x> %x\n\r",temp3,temp4) ; } //semaphore if (cmd1str[0]=='s') { sscanf(cmd1str,"%c%x%c", &temp, &temp1, &temp2); //get pointers to the scb and //slap them in an array i=0; s[i] = aos_ctbl.scb_used_list ; //scan list for valid semaphores while (s[i]->next_scb && inext_scb ; i++; } // i is total number of defined semaphores + 1 if (temp2=='c' && temp1<=i) //count printf("Sem %d count= %d\r\n", temp1, s[temp1]->count); if (temp2=='q' && temp1<=i) //next task { temp3 = s[temp1]->scb_sem_q; if (temp3>0) { i=0; while (t[i]!=temp3) i++; } else i=0xff; printf("Sem %d next task qued = %x\r\n", temp1, i ); } } //help if (cmd1str[0]=='h') { printf(" or break(BreakID) -- stop tasks\r\n"); printf("g -- exit shell and run tasks \r\n"); printf("x -- reboot mcu \r\n"); printf("i ioreg -- read i/o register; ioreg in hex\r\n"); printf("I ioreg data -- write i/o register - hex\r\n"); printf("t tasknumber query\r\n") ; printf(" t total execution time \r\n"); printf(" s status\r\n"); printf(" x suspend\r\n"); printf(" r resume\r\n") ; printf(" d data stack free\r\n"); printf(" h hardware stack free\r\n"); printf(" w remaining wait time\r\n"); printf("r tasknumber datareg; read \r\n"); printf("R tasknumber datareg data; write\r\n"); printf("m addr -- read memory; hex\r\n") ; printf("M addr dat -- write memory; hex\r\n"); printf("s semaphore query; c-count; q-next task \r\n"); } } //if comand was 'g' then unfreeze the timers, start ISRs //then suspend the cmd shell (at the top of the outer loop) TCCR0 = t0temp; TCCR1B = t1temp; TCCR2 = t2temp; #asm("sei") } } //******************************************************** void task2( void ) { char t2str[32]; //make a commuinctions channel from task 2 to task 3 task23_pipe = aos_mbox_create(); while(1) { //toggle the led PORTB ^= 0x02; //read user input aos_gets(t2str); //allow a break to check semaphores if (PINC.1==0) aos_break(2); //and send it aos_mbox_send(task23_pipe,t2str); } } //******************************************************** void task3( void ) { char *msg; char crlf[4]; //create memory lock sem //sem_memory = (aos_semaphore *)aos_sem_create( 1 ); while(1) { //toggle the led PORTB ^= 0x04; //wait for a message msg = aos_mbox_recv(task23_pipe); //and print it aos_puts(msg); //crlf sprintf(crlf,"\n\r"); aos_puts(crlf); } } //******************************************************** void task4( void ) { while(1) { aos_sleep(20); //toggle the led PORTB ^= 0x08; //test break function and test register and memory read if (PINC.0==0) { #asm ldi r16,0x55 ;r16 is trashed mov r1, r16 ;store to r1 sts _store_demo, r1 ;store to memory #endasm aos_break(4); } } } //********************************************************