[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[avr-libc-dev] New Atomic.h header?
From: |
Dean |
Subject: |
[avr-libc-dev] New Atomic.h header? |
Date: |
Sun, 7 Jan 2007 17:18:21 +1100 |
Hi guys!
There was a recent discussion on 'Freaks covering atomic blocks of code, ie.
code blocks which for their duration have interrupts disabled:
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=45041
Many different suggestions were made, from simple macros to more complex and
fool-proof methods. I eventually came up with heavily modified versions of
Darcy Watkin's macro posted at:
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=37733&highlight=atomic+macro
My macro allows for both atomic (interrupts disabled) and non-atomic
(interrupts enabled) blocks of code to be easily made. Unlike conventional
methods these macros are quite foolproof - the epilogue for each is run
automatically on block exit regardless of the exit path. When compiled with
-Os, it results in the smallest possible code.
Two options are avaliable; ATOMIC_RESTORESTATE, where the previous interrupt
enable flag status is restored, and ATOMIC_FORCEON (or ATOMIC_FORCEOFF for the
non-atomic block) which forces the global flag state on block exit - desirable
in some instances.
Despite its simplicity, would it have an application for AVRLibC? Should I add
DoxyGen comments and submit as a patch?
================================================
#ifndef ATOMIC_H
#define ATOMIC_H
#include <avr/io.h>
#include <avr/interrupt.h>
static inline void __iSeiParam(const uint8_t *s) { sei(); (void)s; }
static inline void __iCliParam(const uint8_t *s) { cli(); (void)s; }
static inline uint8_t __iSeiRetVal(void) { sei(); return 1; }
static inline uint8_t __iCliRetVal(void) { cli(); return 1; }
static inline void __iRestore(const uint8_t *s) { SREG = *s; }
#define ATOMIC_BLOCK(exitmode) for ( exitmode, __ToDo = __iCliRetVal();
__ToDo ; __ToDo = 0 )
#define ATOMIC_RESTORESTATE uint8_t sreg_save
__attribute__((__cleanup__(__iRestore))) = SREG
#define ATOMIC_FORCEON uint8_t sreg_save
__attribute__((__cleanup__(__iSeiParam))) = 0
#define NON_ATOMIC_BLOCK(type) for ( type, __ToDo = __iSeiRetVal(); __ToDo
; __ToDo = 0 )
#define NONATOMIC_RESTORESTATE uint8_t sreg_save
__attribute__((__cleanup__(__iRestore))) = SREG
#define NONATOMIC_FORCEOFF uint8_t sreg_save
__attribute__((__cleanup__(__iCliParam))) = 0
#endif
================================================