1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/pkg/tinyusb/hw/hw_stm32_fsdev.c

102 lines
2.7 KiB
C

/*
* 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 STM32 MCUs with USB FS device port
* @author Gunar Schorcht <gunar@schorcht.net>
*/
#include <errno.h>
#include "periph_conf.h"
#include "periph/gpio.h"
#include "pm_layered.h"
#include "tusb.h"
#include "device/usbd.h"
#include "host/usbh.h"
static int tinyusb_hw_init_dev(const stm32_usbdev_fs_config_t *conf)
{
/* Block both STOP and STANDBY, TODO STOP is unblocked during USB suspend
* status */
pm_block(STM32_PM_STOP);
pm_block(STM32_PM_STANDBY);
/* Enable the clock to the peripheral */
periph_clk_en(conf->apb, conf->rcc_mask);
#if defined(PWR_CR2_USV)
/* Validate USB Supply */
PWR->CR2 |= PWR_CR2_USV;
#endif
#if defined(RCC_APB1SMENR_USBSMEN)
RCC->APB1SMENR |= RCC_APB1SMENR_USBSMEN;
#elif defined(RCC_APB1SMENR1_USBSMEN)
RCC->APB1SMENR1 |= RCC_APB1SMENR1_USBSMEN;
#endif
#if defined(CRS_CR_AUTOTRIMEN) && defined(CRS_CR_CEN)
/* Enable CRS with auto trim enabled */
CRS->CR |= (CRS_CR_AUTOTRIMEN | CRS_CR_CEN);
#endif
if (conf->af == GPIO_AF_UNDEF && conf->disconn == GPIO_UNDEF) {
/* If the MCU does not have an internal D+ pullup and there is no
* dedicated GPIO on the board to simulate a USB disconnect, the D+ GPIO
* is temporarily configured as an output and pushed down to simulate
* a disconnect/connect cycle to allow the host to recognize the device.
* This requires an external pullup on D+ signal to work. */
gpio_init(conf->dp, GPIO_OUT);
gpio_clear(conf->dp);
/* wait about a ms */
ztimer_sleep(ZTIMER_MSEC, 1);
gpio_init(conf->dp, GPIO_IN);
}
if (conf->af != GPIO_AF_UNDEF) {
/* Configure AF for the pins */
gpio_init_af(conf->dp, conf->af);
gpio_init_af(conf->dm, conf->af);
}
if (conf->disconn != GPIO_UNDEF) {
/* In case the MCU has no internal D+ pullup, a GPIO is used to
* connect/disconnect from USB bus */
gpio_init(conf->disconn, GPIO_OUT);
gpio_set(conf->disconn);
}
return 0;
}
int tinyusb_hw_init(void)
{
for (unsigned i = 0; i < USBDEV_NUMOF; i++) {
if (tinyusb_hw_init_dev(&stm32_usbdev_fs_config[i]) != 0) {
return -ENODEV;
}
}
return 0;
}
void USBDEV_ISR(void)
{
/* call device interrupt handler with the last device */
if (IS_USED(MODULE_TINYUSB_DEVICE)) {
tud_int_handler(TINYUSB_TUD_RHPORT);
}
cortexm_isr_end();
}