From 7223ec3dbe4c6db0c4b09bb1b1493ccaabbf176e Mon Sep 17 00:00:00 2001 From: halyssonJr Date: Sun, 7 Jul 2024 16:25:27 -0300 Subject: [PATCH] add support to userleds --- boards/Kconfig | 1 + .../rp2040/seeed-xiao-rp2040/include/board.h | 56 ++++- .../rp2040/seeed-xiao-rp2040/src/Make.defs | 6 + .../seeed-xiao-rp2040/src/rp2040_autoleds.c | 180 ++++++++++++++ .../src/rp2040_boardinitialize.c | 14 +- .../seeed-xiao-rp2040/src/rp2040_bringup.c | 15 ++ .../seeed-xiao-rp2040/src/rp2040_gpio.c | 10 +- .../seeed-xiao-rp2040/src/rp2040_pico.h | 6 + .../seeed-xiao-rp2040/src/rp2040_userleds.c | 224 ++++++++++++++++++ 9 files changed, 505 insertions(+), 7 deletions(-) create mode 100644 boards/arm/rp2040/seeed-xiao-rp2040/src/rp2040_autoleds.c create mode 100644 boards/arm/rp2040/seeed-xiao-rp2040/src/rp2040_userleds.c diff --git a/boards/Kconfig b/boards/Kconfig index dc90052624..49dcb4b655 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -1900,6 +1900,7 @@ config ARCH_BOARD_ADAFRUIT_FEATHER_RP2040 config ARCH_BOARD_SEEED_XIAO_RP2040 bool "Seeed Studio XIAO RP2040 board" depends on ARCH_CHIP_RP2040 + select ARCH_HAVE_LEDS ---help--- This is a port to the Seeed Studio XIAO RP2040 board. Support is derived from Raspberry Pi Pico support. diff --git a/boards/arm/rp2040/seeed-xiao-rp2040/include/board.h b/boards/arm/rp2040/seeed-xiao-rp2040/include/board.h index 58b0f5a607..99f1330ad4 100644 --- a/boards/arm/rp2040/seeed-xiao-rp2040/include/board.h +++ b/boards/arm/rp2040/seeed-xiao-rp2040/include/board.h @@ -62,11 +62,63 @@ /* GPIO definitions *********************************************************/ -#define BOARD_GPIO_LED_PIN 25 -#define BOARD_NGPIOOUT 1 +#define BOARD_GPIO_LED_PIN_B 25 +#define BOARD_GPIO_LED_PIN_R 17 +#define BOARD_GPIO_LED_PIN_G 16 + +#define BOARD_NGPIOOUT 3 #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_LED2 1 +#define BOARD_LED3 2 + +#define BOARD_NLEDS 3 + +#define BOARD_LED_BLUE BOARD_LED1 +#define BOARD_LED_RED BOARD_LED2 +#define BOARD_LED_GREEN BOARD_LED3 + +/* LED bits for use with board_userled_all() */ + +#define BOARD_LED1_BIT (1 << BOARD_LED1) +#define BOARD_LED2_BIT (1 << BOARD_LED2) +#define BOARD_LED3_BIT (1 << BOARD_LED3) + +/* 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/seeed-xiao-rp2040/src/Make.defs b/boards/arm/rp2040/seeed-xiao-rp2040/src/Make.defs index 1988bff080..6f0fa641b1 100644 --- a/boards/arm/rp2040/seeed-xiao-rp2040/src/Make.defs +++ b/boards/arm/rp2040/seeed-xiao-rp2040/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/seeed-xiao-rp2040/src/rp2040_autoleds.c b/boards/arm/rp2040/seeed-xiao-rp2040/src/rp2040_autoleds.c new file mode 100644 index 0000000000..772253f31f --- /dev/null +++ b/boards/arm/rp2040/seeed-xiao-rp2040/src/rp2040_autoleds.c @@ -0,0 +1,180 @@ +/**************************************************************************** + * boards/arm/rp2040/seeed-xiao-rp2040/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_init(GPIO_LED2); + rp2040_gpio_init(GPIO_LED3); + + rp2040_gpio_setdir(GPIO_LED1, true); + rp2040_gpio_setdir(GPIO_LED2, true); + rp2040_gpio_setdir(GPIO_LED3, 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; + } + + /* High illuminates */ + + rp2040_gpio_put(GPIO_LED1, ledon); + rp2040_gpio_put(GPIO_LED2, ledon); + rp2040_gpio_put(GPIO_LED3, ledon); +} + +/**************************************************************************** + * 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; + } + + /* High illuminates */ + + rp2040_gpio_put(GPIO_LED1, false); + rp2040_gpio_put(GPIO_LED2, false); + rp2040_gpio_put(GPIO_LED3, false); +} + +#endif /* CONFIG_ARCH_LEDS */ diff --git a/boards/arm/rp2040/seeed-xiao-rp2040/src/rp2040_boardinitialize.c b/boards/arm/rp2040/seeed-xiao-rp2040/src/rp2040_boardinitialize.c index 3f4df88bd2..522877b4fd 100644 --- a/boards/arm/rp2040/seeed-xiao-rp2040/src/rp2040_boardinitialize.c +++ b/boards/arm/rp2040/seeed-xiao-rp2040/src/rp2040_boardinitialize.c @@ -65,9 +65,17 @@ void rp2040_boardearlyinitialize(void) /* Set board LED pin */ - rp2040_gpio_init(BOARD_GPIO_LED_PIN); - rp2040_gpio_setdir(BOARD_GPIO_LED_PIN, true); - rp2040_gpio_put(BOARD_GPIO_LED_PIN, true); + rp2040_gpio_init(BOARD_GPIO_LED_PIN_R); + rp2040_gpio_init(BOARD_GPIO_LED_PIN_G); + rp2040_gpio_init(BOARD_GPIO_LED_PIN_B); + + rp2040_gpio_setdir(BOARD_GPIO_LED_PIN_R, true); + rp2040_gpio_setdir(BOARD_GPIO_LED_PIN_G, true); + rp2040_gpio_setdir(BOARD_GPIO_LED_PIN_B, true); + + rp2040_gpio_put(BOARD_GPIO_LED_PIN_R, true); + rp2040_gpio_put(BOARD_GPIO_LED_PIN_G, true); + rp2040_gpio_put(BOARD_GPIO_LED_PIN_B, true); } /**************************************************************************** diff --git a/boards/arm/rp2040/seeed-xiao-rp2040/src/rp2040_bringup.c b/boards/arm/rp2040/seeed-xiao-rp2040/src/rp2040_bringup.c index 96380f9f52..29217f4b4a 100644 --- a/boards/arm/rp2040/seeed-xiao-rp2040/src/rp2040_bringup.c +++ b/boards/arm/rp2040/seeed-xiao-rp2040/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/seeed-xiao-rp2040/src/rp2040_gpio.c b/boards/arm/rp2040/seeed-xiao-rp2040/src/rp2040_gpio.c index ba00486b52..a3b256a062 100644 --- a/boards/arm/rp2040/seeed-xiao-rp2040/src/rp2040_gpio.c +++ b/boards/arm/rp2040/seeed-xiao-rp2040/src/rp2040_gpio.c @@ -41,10 +41,14 @@ #if defined(CONFIG_DEV_GPIO) && !defined(CONFIG_GPIO_LOWER_HALF) -/* Output pins. GPIO25 is onboard LED any other outputs could be used. +/** + * Output pins. Those pins are onboard LEDs + * any other outputs could be used */ #define GPIO_OUT1 25 +#define GPIO_OUT2 17 +#define GPIO_OUT3 16 /* Input pins. */ @@ -109,7 +113,9 @@ static const struct gpio_operations_s gpout_ops = static const uint32_t g_gpiooutputs[BOARD_NGPIOOUT] = { - GPIO_OUT1 + GPIO_OUT1, + GPIO_OUT2, + GPIO_OUT3, }; static struct rp2040gpio_dev_s g_gpout[BOARD_NGPIOOUT]; diff --git a/boards/arm/rp2040/seeed-xiao-rp2040/src/rp2040_pico.h b/boards/arm/rp2040/seeed-xiao-rp2040/src/rp2040_pico.h index 8e5c5ffaef..acacfd20e7 100644 --- a/boards/arm/rp2040/seeed-xiao-rp2040/src/rp2040_pico.h +++ b/boards/arm/rp2040/seeed-xiao-rp2040/src/rp2040_pico.h @@ -27,6 +27,12 @@ #include +/* LEDs connected on-board */ + +#define GPIO_LED1 25 /* LED color is BLUE */ +#define GPIO_LED2 17 /* LED color is RED */ +#define GPIO_LED3 16 /* LED color is GREEN */ + int rp2040_bringup(void); #ifdef CONFIG_DEV_GPIO diff --git a/boards/arm/rp2040/seeed-xiao-rp2040/src/rp2040_userleds.c b/boards/arm/rp2040/seeed-xiao-rp2040/src/rp2040_userleds.c new file mode 100644 index 0000000000..07e8244f5e --- /dev/null +++ b/boards/arm/rp2040/seeed-xiao-rp2040/src/rp2040_userleds.c @@ -0,0 +1,224 @@ +/**************************************************************************** + * boards/arm/rp2040/seeed-xiao-rp2040/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, + GPIO_LED2, + GPIO_LED3, +}; + +/**************************************************************************** + * 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_init(GPIO_LED2); + rp2040_gpio_init(GPIO_LED3); + + rp2040_gpio_setdir(GPIO_LED1, true); + rp2040_gpio_setdir(GPIO_LED2, true); + rp2040_gpio_setdir(GPIO_LED3, 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)); + rp2040_gpio_put(GPIO_LED2, (ledset & BOARD_LED1_BIT)); + rp2040_gpio_put(GPIO_LED3, (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 */