Skip to content

Commit e59e999

Browse files
committed
Improve hardcoded bootloader code
1 parent 2537caa commit e59e999

File tree

9 files changed

+342
-156
lines changed

9 files changed

+342
-156
lines changed

.clang-format

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# This .clang-format file is tailored for C projects following widely accepted best practices.
2+
# It enforces readability, consistency, and compatibility with most open source C codebases.
3+
BasedOnStyle: LLVM
4+
Language: C
5+
IndentWidth: 4
6+
TabWidth: 4
7+
UseTab: Never
8+
ColumnLimit: 80
9+
AllowShortIfStatementsOnASingleLine: false
10+
AllowShortLoopsOnASingleLine: false
11+
AllowShortFunctionsOnASingleLine: InlineOnly
12+
BreakBeforeBraces: Allman
13+
SpaceBeforeParens: ControlStatements
14+
PointerAlignment: Left
15+
SortIncludes: true
16+
IncludeBlocks: Preserve
17+
IndentCaseLabels: true
18+
AlignConsecutiveAssignments: true
19+
AlignConsecutiveDeclarations: true
20+
AlignTrailingComments: true

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,5 @@ jobs:
4343
with:
4444
name: bootloader
4545
path: |
46-
build/bootloader/bootloader.bin
47-
build/bootloader/bootloader.hex
46+
build/bootloader_hardcoded/bootloader_hardcoded.bin
47+
build/bootloader_hardcoded/bootloader_hardcoded.hex

CMakeLists.txt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
cmake_minimum_required(VERSION 3.10)
2+
23
# Use the AVR toolchain file (set before project())
34
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/toolchain.cmake CACHE STRING "AVR toolchain file")
45
project("AVR Bootloader" C)
@@ -9,6 +10,7 @@ project("AVR Bootloader" C)
910

1011
# MCU and clock settings
1112
set(MCU atmega328p)
13+
1214
# This definition is essential for libraries like <util/delay.h>
1315
set(F_CPU 16000000UL)
1416

@@ -25,17 +27,18 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Os -mmcu=${MCU} -DF_CPU=${F_CPU}")
2527

2628
# Add subprojects
2729
add_subdirectory(blinky)
28-
add_subdirectory(bootloader)
30+
add_subdirectory(bootloader_hardcoded)
2931

3032
# Clean all build files and directories
31-
add_custom_target(clean_build
33+
add_custom_target(
34+
clean_build
3235
COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_BINARY_DIR}"
33-
COMMENT "[[main]] Cleaning the entire build directory..."
36+
COMMENT "[[${PROJECT_NAME}]] Cleaning the entire build directory..."
3437
)
3538

3639
# Fully erase the flash and EEPROM (if present) of the microcontroller
3740
add_custom_target(
3841
erase_flash
3942
COMMAND avrdude -c ${AVRDUDE_PROGRAMMER} -p ${MCU} -e
40-
COMMENT "[[main]] Erasing the flash and EEPROM of \"${MCU}\" using \"${AVRDUDE_PROGRAMMER}\""
43+
COMMENT "[[${PROJECT_NAME}]] Erasing the flash and EEPROM of \"${MCU}\" using \"${AVRDUDE_PROGRAMMER}\""
4144
)

README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ int main(void)
4444
while (1)
4545
{
4646
PORTB ^= (1 << PB5); // Toggle the LED
47-
4847
_delay_ms(100); // Wait for 100 ms
4948
}
5049

@@ -306,23 +305,23 @@ Data: 162 bytes (7.9% Full)
306305

307306
This means that the total size of the `bootloader` program is 664 bytes. As you may noted that 162 bytes is exactly the size of `blinky` program stored in an array inside the `bootloader` program.
308307

309-
By setting the boot section size of flash memory to 512 words (1024 bytes) we can fit our bootloader program (664 bytes) in it. With this configuration the start address of the boot section becomes `0x3E00` (in words). By knowing that each word is equal to 2 bytes, the start address becomes `0x3E00 * 2 = 0x7C00`.
308+
By setting the boot section size of flash memory to 1024 words (2048 bytes) we can fit our bootloader program (664 bytes) in it. With this configuration the start address of the boot section becomes `0x3C00` (in words). By knowing that each word is equal to 2 bytes, the start address becomes `0x3C00 * 2 = 0x7800`.
310309

311310
![image](https://github.com/m3y54m/simple-avr-bootloader/assets/1549028/974ef4eb-b016-4100-91b5-719db5d217f1)
312311

313312
![image](https://github.com/m3y54m/simple-avr-bootloader/assets/1549028/43a6f9f8-abd5-4ee9-9da1-82fe69b287c5)
314313

315314
```
316-
avrdude -c usbasp -p m328p -U lfuse:w:0xFF:m -U hfuse:w:0xDC:m -U efuse:w:0xFD:m
315+
avrdude -c usbasp -p m328p -U lfuse:w:0xFF:m -U hfuse:w:0xDA:m -U efuse:w:0xFD:m
317316
```
318317

319-
[Bootloader fuse bits setting in AVR® Fuse Calculator](https://www.engbedded.com/fusecalc/?P=ATmega328P&V_LOW=0xFF&V_HIGH=0xDC&V_EXTENDED=0xFD&O_HEX=Apply+values)
318+
[Bootloader fuse bits setting in AVR® Fuse Calculator](https://www.engbedded.com/fusecalc/?P=ATmega328P&V_LOW=0xFF&V_HIGH=0xDA&V_EXTENDED=0xFD&O_HEX=Apply+values)
320319

321-
Adding `-Wl,-section-start=.text=0x7C00` flags to linker options of AVR-GCC makes start address of the bootloader program to be set on the start address of boot section.
320+
Adding `-Wl,-section-start=.text=0x7800` flags to linker options of AVR-GCC makes start address of the bootloader program to be set on the start address of boot section.
322321

323322
```
324323
avr-gcc -Wall -Os -mmcu=atmega328p -std=c11 -o build/main.o -c src/main.c
325-
avr-gcc -Wall -Os -mmcu=atmega328p -std=c11 -Wl,-section-start=.text=0x7C00 -o build/program.elf build/main.o
324+
avr-gcc -Wall -Os -mmcu=atmega328p -std=c11 -Wl,-section-start=.text=0x7800 -o build/program.elf build/main.o
326325
```
327326

328327
This is the contents of the output `.hex` file for the [`bootloader`](bootloader) program:

blinky/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
cmake_minimum_required(VERSION 3.10)
2-
project(blinky C)
2+
3+
# Dynamically set project name from directory name
4+
get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME)
5+
project(${PROJECT_NAME} C)
36

47
add_executable(${PROJECT_NAME}.elf src/main.c)
58

blinky/src/main.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
2-
// Blinky for AVR (ATmega328P)
3-
// Board connection:
4-
// PB5 (Arduino Uno D13) ---> LED (with resistor)
5-
#define LED_PIN PB5
1+
/**
2+
* @brief Blinky application for the ATmega328P.
3+
* @details This application blinks an LED connected to pin PB5
4+
* (Arduino Uno D13) at a 5Hz frequency.
5+
*/
66

77
#include <stdint.h>
88
#include <avr/io.h>
99
#include <util/delay.h>
1010

11+
#define LED_PIN PB5
12+
1113
int main(void)
1214
{
13-
// Set LED pin as output
15+
// Configure LED pin as output
1416
DDRB |= (1U << LED_PIN);
1517

1618
while (1)

bootloader/src/main.c

Lines changed: 0 additions & 127 deletions
This file was deleted.
Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,25 @@
1+
12
cmake_minimum_required(VERSION 3.10)
2-
project(bootloader C)
3+
4+
# Dynamically set project name from directory name
5+
get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME)
6+
project(${PROJECT_NAME} C)
7+
8+
# Set the start address for the bootloader (Boot Reset Vector) for ATmega328P
9+
# Fuse bits must be set accordingly to enable the bootloader section
10+
# BOOTSZ0 = 0, BOOTSZ1 = 1 for 1024 words (0x3C00 * 2 = 0x7800 for ATmega328P)
11+
set(BOOTLOADER_START_ADDRESS 0x7800)
12+
13+
# Fuse bits for ATmega328P
14+
# Default values are set for a 16MHz external crystal with 1024 words bootloader size
15+
# CAUTION: Setting incorrect fuse bits can brick your microcontroller.
16+
# https://www.engbedded.com/fusecalc/
17+
set(LFUSE 0xFF)
18+
set(HFUSE 0xDA)
19+
set(EFUSE 0xFD)
320

421
set(CMAKE_EXE_LINKER_FLAGS
5-
"${CMAKE_EXE_LINKER_FLAGS} -Wl,-section-start=.text=0x7C00")
22+
"${CMAKE_EXE_LINKER_FLAGS} -Wl,-section-start=.text=${BOOTLOADER_START_ADDRESS}")
623

724
add_executable(${PROJECT_NAME}.elf src/main.c)
825

@@ -17,14 +34,6 @@ add_custom_target(
1734
COMMENT "[[${PROJECT_NAME}]] Building .hex and .bin files for \"${MCU}\""
1835
)
1936

20-
# Fuse bits for ATmega328P
21-
# Default values are set for a 16MHz external crystal with 512 words bootloader size
22-
# CAUTION: Setting incorrect fuse bits can brick your microcontroller.
23-
# https://www.engbedded.com/fusecalc/
24-
set(LFUSE 0xFF CACHE STRING "Low fuse byte")
25-
set(HFUSE 0xDC CACHE STRING "High fuse byte")
26-
set(EFUSE 0xFD CACHE STRING "Extended fuse byte")
27-
2837
# Write fuse bits
2938
add_custom_target(
3039
${PROJECT_NAME}_write_fusebits
@@ -39,4 +48,5 @@ add_custom_target(
3948
COMMAND avrdude -c ${AVRDUDE_PROGRAMMER} -p ${MCU} -U flash:w:${PROJECT_NAME}.hex
4049
DEPENDS ${PROJECT_NAME}_build
4150
COMMENT "[[${PROJECT_NAME}]] Flashing the bootloader to \"${MCU}\" using \"${AVRDUDE_PROGRAMMER}\""
51+
COMMENT "[[${PROJECT_NAME}]] Bootloader start address: 0x${BOOTLOADER_START_ADDRESS}"
4252
)

0 commit comments

Comments
 (0)