CVS: libraries/include/mspgcc eventhandler.h,NONE,1.1 flash.h,NONE,1.1 fll.h,NONE,1.1 ringbuffer.h,NONE,1.1 util.h,NONE,1.1
Chris Liechti <[email protected]>
| Newsgroups | gmane.comp.hardware.texas-instruments.msp430.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/mspgcc/libraries/include/mspgcc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20077/libraries/include/mspgcc Added Files: eventhandler.h flash.h fll.h ringbuffer.h util.h Log Message: initial import of mspgcc library featuring an event handler/scheduler, ringbuffer, flash erase/write, checksum, hex, delay and a line editor --- NEW FILE: eventhandler.h --- #ifndef MSPGCC_EVENTHANDLER_H #define MSPGCC_EVENTHANDLER_H // Bit definitions and function prototypes for the eventhandler // http://mspgcc.sf.net // chris <[email protected]> #ifndef _GNU_ASSEMBLER_ /** * Simple event handler * * Each event is a function and has a corresponding bit in the variable * eventreg. EVENT00 has bit 0x8000 which is the highest priority, * EVENT01~0x4000 etc. Up to 16 events are supported. * Each event function has to exit by itself (there is no task switching). * This causes a risk of priority inversion when a low priority event * handler consumes too much time. * For devices with human interaction, a maximum time limit for each event of * 20ms is recmended. * * Each time am eventhandler exits, the eventhandler_bits are scanned from * left to right (starting at the higest prio). If no eventhandler_bits is * set, "eventhandler_idle" is called. Scanning for events is restarted when * the control returns from the idle function. * * An event function does not need to save any registers as on each run * the eventhandler is reinitializing all its registers. * * If no events are pending, then "eventhandler_idle" is called. The library * provides a default implementation that enters the LPM0 powesaving mode. * A different function may be provided that e.g. toggles a LED to show the * CPU activity or enters a different lowpower mode etc. Together with a * timer/getTime() function it is possible to implement a load monitor that * records the CPU load. * * @note * It is usual for the "eventhandler_idle" function to enter a lowpower * mode of the CPU, thus starting events from interrupts also requires * to wake it up. See below for more info and examples. * * @param eventreginit initial value of eventhandler_bits. These events are * handled right after the start */ void __attribute__((noreturn)) eventhandler(unsigned short eventreginit); /** * The bits in this variable define which event functions are launched. */ extern volatile unsigned short eventhandler_bits; //priority/activation bits of event /** * This macro start an eventhandler. * * If used in an interrupt, do not forget to use a interrupt handler with * "wakeup" attribute or call "_BIC_SR_IRQ(LPM4_bits);" * * @param eventbit one of the EVENTxx_bits defines or an alias. */ #define EVENTHANDLER_LAUNCH(eventbit) eventhandler_bits |= (eventbit) /** * Table with event functions. Events are set up using a table with * predefined name: "eventhandler_table" is has to be supplied by the user. * * Event functions are "void f(void)". Any registers can be used and have not * to be saved. * (actualy the functions can be void f(unsigned short eventbit) with eventbit * beeing the bit that is associated with that event. This can be used if a * event wants to restart itself: "eventhandler_bits |= eventbit;") * * const EVENTHANDLER_TABLE eventhandler_table[] = { * event_timer, * event_serial, * {0} //sentinel, marks end of list * }; * * It is recomended to make defines for each of these events, so that events * are lauched by their name. This makes it easier to refactor code later and * keep them in sync with the "eventhandler_table". * * #define EVENT_timer EVENT00_bits * #define EVENT_serial EVENT01_bits * * Then to launch an event from an interrupt: * * wakeup interrupt(WDT_VECTOR) intervallTimer(void) { * EVENTHANDLER_LAUNCH(EVENT_timer); * } */ typedef void (*EVENTHANDLER_TABLE)(void); /** * This is a special eventhandler: it starts additional events, based on the * "event_timetable". * * It has an internal clock variable. If the internal clock advanced more than * one tick since the last run of scheduler, then each step in between is * calculated. This is to ensure that no step is left out, even when the * scheduler is called late (because of other events that consume too much * CPU time). * * The schduler table has to be provided by the user. It has to be a global * named scheduler_table. * Example: * * const SCHEDULER_TABLE scheduler_table[] = { * { modulo: 1, shift: 0, eventbits: EVENT_periodic}, * {0} //sentinel, marks the end of the table * }; */ void event_scheduler(void); /** * Increment the internal clock of the scheduler. */ void scheduler_increment(void); /** * Reset the internal clock of the scheduler. */ void scheduler_reset(void); /** * Event table entries. See ::event_scheduler for more information. */ typedef struct { unsigned short modulo; ///< divisor unsigned short shift; ///< remainder unsigned short eventbits; ///< this bits are passed to EVENTHANDLER_LAUNCH } SCHEDULER_TABLE; #endif // Bit masks for taskbit register // It is recomended to define aliases and not using these directly #define EVENT00_bits 0x8000 #define EVENT01_bits 0x4000 #define EVENT02_bits 0x2000 #define EVENT03_bits 0x1000 #define EVENT04_bits 0x0800 #define EVENT05_bits 0x0400 #define EVENT06_bits 0x0200 #define EVENT07_bits 0x0100 #define EVENT08_bits 0x0080 #define EVENT09_bits 0x0040 #define EVENT10_bits 0x0020 #define EVENT11_bits 0x0010 #define EVENT12_bits 0x0008 #define EVENT13_bits 0x0004 #define EVENT14_bits 0x0002 #define EVENT15_bits 0x0001 #endif //MSPGCC_EVENTHANDLER_H --- NEW FILE: flash.h --- #ifndef MSPGCC_FLASH_H #define MSPGCC_FLASH_H /** * Erase a single flash segment. * * This function modifies FCTL1 and FCTL3. * * @note * FCTL2 has to be set up by the user. It is not altered by this * function. It contains the clock settings. * * @param address [in] any address within the segment to erase */ void flash_erase_segment(void *address); /** * Copy a memory block to the flash. Like memcpy but with Flash controller * enabled. * * This function modifies FCTL1 and FCTL3. * * @note * FCTL2 has to be set up by the user. It is not altered by this * function. It contains the clock settings. * * Examples: * int intvar = 1234; * flash_write((void *)0x1000, &intvar, sizeof(int)); * * struct { ... } somestructure; * flash_write((void *)0x1000, &somestructure, sizeof(somestructure)); * * @param dst [in] the memory is written here * @param src [in] the memory that is read * @param size [in] number of bytes to copy */ void flash_write(void *dst, const void *src, unsigned int size); #endif //MSPGCC_FLASH_H --- NEW FILE: fll.h --- #ifndef MSPGCC_FLL_H #define MSPGCC_FLL_H /** * Formula to calculate the multiplier, for fll_adjust(), based on MCLK * and ACLK. * * @param mclk the desired MCLK speed (after divider) * @param aclk the actual ACLK speed (after divider) */ #define FLL_MULTIPLIER(mclk, aclk) ((mclk)/(aclk)) /** * Adjust MCLK using ACLK, doing the software FLL in 1xx devices. * * This function modifies TACTL, CCR2, CCTL2, BCSCTL1 and DCOCTL. * The Timer_A module has to be re-setup by the user after this function * was run. * * @note * BCSCTL2 has to be set up by the user. It is not altered by this * function. It contains the ACLK divider settings. * * @note * Timer_A is stopped after this function is run. * * @note * This function has to timeout, if the crystal fails or the frequency * is impossible to set, this function does not return! * * Example, setting the CPU to 3 MHz based on a watch crystal (32.768 kHz): * * BCSCTL2 = DIVS_DIV4; // select 8192 Hz from XT1 * delay(0xffff); // give osillator some time to settle * fll_adjust(FLL_MULTIPLIER(3000000, 8192)); //adjust frequency * * @param multiplier [in] MCLK = multiplier * ACLK */ void fll_adjust(unsigned short multiplier); #endif //MSPGCC_FLL_H --- NEW FILE: ringbuffer.h --- #ifndef MSPGCC_RINGBUFFER_H #define MSPGCC_RINGBUFFER_H /** * Descriptor for a ringbuffer. * * To use a ringbuffer, initialize the first two fields and zero the * remaining fields. * * E.g. * char ringbuf_memory[40]; * RINGBUFFER_TYPE ringbuffer = {ringbuf_memory, sizeof(ringbuf_memory)}; */ typedef struct { char *memory; ///< memory used for the buffer itself unsigned int size; ///< byte used for the buffer volatile unsigned int fill; ///< number of bytes currently in the buffer volatile unsigned int read_pos; ///< reading position volatile unsigned int write_pos; ///< writing position } RINGBUFFER_TYPE; /** * This macro allocates an new ringbuffer and initializes the descriptor. * NOTE: This macro allocates global variables. */ #define RINGBUFFER_NEW(name, size) \ static char ringmem##name[size]; \ RINGBUFFER_TYPE name = {ringmem##name, (size)}; /** * This macro creates an "extern" declaration for the ringbuffer. * For use in header files. */ #define RINGBUFFER_EXTERN(name) extern RINGBUFFER_TYPE name; /** * Check the number of bytes in the ringbuffer. * * @param buffer [in] The ringbuffer descriptor * @return the number of bytes in the buffer */ int ringbuffer_len(RINGBUFFER_TYPE *buffer); /** * Clear the ringbuffer (setting its length to zero). * * @param buffer [in] The ringbuffer descriptor */ void ringbuffer_clear(RINGBUFFER_TYPE *buffer); /** * Put a character in the ringbuffer. * * @param buffer [in] The ringbuffer descriptor * @param character [in] Byte to store. * @return -1 if the buffer is full, the number of bytes in the * buffer otherwise. */ int ringbuffer_put(RINGBUFFER_TYPE *buffer, char character); /** * Get a character from the ringbuffer. Handle wrap arounds. * * @param buffer [in] The ringbuffer descriptor * @return Byte from the buffer, -1 if the buffer is empty */ int ringbuffer_get(RINGBUFFER_TYPE *buffer); #endif //MSPGCC_RINGBUFFER_H --- NEW FILE: util.h --- #ifndef UTIL_H #define UTIL_H /** * Print a hexdump of the gived memory region. Implemented with printf() * as output function. * * @param buffer [in] this data is dumped * @param length [in] this number of bytes are processed * @param address [in] the first address printed in the hexdump */ void hexdump(const void *buffer, unsigned int length, unsigned int address); /** * Simple delay loop. It uses 3 CPU cycles per count plus a few cyles for * function call and return. * * Calculation: * total_cycles = 6 + count*3 * * This does not account for any code that the compiler generates to call this * function and clean up afterwards! * * @param count [in] number of loops, in effect the delay length */ void delay(unsigned short count); /** * Encode a binary buffer of given size to a string of hexdigits (null terminated). * * @param dst the resulting hex string * @param maxsize available number of bytes in the output string * @param src source binary buffer * @param size number of binary bytes that should be encoded * @return Number of hex digits in the encoded result. The return * value smaller maxsize on success, equal or larger if the * result was truncated. */ unsigned int hex_encode(char *dst, unsigned int maxsize, const void *src, unsigned int size); /** * Decode a string of hexdigits into a binary buffer. * * @param dst the resulting binary * @param maxsize available number of bytes in the output string * @param src source string of hex digits * @param size number of characters that should be decoded. this is an * even number as each hex encoded byte consists of two characters * @return Number of binary bytes that got decoded. The return value * is equal to size on success, smaller if the dst buffer * was too small. */ unsigned int hex_decode(void *dst, unsigned int maxsize, const char *src, unsigned int size); /** * Decode a string of hexdigits into a binary buffer. * * @param srcdst source string of hex digits and the target for the resulting binary * @param size number of characters that should be decoded. this is an * even number as each hex encoded byte consists of two characters * @return Number of binary bytes that got decoded. The return value * is equal to size on success, smaller if the dst buffer * was too small. */ unsigned int hex_decode_inline(void *srcdst, unsigned int size); /** * Convert a hex digit (ASCII character) to a number * * @param x a character * @return 0...15, 0 for illegal characters */ unsigned char hex_fromdigit(unsigned char x); /** An array containing all hex digits as characters (uppercase). */ extern const unsigned char HEX_DIGITS[16]; /** * Simple line reader. Reads with getchar(), prcoesses with * ::lineeditor_simple_process_key * * @note * This function blocks until a line is read, or getchar() returns an * error/EOF. * * @param line [in] buffer to read the line to * @param maxlen [in] size of the buffer */ void simple_readline(char *line, unsigned int maxlen); /** * The line editor function stores its state in such a structure. * Initialize it with a pointer to a buffer for the line and its length. */ typedef struct { char *line; ///< buffer for the editor unsigned char line_size; ///< size of the buffer unsigned char position; ///< internal use } LINEEDITOR_STATE; /** * Clear line. */ #define LINEEDITOR_RESET(state) (state)->position = 0; (state)->line[0] = '\0'; /** * Process the key in the line editor. * Currenly ony very simple editiong is supported: * - Backspace deletes the last character of the line * * The line is at any time terminated with a null character. * * This function generates an echo using putchar(). * * @return true when the line is complete, false otherwise. */ unsigned char lineeditor_simple_process_key(LINEEDITOR_STATE *state, char key); /** * Simple 16 bit bitwise xor checksum. * * The advantage of this checksum is, that the checksum itself can be embedded * anywhere within the data to be checked. Running checksum_xor over the entire * data then returns 0 for correct data or any other number for a data * integrity problem. * * @param address [in] Pointer to the memory to be checked. * @param length [in] Size of the checked mememory in bytes. * Has to be an even number. * @return checksum */ unsigned short checksum_xor(const void *address, unsigned int length); #endif //UTIL_H ------------------------------------------------------- SF.Net email is Sponsored by the Better Software Conference & EXPO September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf