Skip to content
Merged
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
1 change: 1 addition & 0 deletions docs/index.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
* \cond pico_multicore \defgroup pico_multicore pico_multicore \endcond
* \cond pico_rand \defgroup pico_rand pico_rand \endcond
* \cond pico_sha256 \defgroup pico_sha256 pico_sha256 \endcond
* \cond pico_status_led \defgroup pico_status_led pico_status_led \endcond
* \cond pico_stdlib \defgroup pico_stdlib pico_stdlib \endcond
* \cond pico_sync \defgroup pico_sync pico_sync \endcond
* \cond pico_time \defgroup pico_time pico_time \endcond
Expand Down
1 change: 1 addition & 0 deletions src/cmake/rp2_common.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ if (NOT PICO_BARE_METAL)
pico_add_subdirectory(rp2_common/pico_standard_link)

pico_add_subdirectory(rp2_common/pico_fix)
pico_add_subdirectory(rp2_common/pico_status_led)

# at the end as it includes a lot of other stuff
pico_add_subdirectory(rp2_common/pico_runtime_init)
Expand Down
2 changes: 1 addition & 1 deletion src/rp2_common/pico_cyw43_driver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ if (EXISTS ${PICO_CYW43_DRIVER_PATH}/${CYW43_DRIVER_TEST_FILE})
target_sources(pico_cyw43_driver INTERFACE
cyw43_driver.c)
target_include_directories(pico_cyw43_driver_headers SYSTEM INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
pico_mirrored_target_link_libraries(pico_cyw43_driver INTERFACE cyw43_driver)
pico_mirrored_target_link_libraries(pico_cyw43_driver INTERFACE cyw43_driver pico_unique_id)

# cyw43_driver_picow is cyw43_driver plus Pico W specific bus implementation
pico_add_library(cyw43_driver_picow NOFLAG)
Expand Down
12 changes: 6 additions & 6 deletions src/rp2_common/pico_cyw43_driver/cyw43_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,20 +275,20 @@ void cyw43_delay_us(uint32_t us) {
}

#if !CYW43_LWIP
static void no_lwip_fail() {
static void no_lwip_fail(void) {
panic("cyw43 has no ethernet interface");
}
void __attribute__((weak)) cyw43_cb_tcpip_init(cyw43_t *self, int itf) {
void __attribute__((weak)) cyw43_cb_tcpip_init(__unused cyw43_t *self, __unused int itf) {
}
void __attribute__((weak)) cyw43_cb_tcpip_deinit(cyw43_t *self, int itf) {
void __attribute__((weak)) cyw43_cb_tcpip_deinit(__unused cyw43_t *self, __unused int itf) {
}
void __attribute__((weak)) cyw43_cb_tcpip_set_link_up(cyw43_t *self, int itf) {
void __attribute__((weak)) cyw43_cb_tcpip_set_link_up(__unused cyw43_t *self, __unused int itf) {
no_lwip_fail();
}
void __attribute__((weak)) cyw43_cb_tcpip_set_link_down(cyw43_t *self, int itf) {
void __attribute__((weak)) cyw43_cb_tcpip_set_link_down(__unused cyw43_t *self, __unused int itf) {
no_lwip_fail();
}
void __attribute__((weak)) cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf) {
void __attribute__((weak)) cyw43_cb_process_ethernet(__unused void *cb_data, __unused int itf, __unused size_t len, __unused const uint8_t *buf) {
no_lwip_fail();
}
#endif
5 changes: 5 additions & 0 deletions src/rp2_common/pico_cyw43_driver/include/cyw43_configport.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,11 @@ void cyw43_post_poll_hook(void);
#define CYW43_PRINTF(...) (void)0
#endif

// PICO_CONFIG: CYW43_LWIP_DEFAULT, Sets the default value of CYW43_LWIP if it's undefined. CYW43_LWIP defines if cyw43-driver uses LwIP. The default behavior - if it's not defined anywhere - is to set it to 1 and cyw43-driver will use lwIP requiring you to provide an lwipopts.h header file. You can set CYW43_LWIP_DEFAULT to change the default to 0 and avoid using lwIP if CYW43_LWIP is undefined, type=bool, group=pico_cyw43_driver
#if !defined CYW43_LWIP && defined CYW43_LWIP_DEFAULT
#define CYW43_LWIP CYW43_LWIP_DEFAULT
#endif

#ifdef __cplusplus
}
#endif
Expand Down
4 changes: 2 additions & 2 deletions src/rp2_common/pico_lwip/lwip_freertos.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ static void tcpip_init_done(void *param) {
}

bool lwip_freertos_init(async_context_t *context) {
assert(!lwip_context);
lwip_context = context;
assert(!lwip_context || lwip_context == context);
static bool done_lwip_init;
if (!done_lwip_init) {
lwip_context = context;
done_lwip_init = true;
SemaphoreHandle_t init_sem = xSemaphoreCreateBinary();
tcpip_task_blocker = xSemaphoreCreateBinary();
Expand Down
28 changes: 28 additions & 0 deletions src/rp2_common/pico_status_led/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
load("//bazel:defs.bzl", "compatible_with_rp2", "pico_generate_pio_header")

package(default_visibility = ["//visibility:public"])

cc_library(
name = "pico_status_led",
srcs = ["status_led.c"],
hdrs = ["include/pico/status_led.h"],
includes = ["include"],
target_compatible_with = compatible_with_rp2(),
deps = [
"//src/rp2_common/hardware_gpio",
"//src/rp2_common/hardware_pio",
] + select({
"//bazel/constraint:is_pico_w": [
"//src/rp2_common/pico_cyw43_driver",
],
"//bazel/constraint:is_pico2_w": [
"//src/rp2_common/pico_cyw43_driver"
],
"//conditions:default": [],
}),
)

pico_generate_pio_header(
name = "ws2812",
srcs = ["ws2812.pio"],
)
22 changes: 22 additions & 0 deletions src/rp2_common/pico_status_led/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
pico_add_library(pico_status_led)
target_sources(pico_status_led INTERFACE
${CMAKE_CURRENT_LIST_DIR}/status_led.c
)
target_include_directories(pico_status_led_headers SYSTEM INTERFACE
${CMAKE_CURRENT_LIST_DIR}/include
)
pico_mirrored_target_link_libraries(pico_status_led INTERFACE
hardware_gpio
hardware_pio
)
if (PICO_CYW43_SUPPORTED)
pico_mirrored_target_link_libraries(pico_status_led INTERFACE
pico_cyw43_driver cyw43_driver_picow pico_async_context_threadsafe_background
)
target_compile_definitions(pico_status_led INTERFACE
CYW43_LWIP_DEFAULT=0 # Disable LwIP by default. Can be overridden if LwIP is needed.
)
endif()
pico_generate_pio_header(pico_status_led ${CMAKE_CURRENT_LIST_DIR}/ws2812.pio)

get_target_property(OUT pico_status_led LINK_LIBRARIES)
250 changes: 250 additions & 0 deletions src/rp2_common/pico_status_led/include/pico/status_led.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
/*
* Copyright (c) 2025 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/

/** \file pico/status_led.h
* \defgroup pico_status_led pico_status_led
*
* \brief Enables access to the on-board status LED(s)
*
* Boards usually have access to an on-board status LEDs which are configured via the board header (\see PICO_DEFAULT_LED_PIN and \see PICO_DEFAULT_WS2812_PIN)
* This library hides the details so you can use the status LEDs for all boards without changing your code.
*/

#ifndef _PICO_STATUS_LED_H
#define _PICO_STATUS_LED_H

#include "hardware/gpio.h"

#if defined(CYW43_WL_GPIO_LED_PIN)
#include "cyw43.h"
#endif

struct async_context;

#ifdef __cplusplus
extern "C" {
#endif

// PICO_CONFIG: PICO_STATUS_LED_AVAILABLE, Indicate whether a non-colored status LED is available, type=bool, default=1 if PICO_DEFAULT_LED_PIN or CYW43_WL_GPIO_LED_PIN is defined; may be set by the user to 0 to not use either even if they are available, group=pico_status_led
#ifndef PICO_STATUS_LED_AVAILABLE
#if defined(PICO_DEFAULT_LED_PIN) || defined(CYW43_WL_GPIO_LED_PIN)
#define PICO_STATUS_LED_AVAILABLE 1
#else
#define PICO_STATUS_LED_AVAILABLE 0
#endif
#endif

// PICO_CONFIG: PICO_COLORED_STATUS_LED_AVAILABLE, Indicate whether a colored status LED is available, type=bool, default=1 if PICO_DEFAULT_WS2812_PIN is defined; may be set by the user to 0 to not use the colored status LED even if available, group=pico_status_led
#ifndef PICO_COLORED_STATUS_LED_AVAILABLE
#ifdef PICO_DEFAULT_WS2812_PIN
#define PICO_COLORED_STATUS_LED_AVAILABLE 1
#else
#define PICO_COLORED_STATUS_LED_AVAILABLE 0
#endif
#endif

// PICO_CONFIG: PICO_STATUS_LED_VIA_COLORED_STATUS_LED, Indicate if the colored status LED should be used for both status_led and colored_status_led APIs, type=bool, default=1 if PICO_COLORED_STATUS_LED_AVAILABLE is 1 and PICO_STATUS_LED_AVAILABLE is 0, group=pico_status_led
#ifndef PICO_STATUS_LED_VIA_COLORED_STATUS_LED
#define PICO_STATUS_LED_VIA_COLORED_STATUS_LED (PICO_COLORED_STATUS_LED_AVAILABLE && !PICO_STATUS_LED_AVAILABLE)
#endif

// PICO_CONFIG: PICO_COLORED_STATUS_LED_USES_WRGB, Indicate if the colored status LED supports WRGB, type=bool, default=0, group=pico_status_led
#ifndef PICO_COLORED_STATUS_LED_USES_WRGB
#define PICO_COLORED_STATUS_LED_USES_WRGB 0
#endif

/*! \brief Generate an RGB color value for /ref colored_status_led_set_on_with_color
* \ingroup pico_status_led
*/
#ifndef PICO_COLORED_STATUS_LED_COLOR_FROM_RGB
#define PICO_COLORED_STATUS_LED_COLOR_FROM_RGB(r, g, b) (((r) << 16) | ((g) << 8) | (b))
#endif

/*! \brief Generate an WRGB color value for \ref colored_status_led_set_on_with_color
* \ingroup pico_status_led
*
* \note: If your hardware does not support a white pixel, the white component is ignored
*/
#ifndef PICO_COLORED_STATUS_LED_COLOR_FROM_WRGB
#define PICO_COLORED_STATUS_LED_COLOR_FROM_WRGB(w, r, g, b) (((w) << 24) | ((r) << 16) | ((g) << 8) | (b))
#endif

// PICO_CONFIG: PICO_DEFAULT_COLORED_STATUS_LED_ON_COLOR, the default pixel color value of the colored status LED when it is on, type=int, group=pico_status_led
#ifndef PICO_DEFAULT_COLORED_STATUS_LED_ON_COLOR
#if PICO_COLORED_STATUS_LED_USES_WRGB
#define PICO_DEFAULT_COLORED_STATUS_LED_ON_COLOR PICO_COLORED_STATUS_LED_COLOR_FROM_WRGB(0xaa, 0, 0, 0)
#else
#define PICO_DEFAULT_COLORED_STATUS_LED_ON_COLOR PICO_COLORED_STATUS_LED_COLOR_FROM_RGB(0xaa, 0xaa, 0xaa)
#endif
#endif

/*! \brief Initialize the status LED(s)
* \ingroup pico_status_led
*
* Initialize the status LED(s) and the resources they need before use. On some devices (e.g. Pico W, Pico 2 W) accessing
* the status LED requires talking to the WiFi chip, which requires an \ref async_context.
* This method will create an async_context for you.
*
* However an application should only use a single \ref async_context instance to talk to the WiFi chip.
* If the application already has an async context (e.g. created by cyw43_arch_init) you should use \ref
* status_led_init_with_context instead and pass it the \ref async_context already created by your application
*
* \note: You must call this function (or \ref status_led_init_with_context) before using any other pico_status_led functions.
*
* \return Returns true if the LED was initialized successfully, otherwise false on failure
* \sa status_led_init_with_context
*/
bool status_led_init(void);

/*! \brief Initialise the status LED(s)
* \ingroup pico_status_led
*
* Initialize the status LED(s) and the resources they need before use.
*
* \note: You must call this function (or \ref status_led_init) before using any other pico_status_led functions.
*
* \param context An \ref async_context used to communicate with the status LED (e.g. on Pico W or Pico 2 W)
* \return Returns true if the LED was initialized successfully, otherwise false on failure
* \sa status_led_init_with_context
*/
bool status_led_init_with_context(struct async_context *context);

/*! \brief Determine if the `colored_status_led_` APIs are supported (i.e. if there is a colored status LED, and its
* use isn't disabled via \ref PICO_COLORED_STATUS_LED_AVAILABLE being set to 0
* \ingroup pico_status_led
* \return true if the colored status LED API is available and expected to produce visible results
* \sa PICO_COLORED_STATUS_LED_AVAILABLE
*/
static inline bool colored_status_led_supported(void) {
return PICO_COLORED_STATUS_LED_AVAILABLE;
}

/*! \brief Determine if the colored status LED is being used for the non-colored `status_led_` APIs
* \ingroup pico_status_led
* \return true if the olored status LED is being used for the non-colored `status_led_` API
* \sa PICO_STATUS_LED_VIA_COLORED_STATUS_LED
*/
static inline bool status_led_via_colored_status_led(void) {
return PICO_STATUS_LED_VIA_COLORED_STATUS_LED;
}

/*! \brief Determine if the non-colored `status_led_` APIs are supported (i.e. if there is a regular LED, and its
* use isn't disabled via \ref PICO_STATUS_LED_AVAILABLE being set to 0, or if the colored status LED is being used for
* \ingroup pico_status_led
* \return true if the non-colored status LED API is available and expected to produce visible results
* \sa PICO_STATUS_LED_AVAILABLE
* \sa PICO_STATUS_LED_VIA_COLORED_STATUS_LED
*/
static inline bool status_led_supported(void) {
if (status_led_via_colored_status_led()) {
return colored_status_led_supported();
}
return PICO_STATUS_LED_AVAILABLE;
}

/*! \brief Set the colored status LED on or off
* \ingroup pico_status_led
*
* \note: If your hardware does not support a colored status LED (\see PICO_DEFAULT_WS2812_PIN), this function does nothing and returns false.
*
* \param led_on true to turn the colored LED on. Pass false to turn the colored LED off
* \return true if the colored status LED could be set, otherwise false
*/
bool colored_status_led_set_state(bool led_on);

/*! \brief Get the state of the colored status LED
* \ingroup pico_status_led
*
* \note: If your hardware does not support a colored status LED (\see PICO_DEFAULT_WS2812_PIN), this function returns false.
*
* \return true if the colored status LED is on, or false if the colored status LED is off
*/
bool colored_status_led_get_state(void);

/*! \brief Ensure the colored status LED is on, with the specified color
* \ingroup pico_status_led
*
* \note: If your hardware does not support a colored status LED (\see PICO_DEFAULT_WS2812_PIN), this function does nothing and returns false.
*
* \param color The color to use for the colored status LED when it is on, in 0xWWRRGGBB format
* \return true if the coloured status LED could be set, otherwise false on failure
*/
bool colored_status_led_set_on_with_color(uint32_t color);

/*! \brief Get the color used for the status LED value when it is on
* \ingroup pico_status_led
*
* \note: If your hardware does not support a colored status LED (\see PICO_DEFAULT_WS2812_PIN), this function always returns 0x0.
*
* \return The color used for the colored status LED when it is on, in 0xWWRRGGBB format
*/
uint32_t colored_status_led_get_on_color(void);

/*! \brief Set the status LED on or off
* \ingroup pico_status_led
*
* \note: If your hardware does not support a status LED (\see PICO_DEFAULT_LED_PIN), this function does nothing and returns false.
*
* \param led_on true to turn the LED on. Pass false to turn the LED off
* \return true if the status LED could be set, otherwise false
*/
static inline bool status_led_set_state(bool led_on) {
if (status_led_via_colored_status_led()) {
return colored_status_led_set_state(led_on);
} else if (status_led_supported()) {
#if defined(PICO_DEFAULT_LED_PIN)
#if PICO_DEFAULT_LED_PIN_INVERTED
gpio_put(PICO_DEFAULT_LED_PIN, !led_on);
#else
gpio_put(PICO_DEFAULT_LED_PIN, led_on);
#endif
return true;
#elif defined(CYW43_WL_GPIO_LED_PIN)
cyw43_gpio_set(&cyw43_state, CYW43_WL_GPIO_LED_PIN, led_on);
return true;
#endif
}
return false;
}

/*! \brief Get the state of the status LED
* \ingroup pico_status_led
*
* \note: If your hardware does not support a status LED (\see PICO_DEFAULT_LED_PIN), this function always returns false.
*
* \return true if the status LED is on, or false if the status LED is off
*/
static inline bool status_led_get_state() {
if (status_led_via_colored_status_led()) {
return colored_status_led_get_state();
} else if (status_led_supported()) {
#if defined(PICO_DEFAULT_LED_PIN)
#if PICO_DEFAULT_LED_PIN_INVERTED
return !gpio_get(PICO_DEFAULT_LED_PIN);
#else
return gpio_get(PICO_DEFAULT_LED_PIN);
#endif
#elif defined CYW43_WL_GPIO_LED_PIN
bool value = false;
cyw43_gpio_get(&cyw43_state, CYW43_WL_GPIO_LED_PIN, &value);
return value;
#endif
}
return false;
}

/*! \brief De-initialize the status LED(s)
* \ingroup pico_status_led
*
* De-initializes the status LED(s) when they are no longer needed.
*/
void status_led_deinit();

#ifdef __cplusplus
}
#endif

#endif
Loading
Loading