diff options
Diffstat (limited to 'bsp/at32/libraries/rt_drivers')
| -rw-r--r-- | bsp/at32/libraries/rt_drivers/SConscript | 16 | ||||
| -rw-r--r-- | bsp/at32/libraries/rt_drivers/config/f403a_407/usb_config.h | 69 | ||||
| -rw-r--r-- | bsp/at32/libraries/rt_drivers/config/f413/usb_config.h | 69 | ||||
| -rw-r--r-- | bsp/at32/libraries/rt_drivers/config/f415/usb_config.h | 95 | ||||
| -rw-r--r-- | bsp/at32/libraries/rt_drivers/config/f425/usb_config.h | 95 | ||||
| -rw-r--r-- | bsp/at32/libraries/rt_drivers/config/f435_437/usb_config.h | 135 | ||||
| -rw-r--r-- | bsp/at32/libraries/rt_drivers/drv_config.h | 7 | ||||
| -rw-r--r-- | bsp/at32/libraries/rt_drivers/drv_usart_v2.c | 447 | ||||
| -rw-r--r-- | bsp/at32/libraries/rt_drivers/drv_usart_v2.h | 28 | ||||
| -rw-r--r-- | bsp/at32/libraries/rt_drivers/drv_usbd.c | 274 | ||||
| -rw-r--r-- | bsp/at32/libraries/rt_drivers/drv_usbd.h | 27 | ||||
| -rw-r--r-- | bsp/at32/libraries/rt_drivers/drv_usbfs.h | 28 | ||||
| -rw-r--r-- | bsp/at32/libraries/rt_drivers/drv_usbfsd.c | 311 | ||||
| -rw-r--r-- | bsp/at32/libraries/rt_drivers/drv_usbfsh.c | 406 |
14 files changed, 2004 insertions, 3 deletions
diff --git a/bsp/at32/libraries/rt_drivers/SConscript b/bsp/at32/libraries/rt_drivers/SConscript index 2e96d36ac5..434174e117 100644 --- a/bsp/at32/libraries/rt_drivers/SConscript +++ b/bsp/at32/libraries/rt_drivers/SConscript @@ -16,8 +16,11 @@ if GetDepend(['RT_USING_PIN']): if GetDepend(['RT_USING_WDT']): src += ['drv_wdt.c'] -if GetDepend(['BSP_USING_SERIAL']): - src += ['drv_usart.c'] +if GetDepend(['RT_USING_SERIAL']): + if GetDepend(['RT_USING_SERIAL_V2']): + src += ['drv_usart_v2.c'] + else: + src += ['drv_usart.c'] if GetDepend(['BSP_USING_PWM']): src += ['drv_pwm.c'] @@ -59,6 +62,15 @@ if GetDepend(['BSP_USING_CAN']): if GetDepend(['BSP_USING_SDIO']): src += ['drv_sdio.c'] +if GetDepend(['BSP_USING_USBD']): + src += ['drv_usbd.c'] + +if GetDepend(['BSP_USING_DEVICE_USBFS1']) or GetDepend(['BSP_USING_DEVICE_USBFS2']): + src += ['drv_usbfsd.c'] + +if GetDepend(['BSP_USING_HOST_USBFS1']) or GetDepend(['BSP_USING_HOST_USBFS2']): + src += ['drv_usbfsh.c'] + path = [cwd] path += [cwd + '/config'] diff --git a/bsp/at32/libraries/rt_drivers/config/f403a_407/usb_config.h b/bsp/at32/libraries/rt_drivers/config/f403a_407/usb_config.h new file mode 100644 index 0000000000..6c7e8fcabc --- /dev/null +++ b/bsp/at32/libraries/rt_drivers/config/f403a_407/usb_config.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-28 leo first version + */ + +#ifndef __USB_CONFIG_H__ +#define __USB_CONFIG_H__ + +#include <rtthread.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* usb irqhandler */ +#define USB_IRQHandler USBFS_L_CAN1_RX0_IRQHandler + +/** + * @brief usb endpoint number + */ +#define USB_EPT_MAX_NUM 8 + +/** + * @brief auto malloc usb endpoint buffer + */ +#define USB_EPT_AUTO_MALLOC_BUFFER + +#ifndef USB_EPT_AUTO_MALLOC_BUFFER +#define EPT0_TX_ADDR 0x40 +#define EPT0_RX_ADDR 0x80 +#define EPT1_TX_ADDR 0xC0 +#define EPT1_RX_ADDR 0x100 +#define EPT2_TX_ADDR 0x140 +#define EPT2_RX_ADDR 0x180 +#define EPT3_TX_ADDR 0x00 +#define EPT3_RX_ADDR 0x00 +#define EPT4_TX_ADDR 0x00 +#define EPT4_RX_ADDR 0x00 +#define EPT5_TX_ADDR 0x00 +#define EPT5_RX_ADDR 0x00 +#define EPT6_TX_ADDR 0x00 +#define EPT6_RX_ADDR 0x00 +#define EPT7_TX_ADDR 0x00 +#define EPT7_RX_ADDR 0x00 +#endif + +/** + * @brief usb low power wakeup handler enable + */ +#define USB_LOW_POWER_WAKUP + +#if defined(BSP_USING_USBD) +#define USBD_CONFIG \ + { \ + .name = "usbd", \ + .irqn = USBFS_L_CAN1_RX0_IRQn, \ + } +#endif /* BSP_USING_USBD */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/at32/libraries/rt_drivers/config/f413/usb_config.h b/bsp/at32/libraries/rt_drivers/config/f413/usb_config.h new file mode 100644 index 0000000000..6c7e8fcabc --- /dev/null +++ b/bsp/at32/libraries/rt_drivers/config/f413/usb_config.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-28 leo first version + */ + +#ifndef __USB_CONFIG_H__ +#define __USB_CONFIG_H__ + +#include <rtthread.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* usb irqhandler */ +#define USB_IRQHandler USBFS_L_CAN1_RX0_IRQHandler + +/** + * @brief usb endpoint number + */ +#define USB_EPT_MAX_NUM 8 + +/** + * @brief auto malloc usb endpoint buffer + */ +#define USB_EPT_AUTO_MALLOC_BUFFER + +#ifndef USB_EPT_AUTO_MALLOC_BUFFER +#define EPT0_TX_ADDR 0x40 +#define EPT0_RX_ADDR 0x80 +#define EPT1_TX_ADDR 0xC0 +#define EPT1_RX_ADDR 0x100 +#define EPT2_TX_ADDR 0x140 +#define EPT2_RX_ADDR 0x180 +#define EPT3_TX_ADDR 0x00 +#define EPT3_RX_ADDR 0x00 +#define EPT4_TX_ADDR 0x00 +#define EPT4_RX_ADDR 0x00 +#define EPT5_TX_ADDR 0x00 +#define EPT5_RX_ADDR 0x00 +#define EPT6_TX_ADDR 0x00 +#define EPT6_RX_ADDR 0x00 +#define EPT7_TX_ADDR 0x00 +#define EPT7_RX_ADDR 0x00 +#endif + +/** + * @brief usb low power wakeup handler enable + */ +#define USB_LOW_POWER_WAKUP + +#if defined(BSP_USING_USBD) +#define USBD_CONFIG \ + { \ + .name = "usbd", \ + .irqn = USBFS_L_CAN1_RX0_IRQn, \ + } +#endif /* BSP_USING_USBD */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/at32/libraries/rt_drivers/config/f415/usb_config.h b/bsp/at32/libraries/rt_drivers/config/f415/usb_config.h new file mode 100644 index 0000000000..8fedb30599 --- /dev/null +++ b/bsp/at32/libraries/rt_drivers/config/f415/usb_config.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-28 leo first version + */ + +#ifndef __USB_CONFIG_H__ +#define __USB_CONFIG_H__ + +#include <rtthread.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined BSP_USING_DEVICE_USBFS1 +#define USE_OTG_DEVICE_MODE +#endif + +#if defined BSP_USING_HOST_USBFS1 +#define USE_OTG_HOST_MODE +#endif + +/* usbfs irqhandler */ +#define OTGFS1_IRQHandler OTGFS1_IRQHandler + +/** + * @brief usb device mode config + */ +#define USB_EPT_MAX_NUM 4 + +/* otg1 device fifo */ +#define USBD_RX_SIZE 128 +#define USBD_EP0_TX_SIZE 24 +#define USBD_EP1_TX_SIZE 20 +#define USBD_EP2_TX_SIZE 20 +#define USBD_EP3_TX_SIZE 20 +#define USBD_EP4_TX_SIZE 20 +#define USBD_EP5_TX_SIZE 20 +#define USBD_EP6_TX_SIZE 20 +#define USBD_EP7_TX_SIZE 20 + +/** + * @brief usb host mode config + */ +#define USB_HOST_CHANNEL_NUM 8 + +/* otg1 host fifo */ +#define USBH_RX_FIFO_SIZE 128 +#define USBH_NP_TX_FIFO_SIZE 96 +#define USBH_P_TX_FIFO_SIZE 96 + +/** + * @brief usb sof output enable + */ +// #define USB_SOF_OUTPUT_ENABLE + +/** + * @brief usb vbus ignore, not use vbus pin + */ +#define USB_VBUS_IGNORE + +/** + * @brief usb low power wakeup handler enable + */ +// #define USB_LOW_POWER_WAKUP + +#if defined(BSP_USING_HOST_USBFS1) +#undef BSP_USING_DEVICE_USBFS1 +#define USBFS1_CONFIG \ + { \ + .name = "usbh", \ + .id = USB_OTG1_ID, \ + .irqn = OTGFS1_IRQn, \ + } +#endif /* BSP_USING_HOST_USBFS1 */ + +#if defined(BSP_USING_DEVICE_USBFS1) +#define USBFS1_CONFIG \ + { \ + .name = "usbd", \ + .id = USB_OTG1_ID, \ + .irqn = OTGFS1_IRQn, \ + } +#endif /* BSP_USING_DEVICE_USBFS1 */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/at32/libraries/rt_drivers/config/f425/usb_config.h b/bsp/at32/libraries/rt_drivers/config/f425/usb_config.h new file mode 100644 index 0000000000..90ea5ae9c0 --- /dev/null +++ b/bsp/at32/libraries/rt_drivers/config/f425/usb_config.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-28 leo first version + */ + +#ifndef __USB_CONFIG_H__ +#define __USB_CONFIG_H__ + +#include <rtthread.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined BSP_USING_DEVICE_USBFS1 +#define USE_OTG_DEVICE_MODE +#endif + +#if defined BSP_USING_HOST_USBFS1 +#define USE_OTG_HOST_MODE +#endif + +/* usbfs irqhandler */ +#define OTGFS1_IRQHandler OTGFS1_IRQHandler + +/** + * @brief usb device mode config + */ +#define USB_EPT_MAX_NUM 8 + +/* otg1 device fifo */ +#define USBD_RX_SIZE 128 +#define USBD_EP0_TX_SIZE 24 +#define USBD_EP1_TX_SIZE 20 +#define USBD_EP2_TX_SIZE 20 +#define USBD_EP3_TX_SIZE 20 +#define USBD_EP4_TX_SIZE 20 +#define USBD_EP5_TX_SIZE 20 +#define USBD_EP6_TX_SIZE 20 +#define USBD_EP7_TX_SIZE 20 + +/** + * @brief usb host mode config + */ +#define USB_HOST_CHANNEL_NUM 16 + +/* otg1 host fifo */ +#define USBH_RX_FIFO_SIZE 128 +#define USBH_NP_TX_FIFO_SIZE 96 +#define USBH_P_TX_FIFO_SIZE 96 + +/** + * @brief usb sof output enable + */ +// #define USB_SOF_OUTPUT_ENABLE + +/** + * @brief usb vbus ignore, not use vbus pin + */ +#define USB_VBUS_IGNORE + +/** + * @brief usb low power wakeup handler enable + */ +// #define USB_LOW_POWER_WAKUP + +#if defined(BSP_USING_HOST_USBFS1) +#undef BSP_USING_DEVICE_USBFS1 +#define USBFS1_CONFIG \ + { \ + .name = "usbh", \ + .id = USB_OTG1_ID, \ + .irqn = OTGFS1_IRQn, \ + } +#endif /* BSP_USING_HOST_USBFS1 */ + +#if defined(BSP_USING_DEVICE_USBFS1) +#define USBFS1_CONFIG \ + { \ + .name = "usbd", \ + .id = USB_OTG1_ID, \ + .irqn = OTGFS1_IRQn, \ + } +#endif /* BSP_USING_DEVICE_USBFS1 */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/at32/libraries/rt_drivers/config/f435_437/usb_config.h b/bsp/at32/libraries/rt_drivers/config/f435_437/usb_config.h new file mode 100644 index 0000000000..93d69f33d9 --- /dev/null +++ b/bsp/at32/libraries/rt_drivers/config/f435_437/usb_config.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-28 leo first version + */ + +#ifndef __USB_CONFIG_H__ +#define __USB_CONFIG_H__ + +#include <rtthread.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined BSP_USING_DEVICE_USBFS1 || defined BSP_USING_DEVICE_USBFS2 +#define USE_OTG_DEVICE_MODE +#endif + +#if defined BSP_USING_HOST_USBFS1 || defined BSP_USING_HOST_USBFS2 +#define USE_OTG_HOST_MODE +#endif + +/* usbfs irqhandler */ +#define OTGFS1_IRQHandler OTGFS1_IRQHandler +#define OTGFS2_IRQHandler OTGFS2_IRQHandler + +/** + * @brief usb device mode config + */ +#define USB_EPT_MAX_NUM 8 + +/* otg1 device fifo */ +#define USBD_RX_SIZE 128 +#define USBD_EP0_TX_SIZE 24 +#define USBD_EP1_TX_SIZE 20 +#define USBD_EP2_TX_SIZE 20 +#define USBD_EP3_TX_SIZE 20 +#define USBD_EP4_TX_SIZE 20 +#define USBD_EP5_TX_SIZE 20 +#define USBD_EP6_TX_SIZE 20 +#define USBD_EP7_TX_SIZE 20 + +/* otg2 device fifo */ +#define USBD2_RX_SIZE 128 +#define USBD2_EP0_TX_SIZE 24 +#define USBD2_EP1_TX_SIZE 20 +#define USBD2_EP2_TX_SIZE 20 +#define USBD2_EP3_TX_SIZE 20 +#define USBD2_EP4_TX_SIZE 20 +#define USBD2_EP5_TX_SIZE 20 +#define USBD2_EP6_TX_SIZE 20 +#define USBD2_EP7_TX_SIZE 20 + +/** + * @brief usb host mode config + */ +#define USB_HOST_CHANNEL_NUM 16 + +/* otg1 host fifo */ +#define USBH_RX_FIFO_SIZE 128 +#define USBH_NP_TX_FIFO_SIZE 96 +#define USBH_P_TX_FIFO_SIZE 96 + +/* otg2 host fifo */ +#define USBH2_RX_FIFO_SIZE 128 +#define USBH2_NP_TX_FIFO_SIZE 96 +#define USBH2_P_TX_FIFO_SIZE 96 + +/** + * @brief usb sof output enable + */ +// #define USB_SOF_OUTPUT_ENABLE + +/** + * @brief usb vbus ignore, not use vbus pin + */ +#define USB_VBUS_IGNORE + +/** + * @brief usb low power wakeup handler enable + */ +// #define USB_LOW_POWER_WAKUP + +#if defined(BSP_USING_HOST_USBFS1) +#undef BSP_USING_HOST_USBFS2 +#undef BSP_USING_DEVICE_USBFS1 +#define USBFS1_CONFIG \ + { \ + .name = "usbh1", \ + .id = USB_OTG1_ID, \ + .irqn = OTGFS1_IRQn, \ + } +#endif /* BSP_USING_HOST_USBFS1 */ + +#if defined(BSP_USING_DEVICE_USBFS1) +#undef BSP_USING_DEVICE_USBFS2 +#define USBFS1_CONFIG \ + { \ + .name = "usbd", \ + .id = USB_OTG1_ID, \ + .irqn = OTGFS1_IRQn, \ + } +#endif /* BSP_USING_DEVICE_USBFS1 */ + +#if defined(BSP_USING_HOST_USBFS2) +#undef BSP_USING_HOST_USBFS1 +#undef BSP_USING_DEVICE_USBFS2 +#define USBFS2_CONFIG \ + { \ + .name = "usbh2", \ + .id = USB_OTG2_ID, \ + .irqn = OTGFS2_IRQn, \ + } +#endif /* BSP_USING_HOST_USBFS2 */ + +#if defined(BSP_USING_DEVICE_USBFS2) +#undef BSP_USING_DEVICE_USBFS1 +#define USBFS2_CONFIG \ + { \ + .name = "usbd", \ + .id = USB_OTG2_ID, \ + .irqn = OTGFS2_IRQn, \ + } +#endif /* BSP_USING_DEVICE_USBFS2 */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/at32/libraries/rt_drivers/drv_config.h b/bsp/at32/libraries/rt_drivers/drv_config.h index 0fb96ef4f7..f8b8079c69 100644 --- a/bsp/at32/libraries/rt_drivers/drv_config.h +++ b/bsp/at32/libraries/rt_drivers/drv_config.h @@ -12,8 +12,8 @@ #ifndef __DRV_CONFIG_H__ #define __DRV_CONFIG_H__ -#include <board.h> #include <rtthread.h> +#include "drv_common.h" #ifdef __cplusplus extern "C" { @@ -23,14 +23,17 @@ extern "C" { #include "f403a_407/dma_config.h" #include "f403a_407/uart_config.h" #include "f403a_407/spi_config.h" +#include "f403a_407/usb_config.h" #elif defined(SOC_SERIES_AT32F413) #include "f413/dma_config.h" #include "f413/uart_config.h" #include "f413/spi_config.h" +#include "f413/usb_config.h" #elif defined(SOC_SERIES_AT32F415) #include "f415/dma_config.h" #include "f415/uart_config.h" #include "f415/spi_config.h" +#include "f415/usb_config.h" #elif defined(SOC_SERIES_AT32F421) #include "f421/dma_config.h" #include "f421/uart_config.h" @@ -39,10 +42,12 @@ extern "C" { #include "f425/dma_config.h" #include "f425/uart_config.h" #include "f425/spi_config.h" +#include "f425/usb_config.h" #elif defined(SOC_SERIES_AT32F435) || defined (SOC_SERIES_AT32F437) #include "f435_437/dma_config.h" #include "f435_437/uart_config.h" #include "f435_437/spi_config.h" +#include "f435_437/usb_config.h" #endif #ifdef __cplusplus diff --git a/bsp/at32/libraries/rt_drivers/drv_usart_v2.c b/bsp/at32/libraries/rt_drivers/drv_usart_v2.c new file mode 100644 index 0000000000..820bfa12f3 --- /dev/null +++ b/bsp/at32/libraries/rt_drivers/drv_usart_v2.c @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-23 Jonas first version + */ + +#include "drv_usart_v2.h" + +#ifdef RT_USING_SERIAL_V2 +#if !defined(BSP_USING_UART1) && !defined(BSP_USING_UART2) && \ + !defined(BSP_USING_UART3) && !defined(BSP_USING_UART4) && \ + !defined(BSP_USING_UART5) && !defined(BSP_USING_UART6) && \ + !defined(BSP_USING_UART7) && !defined(BSP_USING_UART8) + #error "Please define at least one BSP_USING_UARTx" +#endif + +enum +{ +#ifdef BSP_USING_UART1 + UART1_INDEX, +#endif +#ifdef BSP_USING_UART2 + UART2_INDEX, +#endif +#ifdef BSP_USING_UART3 + UART3_INDEX, +#endif +#ifdef BSP_USING_UART4 + UART4_INDEX, +#endif +#ifdef BSP_USING_UART5 + UART5_INDEX, +#endif +#ifdef BSP_USING_UART6 + UART6_INDEX, +#endif +#ifdef BSP_USING_UART7 + UART7_INDEX, +#endif +#ifdef BSP_USING_UART8 + UART8_INDEX, +#endif +}; + +static struct at32_usart usart_config[] = +{ +#ifdef BSP_USING_UART1 + { + "uart1", + USART1, + USART1_IRQn, + }, +#endif +#ifdef BSP_USING_UART2 + { + "uart2", + USART2, + USART2_IRQn, + }, +#endif +#ifdef BSP_USING_UART3 + { + "uart3", + USART3, + USART3_IRQn, + }, +#endif +#ifdef BSP_USING_UART4 + { + "uart4", + UART4, + UART4_IRQn, + }, +#endif +#ifdef BSP_USING_UART5 + { + "uart5", + UART5, + UART5_IRQn, + }, +#endif +#ifdef BSP_USING_UART6 + { + "uart6", + USART6, + USART6_IRQn, + }, +#endif +#ifdef BSP_USING_UART7 + { + "uart7", + UART7, + UART7_IRQn, + }, +#endif +#ifdef BSP_USING_UART8 + { + "uart8", + UART8, + UART8_IRQn, + }, +#endif +}; + +static rt_err_t at32_configure(struct rt_serial_device *serial, + struct serial_configure *cfg) +{ + struct at32_usart *usart_instance = (struct at32_usart *) serial->parent.user_data; + usart_data_bit_num_type data_bit; + usart_stop_bit_num_type stop_bit; + usart_parity_selection_type parity_mode; + + RT_ASSERT(serial != RT_NULL); + RT_ASSERT(cfg != RT_NULL); + + RT_ASSERT(usart_instance != RT_NULL); + + at32_msp_usart_init((void *)usart_instance->usart_x); + + usart_receiver_enable(usart_instance->usart_x, TRUE); + usart_transmitter_enable(usart_instance->usart_x, TRUE); + + usart_hardware_flow_control_set(usart_instance->usart_x, USART_HARDWARE_FLOW_NONE); + + switch (cfg->data_bits) + { + case DATA_BITS_8: + data_bit = USART_DATA_8BITS; + break; + case DATA_BITS_9: + data_bit = USART_DATA_9BITS; + break; + default: + data_bit = USART_DATA_8BITS; + break; + } + + switch (cfg->stop_bits) + { + case STOP_BITS_1: + stop_bit = USART_STOP_1_BIT; + break; + case STOP_BITS_2: + stop_bit = USART_STOP_2_BIT; + break; + default: + stop_bit = USART_STOP_1_BIT; + break; + } + + switch (cfg->parity) + { + case PARITY_NONE: + parity_mode = USART_PARITY_NONE; + break; + case PARITY_ODD: + parity_mode = USART_PARITY_ODD; + break; + case PARITY_EVEN: + parity_mode = USART_PARITY_EVEN; + break; + default: + parity_mode = USART_PARITY_NONE; + break; + } + usart_parity_selection_config(usart_instance->usart_x, parity_mode); + usart_init(usart_instance->usart_x, cfg->baud_rate, data_bit, stop_bit); + usart_enable(usart_instance->usart_x, TRUE); + + return RT_EOK; +} + +static rt_err_t at32_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + struct at32_usart *usart; + + rt_ubase_t ctrl_arg = (rt_ubase_t)arg; + + RT_ASSERT(serial != RT_NULL); + usart = (struct at32_usart *) serial->parent.user_data; + RT_ASSERT(usart != RT_NULL); + + if (ctrl_arg & (RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_RX_NON_BLOCKING)) + { + ctrl_arg = RT_DEVICE_FLAG_INT_RX; + } + else if (ctrl_arg & (RT_DEVICE_FLAG_TX_BLOCKING | RT_DEVICE_FLAG_TX_NON_BLOCKING)) + { + ctrl_arg = RT_DEVICE_FLAG_INT_TX; + } + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: + nvic_irq_disable(usart->irqn); + if (ctrl_arg == RT_DEVICE_FLAG_INT_RX) + usart_interrupt_enable(usart->usart_x, USART_RDBF_INT, FALSE); + else if (ctrl_arg == RT_DEVICE_FLAG_INT_TX) + usart_interrupt_enable(usart->usart_x, USART_TDBE_INT, FALSE); + break; + case RT_DEVICE_CTRL_SET_INT: + nvic_irq_enable(usart->irqn, 4, 1); + if (ctrl_arg == RT_DEVICE_FLAG_INT_RX) + usart_interrupt_enable(usart->usart_x, USART_RDBF_INT, TRUE); + else if (ctrl_arg == RT_DEVICE_FLAG_INT_TX) + usart_interrupt_enable(usart->usart_x, USART_TDBE_INT, TRUE); + break; + case RT_DEVICE_CTRL_CONFIG: + at32_control(serial, RT_DEVICE_CTRL_SET_INT, (void *)ctrl_arg); + break; + case RT_DEVICE_CHECK_OPTMODE: + { + return RT_SERIAL_TX_BLOCKING_BUFFER; + } + case RT_DEVICE_CTRL_CLOSE: + usart_reset(usart->usart_x); + break; + } + + return RT_EOK; +} + +static int at32_putc(struct rt_serial_device *serial, char ch) +{ + struct at32_usart *usart; + + RT_ASSERT(serial != RT_NULL); + usart = (struct at32_usart *) serial->parent.user_data; + RT_ASSERT(usart != RT_NULL); + + usart_data_transmit(usart->usart_x, (uint8_t)ch); + while (usart_flag_get(usart->usart_x, USART_TDC_FLAG) == RESET); + + return 1; +} + +static int at32_getc(struct rt_serial_device *serial) +{ + int ch; + struct at32_usart *usart; + + RT_ASSERT(serial != RT_NULL); + usart = (struct at32_usart *) serial->parent.user_data; + RT_ASSERT(usart != RT_NULL); + + ch = -1; + if (usart_flag_get(usart->usart_x, USART_RDBF_FLAG) != RESET) + { + ch = usart_data_receive(usart->usart_x) & 0xff; + } + + return ch; +} + +static rt_size_t at32_transmit(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, rt_uint32_t tx_flag) +{ + RT_ASSERT(serial != RT_NULL); + RT_ASSERT(buf != RT_NULL); + + at32_control(serial, RT_DEVICE_CTRL_SET_INT, (void *)tx_flag); + + return size; +} + +static const struct rt_uart_ops at32_usart_ops = +{ + at32_configure, + at32_control, + at32_putc, + at32_getc, + at32_transmit +}; + +static void usart_isr(struct rt_serial_device *serial) +{ + struct at32_usart *usart_instance; + + RT_ASSERT(serial != RT_NULL); + + usart_instance = (struct at32_usart *) serial->parent.user_data; + RT_ASSERT(usart_instance != RT_NULL); + + if (usart_flag_get(usart_instance->usart_x, USART_RDBF_FLAG) != RESET) + { + struct rt_serial_rx_fifo *rx_fifo; + rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx; + RT_ASSERT(rx_fifo != RT_NULL); + + rt_ringbuffer_putchar(&(rx_fifo->rb), usart_data_receive(usart_instance->usart_x)); + + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); + } + else + { + if ((usart_flag_get(usart_instance->usart_x, USART_TDBE_FLAG) != RESET) && usart_instance->usart_x->ctrl1_bit.tdbeien) + { + struct rt_serial_tx_fifo *tx_fifo; + tx_fifo = (struct rt_serial_tx_fifo *) serial->serial_tx; + RT_ASSERT(tx_fifo != RT_NULL); + + rt_uint8_t put_char = 0; + if (rt_ringbuffer_getchar(&(tx_fifo->rb), &put_char)) + { + usart_data_transmit(usart_instance->usart_x, put_char); + } + else + { + usart_interrupt_enable(usart_instance->usart_x, USART_TDBE_INT, FALSE); + usart_interrupt_enable(usart_instance->usart_x, USART_TDC_INT, TRUE); + } + usart_flag_clear(usart_instance->usart_x, USART_TDBE_FLAG); + } + else if (usart_flag_get(usart_instance->usart_x, USART_TDC_FLAG) != RESET) + { + + usart_interrupt_enable(usart_instance->usart_x, USART_TDC_INT, FALSE); + + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DONE); + + usart_flag_clear(usart_instance->usart_x, USART_TDC_FLAG); + } + if (usart_flag_get(usart_instance->usart_x, USART_CTSCF_FLAG) != RESET) + { + usart_flag_clear(usart_instance->usart_x, USART_CTSCF_FLAG); + } + + if (usart_flag_get(usart_instance->usart_x, USART_BFF_FLAG) != RESET) + { + usart_flag_clear(usart_instance->usart_x, USART_BFF_FLAG); + } + + } +} + +#ifdef BSP_USING_UART1 +void USART1_IRQHandler(void) +{ + rt_interrupt_enter(); + + usart_isr(&usart_config[UART1_INDEX].serial); + + rt_interrupt_leave(); +} +#endif +#ifdef BSP_USING_UART2 +void USART2_IRQHandler(void) +{ + rt_interrupt_enter(); + + usart_isr(&usart_config[UART2_INDEX].serial); + + rt_interrupt_leave(); +} +#endif +#ifdef BSP_USING_UART3 +void USART3_IRQHandler(void) +{ + rt_interrupt_enter(); + + usart_isr(&usart_config[UART3_INDEX].serial); + + rt_interrupt_leave(); +} +#endif +#ifdef BSP_USING_UART4 +void UART4_IRQHandler(void) +{ + rt_interrupt_enter(); + + usart_isr(&usart_config[UART4_INDEX].serial); + + rt_interrupt_leave(); +} +#endif +#ifdef BSP_USING_UART5 +void UART5_IRQHandler(void) +{ + rt_interrupt_enter(); + + usart_isr(&usart_config[UART5_INDEX].serial); + + rt_interrupt_leave(); +} +#endif +#ifdef BSP_USING_UART6 +void USART6_IRQHandler(void) +{ + rt_interrupt_enter(); + + usart_isr(&usart_config[UART6_INDEX].serial); + + rt_interrupt_leave(); +} +#endif +#ifdef BSP_USING_UART7 +void UART7_IRQHandler(void) +{ + rt_interrupt_enter(); + + usart_isr(&usart_config[UART7_INDEX].serial); + + rt_interrupt_leave(); +} +#endif +#ifdef BSP_USING_UART8 +void UART8_IRQHandler(void) +{ + rt_interrupt_enter(); + + usart_isr(&usart_config[UART8_INDEX].serial); + + rt_interrupt_leave(); +} +#endif + +int rt_hw_usart_init(void) +{ + rt_size_t obj_num; + int index; + + obj_num = sizeof(usart_config) / sizeof(struct at32_usart); + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + rt_err_t result = 0; + + for (index = 0; index < obj_num; index++) + { + usart_config[index].serial.config = config; + usart_config[index].serial.ops = &at32_usart_ops; + + /* register uart device */ + result = rt_hw_serial_register(&usart_config[index].serial, + usart_config[index].name, + RT_DEVICE_FLAG_RDWR | + RT_DEVICE_FLAG_INT_RX | + RT_DEVICE_FLAG_INT_TX, + &usart_config[index]); + RT_ASSERT(result == RT_EOK); + } + + return result; +} + +#endif /* RT_USING_SERIAL_V2 */ diff --git a/bsp/at32/libraries/rt_drivers/drv_usart_v2.h b/bsp/at32/libraries/rt_drivers/drv_usart_v2.h new file mode 100644 index 0000000000..1fe1cf24ee --- /dev/null +++ b/bsp/at32/libraries/rt_drivers/drv_usart_v2.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-23 Jonas first version + */ + +#ifndef __DRV_USART_V2_H__ +#define __DRV_USART_V2_H__ + +#include <rtthread.h> +#include <rtdevice.h> +#include <drv_common.h> + +struct at32_usart +{ + char *name; + usart_type *usart_x; + IRQn_Type irqn; + struct rt_serial_device serial; +}; + +int rt_hw_usart_init(void); + +#endif /* __DRV_USART_V2_H__ */ diff --git a/bsp/at32/libraries/rt_drivers/drv_usbd.c b/bsp/at32/libraries/rt_drivers/drv_usbd.c new file mode 100644 index 0000000000..25541f85fb --- /dev/null +++ b/bsp/at32/libraries/rt_drivers/drv_usbd.c @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-28 leo first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include "usbd_int.h" +#include "drv_common.h" +#include "drv_usbd.h" +#include "drv_config.h" + +#if defined(BSP_USING_USBD) + +static struct at32_usbd *p_usbd_instance = NULL; +static struct ep_id endpoint_pool[] = +{ + {0x0, USB_EP_ATTR_CONTROL, USB_DIR_INOUT, 64, ID_ASSIGNED }, + {0x1, USB_EP_ATTR_BULK, USB_DIR_IN, 64, ID_UNASSIGNED}, + {0x1, USB_EP_ATTR_BULK, USB_DIR_OUT, 64, ID_UNASSIGNED}, + {0x2, USB_EP_ATTR_INT, USB_DIR_IN, 64, ID_UNASSIGNED}, + {0x2, USB_EP_ATTR_INT, USB_DIR_OUT, 64, ID_UNASSIGNED}, + {0x3, USB_EP_ATTR_ISOC, USB_DIR_IN, 64, ID_UNASSIGNED}, + {0x3, USB_EP_ATTR_ISOC, USB_DIR_OUT, 64, ID_UNASSIGNED}, + {0xFF, USB_EP_ATTR_TYPE_MASK, USB_DIR_MASK, 0, ID_ASSIGNED }, +}; + +enum +{ +#ifdef BSP_USING_USBD + USBD1_INDEX, +#endif +}; + +static struct at32_usbd usbd_config[] = { +#ifdef BSP_USING_USBD + USBD_CONFIG, +#endif +}; + +void USB_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + usbd_irq_handler(p_usbd_instance->p_usbd_core); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +void usbd_reset_callback(usbd_core_type *udev) +{ + udcd_t udcd = (udcd_t)udev->pdata; + rt_usbd_reset_handler(udcd); +} + +void usbd_connectCallback(usbd_core_type *udev) +{ + udcd_t udcd = (udcd_t)udev->pdata; + rt_usbd_connect_handler(udcd); +} + +void usbd_disconnectCallback(usbd_core_type *udev) +{ + udcd_t udcd = (udcd_t)udev->pdata; + rt_usbd_disconnect_handler(udcd); +} + +void usbd_setup_phase_done_callback(usbd_core_type *udev) +{ + udcd_t udcd = (udcd_t)udev->pdata; + rt_usbd_ep0_setup_handler(udcd, (struct urequest*)udev->setup_buffer); +} + +void usbd_data_in_stage_callback(usbd_core_type *udev, uint32_t ept_num) +{ + udcd_t udcd = (udcd_t)udev->pdata; + + if (ept_num == 0) + { + rt_usbd_ep0_in_handler(udcd); + } + else + { + rt_usbd_ep_in_handler(udcd, 0x80 | ept_num, udev->ept_in[ept_num].trans_len); + } +} + +void usbd_sof_callback(usbd_core_type *udev) +{ + udcd_t udcd = (udcd_t)udev->pdata; + rt_usbd_sof_handler(udcd); +} + +void usbd_data_out_stage_callback(usbd_core_type *udev, uint32_t ept_num) +{ + udcd_t udcd = (udcd_t)udev->pdata; + + if (ept_num != 0) + { + rt_usbd_ep_out_handler(udcd, ept_num, udev->ept_out[ept_num].trans_len); + } + else + { + rt_usbd_ep0_out_handler(udcd, udev->ept_out[0].trans_len); + } +} + +static rt_err_t _ep_set_stall(rt_uint8_t address) +{ + usbd_set_stall(p_usbd_instance->p_usbd_core, address); + return RT_EOK; +} + +static rt_err_t _ep_clear_stall(rt_uint8_t address) +{ + usbd_clear_stall(p_usbd_instance->p_usbd_core, address); + return RT_EOK; +} + +static rt_err_t _set_address(rt_uint8_t address) +{ + usbd_set_device_addr(p_usbd_instance->p_usbd_core, address); + return RT_EOK; +} + +static rt_err_t _set_config(rt_uint8_t address) +{ + return RT_EOK; +} + +static rt_err_t _ep_enable(uep_t ep) +{ + RT_ASSERT(ep != RT_NULL); + RT_ASSERT(ep->ep_desc != RT_NULL); + + usbd_ept_open(p_usbd_instance->p_usbd_core, ep->ep_desc->bEndpointAddress, ep->ep_desc->bmAttributes, ep->ep_desc->wMaxPacketSize); + return RT_EOK; +} + +static rt_err_t _ep_disable(uep_t ep) +{ + RT_ASSERT(ep != RT_NULL); + RT_ASSERT(ep->ep_desc != RT_NULL); + usbd_ept_close(p_usbd_instance->p_usbd_core, ep->ep_desc->bEndpointAddress); + return RT_EOK; +} + +static rt_size_t _ep_read(rt_uint8_t address, void *buffer) +{ + rt_size_t size = 0; + RT_ASSERT(buffer != RT_NULL); + return size; +} + +static rt_size_t _ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size) +{ + usbd_ept_recv(p_usbd_instance->p_usbd_core, address, buffer, size); + return size; +} + +static rt_size_t _ep_write(rt_uint8_t address, void *buffer, rt_size_t size) +{ + usbd_ept_send(p_usbd_instance->p_usbd_core, address, buffer, size); + return size; +} + +static rt_err_t _ep0_send_status(void) +{ + usbd_ctrl_send_status(p_usbd_instance->p_usbd_core); + return RT_EOK; +} + +static rt_err_t _suspend(void) +{ + return RT_EOK; +} + +static rt_err_t _wakeup(void) +{ + return RT_EOK; +} + +static rt_err_t at32_dcd_init(rt_device_t device) +{ + /* usb gpio config */ + at32_msp_usb_init(device); + + /* enable usb interrupt */ + nvic_irq_enable(p_usbd_instance->irqn, 2, 0); + + /* usb core init */ + usbd_core_init(p_usbd_instance->p_usbd_core, USB, 0); + + /* enable usb pull-up */ + usbd_connect(p_usbd_instance->p_usbd_core); + + return RT_EOK; +} + +const static struct udcd_ops _udc_ops = +{ + _set_address, + _set_config, + _ep_set_stall, + _ep_clear_stall, + _ep_enable, + _ep_disable, + _ep_read_prepare, + _ep_read, + _ep_write, + _ep0_send_status, + _suspend, + _wakeup, +}; + +int at32_usbd_register(void) +{ + rt_size_t obj_num; + rt_err_t result = 0; + int index; + + obj_num = sizeof(usbd_config) / sizeof(struct at32_usbd); + + for (index = 0; index < obj_num; index++) { + udcd_t udcd = (udcd_t)rt_malloc(sizeof(struct udcd)); + if (udcd == RT_NULL) + { + rt_kprintf("udcd malloc failed\r\n"); + return -RT_ERROR; + } + rt_memset((void *)udcd, 0, sizeof(struct udcd)); + + usbd_core_type *p_usbd_core = (usbd_core_type *)rt_malloc(sizeof(usbd_core_type)); + if (p_usbd_core == RT_NULL) + { + rt_kprintf("usbd_core malloc failed\r\n"); + return -RT_ERROR; + } + rt_memset((void *)p_usbd_core, 0, sizeof(usbd_core_type)); + + udcd->parent.type = RT_Device_Class_USBDevice; + udcd->parent.init = at32_dcd_init; + + udcd->parent.user_data = p_usbd_core; + udcd->ops = &_udc_ops; + p_usbd_core->pdata = udcd; + usbd_config[index].p_usbd_core = p_usbd_core; + + /* register endpoint infomation */ + udcd->ep_pool = endpoint_pool; + udcd->ep0.id = &endpoint_pool[0]; + + result = rt_device_register((rt_device_t)udcd, usbd_config[index].name, 0); + RT_ASSERT(result == RT_EOK); + + p_usbd_instance = &usbd_config[index]; + + result = rt_usb_device_init(); + RT_ASSERT(result == RT_EOK); + } + + return result; +} + +INIT_DEVICE_EXPORT(at32_usbd_register); + +#endif diff --git a/bsp/at32/libraries/rt_drivers/drv_usbd.h b/bsp/at32/libraries/rt_drivers/drv_usbd.h new file mode 100644 index 0000000000..5406537026 --- /dev/null +++ b/bsp/at32/libraries/rt_drivers/drv_usbd.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-28 shelton first version + */ + +#ifndef __DRV_USBD_H__ +#define __DRV_USBD_H__ + +#include <rtthread.h> +#include <rtdevice.h> +#include "drv_common.h" +#include "usbd_core.h" + +struct at32_usbd { + char *name; + usbd_core_type *p_usbd_core; + IRQn_Type irqn; +}; + +#endif /* __DRV_USBD_H__ */ + +/******************* end of file *******************/ diff --git a/bsp/at32/libraries/rt_drivers/drv_usbfs.h b/bsp/at32/libraries/rt_drivers/drv_usbfs.h new file mode 100644 index 0000000000..52d205da27 --- /dev/null +++ b/bsp/at32/libraries/rt_drivers/drv_usbfs.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-28 shelton first version + */ + +#ifndef __DRV_USBFS_H__ +#define __DRV_USBFS_H__ + +#include <rtthread.h> +#include <rtdevice.h> +#include "drv_common.h" +#include "usb_core.h" + +struct at32_usbfs { + char *name; + otg_core_type *p_otg_core; + otg_id_type id; + IRQn_Type irqn; +}; + +#endif /* __DRV_USBFS_H__ */ + +/******************* end of file *******************/ diff --git a/bsp/at32/libraries/rt_drivers/drv_usbfsd.c b/bsp/at32/libraries/rt_drivers/drv_usbfsd.c new file mode 100644 index 0000000000..494db5dabc --- /dev/null +++ b/bsp/at32/libraries/rt_drivers/drv_usbfsd.c @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-28 leo first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include "usbd_int.h" +#include "drv_common.h" +#include "drv_usbfs.h" +#include "drv_config.h" + +#if defined(BSP_USING_DEVICE_USBFS1) || defined(BSP_USING_DEVICE_USBFS2) + +static struct at32_usbfs *p_usbfs_instance = NULL; +static struct ep_id endpoint_pool[] = +{ + {0x0, USB_EP_ATTR_CONTROL, USB_DIR_INOUT, 64, ID_ASSIGNED }, + {0x1, USB_EP_ATTR_BULK, USB_DIR_IN, 64, ID_UNASSIGNED}, + {0x1, USB_EP_ATTR_BULK, USB_DIR_OUT, 64, ID_UNASSIGNED}, + {0x2, USB_EP_ATTR_INT, USB_DIR_IN, 64, ID_UNASSIGNED}, + {0x2, USB_EP_ATTR_INT, USB_DIR_OUT, 64, ID_UNASSIGNED}, + {0x3, USB_EP_ATTR_ISOC, USB_DIR_IN, 64, ID_UNASSIGNED}, + {0x3, USB_EP_ATTR_ISOC, USB_DIR_OUT, 64, ID_UNASSIGNED}, + {0xFF, USB_EP_ATTR_TYPE_MASK, USB_DIR_MASK, 0, ID_ASSIGNED }, +}; + +enum +{ +#ifdef BSP_USING_DEVICE_USBFS1 + USBFS1_INDEX, +#endif +#ifdef BSP_USING_DEVICE_USBFS2 + USBFS2_INDEX, +#endif +}; + +static struct at32_usbfs usbfsd_config[] = { +#ifdef BSP_USING_DEVICE_USBFS1 + USBFS1_CONFIG, +#endif +#ifdef BSP_USING_DEVICE_USBFS2 + USBFS2_CONFIG, +#endif +}; + +#ifdef BSP_USING_DEVICE_USBFS1 +void OTGFS1_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + usbd_irq_handler(p_usbfs_instance->p_otg_core); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif + +#ifdef BSP_USING_DEVICE_USBFS2 +void OTGFS2_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + usbd_irq_handler(p_usbfs_instance->p_otg_core); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif + +void usbd_reset_callback(usbd_core_type *udev) +{ + udcd_t udcd = (udcd_t)udev->pdata; + rt_usbd_reset_handler(udcd); +} + +void usbd_connectCallback(usbd_core_type *udev) +{ + udcd_t udcd = (udcd_t)udev->pdata; + rt_usbd_connect_handler(udcd); +} + +void usbd_disconnectCallback(usbd_core_type *udev) +{ + udcd_t udcd = (udcd_t)udev->pdata; + rt_usbd_disconnect_handler(udcd); +} + +void usbd_setup_phase_done_callback(usbd_core_type *udev) +{ + udcd_t udcd = (udcd_t)udev->pdata; + rt_usbd_ep0_setup_handler(udcd, (struct urequest*)udev->setup_buffer); +} + +void usbd_data_in_stage_callback(usbd_core_type *udev, uint32_t ept_num) +{ + udcd_t udcd = (udcd_t)udev->pdata; + + if (ept_num == 0) + { + rt_usbd_ep0_in_handler(udcd); + } + else + { + rt_usbd_ep_in_handler(udcd, 0x80 | ept_num, udev->ept_in[ept_num].trans_len); + } +} + +void usbd_sof_callback(usbd_core_type *udev) +{ + udcd_t udcd = (udcd_t)udev->pdata; + rt_usbd_sof_handler(udcd); +} + +void usbd_data_out_stage_callback(usbd_core_type *udev, uint32_t ept_num) +{ + udcd_t udcd = (udcd_t)udev->pdata; + + if (ept_num != 0) + { + rt_usbd_ep_out_handler(udcd, ept_num, udev->ept_out[ept_num].trans_len); + } + else + { + rt_usbd_ep0_out_handler(udcd, udev->ept_out[0].trans_len); + } +} + +static rt_err_t _ep_set_stall(rt_uint8_t address) +{ + usbd_set_stall(&p_usbfs_instance->p_otg_core->dev, address); + return RT_EOK; +} + +static rt_err_t _ep_clear_stall(rt_uint8_t address) +{ + usbd_clear_stall(&p_usbfs_instance->p_otg_core->dev, address); + return RT_EOK; +} + +static rt_err_t _set_address(rt_uint8_t address) +{ + usbd_set_device_addr(&p_usbfs_instance->p_otg_core->dev, address); + return RT_EOK; +} + +static rt_err_t _set_config(rt_uint8_t address) +{ + return RT_EOK; +} + +static rt_err_t _ep_enable(uep_t ep) +{ + RT_ASSERT(ep != RT_NULL); + RT_ASSERT(ep->ep_desc != RT_NULL); + + usbd_ept_open(&p_usbfs_instance->p_otg_core->dev, ep->ep_desc->bEndpointAddress, \ + ep->ep_desc->bmAttributes, ep->ep_desc->wMaxPacketSize); + return RT_EOK; +} + +static rt_err_t _ep_disable(uep_t ep) +{ + RT_ASSERT(ep != RT_NULL); + RT_ASSERT(ep->ep_desc != RT_NULL); + + usbd_ept_close(&p_usbfs_instance->p_otg_core->dev, ep->ep_desc->bEndpointAddress); + return RT_EOK; +} + +static rt_size_t _ep_read(rt_uint8_t address, void *buffer) +{ + rt_size_t size = 0; + RT_ASSERT(buffer != RT_NULL); + return size; +} + +static rt_size_t _ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size) +{ + usbd_ept_recv(&p_usbfs_instance->p_otg_core->dev, address, buffer, size); + return size; +} + +static rt_size_t _ep_write(rt_uint8_t address, void *buffer, rt_size_t size) +{ + usbd_ept_send(&p_usbfs_instance->p_otg_core->dev, address, buffer, size); + return size; +} + +static rt_err_t _ep0_send_status(void) +{ + usbd_ept_send(&p_usbfs_instance->p_otg_core->dev, 0x00, NULL, 0); + return RT_EOK; +} + +static rt_err_t _suspend(void) +{ + return RT_EOK; +} + +static rt_err_t _wakeup(void) +{ + return RT_EOK; +} + +static rt_err_t at32_dcd_init(rt_device_t device) +{ + /* usb gpio config */ + at32_msp_usb_init(device); + + /* enable otgfs irq */ + nvic_irq_enable(p_usbfs_instance->irqn, 2, 0); + + /* init usb */ + p_usbfs_instance->p_otg_core->usb_reg = usb_global_select_core(p_usbfs_instance->id); + + /* usb device core config */ + usb_core_config(p_usbfs_instance->p_otg_core, USB_FULL_SPEED_CORE_ID); + + if(p_usbfs_instance->p_otg_core->cfg.sof_out) + { + p_usbfs_instance->p_otg_core->usb_reg->gccfg_bit.sofouten = TRUE; + } + + if(p_usbfs_instance->p_otg_core->cfg.vbusig) + { + p_usbfs_instance->p_otg_core->usb_reg->gccfg_bit.vbusig = TRUE; + } + + /* usb device core init */ + usbd_core_init(&(p_usbfs_instance->p_otg_core->dev), p_usbfs_instance->p_otg_core->usb_reg, + USB_FULL_SPEED_CORE_ID); + + return RT_EOK; +} + +const static struct udcd_ops _udc_ops = +{ + _set_address, + _set_config, + _ep_set_stall, + _ep_clear_stall, + _ep_enable, + _ep_disable, + _ep_read_prepare, + _ep_read, + _ep_write, + _ep0_send_status, + _suspend, + _wakeup, +}; + +int at32_usbd_register(void) +{ + rt_size_t obj_num; + rt_err_t result = 0; + int index; + + obj_num = sizeof(usbfsd_config) / sizeof(struct at32_usbfs); + + for (index = 0; index < obj_num; index++) { + udcd_t udcd = (udcd_t)rt_malloc(sizeof(struct udcd)); + if (udcd == RT_NULL) + { + rt_kprintf("uhcd malloc failed\r\n"); + return -RT_ERROR; + } + rt_memset((void *)udcd, 0, sizeof(struct udcd)); + + otg_core_type *p_otg_core = (otg_core_type *)rt_malloc(sizeof(otg_core_type)); + if (p_otg_core == RT_NULL) + { + rt_kprintf("otg_core malloc failed\r\n"); + return -RT_ERROR; + } + rt_memset((void *)p_otg_core, 0, sizeof(otg_core_type)); + + udcd->parent.type = RT_Device_Class_USBDevice; + udcd->parent.init = at32_dcd_init; + + udcd->parent.user_data = &(p_otg_core->dev); + udcd->ops = &_udc_ops; + p_otg_core->dev.pdata = udcd; + usbfsd_config[index].p_otg_core = p_otg_core; + + /* register endpoint infomation */ + udcd->ep_pool = endpoint_pool; + udcd->ep0.id = &endpoint_pool[0]; + + result = rt_device_register((rt_device_t)udcd, usbfsd_config[index].name, 0); + RT_ASSERT(result == RT_EOK); + + p_usbfs_instance = &usbfsd_config[index]; + + result = rt_usb_device_init(); + RT_ASSERT(result == RT_EOK); + } + + return result; +} + +INIT_DEVICE_EXPORT(at32_usbd_register); + +#endif diff --git a/bsp/at32/libraries/rt_drivers/drv_usbfsh.c b/bsp/at32/libraries/rt_drivers/drv_usbfsh.c new file mode 100644 index 0000000000..8a959cff81 --- /dev/null +++ b/bsp/at32/libraries/rt_drivers/drv_usbfsh.c @@ -0,0 +1,406 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-28 leo first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include "usbh_int.h" +#include "drv_common.h" +#include "drv_usbfs.h" +#include "drv_config.h" + +#if defined(BSP_USING_HOST_USBFS1) || defined(BSP_USING_HOST_USBFS2) + +//#define DRV_DEBUG +#define LOG_TAG "drv.usb" +#include <drv_log.h> + +static struct rt_completion urb_completion; +static volatile rt_bool_t connect_status = RT_FALSE; +static struct at32_usbfs *p_usbfs_instance = NULL; + +enum +{ +#ifdef BSP_USING_HOST_USBFS1 + USBFS1_INDEX, +#endif +#ifdef BSP_USING_HOST_USBFS2 + USBFS2_INDEX, +#endif +}; + +static struct at32_usbfs usbfsh_config[] = { +#ifdef BSP_USING_HOST_USBFS1 + USBFS1_CONFIG, +#endif +#ifdef BSP_USING_HOST_USBFS2 + USBFS2_CONFIG, +#endif +}; + +#ifdef BSP_USING_HOST_USBFS1 +void OTGFS1_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + usbh_irq_handler(p_usbfs_instance->p_otg_core); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif + +#ifdef BSP_USING_HOST_USBFS2 +void OTGFS2_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + usbh_irq_handler(p_usbfs_instance->p_otg_core); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif + +void usbh_connect_callback(usbh_core_type *uhost) +{ + uhcd_t hcd = (uhcd_t)uhost->pdata; + if (!connect_status) + { + connect_status = RT_TRUE; + RT_DEBUG_LOG(RT_DEBUG_USB, ("usb connected\n")); + rt_usbh_root_hub_connect_handler(hcd, 1, RT_FALSE); + } +} + +void usbh_disconnect_callback(usbh_core_type *uhost) +{ + uhcd_t hcd = (uhcd_t)uhost->pdata; + if (connect_status) + { + connect_status = RT_FALSE; + RT_DEBUG_LOG(RT_DEBUG_USB, ("usb disconnnect\n")); + rt_usbh_root_hub_disconnect_handler(hcd, 1); + } +} + +void usbd_notify_urbchange_callback(usbh_core_type *uhost, uint8_t chnum, urb_sts_type sts) +{ + rt_completion_done(&urb_completion); +} + +static rt_err_t drv_reset_port(rt_uint8_t port) +{ + RT_DEBUG_LOG(RT_DEBUG_USB, ("reset port\n")); + usbh_reset_port(&p_usbfs_instance->p_otg_core->host); + return RT_EOK; +} + +static int drv_pipe_xfer(upipe_t pipe, rt_uint8_t token, void *buffer, int nbytes, int timeouts) +{ + int timeout = timeouts; + + while(1) + { + if(!connect_status) + { + return -1; + } + rt_completion_init(&urb_completion); + + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].dir = (pipe->ep.bEndpointAddress & 0x80) >> 7; + + if(token == 0U) + { + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_SETUP; + } + else + { + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA1; + } + + /* endpoint type */ + switch(pipe->ep.bmAttributes) + { + /* endpoint is control type */ + case EPT_CONTROL_TYPE: + if((token == 1U) && (((pipe->ep.bEndpointAddress & 0x80) >> 7) == 0U)) + { + if(nbytes == 0U) + { + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].toggle_out = 1U; + } + if((&p_usbfs_instance->p_otg_core->host)->hch[pipe->pipe_index].toggle_out == 0U) + { + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA0; + } + else + { + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA1; + } + } + break; + /* endpoint is bulk type */ + case EPT_BULK_TYPE: + if(((pipe->ep.bEndpointAddress & 0x80) >> 7) == 0U) + { + if( p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].toggle_out == 0U) + { + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA0; + } + else + { + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA1; + } + } + else + { + if( p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].toggle_in == 0U) + { + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA0; + } + else + { + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA1; + } + } + break; + /* endpoint is int type */ + case EPT_INT_TYPE: + if(((pipe->ep.bEndpointAddress & 0x80) >> 7) == 0U) + { + if( p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].toggle_out == 0U) + { + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA0; + } + else + { + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA1; + } + } + else + { + if( p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].toggle_in == 0U) + { + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA0; + } + else + { + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA1; + } + } + break; + /* endpoint is isoc type */ + case EPT_ISO_TYPE: + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA0; + break; + + default: + break; + } + + /* set transfer buffer */ + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].trans_buf = buffer; + /* set transfer len*/ + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].trans_len = nbytes; + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].urb_sts = URB_IDLE; + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].ch_num = pipe->pipe_index; + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].trans_count = 0; + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].state = HCH_IDLE; + + /* data in/out for host */ + usbh_in_out_request((&p_usbfs_instance->p_otg_core->host), pipe->pipe_index); + + rt_completion_wait(&urb_completion, timeout); + rt_thread_mdelay(1); + + if(usbh_get_status((&p_usbfs_instance->p_otg_core->host), pipe->pipe_index) == HCH_NAK) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("nak\n")); + if (pipe->ep.bmAttributes == USB_EP_ATTR_INT) + { + rt_thread_delay((pipe->ep.bInterval * RT_TICK_PER_SECOND / 1000) > 0 ? (pipe->ep.bInterval * RT_TICK_PER_SECOND / 1000) : 1); + } + usb_hch_halt((&p_usbfs_instance->p_otg_core->host)->usb_reg, pipe->pipe_index); + + usbh_hc_open(&p_usbfs_instance->p_otg_core->host, + pipe->pipe_index, + pipe->ep.bEndpointAddress, + pipe->inst->address, + pipe->ep.bmAttributes, + pipe->ep.wMaxPacketSize, + USB_PRTSPD_FULL_SPEED); + continue; + } + else if (usbh_get_status(&p_usbfs_instance->p_otg_core->host, pipe->pipe_index) == HCH_STALL) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("stall\n")); + pipe->status = UPIPE_STATUS_STALL; + if (pipe->callback != RT_NULL) + { + pipe->callback(pipe); + } + return -1; + } + else if (usbh_get_status(&p_usbfs_instance->p_otg_core->host, pipe->pipe_index) == URB_ERROR) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("error\n")); + pipe->status = UPIPE_STATUS_ERROR; + if (pipe->callback != RT_NULL) + { + pipe->callback(pipe); + } + return -1; + } + else if(URB_DONE == usbh_get_urb_status(&p_usbfs_instance->p_otg_core->host, pipe->pipe_index)) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("ok\n")); + pipe->status = UPIPE_STATUS_OK; + if (pipe->callback != RT_NULL) + { + pipe->callback(pipe); + } + size_t size = (&p_usbfs_instance->p_otg_core->host)->hch[pipe->pipe_index].trans_count; + if (pipe->ep.bEndpointAddress & 0x80) + { + return size; + } + else if (pipe->ep.bEndpointAddress & 0x00) + { + return size; + } + return nbytes; + } + continue; + } +} + +static rt_uint16_t pipe_index = 0; +static rt_uint8_t drv_get_free_pipe_index(void) +{ + rt_uint8_t idx; + for (idx = 1; idx < 16; idx++) + { + if (!(pipe_index & (0x01 << idx))) + { + pipe_index |= (0x01 << idx); + return idx; + } + } + return 0xff; +} + +static void drv_free_pipe_index(rt_uint8_t index) +{ + pipe_index &= ~(0x01 << index); +} + +static rt_err_t drv_open_pipe(upipe_t pipe) +{ + pipe->pipe_index = drv_get_free_pipe_index(); + usbh_hc_open(&p_usbfs_instance->p_otg_core->host, + pipe->pipe_index, + pipe->ep.bEndpointAddress, + pipe->inst->address, + pipe->ep.bmAttributes, + pipe->ep.wMaxPacketSize, + USB_PRTSPD_FULL_SPEED); + /* set data0 pid token*/ + if (p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].dir) + { + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].toggle_in = 0; + } + else + { + p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].toggle_out = 0; + } + return RT_EOK; +} + +static rt_err_t drv_close_pipe(upipe_t pipe) +{ + usb_hch_halt((&p_usbfs_instance->p_otg_core->host)->usb_reg, pipe->pipe_index); + drv_free_pipe_index(pipe->pipe_index); + return RT_EOK; +} + +static struct uhcd_ops _uhcd_ops = +{ + drv_reset_port, + drv_pipe_xfer, + drv_open_pipe, + drv_close_pipe, +}; + +static rt_err_t at32_hcd_init(rt_device_t device) +{ + /* usb gpio config */ + at32_msp_usb_init(device); + + /* enable otgfs irq */ + nvic_irq_enable(p_usbfs_instance->irqn, 2, 0); + + /* init usb */ + usbh_init(p_usbfs_instance->p_otg_core, + USB_FULL_SPEED_CORE_ID, + p_usbfs_instance->id); + return RT_EOK; +} + +int at32_usbh_register(void) +{ + rt_size_t obj_num; + rt_err_t result = 0; + int index; + + obj_num = sizeof(usbfsh_config) / sizeof(struct at32_usbfs); + + for (index = 0; index < obj_num; index++) { + uhcd_t uhcd = (uhcd_t)rt_malloc(sizeof(struct uhcd)); + if (uhcd == RT_NULL) + { + rt_kprintf("uhcd malloc failed\r\n"); + return -RT_ERROR; + } + rt_memset((void *)uhcd, 0, sizeof(struct uhcd)); + + otg_core_type *p_otg_core = (otg_core_type *)rt_malloc(sizeof(otg_core_type)); + if (p_otg_core == RT_NULL) + { + rt_kprintf("otg_core malloc failed\r\n"); + return -RT_ERROR; + } + rt_memset((void *)p_otg_core, 0, sizeof(otg_core_type)); + + uhcd->parent.type = RT_Device_Class_USBHost; + uhcd->parent.init = at32_hcd_init; + uhcd->parent.user_data = &(p_otg_core->host); + + uhcd->ops = &_uhcd_ops; + uhcd->num_ports = 1; + p_otg_core->host.pdata = uhcd; + usbfsh_config[index].p_otg_core = p_otg_core; + + result = rt_device_register(&uhcd->parent, usbfsh_config[index].name, RT_DEVICE_FLAG_DEACTIVATE); + RT_ASSERT(result == RT_EOK); + + p_usbfs_instance = &usbfsh_config[index]; + + result = rt_usb_host_init(usbfsh_config[index].name); + RT_ASSERT(result == RT_EOK); + } + + return result; +} + +INIT_DEVICE_EXPORT(at32_usbh_register); + +#endif |
