A small collection of build tooling, example firmware projects, and supporting files for AVR microcontroller development.
- Provide a minimal, copyable template application for new AVR projects.
- Provide reproducible CMake and Make-based build tooling.
- Include a devcontainer so the same AVR toolchain is available in a consistent environment.
- Keep editor integrations simple by generating compile artifacts in a predictable location.
This repository is organized around a reusable AVR development setup:
development/applications/contains example or project-specific firmware applications.development/applications/template/is the starting point for a new application.development/scripts/contains the shared Make variables and the compile script used by app Makefiles.development/cmake/toolchain-avr.cmakeconfigures the AVR GCC toolchain..devcontainer/contains the Dockerfile and VS Code devcontainer configuration.
The repository is designed around an AVR development toolchain and a serial programmer connection.
- VS Code
- Docker Desktop or Docker Engine
- VS Code Dev Containers extension
- A USB serial adapter or Arduino-compatible device connected to the host for flashing
The devcontainer build installs the required packages and downloads the AVR GNU toolchain automatically via the Dockerfile in .devcontainer/.
For flashing, a device such as an Arduino Uno, Nano, or USB-to-TTL serial adapter must be available at a port such as:
- Linux:
/dev/ttyACM0,/dev/ttyUSB0 - WSL:
/dev/ttyS*,/dev/ttyUSB*, or/dev/ttyACM* - macOS:
/dev/cu.*or/dev/tty.*
The repo defaults to:
- MCU:
atmega328p - programmer:
arduino - baud:
115200 - port:
/dev/ttyACM0
You may need to add your user to the dialout group on Linux or create a udev rule for serial access.
The recommended workflow is to open VS Code in the development/ directory instead of the workspace root. This matches the project layout and the generated compile database.
development/.vscode/c_cpp_properties.jsonpoints IntelliSense atdevelopment/artifacts/compile_commands.json.- The compile script copies the generated
compile_commands.jsonintodevelopment/artifacts/. - Keep the
development/artifacts/folder available so VS Code can resolve correct include paths and compiler flags.
-
Open the repository in VS Code.
-
Reopen the workspace in the container via Reopen in Container command from the Command Palette (Windows, Linux Ctrl+Shift+P)
-
In your terminal, change to a project directory, for example:
cd /workspace/development/applications/template
-
Build the project:
make build
-
Compile and generate the binaries:
make compile
Note: This will also be when intellisense is configured. Open the VSC window to the development/ directory to ensure vscode can resolve any avr-gcc libraries.
-
Flash to the target MCU:
make flash
The project uses the common build script in development/scripts/ to configure the AVR toolchain and output the firmware hex file.
- Copy the contents of
development/applications/template/into a new project folder. - Update the project-local
MakefileandCMakeLists.txtto match the new application name or target. - Add or remove source files in the app-specific project as needed.
- Adjust the build or flash settings in the local project files when your hardware or MCU differs from the defaults.
Tip: Keep project-specific edits inside the application directory so the shared template remains reusable.
The build system is lightweight:
development/scripts/common.mksets the default AVR toolchain, device, port, programmer, and flash arguments.development/scripts/compile.shruns CMake and copies the resulting compile database todevelopment/artifacts/.development/cmake/toolchain-avr.cmakesets the AVR compiler and target flags.development/applications/template/CMakeLists.txtbuilds anfirmwareexecutable and emits a.hexfile from the compiled ELF output.
The default flash step uses avrdude with the Arduino profile and the target MCU set in the shared Makefile.
Example:
make flash
To override defaults for a different board or port:
make flash AVR_DEVICE=atmega328p PORT=/dev/ttyUSB0 BAUD=57600
If you are flashing from inside the devcontainer, make sure the serial device is visible inside the container. The repo mounts /dev into the container to support this pattern.
On Windows/WSL, USB serial adapters may need to be attached to WSL first.
Example:
usbipd wsl list usbipd wsl attach --busid
Replace <busid> with the bus ID reported by usbipd wsl list.
- macOS devices are often under
/dev/cu.*or/dev/tty.*. - Linux devices are often under
/dev/ttyUSB*or/dev/ttyACM*. - Ensure the user has appropriate permissions for the serial device.
- If the container cannot see the device, plug the adapter in before reopening the container or temporarily remove the device mount from the devcontainer configuration.
- If
/dev/ttyACM0does not exist, check the actual port name withls /dev/tty*orls /dev/serial/by-id. - If the serial port is not writable, check user permissions and add yourself to the
dialoutgroup if required. - If IntelliSense is missing include paths, confirm that
development/artifacts/compile_commands.jsonexists and that VS Code is opened in thedevelopment/folder. - If all else fails, CONTACT ME: pattona@southern.edu.
This project is intended for education and local firmware development. The repo is structured to be copied and adapted for general development.