This release contains new libraries and functionality, along with numerous bug fixes and documentation improvements.

Highlights are listed below, or you can see the full list of individual commits here, and the full list of resolved issues here.

Note, these release notes are long and may appear truncated in the “Releases” tab; you can see the full version here.

New Board Support

The following boards have been added and may be specified via PICO_BOARD:

  • nullbits_bit_c_pro
  • waveshare_rp2040_lcd_1.28
  • waveshare_rp2040_one

Library Changes/Improvements


  • clock_gpio_init() now takes a float for the clock divider value, rather than an int.
  • Added clock_gpio_init_int_frac() function to allow initialization of integer and fractional part of the clock divider value, without using float.
  • Added --ref-min option to to override the minimum reference frequency allowed.
  • now additionally considers reference frequency dividers greater than 1.


  • Improved the performance of hw_divider_ functions.


  • Added dma_sniffer_set_output_invert_enabled() and dma_sniffer_set_output_reverse_enabled() functions to configure the DMA sniffer.
  • Added dma_sniffer_set_data_accumulator() and dma_sniffer_get_data_accumulator() functions to access the DMA sniffer accumulator.


  • Added i2c_get_instance() function for consistency with other hardware_ libraries.
  • Added i2c_read_byte_raw(), i2c_write_byte_raw() functions to directly read and write the I2C data register for an I2C instance.


  • Added hardware_alarm_claim_unused() function to claim an unused hardware timer.


  • Added cyw43_arch_wifi_connect_bssid_ variants of cyw43_arch_wifi_connect_ functions to allow connection to a specific access point.
  • Blocking cyw43_arch_wifi_connect_ functions now continue trying to connect rather than failing immediately if the network is not found.
  • cyw43_arch_wifi_connect_ functions now return consistent return codes (PICO_OK, or PICO_ERROR_XXX).
  • The pico_cyw43_arch library has been completely rewritten on top of the new pico_async_context library that generically abstracts the different types of asynchronous operation (poll, threadsafe_background and freertos) previously handled in a bespoke fashion by pico_cyw43_arch. Many edge case bugs have been fixed as a result of this. Note that this change should be entirely backwards compatible from the user point of view.
  • cyw43_arch_init() and cyw43_arch_deinit() functions are now very thin layers which handle async_context life-cycles, along with adding support for the cyw43_driver, pico_lwip etc. to that async_context. Currently, these mechanisms remain the preferred documented way to initialize Pico W networking, however you are free to do similar initialization/de-initialization yourself.
  • Added cyw43_arch_set_async_context() function to specify a custom async_context prior to calling cyw43_arch_init*()
  • Added cyw43_arch_async_context() function to get the async_context used by the CYW43 architecture support.
  • Added cyw43_arch_init_default_async_context() function to return the async_context that cyw43_arch_init*() would initialize if one has not been set by the user.
  • Added cyw43_arch_wait_for_work_until() function to block until there is networking work to be done. This is most useful for poll style applications that have no other work to do and wish to sleep until cyw43_arch_poll() needs to be called again.


  • The functionality has been clarified into 3 separate libraries:
    • cyw43_driver – the raw cyw43_driver code.
    • cyw43_driver_picow – additional support for communication with the Wi-Fi chip over SPI on Pico W.
    • pico_cyw43_driver – integration of the cyw43_driver with the pico-sdk via async_context
  • Added CYW43_WIFI_NVRAM_INCLUDE_FILE define to allow user to override the NVRAM file.


  • Improved the performance of 64-bit divider functions.


  • Add panic_compact() function that discards the message to save space in non-debug (NEBUG defined) builds.


  • Added proper implementation of certain missing newlib system APIs: _gettimeofday(), _times(), _isatty(), _getpid().
  • The above changes enable certain additional C/C++ library functionality such as gettimeofday(), times() and std::chrono.
  • Added settimeofday() implementation such that gettimeofday() can be meaningfully used.
  • Added default (return -1) implementations of the remaining newlib system APIs: _open(), _close(), _lseek(), _fstat(), _isatty(), _kill(), to prevent warnings on GCC 12.
  • Made all newlib system API implementations weak so the user can override them.


  • pico_stdio allows for outputting from within an IRQ handler that creates the potential for deadlocks (especially with pico_stdio_usb), and the intention is to not deadlock but instead discard output in any cases where a deadlock would otherwise occur. The code has been revamped to avoid more deadlock cases, and a new define PICO_STDIO_DEADLOCK_TIMEOUT_MS has been added to catch remaining cases that might be caused by user level locking.
  • Added stdio_set_chars_available_callback() function to set a callback to be called when input is available. See also the new PICO_STDIO_USB_SUPPORT_CHARS_AVAILABLE_CALLBACK and PICO_STDIO_UART_SUPPORT_CHARS_AVAILABLE_CALLBACK defines which both default to 1 and control the availability of this new feature for USB and UART stdio respectively (at the cost of a little more code).
  • Improved performance of stdio_semihosting.
  • Give the user more control over the USB descriptors of stdio_usb via USBD_VID, USBD_PID, USBD_PRODUCT, PICO_STDIO_USB_CONNECTION_WITHOUT_DTR and PICO_STDIO_USB_DEVICE_SELF_POWERED


  • Added critical_section_is_initialized() function to test if a critical section has been initialized.
  • Added mutex_try_enter_block_until() function to wait only up to a certain time to acquire a mutex.


  • Added from_us_since_boot() function to convert a uint64_t timestamp to an absolute_time_t.
  • Added absolute_time_min() function to return the earlier of two absolute_time_t values.
  • Added alarm_pool_create_with_unused_hardware_alarm() function to create an alarm pool using a hardware alarm number claimed using hardware_alarm_claim().
  • Added alarm_pool_core_num() function to determine what core an alarm pool runs on.
  • Added alarm_pool_add_alarm_at_force_in_context() function to add an alarm, and have it always run in the IRQ context even if the target time is in the past, or during the call. This may be simpler in some cases than dealing with the fire_if_past parameters to existing functions, and avoids some callbacks happening from non IRQ context.


  • Added pico_lwip_mqtt library to expose the MQTT app functionality in lwIP.
  • Added pico_lwip_mdns library to expose the MDNS app functionality in lwIP.
  • Added pico_lwip_freertos library for NO_SYS=0 with FreeRTOS as a complement to pico_lwip_nosys for NO_SYS=1.


  • TinyUSB has upgraded from 0.12.0 to 0.15.0. See TinyUSB release notes here for details.
  • Particularly host support should be massively improved.
  • Defaulted new PICO_RP2040_USB_DEVICE_UFRAME_FIX variable to 1 as a workaround for errata RP2040-E15.This sets the default value for TinyUSB’s dcd_rp2040 driver’s TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX flag. This fix is required for correctness, but comes at the cost of some performance, so applications that won’t ever be plugged into a Pi 4 or Pi 400 can optionally disable this by setting the value to 0.

New Libraries


  • Provides support for asynchronous events (timers/IRQ notifications) to be handled in a safe context without concurrent execution (as required by many asynchronous 3rd party libraries).
  • Provides implementations matching those previously implemented in pico_cyw43_arch:
    • poll – Not thread-safe; the user must call async_context_poll() periodically from their main loop, but can call async_context_wait_for_work_until() to block until work is required.
    • threadsafe_background – No polling is required; instead asynchronous work is performed in a low priority IRQ. Locking is provided such that IRQ/non-IRQ or multiple cores can interact safely.
    • freertos – Asynchronous work is performed in a separate FreeRTOS task.
  • async_context guarantees all callbacks happen on a single core.
  • async_context supports multiple instances for providing independent context which can execute concurrently with respect to each other.



  • Added pico_mbedtls library to provide MBed TLS support. You can depend on both pico_lwip_mbedtls and pico_mbedtls to use MBed TLS and lwIP together. See the tls_client example in pico-examples for more details.


  • Implements a new Random Number Generator API.
  • pico_rand generates random numbers at runtime utilizing a number of possible entropy, and uses those sources to modify the state of a 128-bit ‘Pseudo Random Number Generator’ implemented in software.
  • Adds get_rand_32(), get_rand_64() and get_rand_128() functions to return largely unpredictable random numbers (which should be different on each board/run for example).


  • Added a new header hardware/structs/nvic.h with a struct for the Arm Cortex M0+ NVIC available via the nvic_hw pointer.
  • Added new PICO_CXX_DISABLE_ALLOCATION_OVERRIDES which can be set to 1 if you do not want pico_standard_link to include non-exceptional overrides of std::new, std::new[], std::delete and std::delete[] when exceptions are disabled.
  • elf2uf2 now correctly uses LMA instead of VMA of the entry point to determine binary type (flash/RAM). This is required to support some exotic binaries correctly.


  • The build will now check for a functional compiler via the standard CMake mechanism.
  • The build will pick up pre-installed elf2uf2 and pioasm if found via an installed pico-sdk-tools CMake package. If it can do so, then no native compiler is required for the build!
  • It is now possible to switch the board type PICO_BOARD in an existing CMake build directory.
  • ARCHIVE_OUTPUT_DIRECTORY is now respected in build for UF2 output files.
  • Spaces are now supported in the path to the pico-sdk
  • All libraries xxx in the pico-sdk now support a xxx_headers variant that just pulls in the libraries’ headers. These xxx_headers libraries correctly mirror the dependencies of the xxx libraries, so you can use xxx_headers instead of xxx as your dependency if you do not want to pull in any implementation files (perhaps if you are making a STATIC library). Actually the “all” is not quite true, non code libraries such as pico_standard_link and pico_cxx_options are an exception.

Bluetooth Support for Pico W (BETA)

The support is currently available as a beta. More details will be forthcoming with the actual release.

In the meantime, there are examples in pico-examples.

Key changes:

  • The Bluetooth API is provided by BTstack.
  • The following new libraries are provided that expose core BTstack functionality:
    • pico_btstack_ble – Adds Bluetooth Low Energy (LE) support.
    • pico_btstack_classic – Adds Bluetooth Classic support.
    • pico_btstack_sbc_encoder – Adds Bluetooth Sub Band Coding (SBC) encoder support.
    • pico_btstack_sbc_decoder – Adds Bluetooth Sub Band Coding (SBC) decoder support.
    • pico_btstack_bnep_lwip – Adds Bluetooth Network Encapsulation Protocol (BNEP) support using LwIP.
    • pico_btstack_bnep_lwip_sys_freertos – Adds Bluetooth Network Encapsulation Protocol (BNEP) support using LwIP with FreeRTOS for NO_SYS=0.
  • The following integration libraries are also provided:
    • pico_btstack_run_loop_async_context – provides a common async_context backed implementation of a BTstack “run loop” that can be used for all BTstack use with the pico-sdk.
    • pico_btsack_flash_bank – provides a sample implementation for storing required Bluetooth state in flash.
    • pico_btstack_cyw43 – integrates BTstack with the CYW43 driver.
  • Added CMake function pico_btstack_make_gatt_header that can be used to run the BTstack compile_gatt tool to make a GATT header file from a BTstack GATT file.
  • Updated pico_cyw43_driver and cyw43_driver to support HCI communication for Bluetooth.
  • Updated cyw43_driver_picow to support Pico W specific HCI communication for Bluetooth over SPI.
  • Updated cyw43_arch_init() and cyw43_arch_deinit() to additionally handle Bluetooth support if CYW43_ENABLE_BLUETOOTH is 1 (as it will be automatically if you depend on pico_btstack_cyw43).


Thanks to the following for their contributions:


Andrew Burge,

Andrew Scheller,

Attila Wagner,


Damien George,

Daniel Treffenstädt,

David Greaves,


Earle F. Philhower, III,



Flaviu Tamas,

Graham Sanderson,

James Peach,

Jan Niehusmann,

Jay Greco,

Jeremy Grosser,

Jonathan Bell,

Jonathan Reichelt Gjertsen,



Liam Frasier,


Matthias Ringwald,

Mr. Green’s Workshop,

Nicolas Pouillon,

Nikhil Dabas,

Patrick Plenefisch,

Pedro Tôrres,

Peter Harper,

Peter Pettersson,

Radoslav Gerganov,


Stargirl Flowers,

Thomas Roberts,

Timo Kokkonen

Read More