Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add XMEGA E5 support #17

Merged
merged 10 commits into from Oct 11, 2015
9 changes: 6 additions & 3 deletions Makefile
Expand Up @@ -531,10 +531,13 @@ endif
# Sizes in bytes, not works (datasheet generally in words)
# xmega
MCU_S = $(subst atxmega,x,$(MCU))
ifneq ($(filter $(MCU_S), x16a4 x16d4 x16a4u),)
ifneq ($(filter $(MCU_S), x8e5),)
BOOT_SECTION_START =0x002000
endif
ifneq ($(filter $(MCU_S), x16a4 x16d4 x16a4u x16e5),)
BOOT_SECTION_START =0x004000
endif
ifneq ($(filter $(MCU_S), x32a4 x32d4 x32a4u),)
ifneq ($(filter $(MCU_S), x32a4 x32d4 x32a4u x32e5),)
BOOT_SECTION_START =0x008000
endif
ifneq ($(filter $(MCU_S), x64a1 x64a3 x64a4 x64d3 x64d4 x64a3u x64a4u x64b1 x64b3),)
Expand Down Expand Up @@ -773,7 +776,7 @@ sym: $(TARGET).sym
# Configuration support
%.conf %.conf.mk: force
cp $@ config.mk
$(MAKE)
"$(MAKE)"

-include config.h.mk

Expand Down
4 changes: 4 additions & 0 deletions conf/akafuino32a4.conf.mk
Expand Up @@ -11,6 +11,9 @@ MCU = atxmega32a4
# Use 2 MHz internal RC oscillator
F_CPU = 2000000

# DFLL for better stability
USE_DFLL = yes

# Programmer settings
OVERRIDE_AVRDUDE_PROGRAMMER = yes
AVRDUDE_PROGRAMMER = jtag2pdi
Expand Down Expand Up @@ -163,6 +166,7 @@ UART_BAUD_RATE = 115200
UART_PORT_NAME = C
UART_NUMBER = 0
UART_RX_PUEN = yes
UART_REMAP = no

# UART RS485 Enable Output
UART_EN_PORT_NAME = C
Expand Down
4 changes: 4 additions & 0 deletions conf/arduino328p.conf.mk
Expand Up @@ -24,6 +24,9 @@ BOOTSZ=0
# Use 16 MHz external crystal oscillator
F_CPU = 16000000

# DFLL for better stability
USE_DFLL = yes

# Programmer settings
OVERRIDE_AVRDUDE_PROGRAMMER = yes
AVRDUDE_PROGRAMMER = jtag2isp
Expand Down Expand Up @@ -138,6 +141,7 @@ UART_BAUD_RATE = 115200
UART_NUMBER = 0
UART_U2X = yes
UART_RX_PUEN = yes
UART_REMAP = no

# UART RS485 Enable Output
UART_EN_PORT_NAME = C
Expand Down
4 changes: 4 additions & 0 deletions conf/mongoose.conf.mk
Expand Up @@ -24,6 +24,9 @@ BOOTSZ=0
# Use 16 MHz external crystal oscillator
F_CPU = 16000000

# DFLL for better stability
USE_DFLL = yes

# Programmer settings
OVERRIDE_AVRDUDE_PROGRAMMER = yes
AVRDUDE_PROGRAMMER = jtag2isp
Expand Down Expand Up @@ -134,6 +137,7 @@ UART_BAUD_RATE = 115200
UART_NUMBER = 0
UART_U2X = yes
UART_RX_PUEN = yes
UART_REMAP = no

# UART RS485 Enable Output
UART_EN_PORT_NAME = C
Expand Down
4 changes: 4 additions & 0 deletions conf/x32a4.conf.mk
Expand Up @@ -10,6 +10,9 @@ MCU = atxmega32a4
# Use 2 MHz internal RC oscillator
F_CPU = 2000000

# DFLL for better stability
USE_DFLL = yes

# Programmer settings
OVERRIDE_AVRDUDE_PROGRAMMER = yes
AVRDUDE_PROGRAMMER = jtag2pdi
Expand Down Expand Up @@ -162,6 +165,7 @@ UART_BAUD_RATE = 115200
UART_PORT_NAME = C
UART_NUMBER = 0
UART_RX_PUEN = yes
UART_REMAP = no

# UART RS485 Enable Output
UART_EN_PORT_NAME = C
Expand Down
4 changes: 4 additions & 0 deletions conf/x64a3.conf.mk
Expand Up @@ -10,6 +10,9 @@ MCU = atxmega64a3
# Use 2 MHz internal RC oscillator
F_CPU = 2000000

# DFLL for better stability
USE_DFLL = yes

# Programmer settings
OVERRIDE_AVRDUDE_PROGRAMMER = yes
AVRDUDE_PROGRAMMER = jtag2pdi
Expand Down Expand Up @@ -162,6 +165,7 @@ UART_BAUD_RATE = 115200
UART_PORT_NAME = D
UART_NUMBER = 1
UART_RX_PUEN = yes
UART_REMAP = no

# UART RS485 Enable Output
UART_EN_PORT_NAME = C
Expand Down
124 changes: 0 additions & 124 deletions eeprom_driver.c
Expand Up @@ -118,130 +118,6 @@ void wait_for_nvm(void)
while (NVM.STATUS & NVM_NVMBUSY_bm) { };
}

void flush_buffer(void)
{
wait_for_nvm();

if ((NVM.STATUS & NVM_EELOAD_bm) != 0) {
NVM.CMD = NVM_CMD_ERASE_EEPROM_BUFFER_gc;
NVM_EXEC();
}
}


uint8_t EEPROM_read_byte(uint16_t addr)
{
wait_for_nvm();

NVM.ADDR0 = addr & 0xFF;
NVM.ADDR1 = (addr >> 8) & 0x1F;
NVM.ADDR2 = 0;

NVM.CMD = NVM_CMD_READ_EEPROM_gc;
NVM_EXEC();

return NVM.DATA0;
}


void EEPROM_write_byte(uint16_t addr, uint8_t byte)
{
flush_buffer();
NVM.CMD = NVM_CMD_LOAD_EEPROM_BUFFER_gc;

NVM.ADDR0 = addr & 0xFF;
NVM.ADDR1 = (addr >> 8) & 0x1F;
NVM.ADDR2 = 0;

NVM.DATA0 = byte;

NVM.CMD = NVM_CMD_ERASE_WRITE_EEPROM_PAGE_gc;
NVM_EXEC_WRAPPER();
}


uint16_t EEPROM_read_block(uint16_t addr, uint8_t *dest, uint16_t len)
{
uint16_t cnt = 0;

NVM.ADDR2 = 0;

wait_for_nvm();

while (len > 0)
{
NVM.ADDR0 = addr & 0xFF;
NVM.ADDR1 = (addr >> 8) & 0x1F;

NVM.CMD = NVM_CMD_READ_EEPROM_gc;
NVM_EXEC();

*(dest++) = NVM.DATA0; addr++;

len--; cnt++;
}
return cnt;
}


uint16_t EEPROM_write_block(uint16_t addr, const uint8_t *src, uint16_t len)
{
uint8_t byte_addr = addr % EEPROM_PAGE_SIZE;
uint16_t page_addr = addr - byte_addr;
uint16_t cnt = 0;

flush_buffer();
wait_for_nvm();
NVM.CMD = NVM_CMD_LOAD_EEPROM_BUFFER_gc;

NVM.ADDR1 = 0;
NVM.ADDR2 = 0;

while (len > 0)
{
NVM.ADDR0 = byte_addr;

NVM.DATA0 = *(src++);

byte_addr++;
len--;

if (len == 0 || byte_addr >= EEPROM_PAGE_SIZE)
{
NVM.ADDR0 = page_addr & 0xFF;
NVM.ADDR1 = (page_addr >> 8) & 0x1F;

NVM.CMD = NVM_CMD_ERASE_WRITE_EEPROM_PAGE_gc;
NVM_EXEC();

page_addr += EEPROM_PAGE_SIZE;
byte_addr = 0;

wait_for_nvm();

NVM.CMD = NVM_CMD_LOAD_EEPROM_BUFFER_gc;
}

cnt++;
}

return cnt;
}


void EEPROM_erase_page(uint16_t addr)
{
NVM.ADDR0 = addr & 0xFF;
NVM.ADDR1 = (addr >> 8) & 0x1F;
NVM.ADDR2 = 0;

wait_for_nvm();

NVM.CMD = NVM_CMD_ERASE_EEPROM_PAGE_gc;
NVM_EXEC_WRAPPER();
}


void EEPROM_erase_all(void)
{
wait_for_nvm();
Expand Down
20 changes: 1 addition & 19 deletions eeprom_driver.h
Expand Up @@ -34,10 +34,7 @@

#include <avr/io.h>
#include <avr/interrupt.h>

#ifndef __AVR_XMEGA__
#include <avr/eeprom.h>
#endif // __AVR_XMEGA__

#include "xboot.h"

Expand All @@ -52,17 +49,6 @@

// Prototypes

#ifdef __AVR_XMEGA__

uint8_t EEPROM_read_byte(uint16_t addr);
void EEPROM_write_byte(uint16_t addr, uint8_t byte);
uint16_t EEPROM_read_block(uint16_t addr, uint8_t *dest, uint16_t len);
uint16_t EEPROM_write_block(uint16_t addr, const uint8_t *src, uint16_t len);

void EEPROM_erase_page(uint16_t addr);

#else // __AVR_XMEGA__

#define EEPROM_read_byte(addr) eeprom_read_byte((const uint8_t *)((uint16_t)(addr)))
#define EEPROM_write_byte(addr, value) eeprom_write_byte((uint8_t *)((uint16_t)(addr)), (value))
#define EEPROM_read_block(addr, dest, len) eeprom_read_block((dest), (void *)((uint16_t)(addr)), (len))
Expand All @@ -73,12 +59,8 @@ uint8_t enter_eeprom_check(void);
void enter_eeprom_reset(void);
#endif // USE_ENTER_EEPROM

#endif // __AVR_XMEGA__

void EEPROM_erase_all(void);


#endif // __EEPROM_DRIVER_H



#endif // __EEPROM_DRIVER_H
6 changes: 6 additions & 0 deletions uart.c
Expand Up @@ -72,6 +72,9 @@ void uart_init(void)
{
#ifdef __AVR_XMEGA__
UART_PORT.DIRSET = (1 << UART_TX_PIN);
#ifdef UART_REMAP
UART_PORT.REMAP |= PORT_USART0_bm;
#endif // UART_REMAP
UART_DEVICE.BAUDCTRLA = (UART_BSEL_VALUE & USART_BSEL_gm);
UART_DEVICE.BAUDCTRLB = ((UART_BSCALE_VALUE << USART_BSCALE_gp) & USART_BSCALE_gm) | ((UART_BSEL_VALUE >> 8) & ~USART_BSCALE_gm);
#if UART_CLK2X
Expand Down Expand Up @@ -104,6 +107,9 @@ void uart_deinit(void)
#endif // USE_INTERRUPTS
UART_DEVICE.BAUDCTRLA = 0;
UART_DEVICE.BAUDCTRLB = 0;
#ifdef UART_REMAP
UART_PORT.REMAP &= ~PORT_USART0_bm;
#endif // UART_REMAP
UART_PORT.DIRCLR = (1 << UART_TX_PIN);
#else // __AVR_XMEGA__
UART_UCSRA = 0;
Expand Down
37 changes: 29 additions & 8 deletions xboot.c
Expand Up @@ -238,7 +238,7 @@ int main(void)
// Enable RX pin pullup
UART_RX_PIN_CTRL = 0x18;
#endif // UART_RX_PUEN

#else // __AVR_XMEGA__

#ifdef UART_RX_PUEN
Expand All @@ -247,7 +247,7 @@ int main(void)
#endif // UART_RX_PUEN

#endif // __AVR_XMEGA__

// Initialize UART EN pin

#ifdef __AVR_XMEGA__
Expand Down Expand Up @@ -483,19 +483,40 @@ int main(void)
else if (val == CMD_CHIP_ERASE)
{
// Erase the application section
Flash_EraseApplicationSection();
// XMEGA E5: ERASE_APP NVM command (0x20) erases the entire flash - as a workaround, we erase page-by-page.
// From Atmel Support: "The NVM controller design is such that the entire flash will get erased always when application/bootloader erase is called."
#if defined(__AVR_ATxmega8E5__) || defined(__AVR_ATxmega16E5__) || defined(__AVR_ATxmega32E5__)
for(uint32_t addr = APP_SECTION_START; addr < APP_SECTION_END; addr += SPM_PAGESIZE)
{
Flash_EraseWriteApplicationPage(addr);
// Wait for completion
#ifdef __AVR_XMEGA__
#ifdef USE_WATCHDOG
while (NVM_STATUS & NVM_NVMBUSY_bp)
{
// reset watchdog while waiting for erase completion
WDT_Reset();
}
#else // USE_WATCHDOG
SP_WaitForSPM();
#endif // USE_WATCHDOG
#endif // __AVR_XMEGA__
}
#else
Flash_EraseApplicationSection();
// Wait for completion
#ifdef __AVR_XMEGA__
#ifdef __AVR_XMEGA__
#ifdef USE_WATCHDOG
while (NVM_STATUS & NVM_NVMBUSY_bp)
{
// reset watchdog while waiting for erase completion
WDT_Reset();
// reset watchdog while waiting for erase completion
WDT_Reset();
}
#else // USE_WATCHDOG
SP_WaitForSPM();
#endif // USE_WATCHDOG
#endif // __AVR_XMEGA__
#endif // __AVR_XMEGA__
#endif

// Erase EEPROM
EEPROM_erase_all();
Expand Down Expand Up @@ -932,7 +953,7 @@ int main(void)
UART_PORT &= ~(1 << UART_RX_PIN);
#endif // UART_RX_PUEN
#endif // __AVR_XMEGA__

// Shut down UART EN pin
#ifdef USE_UART_EN_PIN
#ifdef __AVR_XMEGA__
Expand Down