Learn, Implement and Share

Introduction

Raspberry Pi Pico is a tiny, fast, and versatile board built using RP2040, a brand new microcontroller chip designed by Raspberry Pi. RP2040 features a dual-core Arm Cortex-M0+ processor with 264KB internal RAM and support for up to 16MB of off-chip Flash. A wide range of flexible I/O options includes I2C, SPI, and uniquely Programmable I/O (PIO).

In this article, we will learn how to create a new C/C++ project for Raspberry Pi Pico and build it using C/C++ SDK.

What You Will Learn

  • How to create a C/C++ project for Raspberry Pi Pico?
  • How to build a new C/C++ program for Raspberry Pi Pico?
  • How to compile and build C/C++ programs for Raspberry Pi Pico using the SDK?
  • How to compile and build C/C++ programs for Raspberry Pi Pico in Windows PC?

Prerequisite Hardware

  • Raspberry Pi Pico
  • Micro USB Cable
  • Windows 10 Computer

Prerequisite Software

Create Folder Structure for New C/C++ Project

  • Use Windows File Explorer to navigate to the folder containing pico-sdk and pico-examples
  • Create an empty folder pico-empty-project
New Project Folder for Raspberry Pi Pico
New C/C++ Project Folder for Raspberry Pi Pico
  • Navigate inside the folder pico-empty-project
  • Create an empty folder build
  • Create an empty folder main
Build and Source Folder Inside Raspberry Pi Pico Project Folder
Build and Source Folder Inside Raspberry Pi Pico C/C++ Project Folder
  • Create a file CMakeLists.txt
  • Add the below code to CMakeLists.txt
cmake_minimum_required(VERSION 3.12)

# Import Pico SDK
include(pico_sdk_import.cmake)

project(pico_examples C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

set(PICO_EXAMPLES_PATH ${PROJECT_SOURCE_DIR})

# Initialize the SDK
pico_sdk_init()

include(example_auto_set_url.cmake)
# Add main Folder
add_subdirectory(main)
  • Navigate to folder pico-examples
  • Copy the file example_auto_set_url.cmake and pico_sdk_import.cmake
  • Navigate to folder pico-empty-project
  • Paste the file example_auto_set_url.cmake and pico_sdk_import.cmake
Raspberry Pi Pico Project Folder Structure
Raspberry Pi Pico C/C++ Project Folder Structure
  • Navigate to folder main
  • Create a file CMakeLists.txt
  • Add the below code to CMakeLists.txt
add_executable(main
         main.c
         )

 # Import pico_stdlib which imports commonly used features
 target_link_libraries(main pico_stdlib)

 # Create map/bin/hex file etc.
 pico_add_extra_outputs(main)

 # Add path via pico_set_program_url CMAKE
 example_auto_set_url(main)
  • Create a file main.c
  • Add your own code or the provided blink code
/**
 * www.ArnabKumarDas.com
 *
 * On-Board LED Blinky
 */

#include "pico/stdlib.h"

int main() 
{
    const uint LED_PIN = PICO_DEFAULT_LED_PIN;
    gpio_init(LED_PIN);
    gpio_set_dir(LED_PIN, GPIO_OUT);
    
    while (1) 
    {
        gpio_put(LED_PIN, 1);
        sleep_ms(250);
        gpio_put(LED_PIN, 0);
        sleep_ms(250);
        gpio_put(LED_PIN, 1);
        sleep_ms(250);
        gpio_put(LED_PIN, 0);
        sleep_ms(750);
    }
}
Inside main Folder of Raspberry Pi Pico C/C++ Project
Inside the main Folder of Raspberry Pi Pico C/C++ Project

Building the New C/C++ Project

  • Open the Visual Studio 2019 Developer Command Prompt
  • Navigate to the new project build folder pico-empty-project\build
 ** Visual Studio 2019 Developer Command Prompt v16.9.4
 ** Copyright (c) 2021 Microsoft Corporation
 
C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools>cd /D D:\Electronics\RP2040\pico-empty-project

D:\Electronics\RP2040\pico-empty-project>cd build
D:\Electronics\RP2040\pico-empty-project\build>
Navigating to build Folder
Navigating to build Folder
  • Execute the command cmake -G "NMake Makefiles" ..
D:\Electronics\RP2040\pico-empty-project\build>cmake -G "NMake Makefiles" ..
D:\Electronics\RP2040\pico-empty-project\build>
Executing cmake
Executing cmake
Successful cmake
cmake Successful
  • Execute the command nmake to build the project
D:\Electronics\RP2040\pico-empty-project\build>nmake
D:\Electronics\RP2040\pico-empty-project\build>
Executing nmake
Executing nmake
nmake Build Successful
nmake Build Successful
  • Navigate to the folder \pico-empty-project\build\main to view the build artifacts
Raspberry Pi Pico C/C++ Build Artifacts
Raspberry Pi Pico C/C++ Build Artifacts

Flashing the Raspberry Pi Pico

  • Push and hold the BOOTSEL button (white colour near USB port)
  • Plug the Pico into the USB port of the Windows 10 Computer
  • Raspberry Pi Pico will mount as a Mass Storage Device called RPI-RP2
  • Drag and Drop or Copy and Paste the main.uf2 UF2 Binary into the RPI-RP2 Drive
  • Pico will Reboot automatically, and the on-board Green LED should start Blinking

Download

  • Download and Extract the file to the folder containing pico-sdk and pico-examples
  • Follow the build instructions
  • Edit the cmake files to add new source and header files
  • Edit the folder name to project name

Crazy Engineer

MAKER - ENGINEER - YOUTUBER

4 Comments

Nigel The Engineer · July 22, 2022 at 7:44 pm

Hi,
It works. Thank you so much for the “Raspberry Pi Pico : Create and Build New C/C++ Project in Windows”. It is the first example I have found that seems to work reliably on my system.
Ideally, I would like to repeat this exercise with the “Empty project” on an external drive on our server but this doesn’t work for some reason. Any ideas?
Thanks, Nigel

Dave · September 23, 2022 at 5:46 am

Have followed the instructions above to the letter, and copied main.uf2 to the board, but the LED does not blink. Have been working on the pico since Sunday, and getting nowhere !
Have copied the screen output for the cmake and nmake below, was wondering if you could possibly take a quick look to see if you can spot anything incorrect ?
Many thanks in advance !
Dave

Output for cmake is :-
C:\Users\DAVE TRADER\pico-empty-project\build>cmake -G “NMake Makefiles” ..
Using PICO_SDK_PATH from environment (‘C:\Users\DAVE TRADER\pico-sdk’)
PICO_SDK_PATH is C:/Users/DAVE TRADER/pico-sdk
Defaulting PICO_PLATFORM to rp2040 since not specified.
Defaulting PICO platform compiler to pico_arm_gcc since not specified.
— Defaulting build type to ‘Release’ since not specified.
PICO compiler is pico_arm_gcc
— The C compiler identification is GNU 11.3.1
— The CXX compiler identification is GNU 11.3.1
— The ASM compiler identification is GNU
— Found assembler: A:/Arm GNU Toolchain arm-none-eabi/11.3 rel1/bin/arm-none-eabi-gcc.exe
Build type is Release
Defaulting PICO target board to pico since not specified.
Using board configuration from C:/Users/DAVE TRADER/pico-sdk/src/boards/include/boards/pico.h
— Found Python3: A:/Python/Python310/python.exe (found version “3.10.7”) found components: Interpreter
TinyUSB available at C:/Users/DAVE TRADER/pico-sdk/lib/tinyusb/src/portable/raspberrypi/rp2040; enabling build support for USB.
cyw43-driver available at C:/Users/DAVE TRADER/pico-sdk/lib/cyw43-driver
lwIP available at C:/Users/DAVE TRADER/pico-sdk/lib/lwip
— Configuring done
— Generating done
— Build files have been written to: C:/Users/DAVE TRADER/pico-empty-project/build

NMAKE OUTPUT
Microsoft (R) Program Maintenance Utility Version 14.33.31630.0
Copyright (C) Microsoft Corporation. All rights reserved.

Scanning dependencies of target bs2_default
[ 1%] Building ASM object pico-sdk/src/rp2_common/boot_stage2/CMakeFiles/bs2_default.dir/compile_time_choice.S.obj
[ 2%] Linking ASM executable bs2_default.elf
[ 2%] Built target bs2_default
[ 4%] Creating directories for ‘PioasmBuild’
[ 5%] No download step for ‘PioasmBuild’
[ 7%] No update step for ‘PioasmBuild’
[ 8%] No patch step for ‘PioasmBuild’
[ 10%] Performing configure step for ‘PioasmBuild’
loading initial cache file C:/Users/DAVE TRADER/pico-empty-project/build/pico-sdk/src/rp2_common/cyw43_driver/pioasm/tmp/PioasmBuild-cache-Release.cmake
— The CXX compiler identification is MSVC 19.33.31630.0
— Detecting CXX compiler ABI info
— Detecting CXX compiler ABI info – done
— Check for working CXX compiler: A:/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.33.31629/bin/Hostx86/x86/cl.exe – skipped
— Detecting CXX compile features
— Detecting CXX compile features – done
— Configuring done
— Generating done
— Build files have been written to: C:/Users/DAVE TRADER/pico-empty-project/build/pioasm
[ 11%] Performing build step for ‘PioasmBuild’

Microsoft (R) Program Maintenance Utility Version 14.33.31630.0
Copyright (C) Microsoft Corporation. All rights reserved.

[ 10%] Building CXX object CMakeFiles/pioasm.dir/main.cpp.obj
main.cpp
[ 20%] Building CXX object CMakeFiles/pioasm.dir/pio_assembler.cpp.obj
pio_assembler.cpp
[ 30%] Building CXX object CMakeFiles/pioasm.dir/pio_disassembler.cpp.obj
pio_disassembler.cpp
[ 40%] Building CXX object CMakeFiles/pioasm.dir/gen/lexer.cpp.obj
lexer.cpp
[ 50%] Building CXX object CMakeFiles/pioasm.dir/gen/parser.cpp.obj
parser.cpp
[ 60%] Building CXX object CMakeFiles/pioasm.dir/c_sdk_output.cpp.obj
c_sdk_output.cpp
[ 70%] Building CXX object CMakeFiles/pioasm.dir/python_output.cpp.obj
python_output.cpp
[ 80%] Building CXX object CMakeFiles/pioasm.dir/hex_output.cpp.obj
hex_output.cpp
[ 90%] Building CXX object CMakeFiles/pioasm.dir/ada_output.cpp.obj
ada_output.cpp
[100%] Linking CXX executable pioasm.exe
[100%] Built target pioasm
[ 13%] No install step for ‘PioasmBuild’
[ 14%] Completed ‘PioasmBuild’
[ 14%] Built target PioasmBuild
[ 16%] Generating bs2_default.bin
[ 17%] Generating bs2_default_padded_checksummed.S
[ 17%] Built target bs2_default_padded_checksummed_asm
[ 19%] Creating directories for ‘ELF2UF2Build’
[ 20%] No download step for ‘ELF2UF2Build’
[ 22%] No update step for ‘ELF2UF2Build’
[ 23%] No patch step for ‘ELF2UF2Build’
[ 25%] Performing configure step for ‘ELF2UF2Build’
— The C compiler identification is MSVC 19.33.31630.0
— The CXX compiler identification is MSVC 19.33.31630.0
— Detecting C compiler ABI info
— Detecting C compiler ABI info – done
— Check for working C compiler: A:/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.33.31629/bin/Hostx86/x86/cl.exe – skipped
— Detecting C compile features
— Detecting C compile features – done
— Detecting CXX compiler ABI info
— Detecting CXX compiler ABI info – done
— Check for working CXX compiler: A:/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.33.31629/bin/Hostx86/x86/cl.exe – skipped
— Detecting CXX compile features
— Detecting CXX compile features – done
— Configuring done
— Generating done
— Build files have been written to: C:/Users/DAVE TRADER/pico-empty-project/build/elf2uf2
[ 26%] Performing build step for ‘ELF2UF2Build’

Microsoft (R) Program Maintenance Utility Version 14.33.31630.0
Copyright (C) Microsoft Corporation. All rights reserved.

[ 50%] Building CXX object CMakeFiles/elf2uf2.dir/main.cpp.obj
main.cpp
C:\Users\DAVE TRADER\pico-sdk\tools\elf2uf2\main.cpp(359): warning C4996: ‘fopen’: This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
C:\Users\DAVE TRADER\pico-sdk\tools\elf2uf2\main.cpp(365): warning C4996: ‘fopen’: This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
[100%] Linking CXX executable elf2uf2.exe
[100%] Built target elf2uf2
[ 28%] No install step for ‘ELF2UF2Build’
[ 29%] Completed ‘ELF2UF2Build’
[ 29%] Built target ELF2UF2Build
Scanning dependencies of target main
[ 31%] Building C object main/CMakeFiles/main.dir/main.c.obj
[ 32%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_stdlib/stdlib.c.obj
[ 34%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/hardware_gpio/gpio.c.obj
[ 35%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/hardware_claim/claim.c.obj
[ 37%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_platform/platform.c.obj
[ 38%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/hardware_sync/sync.c.obj
[ 40%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/hardware_irq/irq.c.obj
[ 41%] Building ASM object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/hardware_irq/irq_handler_chain.S.obj
[ 43%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/common/pico_sync/sem.c.obj
[ 44%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/common/pico_sync/lock_core.c.obj
[ 46%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/common/pico_time/time.c.obj
[ 47%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/common/pico_time/timeout_helper.c.obj
[ 49%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/hardware_timer/timer.c.obj
[ 50%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/common/pico_util/datetime.c.obj
[ 52%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/common/pico_util/pheap.c.obj
[ 53%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/common/pico_util/queue.c.obj
[ 55%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/common/pico_sync/mutex.c.obj
[ 56%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/common/pico_sync/critical_section.c.obj
[ 58%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/hardware_uart/uart.c.obj
[ 59%] Building ASM object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/hardware_divider/divider.S.obj
[ 61%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_runtime/runtime.c.obj
[ 62%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/hardware_clocks/clocks.c.obj
[ 64%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/hardware_pll/pll.c.obj
[ 65%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/hardware_vreg/vreg.c.obj
[ 67%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/hardware_watchdog/watchdog.c.obj
[ 68%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/hardware_xosc/xosc.c.obj
[ 70%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_printf/printf.c.obj
[ 71%] Building ASM object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_bit_ops/bit_ops_aeabi.S.obj
[ 73%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_bootrom/bootrom.c.obj
[ 74%] Building ASM object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_divider/divider.S.obj
[ 76%] Building ASM object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_double/double_aeabi.S.obj
[ 77%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_double/double_init_rom.c.obj
[ 79%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_double/double_math.c.obj
[ 80%] Building ASM object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_double/double_v1_rom_shim.S.obj
[ 82%] Building ASM object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_int64_ops/pico_int64_ops_aeabi.S.obj
[ 83%] Building ASM object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_float/float_aeabi.S.obj
[ 85%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_float/float_init_rom.c.obj
[ 86%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_float/float_math.c.obj
[ 88%] Building ASM object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_float/float_v1_rom_shim.S.obj
[ 89%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_malloc/pico_malloc.c.obj
[ 91%] Building ASM object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_mem_ops/mem_ops_aeabi.S.obj
[ 92%] Building ASM object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_standard_link/crt0.S.obj
[ 94%] Building CXX object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_standard_link/new_delete.cpp.obj
[ 95%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_standard_link/binary_info.c.obj
[ 97%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_stdio/stdio.c.obj
[ 98%] Building C object main/CMakeFiles/main.dir/C_/Users/DAVE_TRADER/pico-sdk/src/rp2_common/pico_stdio_uart/stdio_uart.c.obj
[100%] Linking CXX executable main.elf
a:/armgnu~1/1142da~1.3re/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld.exe: a:/armgnu~1/1142da~1.3re/bin/../lib/gcc/arm-none-eabi/11.3.1/thumb/v6-m/nofp\libc.a(libc_a-closer.o): in function `_close_r’:
/data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/newlib/libc/reent/closer.c:47: warning: _close is not implemented and will always fail
a:/armgnu~1/1142da~1.3re/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld.exe: a:/armgnu~1/1142da~1.3re/bin/../lib/gcc/arm-none-eabi/11.3.1/thumb/v6-m/nofp\libc.a(libc_a-lseekr.o): in function `_lseek_r’:
/data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/newlib/libc/reent/lseekr.c:49: warning: _lseek is not implemented and will always fail
[100%] Built target main

C:\Users\DAVE TRADER\pico-empty-project\build>

Brandon C Rich · June 2, 2023 at 6:47 pm

So I would be willing to bet that your problem has to do with the difference between file systems from Linux to Windows Windows runs in NTFS file system whereas Linux runs a whole bunch of other ones and the problem is is because Windows is copyrighted it does not have any information in it that tells it how to read the other file systems now there may be things that you can update or install and windows nowadays that will allow it I know in Linux you have a thing called the like M tools or are the 3G and NTFS or whatever but basically I always include in my Linux stuff a partition for NTFS just to interact with Windows I know that windows and Linux both can read the fat FAT32 I’m just a different file formats so that’s something that they can share but any of the file systems and Linux so but yeah windows cannot read almost any of the file systems that Linux uses and so that I believe that’s the problem you’re running into

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.