CVS: examples/libraries/eventhandler README.txt,NONE,1.1 main.c,NONE,1.1 makefile,NONE,1.1
Chris Liechti <[email protected]>
| Newsgroups | gmane.comp.hardware.texas-instruments.msp430.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/mspgcc/examples/libraries/eventhandler
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5563/examples/libraries/eventhandler
Added Files:
README.txt main.c makefile
Log Message:
- adding a new folder for examples for libmspgcc and the others
- adding an example for the eventhandler and scheduler
--- NEW FILE: README.txt ---
Eventhandler and Scheduler
==========================
Overview
--------
It is a simple example project for the MSP430 series MCU, the GCC port
of the mspgcc project and libmspgcc.
Features:
- shows how the eventhandler from libmspgcc is used
- shows how the scheduler from libmspgcc is used
- Makefile
- compile and link with libmspgcc
- convert to intel hex format
- generate a listing with mixed C / assembly
About the eventhandler
----------------------
The idea of the eventhandler is to decouple foreground tasks and interrupts
as well as running things quasi-parallel while still beeing able to use the
low power modes of the MSP430.
An eventhandler is a simple ``void f(void)`` function. But it is not called
directly by the user but by the eventhandler. A small eventhandler could look
like this::
// 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
}
The main loop is in the eventhandler. This means the last thing done in main()
is to yield control to ``eventhandler()``
Events can be launched by setting the corresponding event bit with
``EVENTHANDLER_LAUNCH(bit)`` and ensuring that the CPU is awake.
The advantage is that the event bit can be set from interrupt handlers, but
the interrupt handler itself is held short - the main work is done in the
foreground.
As only one eventhandler at a time is executed it is also way to do quasi-
parallel things, but protecting data from concurrent access. The events are
also priorized. the lowest event is always executed first. After one event is
handled, the scan over the event bits is started over (a high priority event
can lauch itself and lock out every lower priority event). Note that each event
handler has to exit on itself so that other events can be handled. This usualy
leads to a design rule like "each event handler shall not use more than 50ms"
etc.
The events are subscribed over a global table::
const EVENTHANDLER_TABLE eventhandler_table[] = {
event_scheduler,
event_led,
0 // sentinel, marks end of list
};
The defines are used to map the table entry to event bits. This means the value
of the EVENTxx_bits has to match the order in the table::
#define EVENT_scheduler EVENT00_bits
#define EVENT_led EVENT01_bits
Is is recomneded to use this inderection as its makes life simpler when
adding an ew event or reordering priorities.
The include file `mspgcc/eventhandler.h`_ contains a more detailed
documentation over its features and the schduler descibed next.
.. _mspgcc/eventhandler.h: ../../../msp430/include/mspgcc/eventhandler.h
Scheduler
---------
The scheduler is a special event that lauches other events based on a clock.
The times and events are set up in a global table::
const SCHEDULER_TABLE scheduler_table[] = {
{modulo: 150, shift: 0, eventbits: EVENT_led},
{modulo: 150, shift: 10, eventbits: EVENT_led},
{0} // sentinel, marks the end of the table
};
Events are lauched if ``time % modulo == shift`` is true. So ``modulo``
specifies the launch frequency and with the ``shift``, it is possible to
lauch different events at the same frequency but not all at once.
Severla ``eventbits`` may be set in an entry
(``eventbits: EVENT_one|EVENT_two``), launching multiple events at once.
The scheduler is usualy subscribed as the highest priority event. It does not
take up much time and it ensures that other time based events are set and can
not be blocked by lower priority events.
The schduler event has to be lauched somewhere of course. Our example does
that in the watchdong intervall timer interrupt::
wakeup interrupt(WDT_VECTOR) intervallTimer(void) {
scheduler_increment();
EVENTHANDLER_LAUNCH(EVENT_scheduler);
}
``scheduler_increment()`` increases the internal clock of the scheduler. And
next to it is lauched. Note that the interrupt is flagged with ``wakeup``, as
the eventhandlers idle function enters LPM0 lowpower mode.
Required hardware
-----------------
- A MSP430F1121 or larger device (any from the F1x series)
- One LED on P1.0 (470 Ohms series resistor to GND), The FET kits from TI
should be compatible.
Disclaimer
----------
This example is part of the mspgcc project http://mspgcc.sf.net.
See license.txt_ for details.
chris
.. _license.txt: ../../license.html
--- NEW FILE: main.c ---
/* Demo application for the eventhandler and schedluer from libmspgcc.
*
* A LED is flashed, using the watchdog as timing source for the
* scheduler, which launches the event that blinks the LED.
*
* MSP430F1121
* -----------------
* /|\| |
* | | |
* --|RST P1.0|-->LED
* | |
* | |
*
* (c) 2005, chris <[email protected]>
*/
#include <io.h>
#include <signal.h>
#include <mspgcc/util.h> // delay()
#include <mspgcc/eventhandler.h>
#define EVENT_scheduler EVENT00_bits
#define EVENT_led EVENT01_bits
// 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
static void event_led(void) {
P1OUT |= BIT0; // LED on
delay(20000);
P1OUT &= ~BIT0; // LED off
}
// 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,
0 // sentinel, marks end of list
};
// 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
const SCHEDULER_TABLE scheduler_table[] = {
{modulo: 150, shift: 10, eventbits: EVENT_led},
{modulo: 150, shift: 20, eventbits: EVENT_led},
{0} // sentinel, marks the end of the table
};
// program entry. set up the hardware and launch the eventhandler
int main(void) {
WDTCTL = WDTPW|WDTTMSEL|WDTCNTCL; // Init watchdog as intervall timer
IE1 = WDTIE;
// DCO (~1.5MHz on a F1xx)
BCSCTL1 = XT2OFF|DIVA1|RSEL0|RSEL2;
BCSCTL2 = 0;
DCOCTL = 0x92;
P1OUT = 0; // LED off
P1DIR = BIT0; // enable pin with LED
eint();
eventhandler(EVENT_led); // enter eventhandler, start event for a first time
}
--- NEW FILE: makefile ---
# makfile configuration
NAME = eventhandler_demo
CSOURCES = main.c
#~ ASOURCES =
CPU = msp430x1121
ASFLAGS = -mmcu=${CPU} -D_GNU_ASSEMBLER_ -I .
CFLAGS = -mmcu=${CPU} -O2 -Wall -g --std=gnu99 -I .
LDFLAGS = -lmspgcc
#switch the compiler (for the internal make rules)
CC = msp430-gcc
AS = msp430-gcc
OBJECTS = ${CSOURCES:.c=.o} ${ASOURCES:.S=.o}
.PHONY: all FORCE clean download download-jtag download-bsl
#all should be the first target. it's built when make is run without args
all: ${NAME}.elf ${NAME}.a43 ${NAME}.lst dependencies.d
#confgigure the next line if you want to use the serial download
download: download-jtag
#~ download: download-bsl
#additional rules for files
${NAME}.elf: ${OBJECTS}
${CC} -mmcu=${CPU} -o $@ ${OBJECTS} $(LDFLAGS)
${NAME}.a43: ${NAME}.elf
msp430-objcopy -O ihex $^ $@
${NAME}.lst: ${NAME}.elf
msp430-objdump -dSt $^ >$@
@echo "----- RAM/Flash Usage -----"
msp430-size $^
download-jtag: all
msp430-jtag -e ${NAME}.elf
download-bsl: all
msp430-bsl $(BSLOPT) -e ${NAME}.elf
clean:
rm -f ${NAME}.elf ${NAME}.a43 ${NAME}.lst ${OBJECTS} dependencies.d
#dummy target as dependecy if something has to be build everytime
FORCE:
#project dependencies
dependencies.d:
$(CC) -MM ${CFLAGS} ${CSOURCES} > dependencies.d
ifdef ASOURCES
$(CC) -MM ${ASFLAGS} ${ASOURCES} >> dependencies.d
endif
-include dependencies.d
-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems? Stop! Download the new AJAX search engine that makes
searching your log files as easy as surfing the web. DOWNLOAD SPLUNK!
http://ads.osdn.com/?ad_id=7637&alloc_id=16865&op=click