PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
app_irqs.c
Go to the documentation of this file.
1 /*
2  * "Copyright (c) 2008 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
3  * All rights reserved.
4  * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
5  * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
6  * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation for any purpose, without fee, and without written agreement is
10  * hereby granted, provided that the above copyright notice, the following
11  * two paragraphs and the authors appear in all copies of this software.
12  *
13  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
15  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
16  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17  *
18  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
23  *
24  * Please maintain this header in its entirety when copying/modifying
25  * these files.
26  *
27  *
28  */
29 
30 /** \file
31  * ESOS application program to measure the pulse width of a button push
32  * using the 32-bit T2/T3 timer. Recreates the program
33  * \ref timer32bit_switch_pulse_measure.c with the same
34  * functionality (see Figures 12.4-12.5 in the text)
35  * \note Application demonstrates user interrupts under ESOS
36  */
37 
38 // INCLUDEs go here (First include the main esos.h file)
39 // After that, the user can include what they need
40 #include "esos.h"
41 #ifdef __linux
42 #include "esos_pc.h"
43 #include "esos_pc_stdio.h"
44 
45 // INCLUDE these so that printf() and our PC hacks work
46 #include <stdio.h>
47 #include <sys/select.h>
48 #include <termios.h>
49 #include <unistd.h>
50 #else
51 #include "esos_pic24.h"
52 #include "esos_pic24_rs232.h"
53 #include "pic24_timer.h"
54 #endif
55 
56 // DEFINEs go here
57 #ifndef __linux
58 #define CONFIG_LED1() CONFIG_RB15_AS_DIG_OUTPUT()
59 #define LED1 _LATB15
60 #else
61 #define CONFIG_LED1() printf("called CONFIG_LED1()\n");
62 uint8_t LED1 = TRUE; // LED1 is initially "on"
63 #endif
64 
65 
66 #define WAITING_FOR_FALLING_EDGE ESOS_USER_FLAG_0
67 #define CAPTURED_FLAG ESOS_USER_FLAG_1
68 
69 // PROTOTYPEs go here
70 
71 // GLOBALs go here
72 // Generally, the user-created semaphores will be defined/allocated here
73 char psz_CRNL[3]= {0x0D, 0x0A, 0};
74 char psz_prompt[] = "Press button...";
75 char psz_r1[] = "Pulse width = ";
76 char psz_r2[] = "us\n";
77 
78 ESOS_SEMAPHORE( sem_CapturedData );
79 
80 volatile UINT32 U32_lastCapture; // UINT32 declared in all_generic.h
81 volatile UINT32 U32_thisCapture;
82 volatile int32_t u32_delta;
83 
84 /// Switch1 configuration, use RB13
85 inline void CONFIG_SW1() {
86  CONFIG_RB13_AS_DIG_INPUT(); //use RB13 for switch input
87  ENABLE_RB13_PULLUP(); //enable the pullup
88  CONFIG_INT1_TO_RP(13); //map INT1 to RP13
89 }
90 
91 //Timer2/3 used as single 32-bit timer, control word of Timer2 controls timer,
92 //interrupt status of Timer3 used for the combined timer
93 void configTimer23(void) {
94  T2CON = T2_OFF | T2_IDLE_CON | T2_GATE_OFF
95  | T2_32BIT_MODE_ON
96  | T2_SOURCE_INT
97  | T2_PS_1_1 ;
98  PR2 = 0xFFFF; //maximum period
99  PR3 = 0xFFFF; //maximum period
100  TMR3HLD = 0; //write MSW first
101  TMR2 = 0; //then LSW
103  T2CONbits.TON = 1; //turn on the timer
104 }
105 
106 //Interrupt Service Routine for INT1
107 //void _ISRFAST _INT1Interrupt (void) {
110  if (esos_IsUserFlagSet(WAITING_FOR_FALLING_EDGE)) {
111  if (esos_IsUserFlagClear(CAPTURED_FLAG)) {
112  U32_lastCapture.u16LoWord = TMR2;
113  U32_lastCapture.u16HiWord = TMR3HLD;
114  _INT1EP = 0; //configure for rising edge
115  esos_ClearUserFlag(WAITING_FOR_FALLING_EDGE);
116  } //endif CAPTURED_FLAG
117  } else {
118  U32_thisCapture.u16LoWord = TMR2;
119  U32_thisCapture.u16HiWord = TMR3HLD;
120  u32_delta = U32_thisCapture.u32 - U32_lastCapture.u32;
121  esos_SetUserFlag(CAPTURED_FLAG);
122  _INT1EP = 1; //configure for falling edge
123  esos_SetUserFlag(WAITING_FOR_FALLING_EDGE);
124  } //endif-else
125 } //end INT1 ISR
126 
127 
128 /*
129  * An ESOS software timer callback function strobe the heartbeat LED.
130  *
131  * Toggles LED1 everytime the callback is called. Exact period is
132  * determined by application when this timer callback function is
133  * registered with ESOS. See \ref esos_RegisterTimer
134  * Application can change timer period on-the-fly with \ref esos_ChangeTimerPeriod
135  *
136  * \note Since this heartbeat is performed in an ESOS software
137  * timer callabck, a flashing LED indicates that the ESOS system
138  * tick ISR is being called properly. If the LED quits flashing,
139  * then the ESOS system tick has ceased working. This probably indicates
140  * some catastrophic failure of the system. However, the cause could
141  * be poorly-behaved user code that is manipulating the hardware registers
142  * with the timer or interrupt enables directly. ESOS provides functions
143  * to change state of interrupts and user code should never modify the
144  * hardware used by ESOS to implement the system tick.
145  * \hideinitializer
146  */
147 
148 // user-created timer callback
149 ESOS_USER_TIMER( swTimerLED ) {
150  LED1 = !LED1;
151 #ifdef __linux
152  if (LED1) {
153  printf("\a");
154  fflush(stdout);
155  }
156 #endif
157 } //endof swTimerLED
158 
159 /* == task1 ==
160  * Print out a counter value local to this task, then delay
161  * for a random period of time. (Delays range from approx.
162  * 0.25 - 4.1 seconds)
163  */
164 ESOS_USER_TASK(task1) {
165  static uint32_t u32_pulseWidth;
166 
167  ESOS_TASK_BEGIN();
168  while (TRUE) {
169  ESOS_TASK_WAIT_ON_SEND_STRING(psz_prompt);
171  u32_pulseWidth = ticksToUs(u32_delta, getTimerPrescale(T2CONbits));
172  esos_ClearUserFlag(CAPTURED_FLAG);
176  } // endof while
177  ESOS_TASK_END();
178 } // end task1()
179 
180 /****************************************************
181  * user_init()
182  ****************************************************
183  */
184 void user_init(void) {
185 
186  // Call the hardware-provided routines to print the
187  // HELLO_MSG to the screen. Must use this call because
188  // the ESOS communications subsystems is not yet fully
189  // initialized, since this call is in user_init()
190  //
191  // In general, users should call hardware-specific
192  // function like this.
193  __esos_unsafe_PutString( HELLO_MSG );
194 
195 #ifdef __linux
196  // register our little ESOS task to mimic MCU's TIMER T1 IRQ which kicks off
197  // the ESOS S/W timers when they expire
198  esos_RegisterTask( __simulated_isr );
199 #endif
200 
201  // configure our hardware to support to support our application
202  CONFIG_LED1();
203  CONFIG_SW1();
204  configTimer23();
205 
206  // initialize the semaphore (initially blocking)
207  //ESOS_INIT_SEMAPHORE( sem_T1CanRun, 0 );
208  //ESOS_INIT_SEMAPHORE( sem_T2CanRun, 0 );
209 
210  // user_init() should register at least one user task
211  esos_RegisterTask(task1);
212  //esos_RegisterTask(task2);
213 
214  // register our callback function with ESOS to create a software timer
215  esos_RegisterTimer( swTimerLED, 250 );
216 
217  // Configure INT1
218  esos_SetUserFlag(WAITING_FOR_FALLING_EDGE);
219  _INT1EP = 1; //negative edge triggerred
222 
223 } // end user_init()
224