From 9e28657aa414a2ce9410d2dceceaceabf920720a Mon Sep 17 00:00:00 2001 From: Alan Carvalho de Assis Date: Sun, 18 Feb 2024 13:02:32 -0300 Subject: [PATCH] boards/raspberrypi-pico: Add autoleds and userleds support This commit adds support to autoleds and userleds for raspberrypi-pico board. It uses the board LED connected to GPIO 25. Signed-off-by: Alan C. Assis --- boards/Kconfig | 1 + .../rp2040/raspberrypi-pico/include/board.h | 42 ++++ .../arm/rp2040/raspberrypi-pico/src/Make.defs | 6 + .../raspberrypi-pico/src/rp2040_autoleds.c | 167 ++++++++++++++ .../raspberrypi-pico/src/rp2040_bringup.c | 15 ++ .../rp2040/raspberrypi-pico/src/rp2040_pico.h | 4 + .../raspberrypi-pico/src/rp2040_userleds.c | 215 ++++++++++++++++++ 7 files changed, 450 insertions(+) create mode 100644 boards/arm/rp2040/raspberrypi-pico/src/rp2040_autoleds.c create mode 100644 boards/arm/rp2040/raspberrypi-pico/src/rp2040_userleds.c diff --git a/boards/Kconfig b/boards/Kconfig index 5fed6ec4c0aaa..817f7b346500e 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -1827,6 +1827,7 @@ config ARCH_BOARD_INTEL64_QEMU config ARCH_BOARD_RASPBERRYPI_PICO bool "Raspberry Pi Pico board (not W)" depends on ARCH_CHIP_RP2040 + select ARCH_HAVE_LEDS ---help--- This is a port to the Raspberry Pi Pico board. diff --git a/boards/arm/rp2040/raspberrypi-pico/include/board.h b/boards/arm/rp2040/raspberrypi-pico/include/board.h index e22882ee6f27d..2b8f1a697e6a1 100644 --- a/boards/arm/rp2040/raspberrypi-pico/include/board.h +++ b/boards/arm/rp2040/raspberrypi-pico/include/board.h @@ -67,6 +67,48 @@ #define BOARD_NGPIOIN 1 #define BOARD_NGPIOINT 1 +/* LED definitions **********************************************************/ + +/* If CONFIG_ARCH_LEDS is not defined, then the user can control the LEDs + * in any way. The following definitions are used to access individual LEDs. + */ + +/* LED index values for use with board_userled() */ + +#define BOARD_LED1 0 +#define BOARD_NLEDS 1 + +#define BOARD_LED_GREEN BOARD_LED1 + +/* LED bits for use with board_userled_all() */ + +#define BOARD_LED1_BIT (1 << BOARD_LED1) + +/* This LED is not used by the board port unless CONFIG_ARCH_LEDS is + * defined. In that case, the usage by the board port is defined in + * include/board.h and src/rp2040_autoleds.c. The LED is used to encode + * OS-related events as follows: + * + * -------------------- ----------------------------- ------ + * SYMBOL Meaning LED + * -------------------- ----------------------------- ------ + */ + +#define LED_STARTED 0 /* NuttX has been started OFF */ +#define LED_HEAPALLOCATE 0 /* Heap has been allocated OFF */ +#define LED_IRQSENABLED 0 /* Interrupts enabled OFF */ +#define LED_STACKCREATED 1 /* Idle stack created ON */ +#define LED_INIRQ 2 /* In an interrupt N/C */ +#define LED_SIGNAL 2 /* In a signal handler N/C */ +#define LED_ASSERTION 2 /* An assertion failed N/C */ +#define LED_PANIC 3 /* The system has crashed FLASH */ +#undef LED_IDLE /* Not used */ + +/* Thus if the LED is statically on, NuttX has successfully booted and is, + * apparently, running normally. If the LED is flashing at approximately + * 2Hz, then a fatal error has been detected and the system has halted. + */ + /**************************************************************************** * Public Types ****************************************************************************/ diff --git a/boards/arm/rp2040/raspberrypi-pico/src/Make.defs b/boards/arm/rp2040/raspberrypi-pico/src/Make.defs index 212f994e83089..ab5f13e26fdab 100644 --- a/boards/arm/rp2040/raspberrypi-pico/src/Make.defs +++ b/boards/arm/rp2040/raspberrypi-pico/src/Make.defs @@ -28,6 +28,12 @@ ifeq ($(CONFIG_DEV_GPIO),y) CSRCS += rp2040_gpio.c endif +ifeq ($(CONFIG_ARCH_LEDS),y) +CSRCS += rp2040_autoleds.c +else +CSRCS += rp2040_userleds.c +endif + DEPPATH += --dep-path board VPATH += :board CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)board diff --git a/boards/arm/rp2040/raspberrypi-pico/src/rp2040_autoleds.c b/boards/arm/rp2040/raspberrypi-pico/src/rp2040_autoleds.c new file mode 100644 index 0000000000000..bba81a6f8bef1 --- /dev/null +++ b/boards/arm/rp2040/raspberrypi-pico/src/rp2040_autoleds.c @@ -0,0 +1,167 @@ +/**************************************************************************** + * boards/arm/rp2040/raspberrypi-pico/src/rp2040_autoleds.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* There are four LED status indicators located on the EVK Board. The + * functions of these LEDs include: + * + * - Main Power Supply(D3) + * Green: DC 5V main supply is normal. + * Red: J2 input voltage is over 5.6V. + * Off: The board is not powered. + * - Reset RED LED(D15) + * - OpenSDA LED(D16) + * - USER LED(D18) + * + * Only a single LED, D18, is under software control. + * + * This LED is not used by the board port unless CONFIG_ARCH_LEDS is + * defined. In that case, the usage by the board port is defined in + * include/board.h and src/rp2040_autoleds.c. The LED is used to encode + * OS-related events as follows: + * + * -------------------- ----------------------- ------ + * SYMBOL Meaning LED + * -------------------- ----------------------- ------ + * + * LED_STARTED 0 NuttX has been started OFF + * LED_HEAPALLOCATE 0 Heap has been allocated OFF + * LED_IRQSENABLED 0 Interrupts enabled OFF + * LED_STACKCREATED 1 Idle stack created ON + * LED_INIRQ 2 In an interrupt N/C + * LED_SIGNAL 2 In a signal handler N/C + * LED_ASSERTION 2 An assertion failed N/C + * LED_PANIC 3 The system has crashed FLASH + * LED_IDLE Not used + * + * Thus if the LED is statically on, NuttX has successfully booted and is, + * apparently, running normally. If the LED is flashing at approximately + * 2Hz, then a fatal error has been detected and the system has halted. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "arm_internal.h" +#include "chip.h" +#include "rp2040_gpio.h" + +#include "rp2040_pico.h" + +#ifdef CONFIG_ARCH_LEDS + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rp2040_autoled_initialize + * + * Description: + * Initialize NuttX-controlled LED logic + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void board_autoled_initialize(void) +{ + /* Configure LED GPIO for output */ + + rp2040_gpio_init(GPIO_LED1); + rp2040_gpio_setdir(GPIO_LED1, true); +} + +/**************************************************************************** + * Name: board_autoled_on + * + * Description: + * Turn on the "logical" LED state + * + * Input Parameters: + * led - Identifies the "logical" LED state (see definitions in + * include/board.h) + * + * Returned Value: + * None + * + ****************************************************************************/ + +void board_autoled_on(int led) +{ + bool ledon = true; + + switch (led) + { + case 0: /* LED Off */ + ledon = false; + break; + + case 2: /* LED No change */ + return; + + case 1: /* LED On */ + case 3: /* LED On */ + break; + } + + rp2040_gpio_put(GPIO_LED1, ledon); /* High illuminates */ +} + +/**************************************************************************** + * Name: board_autoled_off + * + * Description: + * Turn off the "logical" LED state + * + * Input Parameters: + * led - Identifies the "logical" LED state (see definitions in + * include/board.h) + * + * Returned Value: + * None + * + ****************************************************************************/ + +void board_autoled_off(int led) +{ + switch (led) + { + case 0: /* LED Off */ + case 1: /* LED Off */ + case 3: /* LED Off */ + break; + + case 2: /* LED No change */ + return; + } + + rp2040_gpio_put(GPIO_LED1, false); /* High illuminates */ +} + +#endif /* CONFIG_ARCH_LEDS */ diff --git a/boards/arm/rp2040/raspberrypi-pico/src/rp2040_bringup.c b/boards/arm/rp2040/raspberrypi-pico/src/rp2040_bringup.c index a20a397c00798..ac6f4bdfc1b8e 100644 --- a/boards/arm/rp2040/raspberrypi-pico/src/rp2040_bringup.c +++ b/boards/arm/rp2040/raspberrypi-pico/src/rp2040_bringup.c @@ -37,6 +37,10 @@ #include "rp2040_common_bringup.h" #endif /* CONFIG_ARCH_BOARD_COMMON */ +#ifdef CONFIG_USERLED +# include +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -59,5 +63,16 @@ int rp2040_bringup(void) /* --- Place any board specific bringup code here --- */ +#ifdef CONFIG_USERLED + /* Register the LED driver */ + + ret = userled_lower_initialize("/dev/userleds"); + if (ret < 0) + { + syslog(LOG_ERR, \ + "ERROR: userled_lower_initialize() failed: %d\n", ret); + } +#endif + return OK; } diff --git a/boards/arm/rp2040/raspberrypi-pico/src/rp2040_pico.h b/boards/arm/rp2040/raspberrypi-pico/src/rp2040_pico.h index 21a77bd9e8057..914e956dd3000 100644 --- a/boards/arm/rp2040/raspberrypi-pico/src/rp2040_pico.h +++ b/boards/arm/rp2040/raspberrypi-pico/src/rp2040_pico.h @@ -27,6 +27,10 @@ #include +/* LEDs */ + +#define GPIO_LED1 25 /* The board's LED is connected to this pin */ + int rp2040_bringup(void); #ifdef CONFIG_DEV_GPIO diff --git a/boards/arm/rp2040/raspberrypi-pico/src/rp2040_userleds.c b/boards/arm/rp2040/raspberrypi-pico/src/rp2040_userleds.c new file mode 100644 index 0000000000000..e91f47458fbb0 --- /dev/null +++ b/boards/arm/rp2040/raspberrypi-pico/src/rp2040_userleds.c @@ -0,0 +1,215 @@ +/**************************************************************************** + * boards/arm/rp2040/raspberrypi-pico/src/rp2040_userleds.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "arm_internal.h" +#include "chip.h" +#include "rp2040_gpio.h" + +#include "rp2040_pico.h" + +#ifndef CONFIG_ARCH_LEDS + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This array maps an LED number to GPIO pin configuration */ + +static uint32_t g_ledcfg[BOARD_NLEDS] = +{ + GPIO_LED1, +}; + +/**************************************************************************** + * Private Function Protototypes + ****************************************************************************/ + +/* LED Power Management */ + +#ifdef CONFIG_PM +static void led_pm_notify(struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate); +static int led_pm_prepare(struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_PM +static struct pm_callback_s g_ledscb = +{ + .notify = led_pm_notify, + .prepare = led_pm_prepare, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: led_pm_notify + * + * Description: + * Notify the driver of new power state. This callback is called after + * all drivers have had the opportunity to prepare for the new power state. + * + ****************************************************************************/ + +#ifdef CONFIG_PM +static void led_pm_notify(struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate) +{ + switch (pmstate) + { + case(PM_NORMAL): + { + /* Restore normal LEDs operation */ + + board_userled(BOARD_LED, true); + } + break; + + case(PM_IDLE): + { + /* Entering IDLE mode - Turn leds off */ + + board_userled(BOARD_LED, false); + } + break; + + case(PM_STANDBY): + { + /* Entering STANDBY mode - Logic for PM_STANDBY goes here */ + } + break; + + case(PM_SLEEP): + { + /* Entering SLEEP mode - Logic for PM_SLEEP goes here */ + } + break; + + default: + { + /* Should not get here */ + } + break; + } +} +#endif + +/**************************************************************************** + * Name: led_pm_prepare + * + * Description: + * Request the driver to prepare for a new power state. This is a warning + * that the system is about to enter into a new power state. The driver + * should begin whatever operations that may be required to enter power + * state. The driver may abort the state change mode by returning a + * non-zero value from the callback function. + * + ****************************************************************************/ + +#ifdef CONFIG_PM +static int led_pm_prepare(struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate) +{ + /* No preparation to change power modes is required by the LEDs driver. + * We always accept the state change by returning OK. + */ + + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_userled_initialize + ****************************************************************************/ + +uint32_t board_userled_initialize(void) +{ + /* Configure LED GPIO for output */ + + rp2040_gpio_init(GPIO_LED1); + rp2040_gpio_setdir(GPIO_LED1, true); + + return BOARD_NLEDS; +} + +/**************************************************************************** + * Name: board_userled + ****************************************************************************/ + +void board_userled(int led, bool ledon) +{ + if ((unsigned)led < BOARD_NLEDS) + { + rp2040_gpio_put(g_ledcfg[led], ledon); + } +} + +/**************************************************************************** + * Name: board_userled_all + ****************************************************************************/ + +void board_userled_all(uint32_t ledset) +{ + rp2040_gpio_put(GPIO_LED1, (ledset & BOARD_LED1_BIT)); +} + +/**************************************************************************** + * Name: rp2040_led_pminitialize + ****************************************************************************/ + +#ifdef CONFIG_PM +void rp2040_led_pminitialize(void) +{ + /* Register to receive power management callbacks */ + + int ret = pm_register(&g_ledscb); + if (ret != OK) + { + board_autoled_on(LED_ASSERTION); + } +} +#endif /* CONFIG_PM */ + +#endif /* !CONFIG_ARCH_LEDS */