Title: avr cross-compiler setup gentoo and windows Subject: Setup cross-compiler development environment for the AVR board (16c0:0479) on gentoo or windows By: John at stilen dot com #-------------------------------- # Setup Windows #-------------------------------- Software to install: http://winavr.sourceforge.net/download.html Cygwin http://www.pjrc.com/teensy/loader_cli.html save teensy_loader_cli.exe http://www.pjrc.com/teensy/hdi_listen.html save hid_listen.exe Checkout: Start cygwin shell Checkout teensy source Copy software: Copy both teensy_loader_cli.exe and save hid_listen.exe into teensy directory Build: cd teensy make program Press button on Teensy board. Watch Board: double click hid_listen.exe #-------------------------------- # Setup Gentoo #-------------------------------- # # Board identity # lsusb -v -d 16c0:0479 Bus 006 Device 005: ID 16c0:0479 VOTI Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 32 idVendor 0x16c0 VOTI idProduct 0x0479 bcdDevice 1.00 iManufacturer 1 Your Name iProduct 2 Your USB Device iSerial 0 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 34 bNumInterfaces 1 bConfigurationValue 1 iConfiguration 0 bmAttributes 0xc0 Self Powered MaxPower 100mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 1 bInterfaceClass 3 Human Interface Device bInterfaceSubClass 0 No Subclass bInterfaceProtocol 0 None iInterface 0 HID Device Descriptor: bLength 9 bDescriptorType 33 bcdHID 1.11 bCountryCode 0 Not supported bNumDescriptors 1 bDescriptorType 34 Report wDescriptorLength 21 Report Descriptors: ** UNAVAILABLE ** Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x83 EP 3 IN bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x0020 1x 32 bytes bInterval 1 Device Status: 0x0000 (Bus Powered) #---------------------------------------------- # Install Toolchain for distribution software #---------------------------------------------- # # Setup make.conf to use overlay # cat >> /etc/make.conf <<'EOF' PORTDIR_OVERLAY="/usr/local/portage" EOF # # Install crossdev tool chain # echo 'sys-devel/crossdev' >> /etc/portage/package.keywords emerge crossdev eix crossdev [I] sys-devel/crossdev Available versions: 20100814 20101011 20110310 (~)20110705 **99999999 Installed versions: 20110705(08:00:26 AM 08/16/2011) Homepage: http://www.gentoo.org/ Description: Gentoo Cross-toolchain generator # # Remove any previous cross-dev stuff # crossdev -C avr # # Run AVR crossdev setup. # USE="-openmp -hardened" crossdev --target avr --gcc 4.3.5 --binutils 2.20.1-r1 --libc 1.6.8 ---------------------------------------------------------------------------- * crossdev version: 20110819 * Host Portage ARCH: x86 * Target Portage ARCH: * * Target System: avr * Stage: 4 (C/C++ compiler) * ABIs: default * binutils: binutils-2.20.1-r1 * gcc: gcc-4.3.5 * libc: avr-libc-1.6.8 * CROSSDEV_OVERLAY: /usr/local/portage * PORT_LOGDIR: /var/log/portage * PORTAGE_CONFIGROOT: _ - ~ - _ - ~ - _ - ~ - _ - ~ - - _ - ~ - _ - ~ - * leaving sys-devel/binutils in /usr/local/portage * leaving sys-devel/gcc in /usr/local/portage * leaving dev-embedded/avr-libc in /usr/local/portage * leaving sys-devel/gdb in /usr/local/portage * leaving dev-util/insight in /usr/local/portage _ - ~ - _ - ~ - _ - ~ - _ - ~ - - _ - ~ - _ - ~ - * Log: /var/log/portage/cross-avr-binutils.log * Emerging cross-binutils ... [ ok ] * Log: /var/log/portage/cross-avr-gcc-stage1.log * Emerging cross-gcc-stage1 ... [ ok ] * Log: /var/log/portage/cross-avr-avr-libc.log * Emerging cross-avr-libc ... [ ok ] * Log: /var/log/portage/cross-avr-gcc-stage2.log * Emerging cross-gcc-stage2 ... # # Emerging cross-avr-binutils # Emerging cross-avr-gcc-stage1, # Emerging cross-avr-avr-libc, # Emerging cross-gcc-stage2, # # # Sanity Check 1: Verify versions of avr software # eix cross-avr/avr-libc [I] cross-avr/avr-libc [1] Available versions: 1.6.2 (~)1.6.4 (~)1.6.8 [m](~)1.7.0 [m](~)1.7.1 {crosscompile_opts_headers-only doc nls} Installed versions: 1.6.8[?](12:39:01 PM 10/19/2011)(-crosscompile_opts_headers-only -doc) Homepage: http://www.nongnu.org/avr-libc/ Description: C library for Atmel AVR microcontrollers eix cross-avr/binutils [I] cross-avr/binutils [1] Available versions: (avr) 2.16.1-r3 (*)2.16.91.0.6 2.18-r3 (~)2.18-r4 (~)2.19.1-r1 2.20.1-r1 [m](~)2.21 [m](~)2.21.1 [m](~)2.21.1-r1 [m](**)2.21.52.0.1 [m](**)2.21.52.0.2 [m](**)2.21.53.0.1 [m](**)2.21.53.0.2 {multislot multitarget nls test vanilla} Installed versions: 2.20.1-r1(avr)[?](12:31:35 PM 10/19/2011)(nls -multislot -multitarget -static-libs -test -vanilla) Homepage: http://sources.redhat.com/binutils/ Description: Tools necessary to build programs eix cross-avr/gcc [I] cross-avr/gcc [1] Available versions: (avr-2.95) 2.95.3-r9 (~)2.95.3-r10!s (3.1) 3.1.1-r2 (avr-3.2) (**)3.2.2!s (3.2) 3.2.3-r4 (avr-3.3) (~)3.3.6-r1!s (avr-3.4) 3.4.6-r2!s (avr-4.0) (~*)4.0.4!s (avr-4.1) 4.1.2!s (avr-4.2) (~)4.2.4-r1!s (avr-4.3) (~)4.3.3-r2!s 4.3.4!s (~)4.3.5!s [m](~)4.3.6-r1!s (avr-4.4) [m](~)4.4.2!s [m](~)4.4.3-r3!s [m]4.4.4-r2!s [m]4.4.5!s [m](~)4.4.6-r1!s (avr-4.5) [m](~)4.5.1-r1!s [m](~)4.5.2!s [m](~)4.5.3-r1!s (avr-4.6) [m](**)4.6.0!s [m](**)4.6.1-r1!s {altivec bootstrap boundschecking build d doc fixed-point fortran gcj go graphite gtk hardened ip28 ip32r10k java libffi lto mudflap multilib multislot n32 n64 nls nocxx nopie nossp nptl objc objc++ objc-gc openmp static test vanilla} Installed versions: 4.3.5(avr-4.3)!s[?](10:45:07 AM 10/19/2011)(nls nptl -altivec -bootstrap -build -doc -fixed-point -fortran -gcj -gtk -hardened -libffi -mudflap -multilib -multislot -nocxx -nopie -nossp -objc -objc++ -objc-gc -openmp -test -vanilla) Homepage: http://gcc.gnu.org/ Description: The GNU Compiler Collection # # Sanity Check 2: Check for environment # ls -alF /usr/lib/binutils/ total 184 drwxr-xr-x 4 root root 112 Aug 15 13:32 ./ drwxr-xr-x 259 root root 188456 Aug 15 12:53 ../ drwxr-xr-x 3 root root 72 Aug 15 13:32 avr/ drwxr-xr-x 3 root root 72 Jun 17 2010 i686-pc-linux-gnu/ # # Sanity Check 3: What package owns this file # equery belongs /usr/avr * Searching for /usr/avr ... cross-avr/avr-libc-1.6.8 (/usr/avr) # # fix gentoo specific path issue with ldscripts # ln -s avr5/crtusb1286.o /usr/avr/lib/crtusb1286.o ln -s /usr/lib/binutils/avr/2.20.1/ldscripts /usr/avr/lib/ldscripts ls -tlr /usr/avr/lib/crtusb1286.o /usr/avr/lib/ldscripts lrwxrwxrwx 1 root root 17 Oct 19 13:05 /usr/avr/lib/crtusb1286.o -> avr5/crtusb1286.o lrwxrwxrwx 1 root root 38 Oct 19 13:05 /usr/avr/lib/ldscripts -> /usr/lib/binutils/avr/2.20.1/ldscripts #---------------------------------------------- # Configure kernel for Human Interface Device #---------------------------------------------- # # Change kernel config # cd /usr/src/linux make menuconfig # # Enable: /dev/hidraw raw HID device support in kernel # Symbol: HIDRAW [=y] │ Type : boolean │ Prompt: /dev/hidraw raw HID device support │ Defined at drivers/hid/Kconfig:34 │ Depends on: HID_SUPPORT [=y] && HID [=y] │ Location: │ -> Device Drivers │ -> HID Devices (HID_SUPPORT [=y]) │ -> Generic HID support (HID [=y]) │ # # Rebuild and install kernel # genkernel --menuconfig --no-clean --splash=natural_gentoo --splash-res=1440x900 all #---------------------------------------------- # Install Our Development Tarball #---------------------------------------------- # # Dev tarball From Alex B. # File: teensy-dev.tar.gz Md5: ddecf02854dcffd250f7f21b72035453 # # Unpack # tar -zxvpf teensy-dev.tar.gz # # Get into position for source: # cd teensy # # Copy udev rules for this board (16c0:0479) # wget http://www.pjrc.com/teensy/49-teensy.rules cp 49-teensy.rules /etc/udev/rules.d/ # # Build the teensy_loader_cli # wget http://www.pjrc.com/teensy/teensy_loader_cli.2.0.tar.gz tar -zxvpf teensy_loader_cli.2.0.tar.gz pushd teensy_loader_cli make cp teensy_loader_cli /usr/bin/ popd # # Build hid_listen # REF: http://www.pjrc.com/teensy/hid_listen.html # pushd hid_listen/ make cp hid_listen /usr/bin/ popd # # Try to compile main program # make clean -------- begin -------- Cleaning project: rm -f client.hex rm -f client.eep rm -f client.cof rm -f client.elf rm -f client.map rm -f client.sym rm -f client.lss rm -f ./client.o ./usb/print.o ./usb/usb_debug_only.o ./w5100/w5100.o ./w5100/socket.o rm -f ./client.lst ./usb/print.lst ./usb/usb_debug_only.lst ./w5100/w5100.lst ./w5100/socket.lst rm -f client.s usb/print.s usb/usb_debug_only.s w5100/w5100.s w5100/socket.s rm -f client.d usb/print.d usb/usb_debug_only.d w5100/w5100.d w5100/socket.d rm -f client.i usb/print.i usb/usb_debug_only.i w5100/w5100.i w5100/socket.i rm -rf .dep -------- end -------- make all -------- begin -------- avr-gcc (Gentoo 4.4.2 p1.0) 4.4.2 Copyright (C) 2009 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Compiling C: client.c avr-gcc -c -mmcu=at90usb1286 -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -ffunction-sections -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./client.lst -Iusb -Iw5100 -std=gnu99 -MMD -MP -MF .dep/client.o.d client.c -o client.o client.c: In function ‘main’: client.c:93: warning: large integer implicitly truncated to unsigned type client.c:93: warning: large integer implicitly truncated to unsigned type client.c:128: warning: passing argument 4 of ‘recvfrom’ from incompatible pointer type w5100/socket.h:21: note: expected ‘uint8 *’ but argument is of type ‘uint8 (*)[4]’ client.c:169: warning: passing argument 1 of ‘setSHAR’ from incompatible pointer type w5100/w5100.h:265: note: expected ‘uint8 *’ but argument is of type ‘uint8 (*)[6]’ client.c:170: warning: passing argument 1 of ‘setSIPR’ from incompatible pointer type w5100/w5100.h:266: note: expected ‘uint8 *’ but argument is of type ‘uint8 (*)[4]’ client.c:171: warning: passing argument 1 of ‘setSIPR’ from incompatible pointer type w5100/w5100.h:266: note: expected ‘uint8 *’ but argument is of type ‘uint8 (*)[4]’ Compiling C: usb/print.c avr-gcc -c -mmcu=at90usb1286 -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -ffunction-sections -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./usb/print.lst -Iusb -Iw5100 -std=gnu99 -MMD -MP -MF .dep/print.o.d usb/print.c -o usb/print.o Compiling C: usb/usb_debug_only.c avr-gcc -c -mmcu=at90usb1286 -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -ffunction-sections -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./usb/usb_debug_only.lst -Iusb -Iw5100 -std=gnu99 -MMD -MP -MF .dep/usb_debug_only.o.d usb/usb_debug_only.c -o usb/usb_debug_only.o Compiling C: w5100/w5100.c avr-gcc -c -mmcu=at90usb1286 -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -ffunction-sections -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./w5100/w5100.lst -Iusb -Iw5100 -std=gnu99 -MMD -MP -MF .dep/w5100.o.d w5100/w5100.c -o w5100/w5100.o Compiling C: w5100/socket.c avr-gcc -c -mmcu=at90usb1286 -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -ffunction-sections -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./w5100/socket.lst -Iusb -Iw5100 -std=gnu99 -MMD -MP -MF .dep/socket.o.d w5100/socket.c -o w5100/socket.o Linking: client.elf avr-gcc -mmcu=at90usb1286 -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -ffunction-sections -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=client.o -Iusb -Iw5100 -std=gnu99 -MMD -MP -MF .dep/client.elf.d client.o usb/print.o usb/usb_debug_only.o w5100/w5100.o w5100/socket.o --output client.elf -Wl,-Map=client.map,--cref -Wl,--relax -Wl,--gc-sections -lm Creating load file for Flash: client.hex avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature client.elf client.hex Creating load file for EEPROM: client.eep avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ --change-section-lma .eeprom=0 --no-change-warnings -O ihex client.elf client.eep || exit 0 Creating Extended Listing: client.lss avr-objdump -h -S -z client.elf > client.lss Creating Symbol Table: client.sym avr-nm -n client.elf > client.sym Size after: text data bss dec hex filename 4242 8 2105 6355 18d3 client.elf -------- end -------- make program teensy_loader_cli -v -w -mmcu=at90usb1286 client.hex Teensy Loader, Command Line, Version 2.0 Read "client.hex": 9512 bytes, 7.3% usage Waiting for Teensy device... (hint: press the reset button) Found HalfKay Bootloader Read "client.hex": 9512 bytes, 7.3% usage Programming...................................... Booting ---------------------------------------------------- Initial use: Command line tool: Documentation: http://www.pjrc.com/teensy/loader_cli.html teensy_loader_cli -w -mmcu=at90usb1286 teensy_loader_cli/blink_fast.hex # Blink fast teensy_loader_cli -w -mmcu=at90usb1286 teensy_loader_cli/blink_slow.hex # Blink slow teensy_loader_cli -w -mmcu=at90usb1286 teensy_loader_cli/blinky-atmega32u4.hex # No blinking teensy_loader_cli -w -mmcu=at90usb1286 teensy_loader_cli/blinky-at90usb646.hex # Blink: Solid teensy_loader_cli -w -mmcu=at90usb1286 teensy_loader_cli/blinky-at90usb162.hex # Blink: Solid teensy_loader_cli -w -mmcu=at90usb1286 teensy_loader_cli/blinky-at90usb1286.hex # Blink: ...---... ----------------------------------------------------- Alex Bellits frame dumper: make teensy_loader_cli -w -mmcu=at90usb1286 client.hex cat /dev/hidraw1 Press silver button Dumps frames ----------------------------------------------------- Blinky samples: http://www.pjrc.com/teensy/blinky.zip Read http://www.pjrc.com/teensy/first_use.html I/O Pins: The Teensy has 21 I/O pins Some pins are multi-purpose. Set all pins at beginning of program. # # set a bit to 1 or 0 # PORTD |= (1<<6); /* set bit 6 in PORTD to 1 */ PORTD &= ~(1<<6); /* clear bit 6 in PORTD to 0 */ # # Read a big # if (PIND & (1<<2)) { /* Pin D2 is High */ } else { /* Pin D2 is Low */ } # # Each port (8 pin) has 3 registers. # The "x" on the end is replaced by the actual port letter. # DDRx sets Direction, 0=Input, 1=Output PORTx when Direction=Out, 0=Low, 1=High when Direction=In, 0=Normal, 1=Pullup Resistor PINx Read a pin # # Some peripherals, such as the UART, will automatically override the DDRx register, # # When planning a project, usually a first step is # to select the built-in perhipherals that will be used. # The remaining pins may then be allocated to signals # that you will control with DDRx, PORTx and PINx. # Interrupt Basics: "interrupt service routine" to be called when a physical condition occurs. interrupt conditions: pins changing, data received, timers overflowing polling is simpler than interrupts When an interrupt is triggered, a flag bit is set by hardware. A "pending" interrupt = flag is set, but "interrupt service routine" has not been called yet. polling can also use the flag bits. Most interrupt flags are automatically reset when the interrupt service routine is called. Other are reset inside the "interrupt service routine". Others are changed indirectly by manipulating the peripheral that controls the flags. Every interrupt also has a mask bit, which enable or disables that individual interrupt. Complete list of mask and flag names: http://www.pjrc.com/teensy/interrupts.html#names There is a global interrupt enable bit, which lets you disable all interrupts, then enable all interrupts that have their mask bits set. All interrupts are used in roughly the same way. 1. Configure The Peripheral 2. Reset Interrupt Flag 3. Set Interrupt Mask 4. Enable Global Interrupt, with sei() Use interrupts by lincluding the AVR interrupt header. This will define the ISR() macro and names for each of the possible interrupt routines. #include #include Using Interrupts Interrupts are a hardware feature that allows a special piece of code, called an "interrupt service routine" to be called when a physical condition occurs. Many interrupts are available for conditions such as pins changing, data received, timers overflowing. Polling Versus Interrupts Interrupts are complex to use. Often simply checking for the condition periodically (called "polling") is a much simpler solution, if not elegant. Interrupt Basics Every interrupt has a flag bit, which is set by hardware when the interrupt trigger condition occurs. The flag's purpose is to remember the interrupt condition has occurred until it has been handled by software. An interrupt is said to be "pending" if the trigger condition has set the flag but the interrupt service routine has not been called yet, which can happen if the main program has disabled interrupts or another interrupt service routine is running. The flag bit is set even if interrupts are not used. Software polling can read the flag bit to check if the condition has occured, do whatever is necessary, and then reset the flag. Most interrupt flags are automatically reset when the interrupt service routine is called. Some flags must be reset by the software inside the interrupt service routine. Some flags are completely controlled by the peripheral to reflect internal state (such as USART receive) and can only be changed indirectly by manipulating the peripheral. Every interrupt also has a mask bit, which enable or disables that individual interrupt. These mask bits allow you to control which of the many interrupts are enabled. See below for a complete list of mask and flag names. There is also a global interrupt enable bit, which allows you to disable all interrupts and enable all interrupts that have their mask bits set. When the global interrupt enable is set, and individual masks are enabled, and interrupt flags are set, the corresponding interrupt vector is called for each flag. Interrupt Configuration Steps All interrupts are used in roughly the same way. 1. Configure The Peripheral 2. Reset Interrupt Flag 3. Set Interrupt Mask 4. Enable Global Interrupt, with sei() When the interrupt condition occurs, the interrupt flag is set. The interrupt service routine will be called at the first opportunity. Interrupt Service Routine Syntax To use interrupts, you must include the AVR interrupt header. #include #include This will define the ISR() macro and names for each of the possible interrupt routines. A complete list of names appears below. For example, to create an interupt service routine to handle Timer 0 overflow: ISR(TIMER0_OVF_vect) { /* Timer 0 overflow */ } Because the interrupt service routine is called directly by the hardware, rather than your own code, it must use the special name for the desired interrupt, so that the compiler may properly associate it with the interrupt vector. Interrupt service routines must be careful to restore the machine state (except for intentionally shared variables) to exactly what it was, so that the main program does not see random changes. The ISR() macro instructs the compiler to handle all these details. Interrupt Design Strategy When hardware calls an ISR, it clears the global interrupt flag, so that no other interrupt routine may be called. Returning from an ISR automaticly resets the global interrupt flag. If other interrupt flags are set, the hardware will call the next ISR rather than return to main. it is safest to never use sei() within any interrupt service routine. Shared Variables Shared variables must be declared with the "volatile" keyword, which prevents the compiler from optimizing volatile unsigned int overflow_count=0; # 16 bit number counts the number of times Timer 0 has overflowed ISR(TIMER0_OVF_vect) { if (overflow_count < 0xFFFF) overflow_count++; } When accessing shared variables from main, disable the global interrupt setting with cli() and reenable with with sei() Complex operations, such as adding or removing data from a buffer and adjusting pointers need to be protected from start to finish. Alternatively, You can also disable the individual mask bit for your interrupt, rather than using cli(). Interrupt Vector, Mask & Flag Names ISR() Name: The name used with ISR() to define the interrupt service routine. Mask: (byte,bit#) Bit that enables this interrupt. See accessing a single bit for C syntax to write byte,bit# pairs. Flag: (byte,bit#) Flag indicates if the interrupt is pending. Many flags are reset by writing 1 (yes, that seems horribly backwards, but that's the way the hardware works). Most flags are automatically reset when the interrupt service routine is called.