I've been using this Makefile for a couple years with the ATmega328p with no problems. So I got an ATxmega128a4u and changed the top line:
MCU = atxmega128a4u #MCU = atmega328p F_CPU = 16000000UL BAUD = 19200UL LIBDIR = lib print-%: @echo '$*=$($*)' CC = avr-gcc TARGET = main SOURCES=$(wildcard *.c $(LIBDIR)/*.c) OBJECTS=$(SOURCES:.c=.o) HEADERS=$(SOURCES:.c=.h) CPPFLAGS = -DMAIN_C -DF_CPU=$(F_CPU) -DBAUD=$(BAUD) -I. -I$(LIBDIR) CFLAGS = -Os -g -std=gnu99 -Wall CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums CFLAGS += -ffunction-sections -fdata-sections LDFLAGS = -Wl,-Map,$(TARGET).map LDFLAGS += -Wl,--gc-sections TARGET_ARCH = -mmcu=$(MCU) %.o: %.c $(HEADERS) Makefile $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<; $(TARGET).elf: $(OBJECTS) $(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LDLIBS) -o $@ %.hex: %.elf $(OBJCOPY) -j .text -j .data -O ihex $< $@ %.eeprom: %.elf $(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@ %.lst: %.elf $(OBJDUMP) -S $< > $@ ## These targets don't have files named after them .PHONY: all all: $(TARGET).hex debug: @echo @echo "Source files:" $(SOURCES) @echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD) @echo
and I get a strange error:
avr-gcc -Os -g -std=gnu99 -Wall -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -ffunction-sections -fdata-sections -DMAIN_C -DF_CPU=16000000UL -DBAUD=19200UL -I. -Ilib -mmcu=atxmega128a4u -c -o USART.o USART.c; <command-line>:0:6: error: expected identifier or ‘(’ before numeric constant
I did a google search and it has something to do with not escaping nl's in macros.
so I made a script file:
avr-gcc -O2 -Wall -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -ffunction-sections -fdata-sections -fmessage-length=0 -ffunction-sections -DF_CPU=16000000UL -mmcu=atxmega128a4u -c -o main.o main.c avr-gcc -O2 -Wall -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -ffunction-sections -fdata-sections -fmessage-length=0 -ffunction-sections -DF_CPU=16000000UL -mmcu=atxmega128a4u -c -o USART.o USART.c avr-gcc -mmcu=atxmega128a4u -Wl,--gc-sections -Wl, -omain.elf main.o
and it compiles the main.c but the USART.c gives these errors:
In file included from main.c:9:0: USART.h:7:2: warning: #warning "ATxmega128A4U defined" [-Wcpp] #warning "ATxmega128A4U defined" ^ In file included from USART.c:24:0: USART.h:7:2: warning: #warning "ATxmega128A4U defined" [-Wcpp] #warning "ATxmega128A4U defined" ^ USART.c: In function ‘initUSART’: USART.c:29:2: error: ‘UBRR0H’ undeclared (first use in this function) UBRR0H = (UCHAR)(baud >> 8); ^ USART.c:29:2: note: each undeclared identifier is reported only once for each function it appears in USART.c:30:2: error: ‘UBRR0L’ undeclared (first use in this function) UBRR0L = (UCHAR)baud; ^ USART.c:31:2: error: ‘UCSR0B’ undeclared (first use in this function) UCSR0B = (1<<RXEN0) | (1<<TXEN0); ^ USART.c:31:15: error: ‘RXEN0’ undeclared (first use in this function) UCSR0B = (1<<RXEN0) | (1<<TXEN0); ^ USART.c:31:28: error: ‘TXEN0’ undeclared (first use in this function) UCSR0B = (1<<RXEN0) | (1<<TXEN0); ^ USART.c:32:2: error: ‘UCSR0C’ undeclared (first use in this function) UCSR0C = (1<<USBS0) | (3<<UCSZ00); ^ USART.c:32:15: error: ‘USBS0’ undeclared (first use in this function) UCSR0C = (1<<USBS0) | (3<<UCSZ00); ^ USART.c:32:28: error: ‘UCSZ00’ undeclared (first use in this function) UCSR0C = (1<<USBS0) | (3<<UCSZ00); ^ USART.c: In function ‘transmitByte’: USART.c:51:10: error: ‘UCSR0A’ undeclared (first use in this function) while(!(UCSR0A & (1<<UDRE0))) ^ USART.c:51:23: error: ‘UDRE0’ undeclared (first use in this function) while(!(UCSR0A & (1<<UDRE0))) ^ USART.c:52:2: error: ‘UDR0’ undeclared (first use in this function) UDR0 = data; ^ USART.c: In function ‘receiveByte’: USART.c:56:10: error: ‘UCSR0A’ undeclared (first use in this function) while(!(UCSR0A & (1<<RXC0))); ^ USART.c:56:23: error: ‘RXC0’ undeclared (first use in this function) while(!(UCSR0A & (1<<RXC0))); ^ USART.c:57:1: warning: control reaches end of non-void function [-Wreturn-type] } ^ /usr/lib/gcc/avr/4.9.2/../../../avr/bin/ld: cannot find : No such file or directory collect2: error: ld returned 1 exit status
I'm compiling main.c & USART.C:
#include <avr/io.h> #include "../avr8-gnu-toolchain-linux_x86/avr/include/util/delay.h" #include "sfr_helper.h" #include <stdlib.h> #include "macros.h" #include <string.h> #include <stdio.h> #include <stdlib.h> #include "USART.h" int main(void) { unsigned char xbyte; initUSART(19200); _delay_ms(100); xbyte = 0x21; _delay_ms(100); while(1) { _delay_ms(50); transmitByte(xbyte); if(--xbyte < 0x21) xbyte = 0x7e; } return 0; }
#ifndef _USART_H #define _USART_H #include <avr/io.h> #include "../avr8-gnu-toolchain-linux_x86/avr/include/util/delay.h" //#include "../avr8-gnu-toolchain-linux_x86/avr/include/avr/iom128a.h" #include "sfr_helper.h" #include "USART.h" #include <util/setbaud.h> void initUSART(UINT baud) { UBRR0H = (UCHAR)(baud >> 8); UBRR0L = (UCHAR)baud; UCSR0B = (1<<RXEN0) | (1<<TXEN0); UCSR0C = (1<<USBS0) | (3<<UCSZ00); } #if 0 void initUSART(void) { /* requires BAUD */ UBRR0H = UBRRH_VALUE; /* defined in setbaud.h */ UBRR0L = UBRRL_VALUE; #if USE_2X UCSR0A |= (1 << U2X0); #else UCSR0A &= ~(1 << U2X0); #endif /* Enable USART transmitter/receiver */ UCSR0B = (1 << TXEN0) | (1 << RXEN0); UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); /* 8 data bits, 1 stop bit */ } #endif void transmitByte(uint8_t data) { while(!(UCSR0A & (1<<UDRE0))) UDR0 = data; } UCHAR receiveByte(void) { while(!(UCSR0A & (1<<RXC0))); } #if 0 void transmitByte(uint8_t data) { /* Wait for empty transmit buffer */ loop_until_bit_is_set(UCSR0A, UDRE0); UDR0 = data; /* send data */ } uint8_t receiveByte(void) { loop_until_bit_is_set(UCSR0A, RXC0); /* Wait for incoming data */ return UDR0; /* return register value */ } #endif /* Here are a bunch of useful printing commands */ void printString(const char myString[]) { uint8_t i = 0; while (myString[i]) { transmitByte(myString[i]); i++; } } void readString(char myString[], uint8_t maxLength) { char response; uint8_t i; i = 0; while (i < (maxLength - 1)) { /* prevent over-runs */ response = receiveByte(); transmitByte(response); /* echo */ if (response == '\r') { /* enter marks the end */ break; } else { myString[i] = response; /* add in a letter */ i++; } } myString[i] = 0; /* terminal NULL character */ } void printByte(uint8_t byte) { /* Converts a byte to a string of decimal text, sends it */ transmitByte('0' + (byte / 100)); /* Hundreds */ transmitByte('0' + ((byte / 10) % 10)); /* Tens */ transmitByte('0' + (byte % 10)); /* Ones */ } void printWord(UINT word) { transmitByte('0' + (word / 10000)); /* Ten-thousands */ transmitByte('0' + ((word / 1000) % 10)); /* Thousands */ transmitByte('0' + ((word / 100) % 10)); /* Hundreds */ transmitByte('0' + ((word / 10) % 10)); /* Tens */ transmitByte('0' + (word % 10)); /* Ones */ } void printBinaryByte(uint8_t byte) { /* Prints out a byte as a series of 1's and 0's */ uint8_t bit; for (bit = 7; bit < 255; bit--) { if (bit_is_set(byte, bit)) transmitByte('1'); else transmitByte('0'); } } char nibbleToHexCharacter(uint8_t nibble) { /* Converts 4 bits into hexadecimal */ if (nibble < 10) { return ('0' + nibble); } else { return ('A' + nibble - 10); } } void printHexByte(uint8_t byte) { /* Prints a byte as its hexadecimal equivalent */ uint8_t nibble; nibble = (byte & 0b11110000) >> 4; transmitByte(nibbleToHexCharacter(nibble)); nibble = byte & 0b00001111; transmitByte(nibbleToHexCharacter(nibble)); } uint8_t getNumber(void) { // Gets a numerical 0-255 from the serial port. // Converts from string to number. char hundreds = '0'; char tens = '0'; char ones = '0'; char thisChar = '0'; do { /* shift over */ hundreds = tens; tens = ones; ones = thisChar; thisChar = receiveByte(); /* get a new character */ transmitByte(thisChar); /* echo */ } while (thisChar != '\r'); /* until type return */ return (100 * (hundreds - '0') + 10 * (tens - '0') + ones - '0'); } #endif
What's really weird is if I change the top line back to MCU = atmega328p it compiles fine.