From caa97ea6779c19120720fe0ab7dd4aa00c5b8815 Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Sun, 8 Sep 2024 18:33:36 -0500 Subject: [PATCH] Add tiny_blink example which has a minimal binary size --- CMakeLists.txt | 1 + README.md | 5 ++++ tiny/CMakeLists.txt | 56 +++++++++++++++++++++++++++++++++++++++++++++ tiny/blink_tiny.c | 46 +++++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+) create mode 100644 tiny/CMakeLists.txt create mode 100644 tiny/blink_tiny.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 59c958630..24aceb7ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,6 +81,7 @@ add_subdirectory(rtc) add_subdirectory(spi) add_subdirectory(system) add_subdirectory(timer) +add_subdirectory(tiny) add_subdirectory(uart) add_subdirectory(universal) add_subdirectory(usb) diff --git a/README.md b/README.md index d6809a1fc..f283d48e0 100644 --- a/README.md +++ b/README.md @@ -353,6 +353,11 @@ App|Description [periodic_sampler](timer/periodic_sampler) | Sample GPIOs in a timer callback, and push the samples into a concurrency-safe queue. Pop data from the queue in code running in the foreground. [timer_lowlevel](timer/timer_lowlevel) | Example of direct access to the timer hardware. Not generally recommended, as the SDK may use the timer for IO timeouts. +### Tiny (code) +App|Description +---|--- +[tiny_blink](tiny/tiny_blink) | Shows how to minimize the runtime by disabling runtime features via `CMakeLists.txt` to make a very small GPIO 'blink' binary. + ### UART App|Description diff --git a/tiny/CMakeLists.txt b/tiny/CMakeLists.txt new file mode 100644 index 000000000..973f8cfc3 --- /dev/null +++ b/tiny/CMakeLists.txt @@ -0,0 +1,56 @@ +add_executable(blink_tiny + blink_tiny.c +) + +# pull in common dependencies +target_link_libraries(blink_tiny pico_stdlib) + +# create map/bin/hex/uf2 file etc. +pico_add_extra_outputs(blink_tiny) + +# call pico_set_program_url to set path to example on github, so users can find the source for an example via picotool +example_auto_set_url(blink_tiny) + +# Useful CMKake function to help minimize the runtime; we are disabling everything - be careful as disabled things obviously wont work +# +# pico_minimize_runtime(blink_tiny) is equivalent (i.e. everything defaults to off) +# +# you could do something like the following to include standard stuff except the default alarm pool, single precision +# floating point support and double precision floating point support. +# pico_minimize_runtime(blink_tiny INCLUDE ALL EXCLUDE DEFAULT_ALARM_POOL FLOAT DOUBLE) +pico_minimize_runtime(blink_tiny EXCLUDE ALL) + +# More space savings can be made by skipping various bits of the runtime_init (you could alternatively replace the +# implementations as needed either via a non weak function of the appropriate name - note you can omit the default +# weak implementation via PICO_RUNTIME_NO_INIT_XXX=1) +# +# you should be even more careful here skipping bits of runtime initialization code +target_compile_definitions(blink_tiny PRIVATE + PICO_RUNTIME_SKIP_INIT_CLOCKS=1 # we can run with the bootrom clock setup + PICO_RUNTIME_SKIP_POST_CLOCK_RESETS=1 # hangs without init clocks - means we get no clocked peripherals + PICO_RUNTIME_SKIP_INIT_USB_POWER_DOWN=1 # don't care about USB power usage + PICO_RUNTIME_SKIP_INIT_PER_CORE_ENABLE_COPROCESSORS=1 # don't need any coprocessors (float, DCP, or GPIO) + PICO_USE_GPIO_COPROCESSOR=0 # we'd have to init it if we used it + PICO_RUNTIME_SKIP_INIT_RP2040_GPIO_IE_DISABLE=1 # really don't care + PICO_RUNTIME_SKIP_INIT_SPIN_LOCKS_RESET=1 # we don't use spin locks so resetting them is not necessary + PICO_USE_SW_SPIN_LOCKS=0 # no need to sw spin locks on RP2350 as we don;t use them or the affected SIO regions + PICO_RUNTIME_SKIP_INIT_BOOT_LOCKS_RESET=1 # we don't use boot locks so resetting them is not necessary + PICO_RUNTIME_SKIP_INIT_BOOTROM_LOCKING_ENABLE=1 # we don't call bootrom functions requiring locking + PICO_RUNTIME_SKIP_INIT_PER_CORE_IRQ_PRIORITIES=1 # no IRQ use + PICO_NO_RAM_VECTOR_TABLE=1 # so no need for ram vector table + PICO_RUNTIME_SKIP_INIT_PER_CORE_H3_IRQ_REGISTERS=1 # no need to setup RISC-V IRQ handling +) + +if (PICO_C_COMPILER_IS_GNU AND PICO_ON_DEVICE) + # pending resolution of https://github.com/raspberrypi/pico-sdk/issues/1368 we can save space by explicitly + # disabling startfiles at least for tiny_blink + target_link_options(blink_tiny PRIVATE "-nostartfiles") +endif() + +# we can save more by disabling BINARY_INFO if you don't want it, however we leave binary_info on by default +# pass -DBLINK_TINY_NO_BINARY_INFO=1 to CMake to disable it +if (BLINK_TINY_NO_BINARY_INFO) + target_compile_definitions(blink_tiny PRIVATE + PICO_NO_BINARY_INFO=1 + ) +endif() \ No newline at end of file diff --git a/tiny/blink_tiny.c b/tiny/blink_tiny.c new file mode 100644 index 000000000..76f5794aa --- /dev/null +++ b/tiny/blink_tiny.c @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "pico/stdlib.h" + +#ifndef LED_DELAY_MS +#define LED_DELAY_MS 250 +#endif + +// Initialize the GPIO for the LED +void pico_led_init(void) { +#ifdef PICO_DEFAULT_LED_PIN + // A device like Pico that uses a GPIO for the LED will define PICO_DEFAULT_LED_PIN + // so we can use normal GPIO functionality to turn the led on and off + gpio_init(PICO_DEFAULT_LED_PIN); + gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); +#endif +} + +// Turn the LED on or off +void pico_set_led(bool led_on) { +#if defined(PICO_DEFAULT_LED_PIN) + // Just set the GPIO on or off + gpio_put(PICO_DEFAULT_LED_PIN, led_on); +#endif +} + +int main() { + pico_led_init(); + // note these frequencies are approximate +#if PICO_RP2040 + const int cpu_freq = 6500000; +#else + const int cpu_freq = 12000000; +#endif + while (true) { + pico_set_led(true); + // don't have clocks initialized wo wait based on CPU cycles + busy_wait_at_least_cycles((cpu_freq / 1000) * LED_DELAY_MS); + pico_set_led(false); + busy_wait_at_least_cycles((cpu_freq / 1000) * LED_DELAY_MS); + } +}