Skip to content

Commit f6116ee

Browse files
committed
Implement CMake build system and use C11 standard
1 parent 5b1f141 commit f6116ee

File tree

13 files changed

+206
-274
lines changed

13 files changed

+206
-274
lines changed

.github/workflows/build.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: Build binary and hex
2+
3+
on:
4+
push:
5+
branches: [ master ]
6+
pull_request:
7+
branches: [ master ]
8+
workflow_dispatch:
9+
10+
jobs:
11+
build:
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
# Checks out your repository under $GITHUB_WORKSPACE, so your job can access it
16+
- name: Check out repository code
17+
uses: actions/checkout@v4
18+
19+
# Install all necessary dependencies for the build
20+
- name: Install dependencies
21+
run: |
22+
sudo apt-get update
23+
sudo apt-get install -y gcc-avr binutils-avr avr-libc cmake
24+
25+
# Configure and build the entire project in one go
26+
- name: Configure and Build with CMake
27+
run: |
28+
cmake -S . -B build
29+
cmake --build build
30+
31+
# Upload the blinky artifacts
32+
- name: Upload blinky build output
33+
uses: actions/upload-artifact@v4
34+
with:
35+
name: blinky
36+
path: |
37+
build/blinky/blinky.bin
38+
build/blinky/blinky.hex
39+
40+
# Upload the bootloader artifacts
41+
- name: Upload bootloader build output
42+
uses: actions/upload-artifact@v4
43+
with:
44+
name: bootloader
45+
path: |
46+
build/bootloader/bootloader.bin
47+
build/bootloader/bootloader.hex

.github/workflows/main.yml

Lines changed: 0 additions & 42 deletions
This file was deleted.

.gitignore

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,9 @@
1-
.vscode/
2-
build/
1+
# Ignore the build directory
2+
build/
3+
4+
# Ignore the .vscode directory by default...
5+
.vscode/*
6+
7+
# ...but do NOT ignore the cmake-kits.json file and the parent folder
8+
!.vscode/
9+
!/.vscode/cmake-kits.json

.vscode/cmake-kits.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[
2+
{
3+
"name": "AVR-GCC",
4+
"toolchainFile": "${workspaceFolder}/toolchain.cmake",
5+
"preferredGenerator": {
6+
"name": "MinGW Makefiles"
7+
}
8+
}
9+
]

CMakeLists.txt

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
cmake_minimum_required(VERSION 3.10)
2+
# Use the AVR toolchain file (set before project())
3+
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/toolchain.cmake CACHE STRING "AVR toolchain file")
4+
project("AVR Bootloader" C)
5+
6+
# ---------------------------------------------------------------------------
7+
# Common configuration
8+
# ---------------------------------------------------------------------------
9+
10+
# MCU and clock settings
11+
set(MCU atmega328p)
12+
set(F_CPU 16000000UL)
13+
14+
# Programmer for avrdude
15+
set(AVRDUDE_PROGRAMMER usbasp)
16+
17+
# C standard settings (apply project-wide by default)
18+
set(CMAKE_C_STANDARD 11)
19+
set(CMAKE_C_STANDARD_REQUIRED ON)
20+
set(CMAKE_C_EXTENSIONS OFF)
21+
22+
# Common compiler flags for AVR targets
23+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Os -mmcu=${MCU} -DF_CPU=${F_CPU}")
24+
25+
# Add subprojects
26+
add_subdirectory(blinky)
27+
add_subdirectory(bootloader)
28+
29+
# Clean all build files and directories
30+
add_custom_target(clean_build
31+
COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_BINARY_DIR}"
32+
COMMENT "[[main]] Cleaning the entire build directory..."
33+
)
34+
35+
# Fully erase the flash and EEPROM (if present) of the microcontroller
36+
add_custom_target(
37+
erase_flash
38+
COMMAND avrdude -c ${AVRDUDE_PROGRAMMER} -p ${MCU} -e
39+
COMMENT "[[main]] Erasing the flash and EEPROM of \"${MCU}\" using \"${AVRDUDE_PROGRAMMER}\""
40+
)

README.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ To prepare your build environment first read this tutorial:
88

99
**A "bootloader" is a small program that is written to a dedicated section of the non-volatile memory of a computer. In microcontrollers it is mostly used to facilitate the updating of the main program by utilizing a communication peripheral, thereby eliminating the requirement for an external programmer. In more sophisticated computer systems, a bootloader is mostly employed to pre-configure the system clock and input/output interfaces.**
1010

11-
**With this definition in mind, what follows is not a practical bootloader. Instead, it is a tutorial designed to step-by-step illustrate the process of program compilation and configuration to show how a bootloader can self-program the microcontroller. This bootloader is literally hardcoding the binary data of the program you want to upload (**[**`blinky_test`**](blinky_test)**) in the bootloader itself. With some small changes in code you can modify it to receive binary of the program you want to upload through UART, I2C or SPI. To learn how to write a more sophisticated and secure bootloader study the** [**resources**](#resources).
11+
**With this definition in mind, what follows is not a practical bootloader. Instead, it is a tutorial designed to step-by-step illustrate the process of program compilation and configuration to show how a bootloader can self-program the microcontroller. This bootloader is literally hardcoding the binary data of the program you want to upload (**[**`blinky`**](blinky)**) in the bootloader itself. With some small changes in code you can modify it to receive binary of the program you want to upload through UART, I2C or SPI. To learn how to write a more sophisticated and secure bootloader study the** [**resources**](#resources).
1212

1313
*DONE:*
1414
- Configure fuse bits settings for bootloader section size and reset vector
@@ -49,10 +49,10 @@ int main(void)
4949
**Compile and link the program**
5050
5151
```
52-
cd blinky_test
52+
cd blinky
5353
mkdir build
54-
avr-gcc -Wall -Os -mmcu=atmega328p -std=gnu99 -o build/main.o -c src/main.c
55-
avr-gcc -Wall -Os -mmcu=atmega328p -std=gnu99 -o build/program.elf build/main.o
54+
avr-gcc -Wall -Os -mmcu=atmega328p -std=c11 -o build/main.o -c src/main.c
55+
avr-gcc -Wall -Os -mmcu=atmega328p -std=c11 -o build/program.elf build/main.o
5656
```
5757
5858
**Useful commands used to generate `.hex` and `.bin` files used for programming the microcontroller:**
@@ -81,15 +81,15 @@ Convert `.bin` file to `.hex` file:
8181
avr-objcopy -I binary -O ihex build/program.bin build/program.hex
8282
```
8383
84-
This is the contents of the output `.hex` file for the [`blinky_test`](blinky_test) program:
84+
This is the contents of the output `.hex` file for the [`blinky`](blinky) program:
8585
8686
![image](https://github.com/m3y54m/simple-avr-bootloader/assets/1549028/43bb30ea-5cfd-4bab-9002-a3bfe7651469)
8787
8888
8989
- [Intel HEX File Format](https://microchipdeveloper.com/ipe:sqtp-hex-file-format)
9090
9191
92-
This is the contents of the output `.bin` file for the [`blinky_test`](blinky_test) program (shown in a Hex Viewer):
92+
This is the contents of the output `.bin` file for the [`blinky`](blinky) program (shown in a Hex Viewer):
9393
9494
![image](https://github.com/m3y54m/simple-avr-bootloader/assets/1549028/3f6d5e52-2eb7-48e1-b77b-d7f25770e6fb)
9595
@@ -134,14 +134,14 @@ This means that the total size of the `blink_test` program is 162 bytes.
134134
135135
## Self Programming the Microcontroller Inside the Bootloader Program
136136
137-
In the [`bootloader`](bootloader) program we put the binary code of the [`blinky_test`](blinky_test) program in an array called `blinky_test_program_bin`.
137+
In the [`bootloader`](bootloader) program we put the binary code of the [`blinky`](blinky) program in an array called `blinky_test_program_bin`.
138138
139139
At the begining of the program LED blinks 2 times slowly to show that the bootloader program is starting.
140140
141141
The function `write_program()` writes the contents of the `blinky_test_program_bin` to the address `0x0000`
142142
of the flash memory of the microcontroller.
143143
144-
Finally the program jumps to the address `0x0000` of the flash memory and runs the `blinky_test` program. Then LED blinks faster as long as microcontroller is not reset or powered off.
144+
Finally the program jumps to the address `0x0000` of the flash memory and runs the `blinky` program. Then LED blinks faster as long as microcontroller is not reset or powered off.
145145
146146
```c
147147
#define F_CPU 16000000UL
@@ -152,7 +152,7 @@ Finally the program jumps to the address `0x0000` of the flash memory and runs t
152152
#include <avr/interrupt.h>
153153
#include <avr/pgmspace.h>
154154
155-
// This array contains the binary code for the `blinky_test` program
155+
// This array contains the binary code for the `blinky` program
156156
// that blinks LED (on PB5) fast (with 5Hz frequency)
157157
// Program size: 162 bytes
158158
uint8_t blinky_test_program_bin[] = {
@@ -259,12 +259,12 @@ int main(void)
259259
}
260260
/**********************************************************/
261261
262-
// Write the binary code of the user program (`blinky_test`) to flash memory at address 0x0000
262+
// Write the binary code of the user program (`blinky`) to flash memory at address 0x0000
263263
write_program(0x00000, blinky_test_program_bin, sizeof(blinky_test_program_bin));
264264
}
265265
266266
// Jump to the start address of the user program (0x0000)
267-
asm("jmp 0");
267+
__asm__ __volatile__("jmp 0");
268268
269269
// Bootloader ends here
270270
}
@@ -298,7 +298,7 @@ Data: 162 bytes (7.9% Full)
298298
(.data + .bss + .noinit)
299299
```
300300

301-
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_test` program stored in an array inside the `bootloader` program.
301+
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.
302302

303303
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`.
304304

@@ -315,15 +315,15 @@ avrdude -c usbasp -p m328p -U lfuse:w:0xFF:m -U hfuse:w:0xDC:m -U efuse:w:0xFD:m
315315
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.
316316

317317
```
318-
avr-gcc -Wall -Os -mmcu=atmega328p -std=gnu99 -o build/main.o -c src/main.c
319-
avr-gcc -Wall -Os -mmcu=atmega328p -std=gnu99 -Wl,-section-start=.text=0x7C00 -o build/program.elf build/main.o
318+
avr-gcc -Wall -Os -mmcu=atmega328p -std=c11 -o build/main.o -c src/main.c
319+
avr-gcc -Wall -Os -mmcu=atmega328p -std=c11 -Wl,-section-start=.text=0x7C00 -o build/program.elf build/main.o
320320
```
321321

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

324324
![image](https://github.com/m3y54m/simple-avr-bootloader/assets/1549028/5a172cae-d8e5-4d55-bdfd-b982f43de766)
325325

326-
With this settings every time the microcontroller resets, it first executes the `bootloader`, the `bootloader` writes the `blinky_test` to address `0` of the flash memory and it executes `blinky_test` until next reset.
326+
With this settings every time the microcontroller resets, it first executes the `bootloader`, the `bootloader` writes the `blinky` to address `0` of the flash memory and it executes `blinky` until next reset.
327327

328328
## Resources
329329

blinky/CMakeLists.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
cmake_minimum_required(VERSION 3.10)
2+
project(blinky C)
3+
4+
add_executable(${PROJECT_NAME}.elf src/main.c)
5+
6+
add_custom_target(
7+
${PROJECT_NAME}_build ALL
8+
COMMAND avr-objcopy -j .text -j .data -O ihex ${PROJECT_NAME}.elf ${PROJECT_NAME}.hex
9+
COMMAND avr-objcopy -j .text -j .data -O binary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin
10+
COMMAND avr-size --format=avr --mcu=${MCU} ${PROJECT_NAME}.elf
11+
DEPENDS ${PROJECT_NAME}.elf
12+
COMMENT "[[${PROJECT_NAME}]] Building .hex and .bin files for \"${MCU}\""
13+
)
14+
15+
add_custom_target(
16+
${PROJECT_NAME}_flash
17+
COMMAND avrdude -c ${AVRDUDE_PROGRAMMER} -p ${MCU} -U flash:w:${PROJECT_NAME}.hex
18+
DEPENDS ${PROJECT_NAME}_build
19+
COMMENT "[[${PROJECT_NAME}]] Flashing to \"${MCU}\" using \"${AVRDUDE_PROGRAMMER}\""
20+
)
File renamed without changes.

blinky_test/Makefile

Lines changed: 0 additions & 103 deletions
This file was deleted.

0 commit comments

Comments
 (0)