app_irqs.c - demostrates IRQ handling in ESOS¶
ESOS application program to measure the pulse width of a button push using the 32-bit T2/T3 timer. Recreates the program ref timer32bit_switch_pulse_measure.c with the same functionality (see Figures 12.4-12.5 in the text) .. note:
Application demonstrates user interrupts under ESOS
- 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"
#include "pic24_timer.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
#define WAITING_FOR_FALLING_EDGE ESOS_USER_FLAG_0
#define CAPTURED_FLAG ESOS_USER_FLAG_1
PROTOTYPEs go here
- GLOBALs go here
- Generally, the user-created semaphores will be defined/allocated here
ESOS_SEMAPHORE( sem_CapturedData );
volatile UINT32 U32_lastCapture; // UINT32 declared in all_generic.h
volatile UINT32 U32_thisCapture;
volatile int32_t u32_delta;
/// Switch1 configuration, use RB13
inline void CONFIG_SW1() {
CONFIG_RB13_AS_DIG_INPUT(); //use RB13 for switch input
ENABLE_RB13_PULLUP(); //enable the pullup
CONFIG_INT1_TO_RP(13); //map INT1 to RP13
}
//Timer2/3 used as single 32-bit timer, control word of Timer2 controls timer,
//interrupt status of Timer3 used for the combined timer
void configTimer23(void) {
T2CON = T2_OFF | T2_IDLE_CON | T2_GATE_OFF
| T2_32BIT_MODE_ON
| T2_SOURCE_INT
| T2_PS_1_1 ;
PR2 = 0xFFFF; //maximum period
PR3 = 0xFFFF; //maximum period
TMR3HLD = 0; //write MSW first
TMR2 = 0; //then LSW
ESOS_MARK_PIC24_USER_INTERRUPT_SERVICED(ESOS_IRQ_PIC24_T3);
T2CONbits.TON = 1; //turn on the timer
}
/** Converts timer ticks to microseconds
* \param u32_ticks Timer ticks
* \param u16_tmrPre Timer prescale value
* \return time in microseconds
*/
uint32_t ticksToUs(uint32_t u32_ticks, uint16_t u16_tmrPre) {
return ((uint32_t) ((((uint64_t) u32_ticks) * ((uint64_t) u16_tmrPre) * (uint64_t) 1000000L) / ((uint64_t) FCY)));
}
//Interrupt Service Routine for INT1
//void _ISRFAST _INT1Interrupt (void) {
ESOS_USER_INTERRUPT( ESOS_IRQ_PIC24_INT1 ) {
ESOS_MARK_PIC24_USER_INTERRUPT_SERVICED(ESOS_IRQ_PIC24_INT1); //clear the interrupt bit
if (esos_IsUserFlagSet(WAITING_FOR_FALLING_EDGE)) {
if (esos_IsUserFlagClear(CAPTURED_FLAG)) {
U32_lastCapture.u16LoWord = TMR2;
U32_lastCapture.u16HiWord = TMR3HLD;
_INT1EP = 0; //configure for rising edge
esos_ClearUserFlag(WAITING_FOR_FALLING_EDGE);
} //endif CAPTURED_FLAG
} else {
U32_thisCapture.u16LoWord = TMR2;
U32_thisCapture.u16HiWord = TMR3HLD;
u32_delta = U32_thisCapture.u32 - U32_lastCapture.u32;
esos_SetUserFlag(CAPTURED_FLAG);
_INT1EP = 1; //configure for falling edge
esos_SetUserFlag(WAITING_FOR_FALLING_EDGE);
} //endif-else
} //end INT1 ISR
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
== task1 == Print out a counter value local to this task, then delay for a random period of time. (Delays range from approx. 0.25 - 4.1 seconds)
ESOS_USER_TASK(task1) {
static uint32_t u32_pulseWidth;
ESOS_TASK_BEGIN();
while (TRUE) {
Print prompt
ESOS_TASK_WAIT_ON_AVAILABLE_OUT_COMM();
ESOS_TASK_WAIT_ON_SEND_STRING("Press button...\r\n");
ESOS_TASK_SIGNAL_AVAILABLE_OUT_COMM();
Wait on capture flag
ESOS_TASK_WAIT_UNTIL(esos_IsUserFlagSet(CAPTURED_FLAG));
Convert processor ticks to microseconds
u32_pulseWidth = ticksToUs(u32_delta, getTimerPrescale(T2CONbits));
Clear capture flag
esos_ClearUserFlag(CAPTURED_FLAG);
Print delta times
ESOS_TASK_WAIT_ON_AVAILABLE_OUT_COMM();
ESOS_TASK_WAIT_ON_SEND_STRING("Ticks =\t\t");
ESOS_TASK_WAIT_ON_SEND_UINT32_AS_HEX_STRING(u32_delta);
ESOS_TASK_WAIT_ON_SEND_STRING("\r\n");
ESOS_TASK_WAIT_ON_SEND_STRING("Pulse width =\t");
ESOS_TASK_WAIT_ON_SEND_UINT32_AS_HEX_STRING(u32_pulseWidth);
ESOS_TASK_WAIT_ON_SEND_STRING(" us\r\n\r\n");
ESOS_TASK_SIGNAL_AVAILABLE_OUT_COMM();
} // endof while
ESOS_TASK_END();
} // end task1()
/****************************************************
* 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();
CONFIG_SW1();
configTimer23();
initialize the semaphore (initially blocking)
//ESOS_INIT_SEMAPHORE( sem_T1CanRun, 0 );
//ESOS_INIT_SEMAPHORE( sem_T2CanRun, 0 );
user_init() should register at least one user task
esos_RegisterTask(task1);
//esos_RegisterTask(task2);
register our callback function with ESOS to create a software timer
esos_RegisterTimer( swTimerLED, 250 );
Configure INT1
esos_SetUserFlag(WAITING_FOR_FALLING_EDGE);
_INT1EP = 1; //negative edge triggered
ESOS_REGISTER_PIC24_USER_INTERRUPT( ESOS_IRQ_PIC24_INT1, ESOS_USER_IRQ_LEVEL1, _INT1Interrupt);
ESOS_ENABLE_PIC24_USER_INTERRUPT(ESOS_IRQ_PIC24_INT1);
} // end user_init()