From 76bf6285c1a0d7f82450b3ab06df67f8d6f874e3 Mon Sep 17 00:00:00 2001 From: Rushabh Gala <88271018+rushabhvg@users.noreply.github.com> Date: Tue, 23 Jul 2024 22:41:52 +0530 Subject: [PATCH] risc-v/qemu-rv: Add LED Driver for QEMU RISC-V 32-bit and 64-bit - This PR adds the LED Driver for QEMU RISC-V 32-bit and 64-bit (User LEDs and Auto LEDs) - QEMU RISC-V LED Driver will be used by the Rust Blinky App for Google Summer of Code - Blinking the LED is probably the most common Embedded Demo, and now it's supported by QEMU RISC-V - We added NuttX Configs `rv-virt:leds` and `rv-virt:leds64` to support User LEDs for 32-bit and 64-bit RISC-V - Turning on/off a Simulated User LED will print a log message: "LED 1 set to 1" - The code is derived from NuttX PinePhone LED Driver --- .../risc-v/qemu-rv/boards/rv-virt/index.rst | 10 ++ boards/Kconfig | 1 + .../qemu-rv/rv-virt/configs/leds/defconfig | 71 ++++++++ .../qemu-rv/rv-virt/configs/leds64/defconfig | 75 ++++++++ boards/risc-v/qemu-rv/rv-virt/include/board.h | 18 ++ .../risc-v/qemu-rv/rv-virt/src/CMakeLists.txt | 8 + boards/risc-v/qemu-rv/rv-virt/src/Makefile | 8 + .../qemu-rv/rv-virt/src/qemu_rv_appinit.c | 14 ++ .../qemu-rv/rv-virt/src/qemu_rv_autoleds.c | 145 +++++++++++++++ .../qemu-rv/rv-virt/src/qemu_rv_userleds.c | 165 ++++++++++++++++++ 10 files changed, 515 insertions(+) create mode 100644 boards/risc-v/qemu-rv/rv-virt/configs/leds/defconfig create mode 100644 boards/risc-v/qemu-rv/rv-virt/configs/leds64/defconfig 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/Documentation/platforms/risc-v/qemu-rv/boards/rv-virt/index.rst b/Documentation/platforms/risc-v/qemu-rv/boards/rv-virt/index.rst index 522947a2e0..fe7fc02ca6 100644 --- a/Documentation/platforms/risc-v/qemu-rv/boards/rv-virt/index.rst +++ b/Documentation/platforms/risc-v/qemu-rv/boards/rv-virt/index.rst @@ -229,6 +229,16 @@ ksmp64 Identical to the `knsh64`_ configuration but with SMP support. +leds +---- + +Similar to the `nsh`_ configuration, but with User LEDs support for 32-bit RISC-V. + +leds64 +------ + +Similar to the `nsh64`_ configuration, but with User LEDs support for 64-bit RISC-V. + netnsh ------ diff --git a/boards/Kconfig b/boards/Kconfig index b657e74c9b..8b5259417b 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -1993,6 +1993,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/leds/defconfig b/boards/risc-v/qemu-rv/rv-virt/configs/leds/defconfig new file mode 100644 index 0000000000..21155e96bf --- /dev/null +++ b/boards/risc-v/qemu-rv/rv-virt/configs/leds/defconfig @@ -0,0 +1,71 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_DISABLE_OS_API is not set +# CONFIG_NSH_DISABLE_LOSMART is not set +CONFIG_16550_ADDRWIDTH=0 +CONFIG_16550_UART0=y +CONFIG_16550_UART0_BASE=0x10000000 +CONFIG_16550_UART0_CLOCK=3686400 +CONFIG_16550_UART0_IRQ=37 +CONFIG_16550_UART0_SERIAL_CONSOLE=y +CONFIG_16550_UART=y +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="rv-virt" +CONFIG_ARCH_BOARD_QEMU_RV_VIRT=y +CONFIG_ARCH_CHIP="qemu-rv" +CONFIG_ARCH_CHIP_QEMU_RV32=y +CONFIG_ARCH_CHIP_QEMU_RV=y +CONFIG_ARCH_CHIP_QEMU_RV_ISA_A=y +CONFIG_ARCH_CHIP_QEMU_RV_ISA_C=y +CONFIG_ARCH_CHIP_QEMU_RV_ISA_M=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARDCTL_POWEROFF=y +CONFIG_BOARD_LATE_INITIALIZE=y +CONFIG_BOARD_LOOPSPERMSEC=6366 +CONFIG_BUILTIN=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEV_ZERO=y +CONFIG_ELF=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_EXAMPLES_LEDS=y +CONFIG_FS_HOSTFS=y +CONFIG_FS_PROCFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_LIBC_ENVPATH=y +CONFIG_LIBC_EXECFUNCS=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_LIBM=y +CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_PATH_INITIAL="/system/bin" +CONFIG_RAM_SIZE=33554432 +CONFIG_RAM_START=0x80000000 +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_RISCV_SEMIHOSTING_HOSTFS=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_SERIAL_UART_ARCH_MMIO=y +CONFIG_STACK_COLORATION=y +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2021 +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_SYSTEM_NSH=y +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y +CONFIG_USEC_PER_TICK=1000 +CONFIG_USERLED=y +CONFIG_USERLED_LOWER=y diff --git a/boards/risc-v/qemu-rv/rv-virt/configs/leds64/defconfig b/boards/risc-v/qemu-rv/rv-virt/configs/leds64/defconfig new file mode 100644 index 0000000000..4b2dbb55ba --- /dev/null +++ b/boards/risc-v/qemu-rv/rv-virt/configs/leds64/defconfig @@ -0,0 +1,75 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_DISABLE_OS_API is not set +# CONFIG_NSH_DISABLE_LOSMART is not set +CONFIG_16550_ADDRWIDTH=0 +CONFIG_16550_UART0=y +CONFIG_16550_UART0_BASE=0x10000000 +CONFIG_16550_UART0_CLOCK=3686400 +CONFIG_16550_UART0_IRQ=37 +CONFIG_16550_UART0_SERIAL_CONSOLE=y +CONFIG_16550_UART=y +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="rv-virt" +CONFIG_ARCH_BOARD_QEMU_RV_VIRT=y +CONFIG_ARCH_CHIP="qemu-rv" +CONFIG_ARCH_CHIP_QEMU_RV64=y +CONFIG_ARCH_CHIP_QEMU_RV=y +CONFIG_ARCH_CHIP_QEMU_RV_ISA_A=y +CONFIG_ARCH_CHIP_QEMU_RV_ISA_C=y +CONFIG_ARCH_CHIP_QEMU_RV_ISA_M=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BCH=y +CONFIG_BOARDCTL_POWEROFF=y +CONFIG_BOARD_LATE_INITIALIZE=y +CONFIG_BOARD_LOOPSPERMSEC=6366 +CONFIG_BUILTIN=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEVICE_TREE=y +CONFIG_DEV_ZERO=y +CONFIG_ELF=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_EXAMPLES_LEDS=y +CONFIG_FS_HOSTFS=y +CONFIG_FS_PROCFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_STACKSIZE=3072 +CONFIG_LIBC_ENVPATH=y +CONFIG_LIBC_EXECFUNCS=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_LIBM=y +CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_PATH_INITIAL="/system/bin" +CONFIG_RAM_SIZE=33554432 +CONFIG_RAM_START=0x80000000 +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_RISCV_SEMIHOSTING_HOSTFS=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_SERIAL_UART_ARCH_MMIO=y +CONFIG_STACK_COLORATION=y +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2021 +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_NSH_STACKSIZE=3072 +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y +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 d90390b151..17c984d11c 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,24 @@ * Pre-processor Definitions ****************************************************************************/ +/* LED definitions **********************************************************/ + +/* LED index values for use with board_userled() */ + +typedef enum +{ + BOARD_LED1 = 0, + BOARD_LED2 = 1, + BOARD_LED3 = 2, + 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) + #define LED_STARTED 0 /* N/A */ #define LED_HEAPALLOCATE 1 /* N/A */ #define LED_IRQSENABLED 2 /* N/A */ diff --git a/boards/risc-v/qemu-rv/rv-virt/src/CMakeLists.txt b/boards/risc-v/qemu-rv/rv-virt/src/CMakeLists.txt index f33cd75cef..e5f78691fd 100644 --- a/boards/risc-v/qemu-rv/rv-virt/src/CMakeLists.txt +++ b/boards/risc-v/qemu-rv/rv-virt/src/CMakeLists.txt @@ -20,6 +20,14 @@ set(SRCS qemu_rv_appinit.c) +if(CONFIG_ARCH_LEDS) + list(APPEND SRCS qemu_rv_autoleds.c) +endif() + +if(CONFIG_USERLED) + list(APPEND SRCS qemu_rv_userleds.c) +endif() + target_sources(board PRIVATE ${SRCS}) if(CONFIG_ARCH_CHIP_QEMU_RV) diff --git a/boards/risc-v/qemu-rv/rv-virt/src/Makefile b/boards/risc-v/qemu-rv/rv-virt/src/Makefile index f49f361f52..5c26c9a86d 100644 --- a/boards/risc-v/qemu-rv/rv-virt/src/Makefile +++ b/boards/risc-v/qemu-rv/rv-virt/src/Makefile @@ -30,6 +30,14 @@ CSRCS += $(if $(wildcard romfs_boot.c), romfs_boot.c, romfs_stub.c) endif endif +ifeq ($(CONFIG_ARCH_LEDS),y) +CSRCS += qemu_rv_autoleds.c +endif + +ifeq ($(CONFIG_USERLED),y) +CSRCS += qemu_rv_userleds.c +endif + include $(TOPDIR)/boards/Board.mk # don't use single-colon targets as they may coflict with those included ones. 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 fb3292a84a..fc4bd3f4b6 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 @@ -43,6 +43,10 @@ #include "riscv_internal.h" #include "romfs.h" +#ifdef CONFIG_USERLED +#include +#endif + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -181,6 +185,16 @@ void board_late_initialize(void) mount(NULL, "/proc", "procfs", 0, NULL); #endif + +#ifdef CONFIG_USERLED + /* 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 } #ifdef CONFIG_BOARDCTL_POWEROFF 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 0000000000..d82f6910b8 --- /dev/null +++ b/boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_autoleds.c @@ -0,0 +1,145 @@ +/**************************************************************************** + * boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_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 + +/**************************************************************************** + * 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) +{ +} + +/**************************************************************************** + * 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) +{ + /* This stub is required for supporting User LEDs */ + + UNUSED(led); +} + +/**************************************************************************** + * 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) +{ + /* This stub is required for supporting User LEDs */ + + UNUSED(led); +} + +#endif /* CONFIG_ARCH_LEDS */ \ No newline at end of file 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 0000000000..867b3242b5 --- /dev/null +++ b/boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_userleds.c @@ -0,0 +1,165 @@ +/**************************************************************************** + * boards/risc-v/qemu-rv/rv-virt/src/qemu_rv_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 + ****************************************************************************/ + +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) +{ + 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) +{ + if ((unsigned)led < BOARD_LEDS) + { + _info("LED %d set to %d\n", led + 1, ledon ? 1 : 0); + } +} + +/**************************************************************************** + * 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) +{ + int i; + + for (i = 0; i < BOARD_LEDS; i++) + { + bool val = ((ledset & g_led_setmap[i]) != 0); + + board_userled(i, val); + } +} + +#endif /* CONFIG_USERLED */ \ No newline at end of file