Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
AllowShortFunctionsOnASingleLine: None
BasedOnStyle: Google
26 changes: 26 additions & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
Checks: >
-*,
clang-analyzer-*,
bugprone-*,
performance-*,
portability-*,
misc-*,
readability-*,
modernize-*,
-clang-analyzer-alpha*,
-bugprone-easily-swappable-parameters,
-bugprone-exception-escape,
-bugprone-narrowing-conversions,
-bugprone-reserved-identifier,
-misc-include-cleaner,
-modernize-avoid-c-arrays,
-modernize-use-auto,
-modernize-use-nodiscard,
-modernize-use-trailing-return-type,
-readability-function-cognitive-complexity,
-readability-identifier-length,
-readability-implicit-bool-conversion,
-readability-magic-numbers
WarningsAsErrors: ''
HeaderFilterRegex: '.*'
FormatStyle: file
1 change: 1 addition & 0 deletions .clangd-bin
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/stuff/tools/llvm/ATfE-21.1.1/bin/clangd
19 changes: 19 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
version: "3.9"

services:
pico2:
image: pico2:25.10
user: "${UID:-1000}:${GID:-1000}"
working_dir: /stuff/work/pico-sdk
environment:
USER: uzleo
HOME: /home/uzleo
entrypoint: ["/usr/bin/env", "fish"]
volumes:
- /stuff/work:/stuff/work
- /stuff/tools:/stuff/tools
- /home/uzleo:/home/uzleo
- /etc/passwd:/etc/passwd:ro
- /etc/group:/etc/group:ro
stdin_open: true
tty: true
60 changes: 60 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
cmake_minimum_required(VERSION 3.30)

include(../pico_sdk_init.cmake)

set(CMAKE_CXX_SCAN_FOR_MODULES ON)

project(examples C CXX ASM)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

pico_sdk_init()

if (DEFINED PICO_COMPILER_SYSROOT)
set(LIBCXX_STD_MODULE_DIR "${PICO_COMPILER_SYSROOT}/share/libc++/v1")
set(LIBCXX_STD_MODULE "${LIBCXX_STD_MODULE_DIR}/std.cppm")
else()
message(FATAL_ERROR "PICO_COMPILER_SYSROOT is not set; cannot locate libc++ std module")
endif()

if (NOT CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS)
find_program(CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS
NAMES clang-scan-deps clang-scan-deps-21 clang-scan-deps-20
PATHS ${PICO_TOOLCHAIN_PATH}/bin /usr/bin)
endif()

add_executable(led_blink
led_blink_raw.cpp
)
target_compile_features(led_blink PRIVATE cxx_std_26)
target_compile_options(led_blink PRIVATE
$<$<COMPILE_LANG_AND_ID:C,Clang,AppleClang>:-Weverything -Wno-c++98-compat>
$<$<COMPILE_LANG_AND_ID:CXX,Clang,AppleClang>:-Weverything -Wno-c++98-compat>
)
target_link_libraries(led_blink pico_stdlib)
pico_set_printf_implementation(led_blink none)
pico_enable_stdio_usb(led_blink 1)
pico_enable_stdio_uart(led_blink 0)

if (PICO_CLIB STREQUAL "llvm_libc")
# libdummyhost provides stdio symbols for llvm-libc runtimes.
target_link_options(led_blink PRIVATE -ldummyhost)
endif()

target_sources(led_blink PRIVATE
FILE_SET cxx_modules TYPE CXX_MODULES
BASE_DIRS ${CMAKE_CURRENT_LIST_DIR}/sdk
FILES sdk/hw/hw.cppm
)

if (EXISTS "${LIBCXX_STD_MODULE}")
target_sources(led_blink PRIVATE
FILE_SET libcxx_modules TYPE CXX_MODULES
BASE_DIRS "${LIBCXX_STD_MODULE_DIR}"
FILES "${LIBCXX_STD_MODULE}"
)
else()
message(FATAL_ERROR "libc++ std module not found at ${LIBCXX_STD_MODULE}; import std will fail")
endif()

pico_add_extra_outputs(led_blink)
18 changes: 18 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Building without USB/stdio using LLVM Embedded Toolchain

For bare-metal targets that don’t need USB stdio, configure with the LLVM Embedded Toolchain sysroot and skip picotool/UF2. Example (building `led_blink` on pico2):
```
rm -rf build
cmake -G Ninja -S examples -B build -DPICO_BOARD=pico2 \
-DPICO_COMPILER=pico_arm_cortex_m33_clang \
-DPICO_TOOLCHAIN_PATH=/stuff/tools/llvm/ATfE-21.1.1 \
-DPICO_COMPILER_SYSROOT=/stuff/tools/llvm/ATfE-21.1.1/lib/clang-runtimes/arm-none-eabi/armv8m.main_hard_fp_exn_rtti_unaligned_size \
-DPICO_NO_PICOTOOL=1 \
-DCMAKE_TRY_COMPILE_PLATFORM_VARIABLES="PICO_COMPILER_SYSROOT;PICO_CLANG_RUNTIMES;PICO_CLIB" \
-DCMAKE_C_STANDARD_INCLUDE_DIRECTORIES="/stuff/tools/llvm/ATfE-21.1.1/lib/clang-runtimes/arm-none-eabi/include/" \
-DCMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES="/stuff/tools/llvm/ATfE-21.1.1/lib/clang-runtimes/arm-none-eabi/include/c++/v1/;/stuff/tools/llvm/ATfE-21.1.1/lib/clang-runtimes/arm-none-eabi/include/"

cmake --build build
```

Adjust paths for your toolchain install; some ATfE versions add a `_size` suffix to the runtime directory. Re-enable picotool/USB stdio if needed.
12 changes: 12 additions & 0 deletions examples/led_blink_raw.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

import pico.hw;

auto main() -> int {
pico::hw::InitializeBoard();

pico::hw::InitializeLedPin();
while (true) {
pico::hw::ToggleLed();
pico::hw::BusyDelay(12000000);
}
}
70 changes: 70 additions & 0 deletions examples/sdk/hw/hw.cppm
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@

module;

#include "hardware/structs/io_bank0.h"
#include "hardware/structs/padsbank0.h"
#include "hardware/structs/sio.h"
#include "pico/platform.h"
#include "pico/stdio.h"

export module pico.hw;

import std;

namespace pico::hw {

export auto InitializeBoard() -> void;
export auto InitializeLedPin() -> void;
export auto BusyDelay(std::uint32_t cycles) -> void;
export auto ToggleLed() -> void;

} // namespace pico::hw

namespace {

std::uint8_t constexpr kLedPin{25};

template <typename T = std::bitset<32>>
requires(std::unsigned_integral<T> or std::same_as<T, std::bitset<32>>)
consteval auto GetLedMask() -> T {
std::bitset<32> led_mask{};
led_mask.set(kLedPin);

if constexpr (std::is_same_v<T, std::bitset<32>>) {
return led_mask;
}

return static_cast<T>(led_mask.to_ulong());
}

} // namespace

namespace pico::hw {

auto InitializeBoard() -> void {
stdio_init_all();
}

auto InitializeLedPin() -> void {
// Configure the pad for push-pull output: 4 mA drive, Schmitt enabled, no
// pulls.
padsbank0_hw->io[kLedPin] =
(PADS_BANK0_GPIO25_DRIVE_VALUE_4MA << PADS_BANK0_GPIO25_DRIVE_LSB) |
PADS_BANK0_GPIO25_SCHMITT_BITS;

// Route the pin to the SIO peripheral so we can drive it directly.
io_bank0_hw->io[kLedPin].ctrl = GPIO_FUNC_SIO;

// Enable output on the pin via SIO.
sio_hw->gpio_oe_set = GetLedMask<std::uint32_t>();
}

auto BusyDelay(std::uint32_t cycles) -> void {
busy_wait_at_least_cycles(cycles);
}

auto ToggleLed() -> void {
sio_hw->gpio_togl = GetLedMask<std::uint32_t>();
}

} // namespace pico::hw
4 changes: 4 additions & 0 deletions src/rp2_common/pico_clib_interface/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
if (NOT TARGET pico_clib_interface)
pico_add_library(pico_clib_interface)

target_sources(pico_clib_interface INTERFACE
${CMAKE_CURRENT_LIST_DIR}/fini_stub.c
)

# ---- newlib ----
pico_add_library(pico_newlib_interface)

Expand Down
11 changes: 11 additions & 0 deletions src/rp2_common/pico_clib_interface/fini_stub.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright (c) 2025 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/

#include "pico.h"

// Bare-metal stub so __libc_fini_array can resolve _fini without pulling in
// hosted runtime shutdown logic.
void __weak _fini(void) {}
15 changes: 8 additions & 7 deletions src/rp2_common/pico_crt0/rp2350/memmap_default.ld
Original file line number Diff line number Diff line change
Expand Up @@ -77,24 +77,26 @@ SECTIONS

. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
PROVIDE (__bothinit_array_start = .);
PROVIDE (__preinit_array_start = .);
KEEP(*(SORT(.preinit_array.*)))
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
PROVIDE (__preinit_array_end = .);

. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
PROVIDE (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
PROVIDE (__init_array_end = .);
PROVIDE (__bothinit_array_end = .);

. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
PROVIDE (__fini_array_start = .);
*(SORT(.fini_array.*))
*(.fini_array)
PROVIDE_HIDDEN (__fini_array_end = .);
PROVIDE (__fini_array_end = .);

*(.eh_frame*)
. = ALIGN(4);
Expand Down Expand Up @@ -299,4 +301,3 @@ SECTIONS

/* todo assert on extra code */
}

Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@
#else
#define PICO_C_COMPILER_IS_GNU 1
#endif
/* Some libc variants (e.g. picolibc/LLVM embedded toolchain) don't provide
* __printflike; fall back to the usual GCC-style format attribute. */
#ifndef __printflike
#define __printflike(a, b) __attribute__((__format__(printf, a, b)))
#endif
#elif defined __ICCARM__
#ifndef __aligned
#define __aligned(x) __attribute__((__aligned__(x)))
Expand Down
1 change: 1 addition & 0 deletions tools/pioasm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ add_executable(pioasm
gen/lexer.cpp
gen/parser.cpp
)
target_compile_definitions(pioasm PRIVATE _GTHREAD_USE_COND_INIT_FUNC)

target_sources(pioasm PRIVATE c_sdk_output.cpp)
target_sources(pioasm PRIVATE python_output.cpp)
Expand Down