mirror of
https://github.com/Optiboot/optiboot.git
synced 2025-08-17 21:41:03 +03:00
Two important discoveries:
1) Changing the watchdog period (inc turning it on) requires paying attention to synchonization between the WDT clock and system clock. 2) "jmp 512" doesn't work. I'm not sure exactly what happens, but it doesn't go where I expected. For now, do away with the fancy reset-cause logic and revert to old-style bootloader behavior. Don't even do the no-wait mod; at least this permits you to enter the bootloader by power-cycle. Implement LED_INVERT for boards that have the blink LED between +5V and pin. Now working on ATtiny416 Xplained Mini!
This commit is contained in:
@@ -251,19 +251,23 @@ COMMON_OPTIONS += $(VERSION_CMD)
|
||||
|
||||
#UART is handled separately and only passed for devices with more than one.
|
||||
HELPTEXT += "Option UART=n - use UARTn for communications\n"
|
||||
HELPTEXT += "Option UARTTX=pin - describe UART for Mega0, Xtiny
|
||||
ifdef UART
|
||||
UART_CMD = -DUART=$(UART)
|
||||
endif
|
||||
ifdef UARTTX
|
||||
UART_CMD = -DUARTTX=$(UARTTX)
|
||||
endif
|
||||
|
||||
|
||||
# Not supported yet
|
||||
# ifdef TIMEOUT_MS
|
||||
# TIMEOUT_MS_CMD = -DTIMEOUT_MS=$(TIMEOUT_MS)
|
||||
# ifdef TIMEOUT
|
||||
# TIMEOUT_CMD = -DTIMEOUT_MS=$(TIMEOUT)
|
||||
# dummy = FORCE
|
||||
# endif
|
||||
#
|
||||
|
||||
#.PRECIOUS: %.elf
|
||||
.PRECIOUS: %.elf
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# "Chip-level Platform" targets.
|
||||
|
@@ -135,3 +135,26 @@ luminet_isp: EFUSE ?= FE
|
||||
luminet_isp: isp
|
||||
|
||||
|
||||
HELPTEXT += "target atmega4809 - ATmega4809\n"
|
||||
atmega4809: TARGET = atmega4809
|
||||
atmega4809: PROGRAM = optiboot_x
|
||||
atmega4809: MCU_TARGET = atmega4809
|
||||
atmega4809: CFLAGS += $(COMMON_OPTIONS) -DLED=A7 $(UART_CMD)
|
||||
atmega4809: AVR_FREQ ?= 20000000L
|
||||
atmega4809: LDSECTIONS = -Wl,--section-start=.text=0 -Wl,--section-start=.version=0x1fe -Wl,--sections-start=.postapp=0x200
|
||||
atmega4809: $(PROGRAM)_atmega4809.hex
|
||||
ifndef PRODUCTION
|
||||
atmega4809: $(PROGRAM)_atmega4809.lst
|
||||
endif
|
||||
|
||||
HELPTEXT += "target Xplained416 - ATtiny416 Xplained Nano\n"
|
||||
xplained416: TARGET = attiny416
|
||||
xplained416: PROGRAM = optiboot_x
|
||||
xplained416: MCU_TARGET = attiny416
|
||||
xplained416: CFLAGS += $(COMMON_OPTIONS) $(UART_CMD) -DLED_INVERT=1
|
||||
xplained416: AVR_FREQ ?= 20000000L
|
||||
xplained416: LDSECTIONS = -Wl,--section-start=.text=0 -Wl,--section-start=.version=0x1fe -Wl,--section-start=.postapp=0x200
|
||||
xplained416: $(PROGRAM)_attiny416.hex
|
||||
ifndef PRODUCTION
|
||||
xplained416: $(PROGRAM)_attiny416.lst
|
||||
endif
|
||||
|
@@ -137,8 +137,10 @@ optiboot_version = 256*(OPTIBOOT_MAJVER + OPTIBOOT_CUSTOMVER) + OPTIBOOT_MINVER;
|
||||
FUSES = {
|
||||
.WDTCFG = 0, /* Watchdog Configuration */
|
||||
.BODCFG = FUSE_BODCFG_DEFAULT, /* BOD Configuration */
|
||||
.TCD0CFG = FUSE_TCD0CFG_DEFAULT, /* TCD0 Configuration */
|
||||
.OSCCFG = 2, /* 20MHz */
|
||||
#ifdef FUSE_TCD0CFG_DEFAULT
|
||||
.TCD0CFG = FUSE_TCD0CFG_DEFAULT, /* TCD0 Configuration */
|
||||
#endif
|
||||
.SYSCFG0 = 0xC4, /* RESET is not yet */
|
||||
.SYSCFG1 = 0x06, /* startup 32ms */
|
||||
.APPEND = 0, /* Application Code Section End */
|
||||
@@ -290,42 +292,51 @@ int main (void) {
|
||||
// SP points to RAMEND
|
||||
|
||||
__asm__ __volatile__ ("clr __zero_reg__"); // known-zero required by avr-libc
|
||||
|
||||
#define RESET_EXTERNAL (RSTCTRL_EXTRF_bm|RSTCTRL_UPDIRF_bm|RSTCTRL_SWRF_bm)
|
||||
#ifndef FANCY_RESET_LOGIC
|
||||
ch = RSTCTRL.RSTFR; // get reset cause
|
||||
RSTCTRL.RSTFR = ch; // and reset them all!
|
||||
if (ch & RSTCTRL_WDRF_bm) {
|
||||
// Start the app.
|
||||
__asm__ __volatile__ ("mov r2, %0\n" :: "r" (ch));
|
||||
watchdogConfig(WDT_PERIOD_OFF_gc);
|
||||
__asm__ __volatile__ (
|
||||
"jmp app\n"
|
||||
);
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* Protect as much Reset Cause as possible for application
|
||||
* and still skip bootloader if not necessary
|
||||
*/
|
||||
ch = RSTCTRL.RSTFR;
|
||||
// RSTCTRL.RSTFR = ch; // reset causes, for now.
|
||||
ch &= ~RSTCTRL_UPDIRF_bm; // clear "reset by UPDI."
|
||||
// Skip all logic and run bootloader if cause is cleared (application request)
|
||||
if (ch != 0) {
|
||||
/*
|
||||
* To run the boot loader, External Reset Flag must be set.
|
||||
* If not, we could make shortcut and jump directly to application code.
|
||||
* Also WDRF set with EXTRF is a result of Optiboot timeout, so we
|
||||
* shouldn't run bootloader in loop :-) That's why:
|
||||
* 1. application is running if WDRF is cleared
|
||||
* 2. we clear WDRF if it's set with EXTRF to avoid loops
|
||||
* One problematic scenario: broken application code sets watchdog timer
|
||||
* without clearing MCUSR before and triggers it quickly. But it's
|
||||
* recoverable by power-on with pushed reset button.
|
||||
* We want to run the bootloader when an external reset has occurred.
|
||||
* On these mega0/XTiny chips, there are three types of ext reset:
|
||||
* reset pin (may not exist), UPDI reset, and SW-request reset.
|
||||
* One of these reset causes, together with watchdog reset, should
|
||||
* mean that Optiboot timed out, and it's time to run the app.
|
||||
* Other reset causes (notably poweron) should run the app directly.
|
||||
* If a user app wants to utilize and detect watchdog resets, it
|
||||
* must make sure that the other reset causes are cleared.
|
||||
*/
|
||||
if ((ch & (RSTCTRL_WDRF_bm | RSTCTRL_EXTRF_bm)) != RSTCTRL_EXTRF_bm) {
|
||||
if (ch & RSTCTRL_EXTRF_bm) {
|
||||
if (ch & RSTCTRL_WDRF_bm) {
|
||||
if (ch & RESET_EXTERNAL) {
|
||||
/*
|
||||
* Clear WDRF because it was most probably set by wdr in bootloader.
|
||||
* It's also needed to avoid loop by broken application which could
|
||||
* prevent entering bootloader.
|
||||
* '&' operation is skipped to spare few bytes as bits in MCUSR
|
||||
* can only be cleared.
|
||||
* Clear WDRF because it was most probably set by wdr in
|
||||
* bootloader. It's also needed to avoid loop by broken
|
||||
* application which could prevent entering bootloader.
|
||||
*/
|
||||
RSTCTRL.RSTFR = RSTCTRL_WDRF_bm;
|
||||
}
|
||||
}
|
||||
if (!(ch & RESET_EXTERNAL)) {
|
||||
/*
|
||||
* save the reset flags in the designated register
|
||||
* This can be saved in a main program by putting code in .init0 (which
|
||||
* executes before normal c init code) to save R2 to a global variable.
|
||||
* save the reset flags in the designated register.
|
||||
* This can be saved in a main program by putting code in
|
||||
* .init0 (which executes before normal c init code) to save R2
|
||||
* to a global variable.
|
||||
*/
|
||||
__asm__ __volatile__ ("mov r2, %0\n" :: "r" (ch));
|
||||
|
||||
@@ -336,7 +347,9 @@ int main (void) {
|
||||
);
|
||||
}
|
||||
}
|
||||
#endif // Fancy reset cause stuff
|
||||
|
||||
watchdogReset();
|
||||
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, 0); // full speed clock
|
||||
|
||||
MYUART_TXPORT.DIR |= MYUART_TXPIN; // set TX pin to output
|
||||
@@ -351,7 +364,7 @@ int main (void) {
|
||||
MYUART.CTRLB = USART_RXEN_bm | USART_TXEN_bm;
|
||||
|
||||
// Set up watchdog to trigger after 1s
|
||||
watchdogConfig(WDT_PERIOD_1KCLK_gc);
|
||||
watchdogConfig(WDT_PERIOD_8KCLK_gc);
|
||||
|
||||
#if (LED_START_FLASHES > 0) || defined(LED_DATA_FLASH) || defined(LED_START_ON)
|
||||
/* Set LED pin as output */
|
||||
@@ -360,11 +373,17 @@ int main (void) {
|
||||
|
||||
#if LED_START_FLASHES > 0
|
||||
/* Flash onboard LED to signal entering of bootloader */
|
||||
# ifdef LED_INVERT
|
||||
flash_led(LED_START_FLASHES * 2+1);
|
||||
# else
|
||||
flash_led(LED_START_FLASHES * 2);
|
||||
# endif
|
||||
#else
|
||||
#if defined(LED_START_ON)
|
||||
# ifndef LED_INVERT
|
||||
/* Turn on LED to indicate starting bootloader (less code!) */
|
||||
LED_PORT.OUT |= LED;
|
||||
# endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -405,7 +424,9 @@ int main (void) {
|
||||
address.bytes[0] = getch();
|
||||
address.bytes[1] = getch();
|
||||
// ToDo: will there be mega-0 chips with >128k of RAM?
|
||||
/* UPDI chips apparently have byte-addressable FLASH ?
|
||||
address.word *= 2; // Convert from word address to byte address
|
||||
*/
|
||||
verifySpace();
|
||||
}
|
||||
else if(ch == STK_UNIVERSAL) {
|
||||
@@ -540,6 +561,8 @@ void flash_led (uint8_t count) {
|
||||
#endif
|
||||
|
||||
void watchdogConfig (uint8_t x) {
|
||||
while(WDT.STATUS & WDT_SYNCBUSY_bm)
|
||||
;
|
||||
_PROTECTED_WRITE(WDT.CTRLA, x);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user