1/* Copyright (c) 2002,2004,2005,2009 Joerg Wunsch 2 All rights reserved. 3 4 Redistribution and use in source and binary forms, with or without 5 modification, are permitted provided that the following conditions are met: 6 7 * Redistributions of source code must retain the above copyright 8 notice, this list of conditions and the following disclaimer. 9 * Redistributions in binary form must reproduce the above copyright 10 notice, this list of conditions and the following disclaimer in 11 the documentation and/or other materials provided with the 12 distribution. 13 * Neither the name of the copyright holders nor the names of 14 contributors may be used to endorse or promote products derived 15 from this software without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 POSSIBILITY OF SUCH DAMAGE. */ 28 29/* $Id: assembler.dox 2305 2013-01-02 17:53:52Z joerg_wunsch $ */ 30 31/** \page assembler avr-libc and assembler programs 32 33\section ass_intro Introduction 34 35There might be several reasons to write code for AVR microcontrollers 36using plain assembler source code. Among them are: 37 38- Code for devices that do not have RAM and are thus not supported 39 by the C compiler. 40- Code for very time-critical applications. 41- Special tweaks that cannot be done in C. 42 43Usually, all but the first could probably be done easily using the 44\ref inline_asm "inline assembler" facility of the compiler. 45 46Although avr-libc is primarily targeted to support programming AVR 47microcontrollers using the C (and C++) language, there's limited 48support for direct assembler usage as well. The benefits of it are: 49 50- Use of the C preprocessor and thus the ability to use the same 51 symbolic constants that are available to C programs, as well as 52 a flexible macro concept that can use any valid C identifier as 53 a macro (whereas the assembler's macro concept is basically 54 targeted to use a macro in place of an assembler instruction). 55- Use of the runtime framework like automatically assigning 56 interrupt vectors. For devices that have RAM, 57 \ref sec_dot_init "initializing the RAM variables" can also 58 be utilized. 59 60\section ass_tools Invoking the compiler 61 62For the purpose described in this document, the assembler and linker 63are usually not invoked manually, but rather using the C compiler 64frontend (\c avr-gcc) that in turn will call the assembler and linker 65as required. 66 67This approach has the following advantages: 68 69- There is basically only one program to be called directly, 70 \c avr-gcc, regardless of the actual source language used. 71- The invokation of the C preprocessor will be automatic, 72 and will include the appropriate options to locate required 73 include files in the filesystem. 74- The invokation of the linker will be automatic, and will 75 include the appropriate options to locate additional libraries 76 as well as the application start-up code 77 (<tt>crt</tt><em>XXX</em><tt>.o</tt>) and linker script. 78 79Note that the invokation of the C preprocessor will be automatic when 80the filename provided for the assembler file ends in \c .S (the 81capital letter "s"). This would even apply to operating systems that 82use case-insensitive filesystems since the actual decision is made 83based on the case of the filename suffix given on the command-line, 84not based on the actual filename from the file system. 85 86As an alternative to using \c .S, the suffix \c .sx is recognized for 87this purpose (starting with GCC 4.3.0). This is primarily meant to be 88compatible with other compiler environments that have been providing 89this variant before in order to cope with operating systems where 90filenames are case-insensitive (and, with some versions of \c make 91that could not distinguish between \c .s and \c .S on such systems). 92 93Alternatively, the language can explicitly be specified using the 94<tt>-x assembler-with-cpp</tt> option. 95 96\section ass_example Example program 97 98The following annotated example features a simple 100 kHz square wave 99generator using an AT90S1200 clocked with a 10.7 MHz crystal. Pin 100PD6 will be used for the square wave output. 101 102\code 103#include <avr/io.h> ; Note [1] 104 105work = 16 ; Note [2] 106tmp = 17 107 108inttmp = 19 109 110intsav = 0 111 112SQUARE = PD6 ; Note [3] 113 114 ; Note [4]: 115tmconst= 10700000 / 200000 ; 100 kHz => 200000 edges/s 116fuzz= 8 ; # clocks in ISR until TCNT0 is set 117 118 .section .text 119 120 .global main ; Note [5] 121main: 122 rcall ioinit 1231: 124 rjmp 1b ; Note [6] 125 126 .global TIMER0_OVF_vect ; Note [7] 127TIMER0_OVF_vect: 128 ldi inttmp, 256 - tmconst + fuzz 129 out _SFR_IO_ADDR(TCNT0), inttmp ; Note [8] 130 131 in intsav, _SFR_IO_ADDR(SREG) ; Note [9] 132 133 sbic _SFR_IO_ADDR(PORTD), SQUARE 134 rjmp 1f 135 sbi _SFR_IO_ADDR(PORTD), SQUARE 136 rjmp 2f 1371: cbi _SFR_IO_ADDR(PORTD), SQUARE 1382: 139 140 out _SFR_IO_ADDR(SREG), intsav 141 reti 142 143ioinit: 144 sbi _SFR_IO_ADDR(DDRD), SQUARE 145 146 ldi work, _BV(TOIE0) 147 out _SFR_IO_ADDR(TIMSK), work 148 149 ldi work, _BV(CS00) ; tmr0: CK/1 150 out _SFR_IO_ADDR(TCCR0), work 151 152 ldi work, 256 - tmconst 153 out _SFR_IO_ADDR(TCNT0), work 154 155 sei 156 157 ret 158 159 .global __vector_default ; Note [10] 160__vector_default: 161 reti 162 163 .end 164\endcode 165 166\par Note [1] 167 168As in C programs, this includes the central processor-specific file 169containing the IO port definitions for the device. Note that not all 170include files can be included into assembler sources. 171 172\par Note [2] 173 174Assignment of registers to symbolic names used locally. Another 175option would be to use a C preprocessor macro instead: 176 177\code #define work 16 \endcode 178 179\par Note [3] 180 181Our bit number for the square wave output. Note that the right-hand 182side consists of a CPP macro which will be substituted by its value (6 183in this case) before actually being passed to the assembler. 184 185\par Note [4] 186 187The assembler uses integer operations in the host-defined integer size 188(32 bits or longer) when evaluating expressions. This is in contrast 189to the C compiler that uses the C type \c int by default in order to 190calculate constant integer expressions. 191<br> 192In order to get a 100 kHz output, we need to toggle the PD6 line 193200000 times per second. Since we use timer 0 without any prescaling 194options in order to get the desired frequency and accuracy, we already 195run into serious timing considerations: while accepting and processing 196the timer overflow interrupt, the timer already continues to count. 197When pre-loading the \c TCCNT0 register, we therefore have to account 198for the number of clock cycles required for interrupt acknowledge and 199for the instructions to reload \c TCCNT0 (4 clock cycles for interrupt 200acknowledge, 2 cycles for the jump from the interrupt vector, 2 cycles 201for the 2 instructions that reload \c TCCNT0). This is what the 202constant \c fuzz is for. 203 204\par Note [5] 205 206External functions need to be declared to be \c .global. \c main is 207the application entry point that will be jumped to from the 208ininitalization routine in \c crts1200.o. 209 210\par Note [6] 211 212The main loop is just a single jump back to itself. Square wave 213generation itself is completely handled by the timer 0 overflow 214interrupt service. A \c sleep instruction (using idle mode) could be 215used as well, but probably would not conserve much energy anyway since 216the interrupt service is executed quite frequently. 217 218\par Note [7] 219 220Interrupt functions can get the \ref avr_signames "usual names" that 221are also available to C programs. The linker will then put them into 222the appropriate interrupt vector slots. Note that they must be 223declared \c .global in order to be acceptable for this purpose. 224This will only work if <tt><avr/io.h></tt> has been included. 225Note that the assembler or linker have no chance to check the correct 226spelling of an interrupt function, so it should be double-checked. 227(When analyzing the resulting object file using \c avr-objdump or 228\c avr-nm, a name like <tt>__vector_<em>N</em></tt> should appear, 229with \e N being a small integer number.) 230 231\par Note [8] 232 233As explained in the section about 234\ref avr_sfr_notes "special function registers", 235the actual IO port address should be obtained using the macro 236\c _SFR_IO_ADDR. (The AT90S1200 does not have RAM thus the memory-mapped 237approach to access the IO registers is not available. It would be 238slower than using \c in / \c out instructions anyway.) 239<br> 240Since the operation to reload \c TCCNT0 is time-critical, it is even 241performed before saving \c SREG. Obviously, this requires that the 242instructions involved would not change any of the flag bits in \c SREG. 243 244\anchor ass_isr 245\par Note [9] 246 247Interrupt routines must not clobber the global CPU state. Thus, it is 248usually necessary to save at least the state of the flag bits in \c SREG. 249(Note that this serves as an example here only since actually, all the 250following instructions would not modify \c SREG either, but that's not 251commonly the case.) 252<br> 253Also, it must be made sure that registers used inside the interrupt 254routine do not conflict with those used outside. In the case of a 255RAM-less device like the AT90S1200, this can only be done by agreeing 256on a set of registers to be used exclusively inside the interrupt 257routine; there would not be any other chance to "save" a register 258anywhere. 259<br> 260If the interrupt routine is to be linked together with C modules, care 261must be taken to follow the \ref faq_reg_usage "register usage guidelines" 262imposed by the C compiler. Also, any register modified inside the 263interrupt sevice needs to be saved, usually on the stack. 264 265\par Note [10] 266 267As explained in \ref avr_interrupts "Interrupts", a global "catch-all" interrupt 268handler that gets all unassigned interrupt vectors can be installed 269using the name \c __vector_default. This must be \c .global, and 270obviously, should end in a \c reti instruction. (By default, a jump 271to location 0 would be implied instead.) 272 273\section ass_pseudoops Pseudo-ops and operators 274 275The available pseudo-ops in the assembler are described in the GNU 276assembler (gas) manual. The manual can be found online as part of the 277current binutils release under http://sources.redhat.com/binutils/. 278 279As gas comes from a Unix origin, its pseudo-op and overall assembler 280syntax is slightly different than the one being used by other 281assemblers. Numeric constants follow the C notation (prefix \c 0x for 282hexadecimal constants), expressions use a C-like syntax. 283 284Some common pseudo-ops include: 285 286- \c .byte allocates single byte constants 287 288- \c .ascii allocates a non-terminated string of characters 289 290 291- \c .asciz allocates a \\0-terminated string of characters (C string) 292 293- \c .data switches to the .data section (initialized RAM variables) 294 295- \c .text switches to the .text section (code and ROM constants) 296 297- \c .set declares a symbol as a constant expression (identical to 298 \c .equ) 299 300- \c .global (or \c .globl) declares a public symbol that is visible 301 to the linker (e. g. function entry point, global variable) 302 303- \c .extern declares a symbol to be externally defined; this is 304 effectively a comment only, as gas treats all undefined symbols 305 it encounters as globally undefined anyway 306 307Note that \c .org is available in gas as well, but is a fairly 308pointless pseudo-op in an assembler environment that uses relocatable 309object files, as it is the linker that determines the final position 310of some object in ROM or RAM. 311 312Along with the architecture-independent standard operators, there are 313some AVR-specific operators available which are unfortunately not yet 314described in the official documentation. The most notable operators 315are: 316 317- \c lo8 Takes the least significant 8 bits of a 16-bit integer 318 319- \c hi8 Takes the most significant 8 bits of a 16-bit integer 320 321- \c pm Takes a program-memory (ROM) address, and converts it into a 322 RAM address. This implies a division by 2 as the AVR handles ROM 323 addresses as 16-bit words (e.g. in an \c IJMP or \c ICALL 324 instruction), and can also handle relocatable symbols on the 325 right-hand side. 326 327Example: 328\verbatim 329 ldi r24, lo8(pm(somefunc)) 330 ldi r25, hi8(pm(somefunc)) 331 call something 332\endverbatim 333 334This passes the address of function \c somefunc as the first parameter 335to function \c something. 336 337*/ 338