Skip to content

Commit 99a75ba

Browse files
committed
Initial: add bootloader
1 parent 19bbd44 commit 99a75ba

File tree

6 files changed

+223
-2
lines changed

6 files changed

+223
-2
lines changed

boards.txt

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ uno2018.build.extra_flags={build.328emulation} -DMILLIS_USE_TIMERB3
2222
#uno2018.build.extra_flags=-B{runtime.tools.atpack.path}/gcc/dev/{build.mcu}
2323

2424
uno2018.bootloader.tool=avrdude
25+
uno2018.bootloader.file=atmega4809_uart_bl.hex
2526
uno2018.bootloader.SYSCFG0=0xC9
2627
uno2018.bootloader.BOOTEND=0x00
2728
uno2018.fuses.file=fuses_4809.bin

bootloaders/atmega4809_uart_bl.hex

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
:10000000112410994AC080EC80932608A0912311F6
2+
:100010000A2E000CBB0BBC5F2CE530E00E945400A4
3+
:10002000DC01CB019E5FAF4FBF4F2AE0B595A7958E
4+
:10003000979587952A95D1F780932808909329085A
5+
:100040008091E20584608093E205449A669A6E9AF4
6+
:10005000E0E0F1E49DE923E030E48091240887FFAB
7+
:10006000FCCF80912008809322088193AF014F77C5
8+
:100070005527452B51F494BF209300108091021016
9+
:1000800080FDFCCF8DB183278DB9309731F791E09A
10+
:1000900088ED84BF9093410007C082E080930110F7
11+
:1000A000E0E8F0E00995AFCF0E945B00B7FF08954C
12+
:1000B000821B930B0895A29FB001B39FC001A39F21
13+
:1000C000700D811D1124911DB29F700D811D112491
14+
:0400D000911D0895E1
15+
:02000004008278
16+
:00000001FF

bootloaders/boot.c

+193
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
/******************************************************************************
2+
* © 2018 Microchip Technology Inc. and its subsidiaries.
3+
*
4+
* Subject to your compliance with these terms, you may use Microchip software
5+
* and any derivatives exclusively with Microchip products. It is your
6+
* responsibility to comply with third party license terms applicable to your
7+
* use of third party software (including open source software) that may
8+
* accompany Microchip software.
9+
*
10+
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
11+
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY
12+
* IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
13+
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
14+
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR
15+
* EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED,
16+
* EVEN IF MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
17+
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
18+
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
19+
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
20+
* THIS SOFTWARE.
21+
*
22+
*****************************************************************************/
23+
24+
/*
25+
* UART Bootloader for tinyAVR 0- and 1-series, and megaAVR 0-series
26+
* Each byte received is echoed to confirm reception.
27+
*
28+
* For the code to be placed in the constructors section it is necessary
29+
* to disable standard startup files in Toolchain->AVR/GNU Linker->General.
30+
*
31+
* The example is written for ATtiny817 with the following pinout:
32+
* USART0 TxD PB2
33+
* USART0 RxD PB3
34+
* LED0 PB4
35+
* SW1 PC5 (external pull-up)
36+
*/
37+
#define F_CPU_RESET (16E6/6)
38+
39+
#include <avr/io.h>
40+
#include <assert.h>
41+
#include <stdbool.h>
42+
43+
/* Baud rate configuration */
44+
#define BOOT_BAUD (115200)
45+
46+
/* Memory configuration
47+
* BOOTEND_FUSE * 256 must be above Bootloader Program Memory Usage,
48+
* this is 194 bytes at optimization level -O3, so BOOTEND_FUSE = 0x01
49+
*/
50+
#define BOOTEND_FUSE (0x01)
51+
#define BOOT_SIZE (BOOTEND_FUSE * 0x100)
52+
#define MAPPED_APPLICATION_START (MAPPED_PROGMEM_START + BOOT_SIZE)
53+
#define MAPPED_APPLICATION_SIZE (MAPPED_PROGMEM_SIZE - BOOT_SIZE)
54+
55+
/* Fuse configuration
56+
* BOOTEND sets the size (end) of the boot section in blocks of 256 bytes.
57+
* APPEND = 0x00 defines the section from BOOTEND*256 to end of Flash as application code.
58+
* Remaining fuses have default configuration.
59+
*/
60+
FUSES = {
61+
.OSCCFG = FREQSEL_16MHZ_gc,
62+
.SYSCFG0 = CRCSRC_NOCRC_gc | RSTPINCFG_UPDI_gc,
63+
.SYSCFG1 = SUT_64MS_gc,
64+
.APPEND = 0x00,
65+
.BOOTEND = BOOTEND_FUSE
66+
};
67+
68+
/* Define application pointer type */
69+
typedef void (*const app_t)(void);
70+
71+
/* Interface function prototypes */
72+
static bool is_bootloader_requested(void);
73+
static void init_uart(void);
74+
static uint8_t uart_receive(void);
75+
static void uart_send(uint8_t byte);
76+
static void init_status_led(void);
77+
static void toggle_status_led(void);
78+
79+
/*
80+
* Main boot function
81+
* Put in the constructors section (.ctors) to save Flash.
82+
* Naked attribute used since function prologue and epilogue is unused
83+
*/
84+
__attribute__((naked)) __attribute__((section(".ctors"))) void boot(void)
85+
{
86+
/* Initialize system for AVR GCC support, expects r1 = 0 */
87+
asm volatile("clr r1");
88+
89+
/* Check if entering application or continuing to bootloader */
90+
if(!is_bootloader_requested()) {
91+
/* Enable Boot Section Lock */
92+
NVMCTRL.CTRLB = NVMCTRL_BOOTLOCK_bm;
93+
94+
/* Go to application, located immediately after boot section */
95+
app_t app = (app_t)(BOOT_SIZE / sizeof(app_t));
96+
app();
97+
}
98+
99+
/* Initialize communication interface */
100+
init_uart();
101+
init_status_led();
102+
103+
VPORTD.OUT |= PIN6_bm;
104+
105+
/*
106+
* Start programming at start for application section
107+
* Subtract MAPPED_PROGMEM_START in condition to handle overflow on large flash sizes
108+
*/
109+
uint8_t *app_ptr = (uint8_t *)MAPPED_APPLICATION_START;
110+
while(app_ptr - MAPPED_PROGMEM_START <= (uint8_t *)PROGMEM_END) {
111+
/* Receive and echo data before loading to memory */
112+
uint8_t rx_data = uart_receive();
113+
uart_send(rx_data);
114+
115+
/* Incremental load to page buffer before writing to Flash */
116+
*app_ptr = rx_data;
117+
app_ptr++;
118+
if(!((uint16_t)app_ptr % MAPPED_PROGMEM_PAGE_SIZE)) {
119+
/* Page boundary reached, Commit page to Flash */
120+
_PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_PAGEERASEWRITE_gc);
121+
while(NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
122+
123+
toggle_status_led();
124+
}
125+
}
126+
127+
/* Issue system reset */
128+
_PROTECTED_WRITE(RSTCTRL.SWRR, RSTCTRL_SWRE_bm);
129+
}
130+
131+
/*
132+
* Boot access request function
133+
*/
134+
static bool is_bootloader_requested(void)
135+
{
136+
/* Check if SW1 (PA0) is low */
137+
if(VPORTA.IN & PIN0_bm) {
138+
return false;
139+
}
140+
return true;
141+
}
142+
143+
/*
144+
* Communication interface functions
145+
*/
146+
static void init_uart(void)
147+
{
148+
/* Configure UART */
149+
USART1.CTRLB = USART_RXEN_bm | USART_TXEN_bm;
150+
151+
/* From datasheet:
152+
* Baud rate compensated with factory stored frequency error
153+
* Asynchronous communication without Auto-baud (Sync Field)
154+
* 20MHz Clock, 3V
155+
*/
156+
int32_t baud_reg_val = (F_CPU_RESET * 64) / (BOOT_BAUD * 16); // ideal BAUD register value
157+
assert(baud_reg_val >= 0x4A); // Verify legal min BAUD register value with max neg comp
158+
int8_t sigrow_val = SIGROW.OSC16ERR5V; // read signed error
159+
baud_reg_val *= (1024 + sigrow_val); // sum resolution + error
160+
baud_reg_val += 512; // compensate for rounding error
161+
baud_reg_val /= 1024; // divide by resolution
162+
USART1.BAUD = (int16_t) baud_reg_val; // set adjusted baud rate
163+
164+
PORTMUX.USARTROUTEA |= PORTMUX_USART1_ALT1_gc;
165+
166+
/* Set TxD (PB2) as output */
167+
VPORTC.DIR |= PIN4_bm;
168+
}
169+
170+
static uint8_t uart_receive(void)
171+
{
172+
/* Poll for data received */
173+
while(!(USART1.STATUS & USART_RXCIF_bm));
174+
return USART1.RXDATAL;
175+
}
176+
177+
static void uart_send(uint8_t byte)
178+
{
179+
/* Data will be sent when TXDATA is written */
180+
USART1.TXDATAL = byte;
181+
}
182+
183+
static void init_status_led(void)
184+
{
185+
/* Set LED0 (PB4) as output */
186+
VPORTD.DIR |= PIN6_bm;
187+
}
188+
189+
static void toggle_status_led(void)
190+
{
191+
/* Toggle LED0 (PB4) */
192+
VPORTD.OUT ^= PIN6_bm;
193+
}

bootloaders/build.sh

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
if [ $AVR_GCC_PATH == "" ]; then
2+
AVR_GCC_PATH=/bin/
3+
fi
4+
5+
${AVR_GCC_PATH}/avr-gcc -c -g -Os -w -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -Wl,--gc-sections -w -mmcu=atmega4809 -DF_CPU=16000000L boot.c -o boot.o
6+
${AVR_GCC_PATH}/avr-gcc -g -Os -w -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -nostartfiles -Wl,--gc-sections -w -mmcu=atmega4809 -DF_CPU=16000000L boot.o -o boot.elf
7+
8+
${AVR_GCC_PATH}/avr-objcopy -O binary -R .fuses boot.elf boot.bin
9+
#${AVR_GCC_PATH}avr-objcopy -O binary -j .fuses --set-section-flags=.fuses=alloc,load --no-change-warnings --change-section-lma .fuses=0 boot.elf boot.fuses
10+
11+
${AVR_GCC_PATH}/../avrdude/6.3.0-arduino14/bin/avrdude -C${AVR_GCC_PATH}/../avrdude/6.3.0-arduino14/etc/avrdude.conf -v -patmega4809 -cxplainedmini_updi -Pusb -Ufuses:w:boot.fuses:r -Uflash:w:boot.bin:r

bootloaders/fuses.bin

9 Bytes
Binary file not shown.

platform.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ compiler.warning_flags.all=-Wall -Wextra
2121
compiler.path={runtime.tools.avr-gcc-5.4.0-atmel3.6.1-arduino2.path}/bin/
2222
compiler.c.cmd=avr-gcc
2323
compiler.c.flags=-c -g -Os {compiler.warning_flags} -std=gnu11 -ffunction-sections -fdata-sections -MMD -flto -fno-fat-lto-objects
24-
compiler.c.elf.flags={compiler.warning_flags} -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections
24+
compiler.c.elf.flags={compiler.warning_flags} -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections -Wl,--section-start=.text=0x100
2525
compiler.c.elf.cmd=avr-gcc
2626
compiler.S.flags=-c -g -x assembler-with-cpp -flto -MMD
2727
compiler.cpp.cmd=avr-g++
@@ -117,7 +117,7 @@ tools.avrdude.erase.pattern=
117117

118118
tools.avrdude.bootloader.params.verbose=-v
119119
tools.avrdude.bootloader.params.quiet=-q -q
120-
tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Ufuse5:w:{bootloader.SYSCFG0}:m" "-Ufuse8:w:{bootloader.BOOTEND}:m"
120+
tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Ufuse5:w:{bootloader.SYSCFG0}:m" "-Ufuse8:w:{bootloader.BOOTEND}:m" "-Uflash:w:{runtime.platform.path}/bootloaders/{bootloader.file}:i"
121121

122122
tools.avrdude_remote.upload.pattern=/usr/bin/run-avrdude /tmp/sketch.hex {upload.verbose} -p{build.mcu}
123123

0 commit comments

Comments
 (0)