1
0
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:
WestfW
2019-09-10 01:17:13 -07:00
parent adafe79832
commit ad0f55574a
3 changed files with 78 additions and 28 deletions

View File

@@ -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.

View File

@@ -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

View File

@@ -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);
}