Main Page   Compound List   File List   Compound Members   File Members  

iomacros.h

Go to the documentation of this file.
00001 /*
00002    iomacros.h
00003 
00004    Contributors:
00005      Created by Marek Michalkiewicz <marekm@linux.org.pl>
00006 
00007    THIS SOFTWARE IS NOT COPYRIGHTED
00008 
00009    This source code is offered for use in the public domain.  You may
00010    use, modify or distribute it freely.
00011 
00012    This code is distributed in the hope that it will be useful, but
00013    WITHOUT ANY WARRANTY.  ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
00014    DISCLAIMED.  This includes but is not limited to warranties of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016  */
00017 
00018 #ifndef _IOMACROS_H_
00019 #define _IOMACROS_H_
00020 
00021 #include <inttypes.h>
00022 
00023 #ifndef BV
00024   #define BV(x) (1 << (x))
00025 #endif
00026 
00027 /* Memory mapped I/O - use for non-constant I/O space addresses.  */
00028 
00029 #define __mmio(port) (*((volatile uint8_t *)((uint8_t)(port) + 0x20)))
00030 
00031 /* Macros for access to 8-bit I/O registers with constant address.  */
00032 
00033 #define __inb(port) ({                          \
00034         uint8_t __t;                            \
00035         __asm__ __volatile__ (                  \
00036                 "in %0,%1"                      \
00037                 : "=r" (__t)                    \
00038                 : "I" ((uint8_t)(port))         \
00039         );                                      \
00040         __t;                                    \
00041  })
00042 
00043 /* XXX - order of parameters is confusing, but it is probably too late
00044    to change now, should be (port, val) - destination on the left side,
00045    as in memset and C assignment operators.  */
00046 
00047 #define __outb(val, port)                       \
00048         __asm__ __volatile__ (                  \
00049                 "out %1,%0"                     \
00050                 : /* no outputs */              \
00051                 : "r" ((uint8_t)(val)),         \
00052                   "I" ((uint8_t)(port))         \
00053         )
00054 
00055 #define __outb_zero(port)                       \
00056         __asm__ __volatile__ (                  \
00057                 "out %0,__zero_reg__"           \
00058                 : /* no outputs */              \
00059                 : "I" ((uint8_t)(port))         \
00060         )
00061 
00062 /* Macros for access to 8-bit I/O registers (auto detect const address).  */
00063 
00064 #define inp(port) (__builtin_constant_p((port)) ? __inb((port)) : __mmio((port)))
00065 
00066 #define outp(val,port) do {                             \
00067         if (__builtin_constant_p((port))) {             \
00068                 if (__builtin_constant_p((val)) && ((val) == 0)) \
00069                         __outb_zero((port));            \
00070                 else                                    \
00071                         __outb((val), (port));          \
00072         } else                                          \
00073                 __mmio((port)) = (val);                 \
00074  } while (0)
00075 
00076 /* Macros for access to 16-bit I/O registers (ADC, ICR1, OCR1, TCNT1) -
00077    read low byte first, then high byte (from the TEMP register),
00078    write the high byte first (to the TEMP register), then the low byte.
00079    If used from interrupts as well as from the main program, disable
00080    interrupts first, or use the *_atomic versions (avoid interrupts
00081    in the middle of operation - there is only one TEMP register).  */
00082 
00083 #define __inw(port) ({                                  \
00084         uint16_t __t;                                   \
00085         __asm__ __volatile__ (                          \
00086                 "in %A0,%1" "\n\t"                      \
00087                 "in %B0,(%1)+1"                         \
00088                 : "=r" (__t)                            \
00089                 : "I" ((uint8_t)(port))                 \
00090         );                                              \
00091         __t;                                            \
00092  })
00093 
00094 #define __inw_atomic(port) ({                           \
00095         uint16_t __t;                                   \
00096         __asm__ __volatile__ (                          \
00097                 "in __tmp_reg__,__SREG__" "\n\t"        \
00098                 "cli" "\n\t"                            \
00099                 "in %A0,%1" "\n\t"                      \
00100                 "out __SREG__,__tmp_reg__" "\n\t"       \
00101                 "in %B0,(%1)+1"                         \
00102                 : "=r" (__t)                            \
00103                 : "I" ((uint8_t)(port))                 \
00104                 : "r0"                                  \
00105         );                                              \
00106         __t;                                            \
00107  })
00108 
00109 #define __outw(val, port)                               \
00110         __asm__ __volatile__ (                          \
00111                 "out (%1)+1,%B0" "\n\t"                 \
00112                 "out %1,%A0"                            \
00113                 : /* no outputs */                      \
00114                 : "r" ((uint16_t)(val)),                \
00115                   "I" ((uint8_t)(port))                 \
00116         )
00117 
00118 #define __outw_atomic(val, port)                        \
00119         __asm__ __volatile__ (                          \
00120                 "in __tmp_reg__,__SREG__" "\n\t"        \
00121                 "cli" "\n\t"                            \
00122                 "out (%1)+1,%B0" "\n\t"                 \
00123                 "out __SREG__,__tmp_reg__" "\n\t"       \
00124                 "out %1,%A0"                            \
00125                 : /* no outputs */                      \
00126                 : "r" ((uint16_t)(val)),                \
00127                   "I" ((uint8_t)(port))                 \
00128                 : "r0"                                  \
00129         )
00130 
00131 /* __cbi / __sbi require constant port < 0x20 and constant bit */
00132 
00133 #define __cbi(port, bit)                                \
00134         __asm__ __volatile__ (                          \
00135                 "cbi %0,%1"                             \
00136                 : /* no outputs */                      \
00137                 : "I" ((uint8_t)(port)),                \
00138                   "I" ((uint8_t)(bit))                  \
00139         )
00140 
00141 #define __sbi(port, bit)                                \
00142         __asm__ __volatile__ (                          \
00143                 "sbi %0,%1"                             \
00144                 : /* no outputs */                      \
00145                 : "I" ((uint8_t)(port)),                \
00146                   "I" ((uint8_t)(bit))                  \
00147         )
00148 
00149 /* __port_and / __port_or work with any constant port */
00150 
00151 #define __port_and(port, val)                           \
00152         __asm__ __volatile__ (                          \
00153                 "in __tmp_reg__,%0" "\n\t"              \
00154                 "and __tmp_reg__,%1" "\n\t"             \
00155                 "out %0,__tmp_reg__"                    \
00156                 : /* no outputs */                      \
00157                 : "I" ((uint8_t)(port)),                \
00158                   "r" ((uint8_t)(val))                  \
00159                 : "r0"                                  \
00160         )
00161 
00162 #define __port_or(port, val)                            \
00163         __asm__ __volatile__ (                          \
00164                 "in __tmp_reg__,%0" "\n\t"              \
00165                 "or __tmp_reg__,%1" "\n\t"              \
00166                 "out %0,__tmp_reg__"                    \
00167                 : /* no outputs */                      \
00168                 : "I" ((uint8_t)(port)),                \
00169                   "r" ((uint8_t)(val))                  \
00170                 : "r0"                                  \
00171         )
00172 
00173 /* __cbi_const_port / __sbi_const_port work with const or non-const bit */
00174 
00175 #define __cbi_const_port(port, bit) do {                \
00176         if (((port) < 0x20) && __builtin_constant_p((bit))) \
00177                 __cbi((port), (bit));                   \
00178         else                                            \
00179                 __port_and((port), ~BV((bit)));         \
00180  } while (0)
00181 
00182 #define __sbi_const_port(port, bit) do {                \
00183         if (((port) < 0x20) && __builtin_constant_p((bit))) \
00184                 __sbi((port), (bit));                   \
00185         else                                            \
00186                 __port_or((port), BV((bit)));           \
00187  } while (0)
00188 
00189 /* General cbi / sbi macros - work with any (const or non-const) data.  */
00190 
00191 #define cbi(port, bit) do {                             \
00192         if (__builtin_constant_p((port)))               \
00193                 __cbi_const_port((port), (bit));        \
00194         else                                            \
00195                 __mmio((port)) &= ~BV((bit));           \
00196  } while (0)
00197 
00198 #define sbi(port, bit) do {                             \
00199         if (__builtin_constant_p((port)))               \
00200                 __sbi_const_port((port), (bit));        \
00201         else                                            \
00202                 __mmio((port)) |= BV((bit));            \
00203  } while (0)
00204 
00205 #if 1
00206 
00207 /* these might make better optimized code? */
00208 #define bit_is_set(port, bit) (__inb(port) & (1<<(bit)))
00209 #define bit_is_clear(port, bit) (!bit_is_set(port, bit))
00210 
00211 #else
00212 
00213 #define bit_is_clear(port, bit) ({                      \
00214         uint8_t __t;                                    \
00215         __asm__ __volatile__ (                          \
00216                 "clr %0" "\n\t"                         \
00217                 "sbis %1,%2" "\n\t"                     \
00218                 "inc %0"                                \
00219                 : "=r" (__t)                            \
00220                 : "I" ((uint8_t)(port)),                \
00221                   "I" ((uint8_t)(bit))                  \
00222         );                                              \
00223         __t;                                            \
00224  })
00225 
00226 #define bit_is_set(port, bit) ({                        \
00227         uint8_t __t;                                    \
00228         __asm__ __volatile__ (                          \
00229                 "clr %0" "\n\t"                         \
00230                 "sbic %1,%2" "\n\t"                     \
00231                 "inc %0"                                \
00232                 : "=r" (__t)                            \
00233                 : "I" ((uint8_t)(port)),                \
00234                   "I" ((uint8_t)(bit))                  \
00235         );                                              \
00236         __t;                                            \
00237  })
00238 
00239 #endif
00240 
00241 #define loop_until_bit_is_set(port, bit)                \
00242         __asm__ __volatile__ (                          \
00243         "L_%=: " "sbis %0,%1" "\n\t"                    \
00244                 "rjmp L_%="                             \
00245                 : /* no outputs */                      \
00246                 : "I" ((uint8_t)(port)),                \
00247                   "I" ((uint8_t)(bit))                  \
00248         )
00249 
00250 #define loop_until_bit_is_clear(port, bit)              \
00251         __asm__ __volatile__ (                          \
00252         "L_%=: " "sbic %0,%1" "\n\t"                    \
00253                 "rjmp L_%="                             \
00254                 : /* no outputs */                      \
00255                 : "I" ((uint8_t)(port)),                \
00256                   "I" ((uint8_t)(bit))                  \
00257         )
00258 
00259 #define parity_even_bit(val) ({                         \
00260         uint8_t __t;                                    \
00261         __asm__ (                                       \
00262                 "mov __tmp_reg__,%0" "\n\t"             \
00263                 "swap %0" "\n\t"                        \
00264                 "eor %0,__tmp_reg__" "\n\t"             \
00265                 "mov __tmp_reg__,%0" "\n\t"             \
00266                 "lsr %0" "\n\t"                         \
00267                 "lsr %0" "\n\t"                         \
00268                 "eor %0,__tmp_reg__" "\n\t"             \
00269                 "mov __tmp_reg__,%0" "\n\t"             \
00270                 "lsr %0" "\n\t"                         \
00271                 "eor %0,__tmp_reg__"                    \
00272                 : "=r" (__t)                            \
00273                 : "0" ((uint8_t)(val))                  \
00274                 : "r0"                                  \
00275         );                                              \
00276         (__t & 1);                                      \
00277  })
00278 
00279 #endif /* _IOMACROS_H_ */

Generated at Fri Jul 19 14:55:41 2002 for avrgcc by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001