From 80f315f6d1c41c8932dd4538fb471e9d8932bda1 Mon Sep 17 00:00:00 2001 From: Dave VanKampen Date: Fri, 4 Feb 2022 07:52:45 -0500 Subject: [PATCH 1/2] examples/light_ws2812,pkg/light_ws812: added lightweight (assembly based) ws2812 package, and example app using it --- examples/light_ws2812/Makefile | 28 +++++++ examples/light_ws2812/README.md | 9 +++ examples/light_ws2812/main.c | 41 ++++++++++ pkg/light_ws2812/Makefile | 9 +++ pkg/light_ws2812/Makefile.dep | 4 + pkg/light_ws2812/Makefile.include | 1 + pkg/light_ws2812/doc.txt | 15 ++++ pkg/light_ws2812/light_ws2812.mk | 3 + ...m32g0-changes-for-RIOT-compatibility.patch | 75 +++++++++++++++++++ 9 files changed, 185 insertions(+) create mode 100644 examples/light_ws2812/Makefile create mode 100644 examples/light_ws2812/README.md create mode 100644 examples/light_ws2812/main.c create mode 100644 pkg/light_ws2812/Makefile create mode 100644 pkg/light_ws2812/Makefile.dep create mode 100644 pkg/light_ws2812/Makefile.include create mode 100644 pkg/light_ws2812/doc.txt create mode 100644 pkg/light_ws2812/light_ws2812.mk create mode 100644 pkg/light_ws2812/patches/0001-stm32g0-changes-for-RIOT-compatibility.patch diff --git a/examples/light_ws2812/Makefile b/examples/light_ws2812/Makefile new file mode 100644 index 000000000000..fb72b2d311f2 --- /dev/null +++ b/examples/light_ws2812/Makefile @@ -0,0 +1,28 @@ +# name of the application +APPLICATION = light_ws2812 + +# If no BOARD is found in the environment, use this default: +BOARD ?= nucleo-g070rb + +# This has to be the absolute path to the RIOT base directory: +RIOTBASE ?= $(CURDIR)/../.. + +# required packages +USEPKG += light_ws2812 +USEMODULE += xtimer +USEMODULE += random + +# Comment this out to disable code in RIOT that does safety checking +# which is not needed in a production environment but helps in the +# development process: +DEVELHELP ?= 1 + +# Change this to 0 show compiler invocation lines by default: +QUIET ?= 1 + +CFLAGS += -DLIGHT_WS2812_UC_STM32G0XX + +CFLAGS += -DLIGHT_WS2812_GPIO_PIN=7 +CFLAGS += -DLIGHT_WS2812_GPIO_PORT=GPIOA + +include $(RIOTBASE)/Makefile.include diff --git a/examples/light_ws2812/README.md b/examples/light_ws2812/README.md new file mode 100644 index 000000000000..ae9c33f2b20b --- /dev/null +++ b/examples/light_ws2812/README.md @@ -0,0 +1,9 @@ +light_ws2812 +============ + +Demonstrates using the light_ws2812 package to drive some LEDs + +Usage +===== + +Uses the random module to generate random numbers to write out to the LEDs diff --git a/examples/light_ws2812/main.c b/examples/light_ws2812/main.c new file mode 100644 index 000000000000..752a8380a4f5 --- /dev/null +++ b/examples/light_ws2812/main.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2022 BISSELL Homecare, Inc. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup examples + * @{ + * + * @file + * @brief light ws2812 example + * + * @author Dave VanKampen + * + * @} + */ + +#include +#include "light_ws2812_cortex.h" +#include "xtimer.h" +#include "random.h" +#define SEED 234 + +#define NUM_LEDS 5 +uint8_t leds[NUM_LEDS] = { 0x00}; +int main(void) +{ + puts("Generated RIOT application: 'light_ws2812'"); + random_init(SEED); + while(1) { + for (uint8_t idx = 0; idx < NUM_LEDS; idx++) { + leds[idx] = (uint8_t)random_uint32(); + } + ws2812_sendarray(leds, NUM_LEDS); + xtimer_usleep(50000); + } + return 0; +} diff --git a/pkg/light_ws2812/Makefile b/pkg/light_ws2812/Makefile new file mode 100644 index 000000000000..010e51b62e4c --- /dev/null +++ b/pkg/light_ws2812/Makefile @@ -0,0 +1,9 @@ +PKG_NAME=light_ws2812 +PKG_URL=https://github.com/cpldcpu/light_ws2812.git +PKG_VERSION=cd149996012fe96bc3d7883cb18a0103fd8e8b3a +PKG_LICENSE=GPL-3 + +include $(RIOTBASE)/pkg/pkg.mk + +all: + $(QQ)"$(MAKE)" -C $(PKG_SOURCE_DIR)/light_ws2812_ARM/ -f $(CURDIR)/$(PKG_NAME).mk diff --git a/pkg/light_ws2812/Makefile.dep b/pkg/light_ws2812/Makefile.dep new file mode 100644 index 000000000000..bd0a0dd0dfb2 --- /dev/null +++ b/pkg/light_ws2812/Makefile.dep @@ -0,0 +1,4 @@ +# Put the package dependencies here + +# required features +FEATURES_REQUIRED += periph_gpio diff --git a/pkg/light_ws2812/Makefile.include b/pkg/light_ws2812/Makefile.include new file mode 100644 index 000000000000..fde4c670d56c --- /dev/null +++ b/pkg/light_ws2812/Makefile.include @@ -0,0 +1 @@ +INCLUDES += -I$(PKGDIRBASE)/light_ws2812/light_ws2812_ARM diff --git a/pkg/light_ws2812/doc.txt b/pkg/light_ws2812/doc.txt new file mode 100644 index 000000000000..7c3eff6d7d75 --- /dev/null +++ b/pkg/light_ws2812/doc.txt @@ -0,0 +1,15 @@ +/** + * @defgroup pkg_light_ws2812 light_ws2812 + * @ingroup pkg + * @brief lightweight ws2811/2812 driver + * + * # Introduction + * + * Lightweight package for controlling ws281x LEDs + * + * # License + * + * Licensed under GPL-3. + * + * @see https://github.com/cpldcpu/light_ws2812.git + */ diff --git a/pkg/light_ws2812/light_ws2812.mk b/pkg/light_ws2812/light_ws2812.mk new file mode 100644 index 000000000000..bdd8925bf621 --- /dev/null +++ b/pkg/light_ws2812/light_ws2812.mk @@ -0,0 +1,3 @@ +MODULE = light_ws2812 + +include $(RIOTBASE)/Makefile.base diff --git a/pkg/light_ws2812/patches/0001-stm32g0-changes-for-RIOT-compatibility.patch b/pkg/light_ws2812/patches/0001-stm32g0-changes-for-RIOT-compatibility.patch new file mode 100644 index 000000000000..b81e5d4d8391 --- /dev/null +++ b/pkg/light_ws2812/patches/0001-stm32g0-changes-for-RIOT-compatibility.patch @@ -0,0 +1,75 @@ +From c5eaf14a5e26b0f325ab1edb9d0ac599f86519ba Mon Sep 17 00:00:00 2001 +From: Dave VanKampen +Date: Fri, 4 Feb 2022 10:18:39 -0500 +Subject: [PATCH] stm32g0 changes for RIOT compatibility + +--- + light_ws2812_ARM/light_ws2812_cortex.c | 4 ++-- + light_ws2812_ARM/light_ws2812_cortex.h | 14 ++++++++++++-- + 2 files changed, 14 insertions(+), 4 deletions(-) + +diff --git a/light_ws2812_ARM/light_ws2812_cortex.c b/light_ws2812_ARM/light_ws2812_cortex.c +index a183888..7a21340 100644 +--- a/light_ws2812_ARM/light_ws2812_cortex.c ++++ b/light_ws2812_ARM/light_ws2812_cortex.c +@@ -34,13 +34,13 @@ void ws2812_sendarray(uint8_t *data,int datlen) + uint32_t masklo = ws2812_mask_clr; + volatile uint32_t *set = ws2812_port_set; + volatile uint32_t *clr = ws2812_port_clr; +- uint32_t i; ++ uint32_t i = 0; + uint32_t curbyte; + + while (datlen--) { + curbyte=*data++; + +- asm volatile( ++ __asm__ volatile( + " lsl %[dat],#24 \n\t" + " movs %[ctr],#8 \n\t" + "ilop%=: \n\t" +diff --git a/light_ws2812_ARM/light_ws2812_cortex.h b/light_ws2812_ARM/light_ws2812_cortex.h +index 6c43cbe..c7389b3 100644 +--- a/light_ws2812_ARM/light_ws2812_cortex.h ++++ b/light_ws2812_ARM/light_ws2812_cortex.h +@@ -22,6 +22,9 @@ + #elif defined(LIGHT_WS2812_UC_STM32L0XX) + #include "stm32l0xx_hal.h" + #define LIGHT_WS2812_STM32 ++#elif defined(LIGHT_WS2812_UC_STM32G0XX) ++ #include "stm32g0xx.h" ++ #define LIGHT_WS2812_STM32 + #elif defined(LIGHT_WS2812_UC_FSL) + #include "fsl_port.h" + #include "fsl_gpio.h" +@@ -57,11 +60,16 @@ + #endif + #ifdef LIGHT_WS2812_STM32 + // This example is for STM32 family ++#if defined(LIGHT_WS2812_UC_STM32L0XX) + #define ws2812_port_set ((uint32_t*)&LIGHT_WS2812_GPIO_PORT->BSRR) // Address of the data port register to set the pin + #define ws2812_port_clr ((uint32_t*)&LIGHT_WS2812_GPIO_PORT->BRR) // Address of the data port register to clear the pin ++#elif defined(LIGHT_WS2812_UC_STM32G0XX) ++ #define ws2812_port_set ((uint32_t*)&LIGHT_WS2812_GPIO_PORT->BSRR) // Address of the data port register to set the pin ++ #define ws2812_port_clr ((uint32_t*)&LIGHT_WS2812_GPIO_PORT->BSRR) // Address of the data port register to clear the pin ++#endif + +- #define ws2812_mask_set LIGHT_WS2812_GPIO_PIN // Bitmask to set the data out pin +- #define ws2812_mask_clr LIGHT_WS2812_GPIO_PIN // Bitmask to clear the data out pin ++ #define ws2812_mask_set 1 << LIGHT_WS2812_GPIO_PIN // Bitmask to set the data out pin ++ #define ws2812_mask_clr 1 << (LIGHT_WS2812_GPIO_PIN+16) // Bitmask to clear the data out pin + #endif + #ifdef LIGHT_WS2812_FSL + // This example is for Freescale family +@@ -102,6 +110,8 @@ + // predictable code execution timing. + /////////////////////////////////////////////////////////////////////// + ++#include "clk.h" ++#define F_CPU CLOCK_CORECLOCK + #ifndef F_CPU + #error "Error: F_CPU (CPU clock speed) is not defined" + #endif +-- +2.25.1 + From 1b6738e1162ea74b8a5b6f1f4a7dfd1958258929 Mon Sep 17 00:00:00 2001 From: Dave VanKampen Date: Fri, 18 Feb 2022 13:15:39 -0500 Subject: [PATCH 2/2] drivers/ws281x: added arm backend, leveraging the light_ws2812 package --- drivers/ws281x/Makefile.dep | 6 ++++- drivers/ws281x/arm.c | 36 +++++++++++++++++++++++++ drivers/ws281x/include/ws281x_backend.h | 10 ++++++- examples/light_ws2812/main.c | 2 +- 4 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 drivers/ws281x/arm.c diff --git a/drivers/ws281x/Makefile.dep b/drivers/ws281x/Makefile.dep index 31f00f6c33f0..e763af0a014e 100644 --- a/drivers/ws281x/Makefile.dep +++ b/drivers/ws281x/Makefile.dep @@ -1,5 +1,5 @@ # Actually |(periph_timer_poll and periph_gpio_ll), but that's too complex for FEATURES_REQUIRED_ANY to express -FEATURES_REQUIRED_ANY += cpu_core_atmega|arch_esp32|arch_native|periph_timer_poll +FEATURES_REQUIRED_ANY += cpu_core_atmega|arch_esp32|arch_native|periph_timer_poll|arch_arm ifeq (,$(filter ws281x_%,$(USEMODULE))) ifneq (,$(filter cpu_core_atmega,$(FEATURES_USED))) @@ -15,6 +15,10 @@ ifeq (,$(filter ws281x_%,$(USEMODULE))) ifeq (-periph_timer_poll,$(filter ws281x_%,$(USEMODULE))-$(filter periph_timer_poll,$(FEATURES_USED))) USEMODULE += ws281x_timer_gpio_ll endif + ifneq (,$(filter arch_arm,$(FEATURES_USED))) + USEMODULE += ws281x_arm + USEPKG += light_ws2812 + endif endif ifneq (,$(filter ws281x_atmega,$(USEMODULE))) diff --git a/drivers/ws281x/arm.c b/drivers/ws281x/arm.c new file mode 100644 index 000000000000..2f13b765c2bb --- /dev/null +++ b/drivers/ws281x/arm.c @@ -0,0 +1,36 @@ +/* + * Copyright 2022 BISSELL Homecare, Inc. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup drivers_ws281x + * + * @{ + * + * @file + * @brief Implementation of `ws281x_write_buffer()` for the ARM CPU + * + * @author David VanKampen + * + * @} + */ +#include +#include +#include +#include + +#include "ws281x.h" +#include "ws281x_params.h" +#include "ws281x_constants.h" + +#include "light_ws2812_cortex.h" + +void ws281x_write_buffer(ws281x_t *dev, const void *buf, size_t size) +{ + assert(dev); + ws2812_sendarray((uint8_t*)buf, size); +} diff --git a/drivers/ws281x/include/ws281x_backend.h b/drivers/ws281x/include/ws281x_backend.h index 01f74fb87789..6f165c1711cd 100644 --- a/drivers/ws281x/include/ws281x_backend.h +++ b/drivers/ws281x/include/ws281x_backend.h @@ -56,7 +56,15 @@ extern "C" { * @{ */ #ifdef MODULE_WS281X_TIMER_GPIO_LL -#define WS281X_HAVE_INIT (1) +#define WS281X_HAVE_INIT (1) +#endif +/** @} */ + +/** + * @name Properties of the ARM backend. + * @{ + */ +#ifdef MODULE_WS281X_ARM #endif /** @} */ diff --git a/examples/light_ws2812/main.c b/examples/light_ws2812/main.c index 752a8380a4f5..fbec9b0630db 100644 --- a/examples/light_ws2812/main.c +++ b/examples/light_ws2812/main.c @@ -30,7 +30,7 @@ int main(void) { puts("Generated RIOT application: 'light_ws2812'"); random_init(SEED); - while(1) { + while (1) { for (uint8_t idx = 0; idx < NUM_LEDS; idx++) { leds[idx] = (uint8_t)random_uint32(); }