From e26d8523a45a4172bbb3c4c4f632e43f260755fe Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Fri, 21 Oct 2022 07:20:49 +0200 Subject: [PATCH] pkg/tinyusb: add nRF52 support --- pkg/tinyusb/Kconfig | 7 ++ pkg/tinyusb/Makefile | 3 + pkg/tinyusb/Makefile.dep | 3 + pkg/tinyusb/Makefile.include | 7 ++ pkg/tinyusb/Makefile.nrf52 | 5 ++ pkg/tinyusb/hw/hw_nrf52.c | 71 +++++++++++++++ pkg/tinyusb/hw/include/nrf52/nrf_clock.h | 109 +++++++++++++++++++++++ 7 files changed, 205 insertions(+) create mode 100644 pkg/tinyusb/Makefile.nrf52 create mode 100644 pkg/tinyusb/hw/hw_nrf52.c create mode 100644 pkg/tinyusb/hw/include/nrf52/nrf_clock.h diff --git a/pkg/tinyusb/Kconfig b/pkg/tinyusb/Kconfig index b7fd952987..1ccf9da5a6 100644 --- a/pkg/tinyusb/Kconfig +++ b/pkg/tinyusb/Kconfig @@ -38,6 +38,8 @@ menuconfig PACKAGE_TINYUSB select MODULE_TINYUSB_PORTABLE_MICROCHIP if CPU_FAM_SAMD21 || CPU_FAM_SAMR21 \ || CPU_COMMON_SAMD5X || CPU_FAM_SAML21 || CPU_FAM_SAMR34 \ || CPU_FAM_SAMR30 + select MODULE_TINYUSB_PORTABLE_NRF5X if CPU_FAM_NRF52 + select PACKAGE_NRFX if CPU_FAM_NRF52 select MODULE_ZTIMER_MSEC help tinyUSB is an open-source cross-platform USB Host/Device stack for @@ -101,6 +103,11 @@ config MODULE_TINYUSB_PORTABLE_MICROCHIP help tinyUSB Microchip SAM0 driver is used +config MODULE_TINYUSB_PORTABLE_NRF5X + bool + help + tinyUSB nRFx device driver is used + menu "Device Classes" config MODULE_TINYUSB_CLASS_AUDIO bool "Audio Class 2.0 (UAC2)" diff --git a/pkg/tinyusb/Makefile b/pkg/tinyusb/Makefile index c72a1bdf55..f4947cafd7 100644 --- a/pkg/tinyusb/Makefile +++ b/pkg/tinyusb/Makefile @@ -74,6 +74,9 @@ tinyusb_portable_espressif: tinyusb_portable_microchip: $(QQ)"$(MAKE)" -C $(PSRC)/portable/microchip/samd -f $(RIOTBASE)/Makefile.base MODULE=$@ +tinyusb_portable_nrf5x: + $(QQ)"$(MAKE)" -C $(PSRC)/portable/nordic/nrf5x -f $(RIOTPKG)/$(PKG_NAME)/Makefile.nrf52 + tinyusb_portable_stm32_fsdev: $(QQ)"$(MAKE)" -C $(PSRC)/portable/st/stm32_fsdev -f $(RIOTBASE)/Makefile.base MODULE=$@ diff --git a/pkg/tinyusb/Makefile.dep b/pkg/tinyusb/Makefile.dep index 40f58a25c2..a702e0d718 100644 --- a/pkg/tinyusb/Makefile.dep +++ b/pkg/tinyusb/Makefile.dep @@ -54,6 +54,9 @@ endif # tinyUSB hardware driver selection ifneq (,$(filter esp32s2 esp32s3,$(CPU_FAM))) USEMODULE += tinyusb_portable_espressif +else ifeq (nrf52,$(CPU)) + USEPKG += nrfx + USEMODULE += tinyusb_portable_nrf5x else ifneq (,$(filter saml21 samd5x samd21,$(CPU))) USEMODULE += tinyusb_portable_microchip else ifeq (stm32,$(CPU)) diff --git a/pkg/tinyusb/Makefile.include b/pkg/tinyusb/Makefile.include index 8794bbbae4..ed7debf349 100644 --- a/pkg/tinyusb/Makefile.include +++ b/pkg/tinyusb/Makefile.include @@ -10,6 +10,13 @@ ifeq (esp32s2,$(CPU_FAM)) CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_ESP32S2 else ifeq (esp32s3,$(CPU_FAM)) CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_ESP32S3 +else ifeq (nrf52,$(CPU)) + CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_NRF5X + CFLAGS += -Wno-cast-align + CFLAGS += -Wno-unused-parameter + INCLUDES += -I$(PKGDIRBASE)/nrfx/hal + INCLUDES += -I$(PKGDIRBASE)/nrfx/drivers/include + INCLUDES += -I$(PKGDIRBASE)/nrfx/drivers/src else ifeq (stm32,$(CPU)) CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_STM32$(call uppercase_and_underscore,$(CPU_FAM)) else ifeq (saml21,$(CPU)) diff --git a/pkg/tinyusb/Makefile.nrf52 b/pkg/tinyusb/Makefile.nrf52 new file mode 100644 index 0000000000..e34774e1f6 --- /dev/null +++ b/pkg/tinyusb/Makefile.nrf52 @@ -0,0 +1,5 @@ +MODULE = tinyusb_portable_nrf5x + +INCLUDES := -I$(RIOTBASE)/pkg/tinyusb/hw/include/nrf52 $(INCLUDES) + +include $(RIOTBASE)/Makefile.base diff --git a/pkg/tinyusb/hw/hw_nrf52.c b/pkg/tinyusb/hw/hw_nrf52.c new file mode 100644 index 0000000000..2aa1ac5416 --- /dev/null +++ b/pkg/tinyusb/hw/hw_nrf52.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2022 Gunar Schorcht + * + * 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 pkg_tinyusb + * @brief + * @{ + * + * @brief tinyUSB hardware driver for nRF52 MCUs + * @author Gunar Schorcht + */ + +#include + +#include "periph_conf.h" +#include "periph/gpio.h" +#include "periph/pm.h" + +#include "tusb.h" +#include "device/usbd.h" +#include "host/usbh.h" + +/* + * Definition of events as used by the tinyusb/portable/nordic/nrf5x/dcd_nrf5x.c + * https://github.com/hathach/tinyusb/blob/0.14.0/src/portable/nordic/nrf5x/dcd_nrf5x.c#L954 + */ +#define USB_EVT_DETECTED 0 +#define USB_EVT_REMOVED 1 +#define USB_EVT_READY 2 + +int tinyusb_hw_init(void) +{ + if (IS_USED(MODULE_TINYUSB_DEVICE)) { + NVIC_SetPriority(USBD_IRQn, 2); + } + + extern void tusb_hal_nrf_power_event(uint32_t event); + + if ( NRF_POWER->USBREGSTATUS & POWER_USBREGSTATUS_VBUSDETECT_Msk ) { + tusb_hal_nrf_power_event(USB_EVT_DETECTED); + } + + /* it requires some time to activate the clock */ + ztimer_sleep(ZTIMER_MSEC, 1); + + if ( NRF_POWER->USBREGSTATUS & POWER_USBREGSTATUS_OUTPUTRDY_Msk ) { + tusb_hal_nrf_power_event(USB_EVT_READY); + } + + return 0; +} + +void isr_usbd(void) +{ + /* call device interrupt handler with the first device */ + if (IS_USED(MODULE_TINYUSB_DEVICE)) { + tud_int_handler(0); + } + + /* call host interrupt handler with the first device */ + if (IS_USED(MODULE_TINYUSB_HOST)) { + tuh_int_handler(0); + } + + cortexm_isr_end(); +} diff --git a/pkg/tinyusb/hw/include/nrf52/nrf_clock.h b/pkg/tinyusb/hw/include/nrf52/nrf_clock.h new file mode 100644 index 0000000000..4ec451ec27 --- /dev/null +++ b/pkg/tinyusb/hw/include/nrf52/nrf_clock.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2022 Gunar Schorcht + * + * 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 pkg_tinyusb + * @brief + * @{ + * + * @brief nRF52 specific clock definitions as required by tinyUSB + * + * RIOT does not use the clock module from `pkg/nrfx/drivers`. Therefore + * the part of the clock module interface needed by tinyUSB in + * `tinyusb/src/portable/nordic/dcd_nrf5x.c` has to be defined explicitly. + * + * @author Gunar Schorcht + */ + +#ifndef NRF52_NRF_CLOCK_H +#define NRF52_NRF_CLOCK_H + +#include + +#include "nrf.h" +#include_next "nrf_clock.h" + +#if !DOXYGEN + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRF_CLOCK_HFCLK_HIGH_ACCURACY (1UL) +#define NRF_CLOCK_EVENT_HFCLKSTARTED offsetof(NRF_CLOCK_Type, EVENTS_HFCLKSTARTED) + +typedef enum { + NRF_CLOCK_TASK_HFCLKSTART, + NRF_CLOCK_TASK_HFCLKSTOP, +} nrf_clock_task_t; + +/** + * @brief Status HF clock acitvation/deactivation in `dcd_nrf52.c` + * + * The `clock_hfxo_request` and `clock_hfxo_release` functions are used in + * RIOT to enable/disable the HF clock if necessary. Since `hfclk_enable` + * in `tinyusb/src/portable/nordic/dcd_nrf5x.c` activates the RF clock only + * if it is not already running, the status of the RF clock cannot be + * determined via registers. It therefore needs its own static variable + * that holds the current state of activation/deactivation by the function + * `nrf_clock_task_trigger`. + */ +static bool _nrf_clock_hf_running = false; + +/** + * @brief Check whether HF clock is running + */ +static inline bool nrf_clock_hf_is_running(NRF_CLOCK_Type const *reg, + uint32_t clk_src) +{ + + return _nrf_clock_hf_running; +} + +/** + * @brief Clear a specific event + * + * This function is not required in RIOT, it is therefore defined as dummy + * function. + */ +static inline bool nrf_clock_event_clear(NRF_CLOCK_Type *reg, uint32_t event) +{ + (void)reg; + (void)event; + return true; +} + +/** + * @brief Function used in tinyUSB to start and stop the HF clock + * + * This function is mapped to `clock_hfxo_request`/`clock_hfxo_release` in RIOT. + */ +static inline void nrf_clock_task_trigger(NRF_CLOCK_Type *reg, + nrf_clock_task_t task) +{ + switch (task) { + case NRF_CLOCK_TASK_HFCLKSTART: + clock_hfxo_request(); + _nrf_clock_hf_running = true; + break; + case NRF_CLOCK_TASK_HFCLKSTOP: + clock_hfxo_release(); + _nrf_clock_hf_running = false; + break; + default: + break; + } +} + +#ifdef __cplusplus +} +#endif + +#endif /* !DOXYGEN */ +#endif /* NRF52_NRF_CLOCK_H */ +/** @} */