<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"> <title>avr-libc: Additional notes from <avr/sfr_defs.h></title> <link href="dox.css" rel="stylesheet" type="text/css"> </head> <body> <center> <table width="80%"> <tr> <td align="left"><a href="http://www.nongnu.org/avr-libc/">AVR Libc Home Page</a></td> <td align="center" colspan=4><img src="avrs.png" alt="AVRs" align="middle" border="0"></td> <td align="right"><a href="https://savannah.nongnu.org/projects/avr-libc/">AVR Libc Development Pages</a></td> </tr> <tr> <td align="center" width="13%"><a href="index.html">Main Page</a></td> <td align="center" width="13%"><a href="pages.html">User Manual</a></td> <td align="center" width="13%"><a href="modules.html">Library Reference</a></td> <td align="center" width="13%"><a href="FAQ.html">FAQ</a></td> <td align="center" width="13%"><a href="globals.html">Alphabetical Index</a></td> <td align="center" width="13%"><a href="group__demos.html">Example Projects</a></td> </tr> </table> </center> <hr width="80%"> <!-- Generated by Doxygen 1.6.1 --> <div class="contents"> <h1>Additional notes from <avr/sfr_defs.h><br/> <small> [<a class="el" href="group__avr__sfr.html"><avr/sfr_defs.h>: Special function registers</a>]</small> </h1><table border="0" cellpadding="0" cellspacing="0"> </table> <p>The <code><avr/sfr_defs.h></code> file is included by all of the <code><avr/ioXXXX.h></code> files, which use macros defined here to make the special function register definitions look like C variables or simple constants, depending on the <code>_SFR_ASM_COMPAT</code> define. Some examples from <code><avr/iocanxx.h></code> to show how to define such macros:</p> <div class="fragment"><pre class="fragment"><span class="preprocessor">#define PORTA _SFR_IO8(0x02)</span> <span class="preprocessor"></span><span class="preprocessor">#define EEAR _SFR_IO16(0x21)</span> <span class="preprocessor"></span><span class="preprocessor">#define UDR0 _SFR_MEM8(0xC6)</span> <span class="preprocessor"></span><span class="preprocessor">#define TCNT3 _SFR_MEM16(0x94)</span> <span class="preprocessor">#define CANIDT _SFR_MEM32(0xF0)</span> </pre></div><p>If <code>_SFR_ASM_COMPAT</code> is not defined, C programs can use names like <code>PORTA</code> directly in C expressions (also on the left side of assignment operators) and GCC will do the right thing (use short I/O instructions if possible). The <code>__SFR_OFFSET</code> definition is not used in any way in this case.</p> <p>Define <code>_SFR_ASM_COMPAT</code> as 1 to make these names work as simple constants (addresses of the I/O registers). This is necessary when included in preprocessed assembler (*.S) source files, so it is done automatically if <code>__ASSEMBLER__</code> is defined. By default, all addresses are defined as if they were memory addresses (used in <code>lds/sts</code> instructions). To use these addresses in <code>in/out</code> instructions, you must subtract 0x20 from them.</p> <p>For more backwards compatibility, insert the following at the start of your old assembler source file:</p> <div class="fragment"><pre class="fragment"><span class="preprocessor">#define __SFR_OFFSET 0</span> </pre></div><p>This automatically subtracts 0x20 from I/O space addresses, but it's a hack, so it is recommended to change your source: wrap such addresses in macros defined here, as shown below. After this is done, the <code>__SFR_OFFSET</code> definition is no longer necessary and can be removed.</p> <p>Real example - this code could be used in a boot loader that is portable between devices with <code>SPMCR</code> at different addresses.</p> <div class="fragment"><pre class="fragment"> <avr/iom163.h>: #define SPMCR _SFR_IO8(0x37) <avr/iom128.h>: #define SPMCR _SFR_MEM8(0x68) </pre></div><div class="fragment"><pre class="fragment"><span class="preprocessor">#if _SFR_IO_REG_P(SPMCR)</span> <span class="preprocessor"></span> out _SFR_IO_ADDR(SPMCR), r24 <span class="preprocessor">#else</span> <span class="preprocessor"></span> sts _SFR_MEM_ADDR(SPMCR), r24 <span class="preprocessor">#endif</span> </pre></div><p>You can use the <code>in/out/cbi/sbi/sbic/sbis</code> instructions, without the <code>_SFR_IO_REG_P</code> test, if you know that the register is in the I/O space (as with <code>SREG</code>, for example). If it isn't, the assembler will complain (I/O address out of range 0...0x3f), so this should be fairly safe.</p> <p>If you do not define <code>__SFR_OFFSET</code> (so it will be 0x20 by default), all special register addresses are defined as memory addresses (so <code>SREG</code> is 0x5f), and (if code size and speed are not important, and you don't like the ugly #if above) you can always use lds/sts to access them. But, this will not work if <code>__SFR_OFFSET</code> != 0x20, so use a different macro (defined only if <code>__SFR_OFFSET</code> == 0x20) for safety:</p> <div class="fragment"><pre class="fragment"> sts _SFR_ADDR(SPMCR), r24 </pre></div><p>In C programs, all 3 combinations of <code>_SFR_ASM_COMPAT</code> and <code>__SFR_OFFSET</code> are supported - the <code>_SFR_ADDR(SPMCR)</code> macro can be used to get the address of the <code>SPMCR</code> register (0x57 or 0x68 depending on device). </p> </div> <hr width="80%"> <p><center>Automatically generated by Doxygen 1.6.1 on 30 Nov 2009.</center></p> </body> </html>