app_childtask.c - demonstrates child tasks¶
ESOS application program to recreate demonstrate child tasks in ESOS.
Application is a fancier version of the “Echo” program echo.c
in Chapter 8. (See Figure 8.6 in the text.)
In this version, the user selected a number 0-9 which is the increment to add each character in the “echo”. The application will echo until an exclamation point “!” is sent. Then, the user is prompted for a new increment and the process repeats.
Application also has a flashing LED on RB15. Flashing LED is generated by an software timer calling a user-provided callback function.
Note
Demonstrates child tasks (with input argument) and ESOS software timers
- INCLUDEs go here (First include the main esos.h file)
- After that, the user can include what they need
#include "esos.h"
#ifdef __linux
#include "esos_pc.h"
#include "esos_pc_stdio.h"
INCLUDE these so that printf() and our PC hacks work
#include <stdio.h>
#include <sys/select.h>
#include <termios.h>
#include <unistd.h>
#else
#include "esos_pic24.h"
#include "esos_pic24_rs232.h"
#endif
DEFINEs go here
#ifndef __linux
#define CONFIG_LED1() CONFIG_RB15_AS_DIG_OUTPUT()
#define LED1 _LATB15
#else
#define CONFIG_LED1() printf("called CONFIG_LED1()\n");
uint8_t LED1 = TRUE; // LED1 is initially "on"
#endif
PROTOTYPEs go here
- GLOBALs go here
- Generally, the user-created semaphores will be defined/allocated here
char psz_CRNL[3]= {0x0D, 0x0A, 0};
char psz_prompt[] = "Enter number 0-9 for echo increment: ";
char psz_done[9]= {' ','D','O','N','E','!',0x0D, 0x0A, 0};
#ifdef __linux
- Simulate the timer ISR found on a MCU
- The PC doesn’t have a timer ISR, so this task will periodically call the timer services callback instead. USED ONLY FOR DEVELOPMENT AND TESTING ON PC. Real MCU hardware doesn’t need this task
ESOS_USER_TASK( __simulated_isr ) {
ESOS_TASK_BEGIN();
while (TRUE) {
call the ESOS timer services callback just like a real H/W ISR would
__esos_tmrSvcsExecute();
ESOS_TASK_WAIT_TICKS( 1 );
} // endof while(TRUE)
ESOS_TASK_END();
} // end child_task
#endif
/************************************************************************
* User supplied functions
************************************************************************
*/
An ESOS software timer callback function strobe the heartbeat LED.
Toggles LED1 everytime the callback is called. Exact period is determined by application when this timer callback function is registered with ESOS. See ref esos_RegisterTimer Application can change timer period on-the-fly with ref esos_ChangeTimerPeriod
note Since this heartbeat is performed in an ESOS software timer callabck, a flashing LED indicates that the ESOS system tick ISR is being called properly. If the LED quits flashing, then the ESOS system tick has ceased working. This probably indicates some catastrophic failure of the system. However, the cause could be poorly-behaved user code that is manipulating the hardware registers with the timer or interrupt enables directly. ESOS provides functions to change state of interrupts and user code should never modify the hardware used by ESOS to implement the system tick. hideinitializer
user-created timer callback
ESOS_USER_TIMER( swTimerLED ) {
LED1 = !LED1;
#ifdef __linux
if (LED1) {
printf("\a");
fflush(stdout);
}
#endif
} //endof swTimerLED
Child task to echo incoming characters back with an arbitrary increment. Will continue echoing characters until user sends an exclamation point “!”
ESOS_CHILD_TASK(echo_child, uint8_t u8_in) {
static uint8_t u8_char;
ESOS_TASK_BEGIN();
do {
ESOS_TASK_WAIT_ON_AVAILABLE_IN_COMM();
ESOS_TASK_WAIT_ON_GET_UINT8(u8_char);
ESOS_TASK_SIGNAL_AVAILABLE_IN_COMM();
ESOS_TASK_WAIT_ON_AVAILABLE_OUT_COMM();
ESOS_TASK_WAIT_ON_SEND_UINT8(u8_char+u8_in);
ESOS_TASK_SIGNAL_AVAILABLE_OUT_COMM();
} while (u8_char != '!');
ESOS_TASK_WAIT_ON_AVAILABLE_OUT_COMM();
ESOS_TASK_WAIT_ON_SEND_STRING(psz_done);
ESOS_TASK_SIGNAL_AVAILABLE_OUT_COMM();
ESOS_TASK_END();
} // end echo_child()
Task to prompt user for the desired echo increment that is between 0-9. After getting increment, this task will spawn a child task to do the actual echo operation.
ESOS_USER_TASK(prompter) {
static uint8_t u8_char;
static ESOS_TASK_HANDLE th_child;
ESOS_TASK_BEGIN();
while (TRUE) {
ESOS_TASK_WAIT_ON_AVAILABLE_OUT_COMM();
ESOS_TASK_WAIT_ON_SEND_STRING(psz_prompt);
ESOS_TASK_WAIT_ON_AVAILABLE_IN_COMM();
do {
ESOS_TASK_WAIT_ON_GET_UINT8(u8_char);
} while ((u8_char < '0') | (u8_char > '9'));
ESOS_TASK_SIGNAL_AVAILABLE_IN_COMM();
ESOS_TASK_WAIT_ON_SEND_STRING(psz_CRNL);
ESOS_TASK_SIGNAL_AVAILABLE_OUT_COMM();
ESOS_ALLOCATE_CHILD_TASK(th_child);
ESOS_TASK_SPAWN_AND_WAIT(th_child, echo_child, u8_char-'0');
}
ESOS_TASK_END();
} // end prompter()
/****************************************************
* user_init()
****************************************************
*/
void user_init(void) {
Call the hardware-provided routines to print the HELLO_MSG to the screen. Must use this call because the ESOS communications subsystems is not yet fully initialized, since this call is in user_init()
In general, users should call hardware-specific function like this.
__esos_unsafe_PutString( HELLO_MSG );
#ifdef __linux
register our little ESOS task to mimic MCU’s TIMER T1 IRQ which kicks off the ESOS S/W timers when they expire
esos_RegisterTask( __simulated_isr );
#endif
configure our hardware to support to support our application
CONFIG_LED1();
user_init() should register at least one user task
esos_RegisterTask(prompter);
register our callback function with ESOS to create a software timer
esos_RegisterTimer( swTimerLED, 250);
} // end user_init()