CVS: examples/libraries/eventhandler README.txt, 1.2, 1.3 main.c, 1.1, 1.2 makefile, 1.1, 1.2
Chris Liechti <[email protected]> Wed, 14 Jun 2006 15:18:26 -0700
| Newsgroups | gmane.comp.hardware.texas-instruments.msp430.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/mspgcc/examples/libraries/eventhandler In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv31319/examples/libraries/eventhandler Modified Files: README.txt main.c makefile Log Message: add profiling code Index: README.txt =================================================================== RCS file: /cvsroot/mspgcc/examples/libraries/eventhandler/README.txt,v retrieving revision 1.2 retrieving revision 1.3 diff -u -w -d -r1.2 -r1.3 --- README.txt 13 Mar 2006 18:22:52 -0000 1.2 +++ README.txt 14 Jun 2006 22:18:23 -0000 1.3 @@ -12,6 +12,8 @@ - shows how the scheduler from libmspgcc is used +- shows how the idle function can be overriden to implement simple profiling + - Makefile - compile and link with libmspgcc @@ -123,6 +125,8 @@ - One LED on P1.0 (470 Ohms series resistor to GND), The FET kits from TI should be compatible. +- The profiling example uses 5 switches and an additional LED array + Source ------ Index: main.c =================================================================== RCS file: /cvsroot/mspgcc/examples/libraries/eventhandler/main.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -w -d -r1.1 -r1.2 --- main.c 27 Dec 2005 20:51:14 -0000 1.1 +++ main.c 14 Jun 2006 22:18:23 -0000 1.2 @@ -3,6 +3,8 @@ * A LED is flashed, using the watchdog as timing source for the * scheduler, which launches the event that blinks the LED. * + * Simple variant: + * * MSP430F1121 * ----------------- * /|\| | @@ -11,7 +13,22 @@ * | | * | | * - * (c) 2005, chris <[email protected]> + * With profiling: + * MSP430F133 + * ----------------- + * /|\| | + * | | | + * --|RST P1.0|-->LED blinking + * | P1.1|<--KEY 100% CPU load + * | P1.2|<--KEY \ + * | P1.3|<--KEY | CPU load switch + * | P1.4|<--KEY | + * | P1.5|<--KEY / + * | P1.7|-->LED CPU load + * | | + * | P2.x|--> 8 LED array as bargraph + * + * (c) 2006, chris <[email protected]> */ #include <io.h> @@ -21,56 +38,127 @@ #define EVENT_scheduler EVENT00_bits #define EVENT_led EVENT01_bits +#define EVENT_cpu_load EVENT02_bits -// the watchdog is programmed as intervall timer. this function is called -// periodicaly and it launches the scheduler +// switch to enable profiling demo code +#define ENABLE_EVENTHANDLER_PROFILING + + +// The watchdog is programmed as intervall timer. This function is called +// periodicaly and it launches the scheduler. wakeup interrupt(WDT_VECTOR) intervallTimer(void) { scheduler_increment(); EVENTHANDLER_LAUNCH(EVENT_scheduler); } -// this event is launched by the scheduler -// it flashes once with the LED on P1.0 +// This event is launched by the scheduler. +// It flashes once with the LED on P1.0 static void event_led(void) { P1OUT |= BIT0; // LED on delay(20000); P1OUT &= ~BIT0; // LED off } -// table with the event handlers +// This event is used to generate a variable CPU load. It reads +// switches on P1IN and generates a delay depending on them. +// Usefull to watch the profiler at work. +static void event_cpu_load(void) { + if (P1IN & BIT1) EVENTHANDLER_LAUNCH(EVENT_cpu_load); //restart self + delay((P1IN & 0x3c) << 6); // variable delay +} + +// Table with the event handlers // NOTE: must keep it in sync with the EVENT_* defines above! const EVENTHANDLER_TABLE eventhandler_table[] = { event_scheduler, event_led, + event_cpu_load, 0 // sentinel, marks end of list }; -// table with the events that are started by the scheduler. +#ifdef ENABLE_EVENTHANDLER_PROFILING +// An implementation of the following function is provided by libmspgcc. +// That implementation simply enters the lowpowermode LPM0. We're overriding +// the function here to implement run/idle measurements. + +// This function is called when no event bits are set. It typically enters +// a lowpower mode. Setting event bits then also involves waking up the CPU. +void eventhandler_idle(void) { + P1OUT &= ~BIT7; // P1.7 is used to display idle/run -> going to idle + LPM0; // enter lowpower mode, wait for wakeup + P1OUT |= BIT7; // P1.7 is used to display idle/run -> going to run +} + +// Statistical approach... +// Make samples of cpu activity and analyze display activity/idle as LED bar +// 8 samples are made and summed up. Every 8 samples is the counter passed +// to a lowpass filter. The filtered value is output as bargraph with eight +// levels on a port. +interrupt(TIMERA0_VECTOR) taccr0(void) { + static unsigned char load = 0; + static unsigned char count = 0; + static unsigned char activity = 0; + if (count == 0) { + // fixed point arithmetics. 3 bits after the point + // lowpass filter 7/8 old value + 1/8 new value + // load already has the right scale, while activity hasn't + load = ((unsigned short)load * 7 + (activity * 8)) / 8; + P2OUT = (1 << load) - 1; // bargraph + //~ P2OUT = 1 << (load-1); // moving dot only + activity = 0; + count = 7; + } else { + count--; + } + // It would be better to use an internal variable, as reading the out bit + // back requires that this pin is used as CPU load display which may not + // be desired for a final product. + if (P1OUT & BIT7) activity++; + // Also note that interrupts are not visible here and thus are not + // included in the CPU load calculation. Interrupts however can have + // an indirect influence as the event handlers get a longer runtime + // because they are interrupted. +} +#endif //ENABLE_EVENTHANDLER_PROFILING + +// Table with the events that are started by the scheduler. // Two led events are set up close together so that a double blink // pattrern is generated. something like this: // _ _ _ _ // ____| |_| |______________________________| |_| |___ // -// as the event is also lauched on startup, use a shift of 10 and 20 -> -// triple blink the first time +// As the event is also launched on startup, use a shift of 10 and 20 -> +// triple blink the first time. const SCHEDULER_TABLE scheduler_table[] = { {modulo: 150, shift: 10, eventbits: EVENT_led}, {modulo: 150, shift: 20, eventbits: EVENT_led}, + {modulo: 1, shift: 0, eventbits: EVENT_cpu_load}, {0} // sentinel, marks the end of the table }; -// program entry. set up the hardware and launch the eventhandler +// Program entry. Set up the hardware and launch the eventhandler. int main(void) { - WDTCTL = WDTPW|WDTTMSEL|WDTCNTCL; // Init watchdog as intervall timer + WDTCTL = WDTPW|WDTTMSEL|WDTCNTCL; // Init watchdog as interval timer IE1 = WDTIE; // DCO (~1.5MHz on a F1xx) - BCSCTL1 = XT2OFF|DIVA1|RSEL0|RSEL2; + BCSCTL1 = XT2OFF|RSEL0|RSEL2; BCSCTL2 = 0; DCOCTL = 0x92; P1OUT = 0; // LED off - P1DIR = BIT0; // enable pin with LED + P1DIR = BIT0|BIT7; // enable pins with LEDs + +#ifdef ENABLE_EVENTHANDLER_PROFILING + P2OUT = 0; + P2DIR = 0xff; // LED bar used to display CPU load + + TACTL = TACLR|TASSEL_SMCLK|MC_UPTO_CCR0; // PWM mode + TACCR0 = 10027; // random time, should not be synchronous to scheduler time base + TACCTL0 = CCIE; // enable capture interrupts for CPU load supervision + + P1OUT |= BIT7; // P1.7 is used to display idle/run -> going to run +#endif //ENABLE_EVENTHANDLER_PROFILING eint(); eventhandler(EVENT_led); // enter eventhandler, start event for a first time Index: makefile =================================================================== RCS file: /cvsroot/mspgcc/examples/libraries/eventhandler/makefile,v retrieving revision 1.1 retrieving revision 1.2 diff -u -w -d -r1.1 -r1.2 --- makefile 27 Dec 2005 20:51:14 -0000 1.1 +++ makefile 14 Jun 2006 22:18:23 -0000 1.2 @@ -2,7 +2,8 @@ NAME = eventhandler_demo CSOURCES = main.c #~ ASOURCES = -CPU = msp430x1121 +#~ CPU = msp430x1121 +CPU = msp430x133 ASFLAGS = -mmcu=${CPU} -D_GNU_ASSEMBLER_ -I .