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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.