DevToPrd
  • Home
  • Knowledge Base
  • About Me
  1. Knowledge Base
  2. Articles
  3. Programming Arduino (AVR) and Raspberry Pi Pico (ARM) in C
  • Knowledge Base
    • Articles
      • 3D Printing and CNC
      • 6502 Programming in C
      • Add Settings File to .NET Console Application
      • AMD Ryzen 3 3200G with Radeon Vega Graphics Keeps Freezing
      • Angular Cheat Sheet
      • Angular CLI
      • Arduino / Raspberry Pi Remote Sensor
      • Bad owner or permissions on ssh config file
      • Basic Arduino Uno Dev Setup in Linux (Debian-based)
      • Boilerplate Date Definitions for SQL
      • Boot Linux Mint from flash drive on a netbook
      • Boot Linux to text mode
      • Bundling a Multiple Module Python Project Into a Zip File
      • Cache Resources Exhausted in Imagemagick
      • Call Async Method from Non-Async Method
      • Check an XML file to see if it is well-formed
      • Clear Linux Cache
      • Command-Line Arduino
      • Complex Object Collections in C++
      • Component Not Found error in VirtualBox
      • Compress and Extract Entire Directory Tree With Tar
      • Conditions on aggregates in SQL
      • Configuration of hddtemp
      • Connect To MySQL From .NET
      • Create Code Behind File for Razor Page In Blazor Application
      • Create An ISO File From a CD or DVD-ROM Using the Terminal
      • Cross-Compile Rust, Targeting Windows from Linux
      • C# Language Versioning
      • Dependency Injection in .NET/C#
      • Determine path to web.config at runtime
      • Display GRUB Menu
      • Docker in Linux
      • .NET IoT
      • Entity Framework
      • Enumeration Scoping in C++
      • File Operations in Java
      • Find Duplicate Rows By Specific Columns
      • Find Unique Instances of Text in Bash
      • Flash Disk Image to SD Card
      • Flask
      • Force SSL On Domain
      • GDB and GPROF
      • Get Started With Laravel
      • Git Tips and Tricks
      • Graphical sudo
      • Hide website from search engines
      • Hostname On Linux
      • How to install a .bundle file in Ubuntu Linux
      • HP Laptop Keyboard Not Working At Boot Start
      • Install .NET From Microsoft Feed in Ubuntu
      • Install Node.js
      • Install php7-xml to avoid utf encode/decode issue
      • Install truetype fonts in Ubuntu Linux
      • Java Links
      • JCL and Programming On the MVS Turnkey System
      • List Hardware Information in Ubuntu and other Debian-based Linux
      • Mainframe Emulation on Raspberry Pi Zero
      • Making Colors in a GIF Transparent
      • Manually Install Firefox
      • Markup and Code-Behind Examples for reveal.js
      • Merge Images
      • MicroPython on ESP32
      • Microservice Notes
      • Migrating from Windows to Linux
      • MiniDLNA - A lightweight, simple media server
      • Modify Default Folders in Ubuntu Linux
      • Modify default Java runtime in Linux
      • MongoDB Quick Start in Docker
      • Mount local folder as drive C in DOSBox
      • MVS Turnkey in Docker
      • MySQL command line – quick tips
      • No Frameworks Were Found error
      • NPM Cheat Sheet
      • NT_STATUS_UNSUCCESSFUL error when browsing machines/shares in Ubuntu Linux
      • Online IoT/Embedded Simulators
      • Package and Publish To NuGet
      • Packaging Python Projects
      • Passing a value in the URL for use by PHP
      • PDF Conversion Policy Error
      • PHP Login Script Tutorial
      • Pip Behind a Corporate Proxy
      • Prevent Code Injection In PHP
      • Programming Arduino (AVR) and Raspberry Pi Pico (ARM) in C
      • Publish to Crates.io
      • Python Optimization and Language Binding
      • Python Tkinter Examples
      • Query Windows shares from the command line in Ubuntu Linux
      • RabbitMQ in Docker
      • React Cheat Sheet
      • Recursive File Search
      • Redirect in PHP
      • Remote Access for Raspberry Pi
      • Remove Duplicates From List Collection
      • Requirements Files for Python
      • Rhythmbox tray icon plugin
      • Rsync as a Backup Solution
      • Rust Books (online)
      • Rust/Cargo Behind a Corporate Proxy
      • Selective chmod for directories and files
      • Sense HAT
      • Side-by-Side .NET Core Installations
      • Simple Raspberry Pi Control With .NET IoT and Python
      • Simple Web Server, Using Python or PHP
      • Single-File / Multi-OS / Multi-Architecture Publishing in .NET
      • Slim Framework
      • SQL Server in Docker
      • SQL Server in Linux
      • SQL Transaction Template
      • Start an X Windows session in Cygwin
      • stdio.h: No such file or directory
      • Stream Media from Ubuntu/Mint Linux to XBox360
      • Supporting Material for ‘.NET and Linux’ tech talk
      • TUI Frameworks for .NET
      • Use a value from a posted form in PHP
      • Using Your Router As A Wireless Repeater
      • Verbose PHP Logging To Web Browser
      • Version Mismatch in Python Package
      • Vim Tips and Tricks
      • Virtual Environment for Python
      • Vue.js Cheat Sheet
      • WCF Export
      • Web API with ASP.NET
      • Web Frameworks, Libraries, and Plugins
    • Glossary
      • Initial Program Load (IPL)
      • Job Control Language (JCL)
      • Just-in-time compilation (JIT)
      • Model–View–Controller (MVC)
      • Multiple Virtual Storage (MVS)
      • Resource Access Control Facility (RACF)
      • Real-time locating system (RTLS)
      • Time Sharing Option (TSO)
    • Learning Paths
      • Embedded and IoT
      • Low-Level
      • Mainframe
    • Other
      • Job and Employment Tools
  • Pages
    • About Me
  • Posts
    • 2007
      • Fake Science Makes Me Angry
      • Genetic Material from T-Rex Decoded
      • Vacuum and the Nature of Mass
    • 2011
      • Unhitched
    • 2012
      • Chick-fil-A
      • Choosing a First Telescope
      • Interesting Fossil
      • Rigorous Logic and Amelia
      • Pale Blue Dot
      • Science and Youth
      • Steve Jobs: The Lost Interview
      • Theism and the Thinking Mind
    • 2013
      • Duck and Cover
      • Duct Tape
      • Firefox OS
      • Idiocracy is Upon Us
      • It’s Just a Theory
      • Ken Feder and the Myth of the Ancient Astronauts
      • Martian Exopaleontology
      • …from the Moon and Mars
      • SunWatch Video Podcast
      • Tech Generation… not?
    • 2014
      • ‘Andean Gold’ lecture at SunWatch
      • Chelyabinsk Meteor
      • Lunar Eclipse
      • A New Meteor Shower Is Coming
      • Sleep Well, Philae
      • Why do I not believe?
    • 2015
      • Early Humans in the Americas
      • SETI@Home
      • What is a fossil?
    • 2017
      • Cleaning Fossils
      • The Dating Game
      • How Firefox Got Its Groove Back
      • March For Science
      • Printing the Past
      • Who Ya Gonna Call?
    • 2018
      • 2018 AIA/SunWatch Lecture Series: Science vs. Pseudoscience
      • Coordinate Systems: Finding Your Way Around the Sky
      • Natural Selection At Work
      • Like Water For Gravity
    • 2019
      • ‘Astronomy for Beginners’ Program
      • Homeopathy
      • Scientific and Critical Thinking Omnibus
      • Show Me What You’re Made Of
      • Visitors From Space
    • 2020
      • A Dim View of Betelgeuse
      • Cleveland Archaeological Society Lecture Series
      • Going Viral
      • The Trinity Mineral
      • Venusians, Perchance
    • 2021
      • Create Extension for Visual Studio Code
      • Early .NET 6 Observations
      • The Upcoming Lunar Eclipse: Real-World Application of the Practical Astronomy .NET Library (+ Python!)
      • Enumeration Scoping in C++
      • Fossil Hunting in Central Kentucky
      • Fossil Sites Map in Leaflet.js
      • Geology of Jezero
      • Python and XML
      • Running a Mainframe Emulator on a Raspberry Pi Zero (Lunch-n-Learn)
      • Rust in the Android Platform
      • Rust Foundation
      • Speak with Elegance (or not)
      • Supporting Material for ‘.NET and Linux’ tech talk
      • Traditional Programming on Hobbyist Microcontroller Boards
      • ‘Visual Studio Code: The Swiss Army Knife of Editors’ (tech talk)
    • 2022
      • James Webb Space Telescope
      • Program Like It’s 1982
      • Rust In the Linux Kernel
    • 2023
      • .NET IoT and Terminal GUI
      • Modern .NET Tooling in VS Code
      • Perl: Is It Really That Bad?
      • Sci-Fi Recommendations
    • 2024
      • 6502 Programming in C
      • DuckDuckGo AI Chat
      • Modern Perl
      • My AI Chatbot Experience
      • Practical Astronomy Algorithms in Various Languages
      • Site Updates
      • Think Async

On this page

  • Arduino (AVR)
    • Requirements
    • Source
    • Build and Upload
  • Raspberry Pi Pico (ARM Cortex)
    • Requirements / Setup
    • Build
    • Load and Run
    • The Code
  1. Knowledge Base
  2. Articles
  3. Programming Arduino (AVR) and Raspberry Pi Pico (ARM) in C

Programming Arduino (AVR) and Raspberry Pi Pico (ARM) in C

Embedded and IoT
C

This article will document the steps required to blink the onboard LED (the “Hello World” of the hobbyist microcontroller world) on Arduino UNO and Raspberry Pi Pico boards.

This will use standards-compliant C code in a CLI environment.

Arduino (AVR)

AVR chips are used on Arduino boards. This section assumes that you’re using an Arduino Uno. If you’re using something else, you’ll need to update the command line arguments for avr-gcc and avrdude to reflect the chip model.

Requirements

Instructions assume a Debian-based system.

Required packages:

Package Name Description
binutils The programs in this package are used to assemble, link and manipulate binary and object files. They may be used in conjunction with a compiler and various libraries to build programs.
gcc-avr This is the GNU C compiler for AVR, a fairly portable optimizing compiler which supports multiple languages. This package includes support for C.
gdb-avr This package has been compiled to target the avr architecture. GDB is a source-level debugger, capable of breaking programs at any specific line, displaying variable values, and determining where errors occurred. Currently, it works for C, C++, Fortran Modula 2 and Java programs. A must-have for any serious programmer. This package is primarily for avr developers and cross-compilers and is not needed by normal users or developers.
avr-libc Standard library used for the development of C programs for the Atmel AVR micro controllers. This package contains static libraries as well as the header files needed.
avrdude AVRDUDE is an open source utility to download/upload/manipulate the ROM and EEPROM contents of AVR microcontrollers using the in-system programming technique (ISP)

Installation:

sudo apt install binutils gcc-avr gdb-avr avr-libc avrdude

Source

blink.c

#include <avr/io.h> // defines pins and ports
#include <util/delay.h>
    
#define BLINK_DELAY 500 // number of milliseconds to wait between LED toggles.
    
int main(void) {
    DDRB |= (1 << PB5); // Data Direction Register B: writing a 1 to the Pin B5
                        // bit enables output
    
    // Event loop (runs forever)
    while (1) {
    PORTB = 0b00100000; // turn on 5th LED bit/pin in PORT B (Pin13 in Arduino)
    _delay_ms(BLINK_DELAY);
    
    PORTB = 0b00000000; // turn off all bits/pins on PB
    _delay_ms(BLINK_DELAY);
    }
    
    return (0); // main() requires a return value, but this will never happen, as
                // the polling loop is infinite.
}

Makefile

FORMATTER = clang-format -i
ROOT_FILE_NAME = blink
SRC_FILE = $(ROOT_FILE_NAME).c
OBJ_FILE = $(ROOT_FILE_NAME).o
EXE_FILE = $(ROOT_FILE_NAME)
HEX_FILE = $(ROOT_FILE_NAME).hex
    
default:
    @echo 'Targets:'
    @echo '  compile'
    @echo '  link'
    @echo '  hex'
    @echo '  upload'
    @echo '  format'
    @echo '  clean'
    
$(OBJ_FILE): $(SRC_FILE)
    avr-gcc -Os -DF_CPU=16000000UL -mmcu=atmega328p -c -o $(OBJ_FILE) $(SRC_FILE)
    
compile: $(OBJ_FILE)
    
$(EXE_FILE): $(OBJ_FILE)
    avr-gcc -mmcu=atmega328p $(OBJ_FILE) -o $(EXE_FILE)
    
link: $(EXE_FILE)
    
$(HEX_FILE): $(EXE_FILE)
    avr-objcopy -O ihex -R .eeprom $(EXE_FILE) $(HEX_FILE)
    
hex: $(HEX_FILE)
    
upload: $(HEX_FILE)
    avrdude -F -V -c arduino -p ATMEGA328P -P /dev/ttyACM0 -b 115200 -U flash:w:$(HEX_FILE)
    
format:
    $(FORMATTER) $(SRC_FILE)
    
clean:
    -rm -f $(OBJ_FILE) $(EXE_FILE) $(HEX_FILE) $(SRC_FILE).orig

Build and Upload

To build the code, and upload to the Arduino, first plug in your Arduino board, and then:

make upload

What’s going on:

  1. avr-gcc produces an object file compatible with the AVR chipset, and then links it into a binary.
  2. Only the hex code is used by the chip, so avr-objcopy extracts it.
  3. avrdude uploads the hex code to the board.

Raspberry Pi Pico (ARM Cortex)

Requirements / Setup

cd ~/
 
mkdir pico
 
cd pico

Clone the pico-sdk and pico-examples repositories:

git clone -b master https://github.com/raspberrypi/pico-sdk.git
 
cd pico-sdk
 
git submodule update --init
 
cd ..
 
git clone -b master https://github.com/raspberrypi/pico-examples.git

Install the toolchain:

sudo apt update
 
sudo apt install cmake gcc-arm-none-eabi libnewlib-arm-none-eabi build-essential

Build

Create a build directory:

cd pico-examples
 
mkdir build
 
cd build

Set the SDK path:

export PICO_SDK_PATH=../../pico-sdk

Prepare the CMAKE build directory:

cmake ..

Build:

cd blink
 
make -j4

This produces the following outputs:

  • blink.elf - This is used by the debugger
  • blink.uf2 - This is the file to be uploaded to the RP2040

Load and Run

To load a .uf2 file onto the Pico, the board must be in BOOTSEL mode. To accomplish this:

  1. Hold down the BOOTSEL button on the Pico.
  2. Plug the micro USB cable into the Pico.
  3. Release the BOOTSEL button.

The Pico will mount as a USB mass storage device. To load the binary code we just created, drag and drop the blink.uf2 file to the mounted drive. The UF2 file will be loaded on the Pico, and the drive will automatically unmount.

If you want to load an updated UF2 file to the board, you must go through the same BOOTSEL steps, after first unplugging the board.

It can be a pain, having to unplug the board and plug it back in (in BOOTSEL mode) every time you want to apply an update. I recommend purchasing a microUSB cable with a switch. Then, instead of unplugging and plugging the cable every time, your BOOTSEL steps become:

  1. Switch off the micro USB cable.
  2. Hold down the BOOTSEL button on the Pico.
  3. Switch on the micro USB cable.
  4. Release the BOOTSEL button.

Make sure you purchase a cable that supports data transfer, not just power. This is the one I’m using, but any micro USB cable with data support should work.

The Code

blink.c

#include "pico/stdlib.h"
    
int main() {
#ifndef PICO_DEFAULT_LED_PIN
#warning blink example requires a board with a regular LED
#else
    const uint LED_PIN = PICO_DEFAULT_LED_PIN; // Default PIN number for the built-in LED
    
    gpio_init(LED_PIN); // Initialize the LED
    
    gpio_set_dir(LED_PIN, GPIO_OUT);
    
    // Never-ending polling loop
    while (true) {
        // Turn on the LED, then wait 1/2 second
        gpio_put(LED_PIN, 1);
        sleep_ms(500);
    
        // Turn off the LED, then wait 1/2 second
        gpio_put(LED_PIN, 0);
        sleep_ms(500);
    }
#endif
}
 

Copyright 2024, Jim Carr

Cookie Preferences