From 1037eda906f11aef44f7670f8cc5a1c1d2141911 Mon Sep 17 00:00:00 2001 From: Lee Lup Yuen Date: Mon, 12 Feb 2024 10:22:18 +0800 Subject: [PATCH] Add LED Driver. Tested OK --- boards/Kconfig | 1 + .../qemu-rv/rv-virt/configs/knsh64/defconfig | 3 + boards/risc-v/qemu-rv/rv-virt/include/board.h | 22 +- boards/risc-v/qemu-rv/rv-virt/src/Makefile | 2 +- .../qemu-rv/rv-virt/src/qemu_rv_appinit.c | 11 + .../qemu-rv/rv-virt/src/qemu_rv_autoleds.c | 250 ++++++++++++++++++ .../qemu-rv/rv-virt/src/qemu_rv_userleds.c | 188 +++++++++++++ 7 files changed, 475 insertions(+), 2 deletions(-) create mode 100644 boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_autoleds.c create mode 100644 boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_userleds.c diff --git a/boards/Kconfig b/boards/Kconfig index 5fed6ec4c0aaa..c61a4faadcce0 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -1927,6 +1927,7 @@ config ARCH_BOARD_RV32M1_VEGA config ARCH_BOARD_QEMU_RV_VIRT bool "QEMU RV Virt" depends on ARCH_CHIP_QEMU_RV + select ARCH_HAVE_LEDS ---help--- This is the board configuration for the port of NuttX to the QEMU RV32 Virt board. This board features the QEMU RV32 CPU. diff --git a/boards/risc-v/qemu-rv/rv-virt/configs/knsh64/defconfig b/boards/risc-v/qemu-rv/rv-virt/configs/knsh64/defconfig index c453ae096e377..867db2a567f93 100644 --- a/boards/risc-v/qemu-rv/rv-virt/configs/knsh64/defconfig +++ b/boards/risc-v/qemu-rv/rv-virt/configs/knsh64/defconfig @@ -51,6 +51,7 @@ CONFIG_DEBUG_SYMBOLS=y CONFIG_DEV_ZERO=y CONFIG_ELF=y CONFIG_EXAMPLES_HELLO=m +CONFIG_EXAMPLES_LEDS=y CONFIG_FS_HOSTFS=y CONFIG_FS_PROCFS=y CONFIG_IDLETHREAD_STACKSIZE=3072 @@ -98,3 +99,5 @@ CONFIG_TESTING_GETPRIME=y CONFIG_TESTING_OSTEST=y CONFIG_TLS_LOG2_MAXSTACK=16 CONFIG_USEC_PER_TICK=1000 +CONFIG_USERLED=y +CONFIG_USERLED_LOWER=y diff --git a/boards/risc-v/qemu-rv/rv-virt/include/board.h b/boards/risc-v/qemu-rv/rv-virt/include/board.h index d90390b151c27..51149c6c38240 100644 --- a/boards/risc-v/qemu-rv/rv-virt/include/board.h +++ b/boards/risc-v/qemu-rv/rv-virt/include/board.h @@ -31,6 +31,26 @@ * Pre-processor Definitions ****************************************************************************/ +/* LED definitions **********************************************************/ + +/* LED index values for use with board_userled() */ + +typedef enum +{ + BOARD_LED1 = 0, /* Green LED */ + BOARD_LED2 = 1, /* Red LED */ + BOARD_LED3 = 2, /* Blue LED */ + BOARD_LEDS /* Number of LEDs */ +} led_typedef_enum; + +/* 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) + +/* Auto LEDs */ + #define LED_STARTED 0 /* N/A */ #define LED_HEAPALLOCATE 1 /* N/A */ #define LED_IRQSENABLED 2 /* N/A */ @@ -39,7 +59,7 @@ #define LED_SIGNAL 5 /* N/A */ #define LED_ASSERTION 6 /* N/A */ #define LED_PANIC 7 /* N/A */ -#define LED_CPU 8 /* LED */ +#define LED_IDLE 8 /* LED */ /**************************************************************************** * Public Types diff --git a/boards/risc-v/qemu-rv/rv-virt/src/Makefile b/boards/risc-v/qemu-rv/rv-virt/src/Makefile index f49f361f52f97..fd727152ae172 100644 --- a/boards/risc-v/qemu-rv/rv-virt/src/Makefile +++ b/boards/risc-v/qemu-rv/rv-virt/src/Makefile @@ -22,7 +22,7 @@ include $(TOPDIR)/Make.defs RCSRCS = etc/init.d/rc.sysinit etc/init.d/rcS -CSRCS = qemu_rv_appinit.c +CSRCS = qemu_rv_appinit.c qemu_rv_autoleds.c qemu_rv_userleds.c ifeq ($(CONFIG_BUILD_KERNEL),y) ifeq ($(CONFIG_RISCV_SEMIHOSTING_HOSTFS),) diff --git a/boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_appinit.c b/boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_appinit.c index 357ecba97a8b8..4ea9de5ab217b 100644 --- a/boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_appinit.c +++ b/boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_appinit.c @@ -129,6 +129,17 @@ int board_app_initialize(uintptr_t arg) qemu_virtio_register_mmio_devices(); #endif +#ifdef CONFIG_USERLED + ////TODO: Move to bringup.c + /* Register the LED driver */ + + int ret = userled_lower_initialize("/dev/userleds"); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: userled_lower_initialize() failed: %d\n", ret); + } +#endif + return OK; #endif } diff --git a/boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_autoleds.c b/boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_autoleds.c new file mode 100644 index 0000000000000..4c3e784cbe4e1 --- /dev/null +++ b/boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_autoleds.c @@ -0,0 +1,250 @@ +/**************************************************************************** + * boards/arm64/a64/pinephone/src/pinephone_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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include +#include + +#include "chip.h" + +#ifdef CONFIG_ARCH_LEDS + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* LED index */ + +// static const uint32_t g_led_map[BOARD_LEDS] = +// { +// LED1, +// LED2, +// LED3 +// }; + +static bool g_initialized; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Turn on selected led */ + +static void qemu_led_on(led_typedef_enum led_num) +{ + ////TODO: gpio_write(g_led_map[led_num], true); +} + +/* Turn off selected led */ + +static void qemu_led_off(led_typedef_enum led_num) +{ + ////TODO: gpio_write(g_led_map[led_num], false); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_autoled_initialize + * + * Description: + * This function is called very early in initialization to perform board- + * specific initialization of LED-related resources. This includes such + * things as, for example, configure GPIO pins to drive the LEDs and also + * putting the LEDs in their correct initial state. + * + * NOTE: In most architectures, board_autoled_initialize() is called from + * board-specific initialization logic. But there are a few architectures + * where this initialization function is still called from common chip + * architecture logic. This interface is not, however, a common board + * interface in any event and, hence, the usage of the name + * board_autoled_initialize is deprecated. + * + * WARNING: This interface name will eventually be removed; do not use it + * in new board ports. New implementations should use the naming + * conventions for "Microprocessor-Specific Interfaces" or the "Board- + * Specific Interfaces" as described above. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void board_autoled_initialize(void) +{ + int i; + + /* Configure the LED GPIO for output. */ + + for (i = 0; i < BOARD_LEDS; i++) + { + ////TODO: int ret = gpio_config(g_led_map[i]); + ////TODO: DEBUGASSERT(ret == OK); + } +} + +/**************************************************************************** + * Name: board_autoled_on + * + * Description: + * Set the LED configuration into the ON condition for the state provided + * by the led parameter. This may be one of: + * + * LED_STARTED NuttX has been started + * LED_HEAPALLOCATE Heap has been allocated + * LED_IRQSENABLED Interrupts enabled + * LED_STACKCREATED Idle stack created + * LED_INIRQ In an interrupt + * LED_SIGNAL In a signal handler + * LED_ASSERTION An assertion failed + * LED_PANIC The system has crashed + * LED_IDLE MCU is in sleep mode + * + * Where these values are defined in a board-specific way in the standard + * board.h header file exported by every architecture. + * + * Input Parameters: + * led - Identifies the LED state to put in the ON state (which may or may + * not equate to turning an LED on) + * + * Returned Value: + * None + * + ****************************************************************************/ + +void board_autoled_on(int led) +{ + switch (led) + { + case LED_HEAPALLOCATE: + qemu_led_on(BOARD_LED1); + break; + + case LED_IRQSENABLED: + qemu_led_on(BOARD_LED2); + break; + + case LED_STACKCREATED: + qemu_led_on(BOARD_LED3); + g_initialized = true; + break; + + case LED_INIRQ: + qemu_led_on(BOARD_LED1); + qemu_led_on(BOARD_LED2); + break; + + case LED_SIGNAL: + qemu_led_on(BOARD_LED1); + qemu_led_on(BOARD_LED3); + break; + + case LED_ASSERTION: + qemu_led_on(BOARD_LED2); + qemu_led_on(BOARD_LED3); + break; + + case LED_PANIC: + qemu_led_on(BOARD_LED1); + break; + + case LED_IDLE: + qemu_led_on(BOARD_LED2); + break; + + default: + break; + } +} + +/**************************************************************************** + * Name: board_autoled_off + * + * Description: + * Set the LED configuration into the OFF condition for the state provided + * by the led parameter. This may be one of: + * + * LED_INIRQ Leaving an interrupt + * LED_SIGNAL Leaving a signal handler + * LED_ASSERTION Recovering from an assertion failure + * LED_PANIC The system has crashed (blinking). + * LED_IDLE MCU is not in sleep mode + * + * Where these values are defined in a board-specific way in the standard + * board.h header file exported by every architecture. + * + * Input Parameters: + * led - Identifies the LED state to put in the OFF state (which may or may + * not equate to turning an LED off) + * + * Returned Value: + * None + * + ****************************************************************************/ + +void board_autoled_off(int led) +{ + switch (led) + { + case LED_SIGNAL: + qemu_led_off(BOARD_LED1); + qemu_led_off(BOARD_LED3); + break; + + case LED_INIRQ: + qemu_led_off(BOARD_LED1); + qemu_led_off(BOARD_LED2); + break; + + case LED_ASSERTION: + qemu_led_off(BOARD_LED2); + qemu_led_off(BOARD_LED3); + break; + + case LED_PANIC: + qemu_led_off(BOARD_LED1); + break; + + case LED_IDLE: + qemu_led_off(BOARD_LED2); + break; + + default: + break; + } +} + +#endif /* CONFIG_ARCH_LEDS */ diff --git a/boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_userleds.c b/boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_userleds.c new file mode 100644 index 0000000000000..f407def28bf2c --- /dev/null +++ b/boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_userleds.c @@ -0,0 +1,188 @@ +/**************************************************************************** + * boards/arm64/a64/pinephone/src/pinephone_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 "chip.h" + +#ifdef CONFIG_USERLED + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* LED index */ + +// static const uint32_t g_led_map[BOARD_LEDS] = +// { +// LED1, +// LED2, +// LED3 +// }; + +static const uint32_t g_led_setmap[BOARD_LEDS] = +{ + BOARD_LED1_BIT, + BOARD_LED2_BIT, + BOARD_LED3_BIT +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_userled_initialize + * + * Description: + * This function may called from application-specific logic during its + * to perform board-specific initialization of LED resources. This + * includes such things as, for example, configure GPIO pins to drive the + * LEDs and also putting the LEDs in their correct initial state. + * + * If CONFIG_ARCH_LEDS is defined, then NuttX will control the on-board + * LEDs. If CONFIG_ARCH_LEDS is not defined, then this interfaces may be + * available to control the LEDs directly from user board logic or + * indirectly user applications (via the common LED character driver). + * + * Most boards have only a few LEDs and in those cases all LEDs may be + * used by the NuttX LED logic exclusively and may not be available for + * use by user logic if CONFIG_ARCH_LEDS=y. + * + * NOTE: The LED number is returned. + * + * Input Parameters: + * None + * + * Returned Value: + * Number of LEDs on board + * + ****************************************************************************/ + +uint32_t board_userled_initialize(void) +{ + int i; + + /* Configure the LED GPIO for output. */ + + for (i = 0; i < BOARD_LEDS; i++) + { + ////TODO: int ret = gpio_config(g_led_map[i]); + ////TODO: DEBUGASSERT(ret == OK); + } + + return BOARD_LEDS; +} + +/**************************************************************************** + * Name: board_userled + * + * Description: + * This interface may be used by application specific logic to set the + * state of a single LED. Definitions for the led identification are + * provided in the board-specific board.h header file that may be included + * like: + * + * #included + * + * If CONFIG_ARCH_LEDS is defined, then NuttX will control the on-board + * LEDs. If CONFIG_ARCH_LEDS is not defined, then this interfaces may be + * available to control the LEDs directly from user board logic or + * indirectly user applications (via the common LED character driver). + * + * Most boards have only a few LEDs and in those cases all LEDs may be + * used by the NuttX LED logic exclusively and may not be available for + * use by user logic if CONFIG_ARCH_LEDS=y. + * + * Input Parameters: + * led - LED number + * ledon - True if LED should be turned on; False to turn off + * + * Returned Value: + * None + * + ****************************************************************************/ + +void board_userled(int led, bool ledon) +{ + _info("led=%d, ledon=%d\n", led, ledon);//// + if ((unsigned)led < BOARD_LEDS) + { + ////TODO: gpio_write(g_led_map[led], ledon); + } +} + +/**************************************************************************** + * Name: board_userled_all + * + * Description: + * This interface may be used by application specific logic to set the + * state of all board LED. Definitions for the led set member + * identification is provided in the board-specific board.h header file + * that may be includedlike: + * + * #included + * + * If CONFIG_ARCH_LEDS is defined, then NuttX will control the on-board + * LEDs. If CONFIG_ARCH_LEDS is not defined, then this interfaces may be + * available to control the LEDs directly from user board logic or + * indirectly user applications (via the common LED character driver). + * + * Most boards have only a few LEDs and in those cases all LEDs may be + * used by the NuttX LED logic exclusively and may not be available for + * use by user logic if CONFIG_ARCH_LEDS=y. + * + * Input Parameters: + * ledset - Bitset of LEDs to be turned on and off + * + * Returned Value: + * None + * + ****************************************************************************/ + +void board_userled_all(uint32_t ledset) +{ + _info("ledset=0x%x\n", ledset);//// + int i; + + /* Configure LED1-3 GPIOs for output */ + + for (i = 0; i < BOARD_LEDS; i++) + { + bool val = ((ledset & g_led_setmap[i]) != 0); + _info("led=%d, val=%d\n", i, val);//// + ////TODO: gpio_write(g_led_map[i], (ledset & g_led_setmap[i]) != 0); + } +} + +#endif /* CONFIG_USERLED */