From a38b39ac253432d8fe481390a51aeeaefaaaece3 Mon Sep 17 00:00:00 2001 From: emuzit <98307908+emuzit@users.noreply.github.com> Date: Wed, 24 Aug 2022 19:59:37 +0800 Subject: [PATCH] ch569w-evt: add usbhs device mode driver (#6330) ch569w-evt: add usbhs device mode driver * usbd driver tested with cdc_vcom, internal loopback (can't run both MSH & usbd due to 16KB RAM limitation) * reduce usrstack & main thread stack size for usbd test * ch56x_uart.c : iron out UART0_PIN_ALT assignment --- .../risc-v/Libraries/ch56x_drivers/SConscript | 3 + .../Libraries/ch56x_drivers/ch56x_uart.c | 20 +- .../Libraries/ch56x_drivers/ch56x_usbd.c | 574 +++++++++++++++ .../Libraries/ch56x_drivers/ch56x_usbhs.h | 679 ++++++++++++++++++ bsp/wch/risc-v/Libraries/ch56x_drivers/soc.h | 6 +- bsp/wch/risc-v/ch569w-evt/.config | 6 +- .../risc-v/ch569w-evt/applications/SConscript | 6 +- bsp/wch/risc-v/ch569w-evt/applications/test.c | 47 ++ .../ch569w-evt/board/linker_scripts/link.lds | 332 ++++----- bsp/wch/risc-v/ch569w-evt/rtconfig.h | 4 +- 10 files changed, 1493 insertions(+), 184 deletions(-) create mode 100644 bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_usbd.c create mode 100644 bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_usbhs.h diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/SConscript b/bsp/wch/risc-v/Libraries/ch56x_drivers/SConscript index b3c2736e2b..b92cfcb3db 100644 --- a/bsp/wch/risc-v/Libraries/ch56x_drivers/SConscript +++ b/bsp/wch/risc-v/Libraries/ch56x_drivers/SConscript @@ -12,6 +12,9 @@ if GetDepend('SOC_SERIES_CH569'): if GetDepend('RT_USING_WDT'): src += ['ch56x_wdt.c'] +if GetDepend('RT_USING_USB_DEVICE'): + src += ['ch56x_usbd.c'] + if GetDepend('RT_USING_PWM'): src += ['ch56x_pwm.c'] diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.c b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.c index 24d2183339..a2c1aec551 100644 --- a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.c +++ b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.c @@ -45,8 +45,13 @@ static struct serial_device serial_device_0 = { .reg_base = (struct uart_registers *)UART0_REG_BASE, .irqn = UART0_IRQn, +#ifndef BSP_USING_UART0_PIN_ALT .rxd_pin = UART_RXD0_PIN, .txd_pin = UART_TXD0_PIN, +#else + .rxd_pin = UART_RXD0_ALT, + .txd_pin = UART_TXD0_ALT, +#endif .name = "uart0", }; #endif @@ -250,22 +255,13 @@ int rt_hw_uart_init(void) while (--n >= 0) { - uint32_t flag, txd_pin, rxd_pin; + uint32_t flag; struct serial_device *serial = devices[n]; serial->parent.ops = &uart_ops; serial->parent.config = config; - txd_pin = serial->txd_pin; - rxd_pin = serial->rxd_pin; -#ifdef BSP_USING_UART0_PIN_ALT - if (serial->irqn == UART0_IRQn) - { - txd_pin = UART_TXD0_ALT; - rxd_pin = UART_RXD0_ALT; - } -#endif - rt_pin_mode(txd_pin, PIN_MODE_OUTPUT); - rt_pin_mode(rxd_pin, PIN_MODE_INPUT_PULLUP); + rt_pin_mode(serial->txd_pin, PIN_MODE_OUTPUT); + rt_pin_mode(serial->rxd_pin, PIN_MODE_INPUT_PULLUP); sys_clk_off_by_irqn(serial->irqn, SYS_SLP_CLK_ON); diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_usbd.c b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_usbd.c new file mode 100644 index 0000000000..44ac67f475 --- /dev/null +++ b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_usbd.c @@ -0,0 +1,574 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-08-22 Emuzit first version + */ +#include +#include +#include +#include +#include "ch56x_usbhs.h" +#include "ch56x_sys.h" +#include "isr_sp.h" + +/*--------------------------------------------------------*/ +/* Warning : Not fully tested, use at your own discretion */ +/*--------------------------------------------------------*/ + +#ifdef SOC_SERIES_CH569 +#define _attr_uepdma __attribute__((section(".dmadata"), aligned(16))) +#define _ep0_setup_dmabuf _dmadata_start +#else +#define _attr_uepdma __attribute__((aligned(4))) +#define _ep0_setup_dmabuf _dmadata_start +#define usbhs_irq_handler usb1_irq_handler +#define USBHS_IRQn USB1_IRQn +#define USBHS_REG_BASE USB1_REG_BASE +#define RAMX_BASE_ADDRESS RAMS_BASE_ADDRESS +#define UEP0_RT_DMA UEP_DMA[0] +#endif + +#define UEP_MPS_64 64 +#define UEP_MPS_512 512 + +#define _get_ep_idx(address) ((address) & USB_EPNO_MASK) +#define _get_ep_dir(address) ((address) & USB_DIR_MASK) + +#define uep_dir_is_in(address) (_get_ep_dir(address) == USB_DIR_IN) +#define uep_dir_is_out(address) (_get_ep_dir(address) == USB_DIR_OUT) + +extern uint32_t _dmadata_start[]; + +static uint32_t ep0_dmabuf[UEP_MPS_64 / 4] _attr_uepdma; +static uint32_t epx_dmabuf[UEP_ADDRESS_MAX][UEP_MPS_512 / 4] _attr_uepdma; + +static struct ep_id usbhs_ep_pool[] = +{ + {0x0, USB_EP_ATTR_CONTROL, USB_DIR_INOUT, 64, ID_ASSIGNED}, + {0x1, USB_EP_ATTR_BULK, USB_DIR_IN, 512, ID_UNASSIGNED}, + {0x1, USB_EP_ATTR_BULK, USB_DIR_OUT, 512, ID_UNASSIGNED}, + {0x2, USB_EP_ATTR_INT, USB_DIR_IN, 512, ID_UNASSIGNED}, + {0x2, USB_EP_ATTR_INT, USB_DIR_OUT, 512, ID_UNASSIGNED}, + {0x3, USB_EP_ATTR_BULK, USB_DIR_IN, 512, ID_UNASSIGNED}, + {0x3, USB_EP_ATTR_BULK, USB_DIR_OUT, 512, ID_UNASSIGNED}, +#ifdef SOC_SERIES_CH569 + /* FIXME: not sure how to deal with EP4, no UEP4_DMA register */ + {0x4, USB_EP_ATTR_INT, USB_DIR_IN, 512, ID_UNASSIGNED}, + {0x4, USB_EP_ATTR_INT, USB_DIR_OUT, 512, ID_UNASSIGNED}, + {0x5, USB_EP_ATTR_BULK, USB_DIR_IN, 512, ID_UNASSIGNED}, + {0x5, USB_EP_ATTR_BULK, USB_DIR_OUT, 512, ID_UNASSIGNED}, + {0x6, USB_EP_ATTR_INT, USB_DIR_IN, 512, ID_UNASSIGNED}, + {0x6, USB_EP_ATTR_INT, USB_DIR_OUT, 512, ID_UNASSIGNED}, + {0x7, USB_EP_ATTR_BULK, USB_DIR_IN, 512, ID_UNASSIGNED}, + {0x7, USB_EP_ATTR_BULK, USB_DIR_OUT, 512, ID_UNASSIGNED}, +#endif + {0xff, USB_EP_ATTR_TYPE_MASK, USB_DIR_MASK, 0, ID_ASSIGNED}, +}; + +static struct udcd udc_device; + +static uint8_t setup_set_address; + +static rt_err_t udc_set_address(uint8_t address) +{ + /* DEV_AD should be updated after status stage IN token of SET_ADDRESS + * such that that IN token could still reach our device. + */ + setup_set_address = address | 0x80; + return RT_EOK; +} + +static rt_err_t udc_set_config(uint8_t address) +{ + return RT_EOK; +} + +static rt_err_t udc_ep_set_stall(uint8_t address) +{ + volatile struct usbhs_registers *usbhs = (void *)USBHS_REG_BASE; + + uint8_t ep_idx = _get_ep_idx(address); + + if (uep_dir_is_in(address)) + usbhs->UEP_CTRL[ep_idx].TX_CTRL.res_mask = UEP_RES_STALL; + else + usbhs->UEP_CTRL[ep_idx].RX_CTRL.res_mask = UEP_RES_STALL; + + return RT_EOK; +} + +static rt_err_t udc_ep_clear_stall(uint8_t address) +{ + volatile struct usbhs_registers *usbhs = (void *)USBHS_REG_BASE; + + uint8_t ep_idx = _get_ep_idx(address); + + if (uep_dir_is_in(address)) + usbhs->UEP_CTRL[ep_idx].TX_CTRL.res_mask = UEP_RES_NAK; + else + usbhs->UEP_CTRL[ep_idx].RX_CTRL.res_mask = UEP_RES_NAK; + + return RT_EOK; +} + +static rt_err_t udc_ep_enable(struct uendpoint *ep) +{ + volatile struct usbhs_registers *usbhs = (void *)USBHS_REG_BASE; + + uint8_t ep_idx, address, mod; + + RT_ASSERT(ep != RT_NULL); + RT_ASSERT(ep->ep_desc != RT_NULL); + + address = EP_ADDRESS(ep); + ep_idx = _get_ep_idx(address); + + if (ep_idx > 0 && ep_idx <= UEP_ADDRESS_MAX) + { + mod = uep_dir_is_in(address) ? RB_UEP_TX_EN : RB_UEP_RX_EN; + mod = _uep_mod_get(usbhs, ep_idx) | mod; + _uep_mod_set(usbhs, ep_idx, mod); + } + + return RT_EOK; +} + +static rt_err_t udc_ep_disable(struct uendpoint *ep) +{ + volatile struct usbhs_registers *usbhs = (void *)USBHS_REG_BASE; + + uint8_t ep_idx, address, mod; + + RT_ASSERT(ep != RT_NULL); + RT_ASSERT(ep->ep_desc != RT_NULL); + + address = EP_ADDRESS(ep); + ep_idx = _get_ep_idx(address); + + if (ep_idx > 0 && ep_idx <= UEP_ADDRESS_MAX) + { + mod = uep_dir_is_in(address) ? RB_UEP_TX_EN : RB_UEP_RX_EN; + mod = _uep_mod_get(usbhs, ep_idx) & ~mod; + _uep_mod_set(usbhs, ep_idx, mod); + } + + return RT_EOK; +} + +static rt_size_t udc_ep_read_prepare(uint8_t address, void *buffer, rt_size_t size) +{ + volatile struct usbhs_registers *usbhs = (void *)USBHS_REG_BASE; + + uint8_t ep_idx = _get_ep_idx(address); + + uint32_t dmabuf = (uint32_t)buffer; + + if (uep_dir_is_in(address)) + return 0; + + if (size > (ep_idx ? UEP_MPS_512 : UEP_MPS_64)) + size = (ep_idx ? UEP_MPS_512 : UEP_MPS_64); + + /* need extra `buffer` copy if H/W requirement not met + * CH565/CH569 : DMA buffer resides in RAMX, 16-byte aligned + * CH567/CH568 : 4-byte aligned + */ +#ifdef SOC_SERIES_CH569 + if (size > 0 && (dmabuf < RAMX_BASE_ADDRESS || (dmabuf & 0xf))) + { + dmabuf = (uint32_t)(ep_idx ? epx_dmabuf[ep_idx] : ep0_dmabuf); + } + /* Note : usbhs->UEP_RX_DMA[0] maps to usbhs->UEP0_RT_DMA actually */ + usbhs->UEP_RX_DMA[ep_idx] = dmabuf & UEP_RT_DMA_MASK; +#else + if (size > 0 && (dmabuf & 3)) + { + dmabuf = (uint32_t)(ep_idx ? epx_dmabuf[ep_idx] : ep0_dmabuf); + } + usbhs->UEP_DMA[ep_idx] = dmabuf & UEP_RT_DMA_MASK; +#endif + + if (ep_idx == 0 && size == 0) + { + /* SETUP status stage, expect DATA1 */ + usbhs->UEP_CTRL[0].RX_CTRL.reg = RB_UEP_RES_ACK | RB_UEP_TOG_DATA1; + } + else + { + /* keep TOG_MASK & AUTOTOG */ + usbhs->UEP_CTRL[ep_idx].RX_CTRL.res_mask = UEP_RES_ACK; + } + + return size; +} + +static rt_size_t udc_ep_read(uint8_t address, void *buffer) +{ + volatile struct usbhs_registers *usbhs = (void *)USBHS_REG_BASE; + + uint8_t ep_idx = _get_ep_idx(address); + + uint32_t dmabuf; + rt_size_t size; + + if (uep_dir_is_in(address)) + return 0; + +#ifdef SOC_SERIES_CH569 + /* Note : usbhs->UEP_RX_DMA[0] maps to usbhs->UEP0_RT_DMA actually */ + dmabuf = usbhs->UEP_RX_DMA[ep_idx] & UEP_RT_DMA_MASK; +#else + dmabuf = usbhs->UEP_DMA[ep_idx] & UEP_RT_DMA_MASK; +#endif + size = usbhs->RX_LEN; + + /* copy if proxy buffer */ + if (size > 0 && ((uint32_t)buffer & UEP_RT_DMA_MASK) != dmabuf) + { + dmabuf |= RAMX_BASE_ADDRESS; + rt_memcpy(buffer, (void *)dmabuf, size); + } + + return size; +} + +static rt_size_t udc_ep_write(uint8_t address, void *buffer, rt_size_t size) +{ + volatile struct usbhs_registers *usbhs = (void *)USBHS_REG_BASE; + + uint8_t ep_idx = _get_ep_idx(address); + + uint32_t dmabuf = (uint32_t)buffer; + + union _uh_rt_ctrl ctrl; + + if (uep_dir_is_out(address)) + return 0; + + if (size > (ep_idx ? UEP_MPS_512 : UEP_MPS_64)) + size = (ep_idx ? UEP_MPS_512 : UEP_MPS_64); + + /* need extra `buffer` copy if H/W requirement not met + * CH565/CH569 : DMA buffer resides in RAMX, 16-byte aligned + * CH567/CH568 : 4-byte aligned + */ +#ifdef SOC_SERIES_CH569 + if (size > 0 && (dmabuf < RAMX_BASE_ADDRESS || (dmabuf & 0xf))) + { + dmabuf = (uint32_t)(ep_idx ? epx_dmabuf[ep_idx] : ep0_dmabuf); + rt_memcpy((void *)dmabuf, buffer, size); + } + if (ep_idx == 0) + usbhs->UEP0_RT_DMA = dmabuf & UEP_RT_DMA_MASK; + else + usbhs->UEP_TX_DMA[ep_idx] = dmabuf & UEP_RT_DMA_MASK; +#else + if (size > 0 && (dmabuf & 3)) + { + dmabuf = (uint32_t)(ep_idx ? epx_dmabuf[ep_idx] : ep0_dmabuf); + rt_memcpy((void *)dmabuf, buffer, size); + } + usbhs->UEP_DMA[ep_idx] = dmabuf & UEP_RT_DMA_MASK; +#endif + usbhs->UEP_CTRL[ep_idx].t_len = size; + + /* keep TOG_MASK & AUTOTOG */ + usbhs->UEP_CTRL[ep_idx].TX_CTRL.res_mask = UEP_RES_ACK; + + return size; +} + +static rt_err_t udc_ep0_send_status(void) +{ + volatile struct usbhs_registers *usbhs = (void *)USBHS_REG_BASE; + + /* SETUP status stage : zero data length, always DATA1 */ + usbhs->UEP_CTRL[0].t_len = 0; + /* This is the only case UEP0_RT_DMA is set to 0. */ + usbhs->UEP0_RT_DMA = 0; + usbhs->UEP_CTRL[0].TX_CTRL.reg = RB_UEP_RES_ACK | RB_UEP_TOG_DATA1; + return RT_EOK; +} + +static rt_err_t udc_suspend(void) +{ + return RT_EOK; +} + +static rt_err_t udc_wakeup(void) +{ + return RT_EOK; +} + +static const struct udcd_ops udcd_ops = +{ + .set_address = udc_set_address, + .set_config = udc_set_config, + .ep_set_stall = udc_ep_set_stall, + .ep_clear_stall = udc_ep_clear_stall, + .ep_enable = udc_ep_enable, + .ep_disable = udc_ep_disable, + .ep_read_prepare = udc_ep_read_prepare, + .ep_read = udc_ep_read, + .ep_write = udc_ep_write, + .ep0_send_status = udc_ep0_send_status, + .suspend = udc_suspend, + .wakeup = udc_wakeup, +}; + +static void _hsbhs_device_mode_init(volatile struct usbhs_registers *usbhs) +{ + uint8_t ep_idx; + + /* disable all endpoints, use single buffer mode (BUF_MOD : 0) */ + usbhs->UHOST_CTRL.reg = 0; + usbhs->SUSPEND.reg = 0; + usbhs->R32_UEP_MOD = 0; + usbhs->DEV_AD = 0; + + usbhs->CTRL.reg = RB_USB_RESET_SIE | RB_USB_CLR_ALL; + usbhs->CTRL.reg = RB_USB_DEVICE_MODE | + RB_SPTP_HIGH_SPEED | + RB_DEV_PU_EN | + RB_USB_INT_BUSY | + RB_USB_DMA_EN; + + usbhs->INT_EN.reg = RB_USB_IE_BUSRST | + RB_USB_IE_TRANS | + RB_USB_IE_FIFOOV | + RB_USB_IE_SETUPACT; + + usbhs->UEP_MAX_LEN[0].reg = UEP_MPS_64; + /* + * It seems EP0 SETUP uses the first 8 bytes of RAMX as dmabuf and + * handles DATA0 transfer & ACK on its own. Here we still needs to + * RES_NAK TX/RX to block SETUP data stage till dma data is ready. + */ + usbhs->UEP_CTRL[0].TX_CTRL.reg = RB_UEP_RES_NAK | RB_UEP_TOG_DATA1; + usbhs->UEP_CTRL[0].RX_CTRL.reg = RB_UEP_RES_NAK | RB_UEP_TOG_DATA1; + + for (ep_idx = 1; ep_idx <= UEP_ADDRESS_MAX; ep_idx++) + { + usbhs->UEP_MAX_LEN[ep_idx].reg = UEP_MPS_512; + /* set to DATA0, remains to be initialized (SET_CONFIGURATION...) */ + usbhs->UEP_CTRL[ep_idx].TX_CTRL.reg = RB_UEP_RES_NAK | RB_UEP_AUTOTOG; + usbhs->UEP_CTRL[ep_idx].RX_CTRL.reg = RB_UEP_RES_NAK | RB_UEP_AUTOTOG; + } +} + +static rt_err_t udc_device_init(struct rt_device *device) +{ + volatile struct usbhs_registers *usbhs = device->user_data; + + sys_clk_off_by_irqn(USBHS_IRQn, SYS_SLP_CLK_ON); + + _hsbhs_device_mode_init(usbhs); + + rt_hw_interrupt_umask(USBHS_IRQn); + + return RT_EOK; +} + +#ifdef RT_USING_DEVICE_OPS +static struct rt_device_ops device_ops; +#endif + +static int rt_hw_usbd_init(void) +{ + int ret; + + udc_device.parent.type = RT_Device_Class_USBDevice; +#ifdef RT_USING_DEVICE_OPS + device_ops.init = udc_device_init; + udc_device.parent.ops = &device_ops; +#else + udc_device.parent.init = udc_device_init; +#endif + udc_device.parent.user_data = (void *)USBHS_REG_BASE; + udc_device.ops = &udcd_ops; + udc_device.ep_pool = usbhs_ep_pool; + udc_device.ep0.id = &usbhs_ep_pool[0]; + udc_device.device_is_hs = RT_TRUE; + + ret = rt_device_register(&udc_device.parent, "usbd", 0); + if (ret == RT_EOK) + ret = rt_usb_device_init(); + + return ret; +} +INIT_DEVICE_EXPORT(rt_hw_usbd_init); + +rt_inline uint8_t _uep_tog_datax(uint8_t tog) +{ + /* Note: treat tog as RB_UEP_TOG_DATA0 if not RB_UEP_TOG_DATA1 */ + return (tog == RB_UEP_TOG_DATA1) ? RB_UEP_TOG_DATA0 : RB_UEP_TOG_DATA1; +} + +static void _isr_ep_stall(volatile struct usbhs_registers *usbhs) +{ + uint8_t ep_idx = usbhs->INT_ST.dev_endp_mask; + + usbhs->UEP_CTRL[ep_idx].TX_CTRL.res_mask == UEP_RES_STALL; + usbhs->UEP_CTRL[ep_idx].RX_CTRL.res_mask == UEP_RES_STALL; +} + +static void _isr_handle_setup(volatile struct usbhs_registers *usbhs) +{ + struct urequest setup, *packet; + + uint8_t ep_idx, xctrl, recipient; + + /* RES_NAK to block data stage, will expect or response DATA1 */ + usbhs->UEP_CTRL[0].TX_CTRL.reg = RB_UEP_RES_NAK | RB_UEP_TOG_DATA1; + usbhs->UEP_CTRL[0].RX_CTRL.reg = RB_UEP_RES_NAK | RB_UEP_TOG_DATA1; + + packet = (struct urequest *)_ep0_setup_dmabuf; + + setup.request_type = packet->request_type; + setup.bRequest = packet->bRequest; + setup.wValue = packet->wValue; + setup.wIndex = packet->wIndex; + setup.wLength = packet->wLength; + + /* Init data toggle bit. Not sure if it has been done by h/w.*/ + xctrl = RB_UEP_RES_NAK | RB_UEP_AUTOTOG | RB_UEP_TOG_DATA0; + recipient = setup.request_type & USB_REQ_TYPE_RECIPIENT_MASK; + if (recipient == USB_REQ_TYPE_DEVICE && + setup.bRequest == USB_REQ_SET_CONFIGURATION) + { + for (ep_idx = 1; ep_idx <= UEP_ADDRESS_MAX; ep_idx++) + { + usbhs->UEP_CTRL[ep_idx].TX_CTRL.reg = xctrl; + usbhs->UEP_CTRL[ep_idx].RX_CTRL.reg = xctrl; + } + } + else if (recipient == USB_REQ_TYPE_ENDPOINT && + setup.bRequest == USB_REQ_CLEAR_FEATURE && + setup.wValue == USB_EP_HALT) + { + ep_idx = setup.wIndex; + if (ep_idx > 0 && ep_idx <= UEP_ADDRESS_MAX) + { + usbhs->UEP_CTRL[ep_idx].TX_CTRL.reg = xctrl; + usbhs->UEP_CTRL[ep_idx].RX_CTRL.reg = xctrl; + } + } + + rt_usbd_ep0_setup_handler(&udc_device, &setup); +} + +static void _isr_handle_transfer(volatile struct usbhs_registers *usbhs) +{ + rt_size_t size; + + uint8_t ep_idx, token, tog; + + ep_idx = usbhs->INT_ST.dev_endp_mask; + token = usbhs->INT_ST.dev_token_mask; + + if (ep_idx == 0) + { + if (token == DEV_TOKEN_IN) + { + /* UEP0 does not support AUTOTOG, generate DATAx manually */ + tog = usbhs->UEP_CTRL[0].TX_CTRL.reg & RB_UEP_TOG_MASK; + tog = _uep_tog_datax(tog); + /* wait for udc_ep_write or udc_ep0_send_status to RES_ACK */ + usbhs->UEP_CTRL[0].TX_CTRL.reg = RB_UEP_RES_NAK | tog; + + if (setup_set_address != 0 && usbhs->UEP_CTRL[0].t_len == 0) + { + usbhs->DEV_AD = setup_set_address & 0x7f; + setup_set_address = 0; + } + /* don't call in_handler if send_status */ + if (usbhs->UEP0_RT_DMA != 0) + { + rt_usbd_ep0_in_handler(&udc_device); + } + } + else if (token == DEV_TOKEN_OUT) + { + if (usbhs->INT_ST.st_togok) + { + /* UEP0 does not support AUTOTOG, generate DATAx manually */ + tog = usbhs->UEP_CTRL[0].RX_CTRL.reg & RB_UEP_TOG_MASK; + tog = _uep_tog_datax(tog); + /* wait for udc_ep_read_prepare to RES_ACK */ + usbhs->UEP_CTRL[0].RX_CTRL.reg = RB_UEP_RES_NAK | tog; + rt_usbd_ep0_out_handler(&udc_device, usbhs->RX_LEN); + } + else + { + /* Corrupted ACK Handshake => ignore data, keep sequence bit */ + usbhs->UEP_CTRL[0].RX_CTRL.res_mask = UEP_RES_NAK; + } + } + } + else if (token == DEV_TOKEN_IN) + { + /* wait for udc_ep_write to RES_ACK */ + usbhs->UEP_CTRL[ep_idx].TX_CTRL.res_mask = UEP_RES_NAK; + size = usbhs->UEP_CTRL[ep_idx].t_len; + rt_usbd_ep_in_handler(&udc_device, ep_idx | USB_DIR_IN, size); + } + else if (token == DEV_TOKEN_OUT) + { + /* wait for udc_ep_read_prepare to RES_ACK */ + usbhs->UEP_CTRL[ep_idx].RX_CTRL.res_mask = UEP_RES_NAK; + /* ignore data if Corrupted ACK Handshake */ + if (usbhs->INT_ST.st_togok) + { + /* size:0 to trigger dcd_ep_read() in _data_notify() */ + rt_usbd_ep_out_handler(&udc_device, ep_idx | USB_DIR_OUT, 0); + } + } +} + +/* + * CAVEAT: The usbd design of ch56x relies on instant isr to RES_NAK + * UEP_CTRL[n].TX_CTRL/RX_CTRL. A long tarried isr may leave RES_ACK + * in UEP_CTRL[n] and starts unintended DMA upon arrival of IN/OUT. + */ +void usbhs_irq_handler(void) __attribute__((interrupt())); +void usbhs_irq_handler(void) +{ + volatile struct usbhs_registers *usbhs; + union _usb_int_fg intflag; + + isr_sp_enter(); + rt_interrupt_enter(); + + usbhs = (struct usbhs_registers *)USBHS_REG_BASE; + intflag.reg = usbhs->INT_FG.reg; + + if (intflag.fifoov) + { + /* FIXME: fifo overflow */ + _isr_ep_stall(usbhs); + } + else + { + if (intflag.transfer) + _isr_handle_transfer(usbhs); + + if (intflag.setupact) + _isr_handle_setup(usbhs); + } + + if (intflag.busrst) + { + _hsbhs_device_mode_init(usbhs); + rt_usbd_reset_handler(&udc_device); + } + + /* clear all pending intflag (suspend, isoact & nak ignored) */ + usbhs->INT_FG.reg = intflag.reg; + + rt_interrupt_leave(); + isr_sp_leave(); +} diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_usbhs.h b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_usbhs.h new file mode 100644 index 0000000000..045ef75eba --- /dev/null +++ b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_usbhs.h @@ -0,0 +1,679 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-08-22 Emuzit first version + */ +#ifndef __CH56X_USBHS_H__ +#define __CH56X_USBHS_H__ + +#include "soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef SOC_SERIES_CH569 +#define UEP_ADDRESS_MAX 7 +#define UEP_RT_DMA_MASK 0x1fff0 +#else +#define UEP_ADDRESS_MAX 4 +#define UEP_RT_DMA_MASK 0x0fffc +#endif + +union _usb_ctrl +{ + uint8_t reg; + struct + { + uint8_t dma_en : 1; // RW, USB DMA and DMA interrupt enable bit + uint8_t clr_all : 1; // RW, Empty USB interrupt flag and FIFO + uint8_t reset_sie : 1; // RW, Forcibly reset the USB SIE + uint8_t int_busy : 1; // RW, Auto pause enable bit @ RB_USB_IF_TRANSFER + uint8_t pu_en : 1; // RW, device & pull-up-R enable, DEVICE mode + uint8_t sptp_mask : 2; // RW, USB bus signal transfer rate selection bit + uint8_t mode : 1; // RW, USB working mode selection bit + }; +}; +#define RB_USB_DMA_EN 0x01 +#define RB_USB_CLR_ALL 0x02 +#define RB_USB_RESET_SIE 0x04 +#define RB_USB_INT_BUSY 0x08 +#define RB_DEV_PU_EN 0x10 +#define RB_USB_SPTP_MASK 0x60 +#define RB_USB_MODE 0x80 + +#define USBHS_FULL_SPEED 0 +#define USBHS_HIGH_SPEED 1 +#define USBHS_LOW_SPEED 2 + +#define USBHS_DEVICE_MODE 0 +#define USBHS_HOST_MODE 1 + +#define RB_SPTP_FULL_SPEED (USBHS_FULL_SPEED << 5) +#define RB_SPTP_HIGH_SPEED (USBHS_HIGH_SPEED << 5) +#define RB_SPTP_LOW_SPEED (USBHS_LOW_SPEED << 5) + +#define RB_USB_DEVICE_MODE (USBHS_DEVICE_MODE << 7) +#define RB_USB_HOST_MODE (USBHS_HOST_MODE << 7) + +union _usb_int_en +{ + uint8_t reg; + struct + { + uint8_t busrst : 1; // RW, USB bus reset event IE, DEVICE mode + uint8_t trans : 1; // RW, USB transfer complete interrupt enable + uint8_t suspend : 1; // RW, USB bus suspend/wake-up event IE + uint8_t sof : 1; // RW, SOF packet/timing interrupt enable + uint8_t fifoov : 1; // RW, Internal FIFO overflow interrupt enable +#ifdef SOC_SERIES_CH569 + uint8_t setupact : 1; // RW, SETUP transaction complete interrupt + uint8_t isoact : 1; // RW, ISOchronous token received IE + uint8_t dev_nak : 1; // RW, NAK interrupt enable, DEVICE mode +#else + uint8_t resv_5 : 1; + uint8_t dev_nak : 1; // RW, NAK interrupt enable, DEVICE mode + uint8_t dev_sof : 1; // RW, SOF packet received IE, DEVICE mode +#endif + }; + struct + { + uint8_t detect : 1; // RW, USB device connect/disconnect IE, HOST mode + uint8_t stuff_1 : 7; + }; +}; +#define RB_USB_IE_BUSRST 0x01 +#define RB_USB_IE_DETECT 0x01 +#define RB_USB_IE_TRANS 0x02 +#define RB_USB_IE_SUSPEND 0x04 +#define RB_USB_IE_SOF 0x08 +#define RB_USB_IE_FIFOOV 0x10 + +#ifdef SOC_SERIES_CH569 +#define RB_USB_IE_SETUPACT 0x20 +#define RB_USB_IE_ISOACT 0x40 +#define RB_USB_IE_DEV_NAK 0x80 +#else +#define RB_USB_IE_DEV_NAK 0x40 +#define RB_USB_IE_DEV_SOF 0x80 +#endif + +union _usb_suspend +{ + uint8_t reg; + struct + { + uint8_t resv_0 : 1; + uint8_t dev_wakeup : 1; // RW, Remote wake-up control bit + uint8_t resv_2 : 6; + }; +}; +#define RB_DEV_WAKEUP 0x02 + +union _usb_spd_type +{ + uint8_t reg; + struct + { + uint8_t speed_mask : 2; // RO, Actual transfer speed + uint8_t resv_2 : 6; + }; +}; +#define RB_USBSPEED_MASK 0x03 // same USBHS_FULL_SPEED... + +union _usb_mis_st +{ + uint8_t reg; + struct + { + uint8_t split_en : 1; // RO, SPLIT packet transmission enabled, HOST mode + uint8_t attach : 1; // RO, USB device connection status bit, HOST mode + uint8_t bus_suspend : 1; // RO, USB suspend status bit + uint8_t bus_reset : 1; // RO, USB bus reset status bit + uint8_t fifo_rdy : 1; // RO, USB receive FIFO data ready status bit + uint8_t sie_free : 1; // RO, Free status bit of USB protocol processor + uint8_t sof_act : 1; // RO, SOF packet transfer status bit, HOST mode + uint8_t sof_pres : 1; // RO, SOF packet presage status bit, HOST mode + }; +}; +#define RB_HOST_SPLIT_EN 0x01 +#define RB_USB_ATTACH 0x02 +#define RB_USBBUS_SUSPEND 0x04 +#define RB_USBBUS_RESET 0x08 +#define RB_USB_FIFO_RDY 0x10 +#define RB_USB_SIE_FREE 0x20 +#define RB_USB_SOF_ACT 0x40 +#define RB_USB_SOF_PRES 0x80 + +union _usb_int_fg +{ + uint8_t reg; + struct + { + uint8_t busrst : 1; // RW1, USB bus reset event IF, DEVICE mode + uint8_t transfer : 1; // RW1, USB transmission complete interrupt flag + uint8_t suspend : 1; // RW1, USB bus suspend/wake-up event IF + uint8_t hst_sof : 1; // RW1, SOF timing interrupt flag bit, HOST mode + uint8_t fifoov : 1; // RW1, USB FIFO overflow interrupt flag + uint8_t setupact : 1; // RW1, SETUP transaction complete IF (CH569) + uint8_t isoact : 1; // RW1, ISOchronous token received IF (CH569) + uint8_t resv_7 : 1; + }; + struct + { + uint8_t detect : 1; // RW1, USB device connect/disconnect IF, HOST mode + uint8_t stuff_1 : 7; + }; +}; +#define RB_USB_IF_BUSRST 0x01 +#define RB_USB_IF_DETECT 0x01 +#define RB_USB_IF_TRANSFER 0x02 +#define RB_USB_IF_SUSPEND 0x04 +#define RB_USB_IF_HST_SOF 0x08 +#define RB_USB_IF_FIFOOV 0x10 +#define RB_USB_IF_SETUPACT 0x20 +#define RB_USB_IF_ISOACT 0x40 + +union _usb_int_st +{ + uint8_t reg; + struct + { + uint8_t host_res_mask : 4; // RO, Current response PID, HOST mode + uint8_t dev_token_mask : 2; // RO, Current token PID, DEVICE mode + uint8_t st_togok : 1; // RO, Current transmit DATA0/1 sync state + uint8_t st_nak : 1; // RO, NAK response status bit, DEVICE mode + }; + struct + { + uint8_t dev_endp_mask : 4; // RO, Current endpoint number, DEVICE mode + uint8_t stuff_4 : 4; + }; +}; +#define RB_HOST_RES_MASK 0x0f +#define RB_DEV_ENDP_MASK 0x0f +#define RB_DEV_TOKEN_MASK 0x30 +#define RB_USB_ST_TOGOK 0x40 +#define RB_USB_ST_NAK 0x80 + +#define DEV_TOKEN_OUT 0 +#define DEV_TOKEN_SOF 1 +#define DEV_TOKEN_IN 2 +#define DEV_TOKEN_SETUP 3 // CH567/CH568 + +#define RB_DEV_TOKEN_OUT (DEV_TOKEN_OUT << 4) +#define RB_DEV_TOKEN_SOF (DEV_TOKEN_SOF << 4) +#define RB_DEV_TOKEN_IN (DEV_TOKEN_IN << 4) + +/* + * RB_UEPn_ RB_UEPn_ RB_UEPn_ R32_UEPn_DMA as starting address, low to high + * RX_EN TX_EN BUF_MOD + * 0 0 x Endpoint is disabled, UEPn_DMA not used + * 1 0 0 1st address of RX (OUT) buffer is R32_UEPn_RX_DMA + * 1 0 1 RB_UEP_R_TOG_MASK=0, use R32_UEPn_RX_DMA + * RB_UEP_R_TOG_MASK=1, use R32_UEPn_TX_DMA + * 0 1 0 1st address of TX (IN) buffer is R32_UEPn_TX_DMA + * 0 1 1 RB_UEP_T_TOG_MASK=0, use R32_UEPn_TX_DMA + * RB_UEP_T_TOG_MASK=1, use R32_UEPn_RX_DMA + */ +#define RB_UEP_BUF_MOD 0x01 +#define RB_UEP_TX_EN 0x04 +#define RB_UEP_RX_EN 0x08 + +/* UEP_MOD offset 0 */ +#define RB_UEP4_BUF_MOD 0x01 +#define RB_UEP4_TX_EN 0x04 +#define RB_UEP4_RX_EN 0x08 +#define RB_UEP1_BUF_MOD 0x10 +#define RB_UEP1_TX_EN 0x40 +#define RB_UEP1_RX_EN 0x80 + +/* UEP_MOD offset 1 */ +#define RB_UEP2_BUF_MOD 0x01 +#define RB_UEP2_TX_EN 0x04 +#define RB_UEP2_RX_EN 0x08 +#define RB_UEP3_BUF_MOD 0x10 +#define RB_UEP3_TX_EN 0x40 +#define RB_UEP3_RX_EN 0x80 + +/* UEP_MOD offset 2 */ +#define RB_UEP5_BUF_MOD 0x01 +#define RB_UEP5_TX_EN 0x04 +#define RB_UEP5_RX_EN 0x08 +#define RB_UEP6_BUF_MOD 0x10 +#define RB_UEP6_TX_EN 0x40 +#define RB_UEP6_RX_EN 0x80 + +/* UEP_MOD offset 3 */ +#define RB_UEP7_BUF_MOD 0x01 +#define RB_UEP7_TX_EN 0x04 +#define RB_UEP7_RX_EN 0x08 + +/* each nibble is an ep index map : {hi_lo_nibble(1), reg_offset(3)} */ +#define UEP_MOD_MAP 0x3a209180 +#define uep_mod_offset(ep) (((UEP_MOD_MAP >> (ep * 4)) & 3)) +#define uep_mod_shift(ep) (((UEP_MOD_MAP >> (ep * 4)) & 8) ? 4 : 0) + +union _uep_rt_ctrl +{ + uint8_t reg; + struct + { + uint8_t res_mask : 2; // RW, response control bits + uint8_t res_no : 1; // RW, not expecting response + uint8_t tog_mask : 2; // RW, transmit/expect DATAx + uint8_t autotog : 1; // RW, auto DATAx toggle (not for EP0) + uint8_t resv_6 : 2; + }; +}; +#define RB_UEP_RES_MASK 0x03 +#define RB_UEP_RES_NO 0x04 +#define RB_UEP_TOG_MASK 0x18 +#define RB_UEP_AUTOTOG 0x20 + +#define UEP_RES_ACK 0 +#define UEP_RES_NYET 1 +#define UEP_RES_NAK 2 +#define UEP_RES_STALL 3 + +#define UEP_TOG_DATA0 0 +#define UEP_TOG_DATA1 1 +#define UEP_TOG_DATA2 2 +#define UEP_TOG_MDATA 3 + +#define RB_UEP_RES_ACK (UEP_RES_ACK << 0) +#define RB_UEP_RES_NYET (UEP_RES_NYET << 0) +#define RB_UEP_RES_NAK (UEP_RES_NAK << 0) +#define RB_UEP_RES_STALL (UEP_RES_STALL << 0) + +#define RB_UEP_TOG_DATA0 (UEP_TOG_DATA0 << 3) +#define RB_UEP_TOG_DATA1 (UEP_TOG_DATA1 << 3) +#define RB_UEP_TOG_DATA2 (UEP_TOG_DATA2 << 3) +#define RB_UEP_TOG_MDATA (UEP_TOG_MDATA << 3) + +union _uh_rt_ctrl +{ + uint8_t reg; + struct + { + uint8_t res_mask : 2; // RW, response control bits + uint8_t res_no : 1; // RW, not expecting response + uint8_t tog_mask : 2; // RW, expected DATAx + uint8_t autotog : 1; // RW, auto DATAx toggle + uint8_t data_no : 1; // RW, not expecting data + uint8_t resv_7 : 1; + }; +}; +#define RB_UH_RES_MASK 0x03 +#define RB_UH_RES_NO 0x04 +#define RB_UH_TOG_MASK 0x18 +#define RB_UH_AUTOTOG 0x20 +#define RB_UH_DATA_NO 0x40 + +#define UH_RES_ACK 0 +#define UH_RES_NYET 1 +#define UH_RES_NAK 2 +#define UH_RES_STALL 3 + +#define UH_TOG_DATA0 0 +#define UH_TOG_DATA1 1 +#define UH_TOG_DATA2 2 +#define UH_TOG_MDATA 3 + +#define RB_UH_RES_ACK (UH_RES_ACK << 0) +#define RB_UH_RES_NYET (UH_RES_NYET << 0) +#define RB_UH_RES_NAK (UH_RES_NAK << 0) +#define RB_UH_RES_STALL (UH_RES_STALL << 0) + +#define RB_UH_TOG_DATA0 (UH_TOG_DATA0 << 3) +#define RB_UH_TOG_DATA1 (UH_TOG_DATA1 << 3) +#define RB_UH_TOG_DATA2 (UH_TOG_DATA2 << 3) +#define RB_UH_TOG_MDATA (UH_TOG_MDATA << 3) + +union _uhost_ctrl +{ + uint8_t reg; + struct + { + uint8_t bus_reset : 1; // RW, USB host transmit bus reset signal + uint8_t bus_suspend : 1; // RW, USB host transmit suspend signal + uint8_t bus_resume : 1; // RW, wake up device when bus suspended + uint8_t resv_3 : 4; + uint8_t autosof_en : 1; // RW, Auto generate SOF packet enable (CH569) + }; +}; +#define RB_UH_BUS_RESET 0x01 +#define RB_UH_BUS_SUSPEND 0x02 +#define RB_UH_BUS_RESUME 0x04 +#define RB_UH_AUTOSOF_EN 0x80 + +union _uh_ep_mod +{ + uint8_t reg; + struct + { + uint8_t rbuf_mod : 1; // RW, CH567/CH568 only + uint8_t resv_1 : 2; + uint8_t rx_en : 1; // RW, enable HOST receiver (IN) + uint8_t tbuf_mod : 1; // RW, CH567/CH568 only + uint8_t resv_5 : 1; + uint8_t tx_en : 1; // RW, enable HOST transmitter (SETUP/OUT) + uint8_t resv_7 : 1; + }; +}; +#define RB_UH_RBUF_MOD 0x01 +#define RB_UH_RX_EN 0x08 +#define RB_UH_TBUF_MOD 0x10 +#define RB_UH_TX_EN 0x40 + +union _uh_ep_pid +{ + uint16_t reg; + struct + { + uint8_t epnum_mask : 4; // RW, Set endpoint number of the target device + uint8_t token_mask : 4; // RW, Set the token PID packet identification + uint8_t resv; + }; +}; +#define RB_UH_EPNUM_MASK 0x0f +#define RB_UH_TOKEN_MASK 0xf0 + +#ifndef SOC_SERIES_CH569 +union _uh_setup +{ + uint8_t reg; + struct + { + uint8_t resv_0 : 6; + uint8_t sof_en : 1; // WO, Auto generate SOF packet enable + uint8_t resv_7 : 1; + }; +}; +#define RB_UH_SOF_EN 0x40 +#endif + +/* + * USBHS Global Registers : + * + * 0x00 R8_USB_CTRL: USB control register + * 0x02 R8_USB_INT_EN: USB interrupt enable register + * 0x03 R8_USB_DEV_AD: USB addresss register + * 0x04 R16_USB_FRAME_NO: USBHS frame number register + * 0x06 R8_USB_SUSPEND: USB suspend control register + * 0x08 R8_USB_SPD_TYPE: USB current speed type register + * 0x09 R8_USB_MIS_ST: USB miscellaneous status register + * 0x0a R8_USB_INT_FG: USB interrupt flag register + * 0x0b R8_USB_INT_ST: USB interrpt status register + * 0x0c R16_USB_RX_LEN: USB reception length register + */ + +/* + * CH565/CH569 USBHS DEVICE Related Registers : + * + * 0x10 R8_UEP4_1_MOD: Endpoint 1(9) / 4(8/12) mode control register + * 0x11 R8_UEP2_3_MOD: Endpoint 2(10) / 3(11) mode control register + * 0x12 R8_UEP5_6_MOD: Endpoint 5(13) / 6(14) mode control register + * 0x13 R8_UEP7_MOD: Endpoint 7(15) mode control register + * 0x14 R32_UEP0_RT_DMA: Start address of endpoint0 buffer + * 0x18 R32_UEP1_RX_DMA: Start address of endpoint 1(9) receive buffer + * 0x1c R32_UEP2_RX_DMA: Start address of endpoint 2(10) receive buffer + * 0x20 R32_UEP3_RX_DMA: Start address of endpoint 3(11) receive buffer + * 0x24 R32_UEP4_RX_DMA: Start address of endpoint 4(8/12) receive buffer + * 0x28 R32_UEP5_RX_DMA: Start address of endpoint 5(13) receive buffer + * 0x2c R32_UEP6_RX_DMA: Start address of endpoint 6(14) receive buffer + * 0x30 R32_UEP7_RX_DMA: Start address of endpoint 7(15) receive buffer + * 0x34 R32_UEP1_TX_DMA: Start address of endpoint 1(9) transmit buffer + * 0x38 R32_UEP2_TX_DMA: Start address of endpoint 2(10) transmit buffer + * 0x3c R32_UEP3_TX_DMA: Start address of endpoint 3(11) transmit buffer + * 0x40 R32_UEP4_TX_DMA: Start address of endpoint 4(8/12) transmit buffer + * 0x44 R32_UEP5_TX_DMA: Start address of endpoint 5(13) transmit buffer + * 0x48 R32_UEP6_TX_DMA: Start address of endpoint 6(14) transmit buffer + * 0x4c R32_UEP7_TX_DMA: Start address of endpoint 7(15) transmit buffer + * 0x50 R16_UEP0_MAX_LEN: Endpoint 0 receive maximum length packet register + * 0x54 R16_UEP1_MAX_LEN: Endpoint 1(9) receive maximum length packet register + * 0x58 R16_UEP2_MAX_LEN: Endpoint 2(10) receive maximum length packet register + * 0x5c R16_UEP3_MAX_LEN: Endpoint 3(11) receive maximum length packet register + * 0x60 R16_UEP4_MAX_LEN: Endpoint 4(8/12) receive maximum length packet register + * 0x64 R16_UEP5_MAX_LEN: Endpoint 5(13) receive maximum length packet register + * 0x68 R16_UEP6_MAX_LEN: Endpoint 6(14) receive maximum length packet register + * 0x6c R16_UEP7_MAX_LEN: Endpoint 7(15) receive maximum length packet register + * 0x70 R16_UEP0_T_LEN: Endpoint 0 transmission length register + * 0x72 R8_UEP0_TX_CTRL: Endpoint 0 transmit control register + * 0x73 R8_UEP0_RX_CTRL: Endpoint 0 receive control register + * 0x74 R16_UEP1_T_LEN: Endpoint 1(9) transmission length register + * 0x76 R8_UEP1_TX_CTRL: Endpoint 1(9) transmit control register + * 0x77 R8_UEP1_RX_CTRL: Endpoint 1(9) receive control register + * 0x78 R16_UEP2_T_LEN: Endpoint 2(10) transmission length register + * 0x7a R8_UEP2_TX_CTRL: Endpoint 2(10) transmit control register + * 0x7b R8_UEP2_RX_CTRL: Endpoint 2(10) receive control register + * 0x7c R16_UEP3_T_LEN: Endpoint 3(11) transmission length register + * 0x7e R8_UEP3_TX_CTRL: Endpoint 3(11) transmit control register + * 0x7f R8_UEP3_RX_CTRL: Endpoint 3(11) receive control register + * 0x80 R16_UEP4_T_LEN: Endpoint 4(8/12) transmission length register + * 0x82 R8_UEP4_TX_CTRL: Endpoint 4(8/12) transmit control register + * 0x83 R8_UEP4_RX_CTRL: Endpoint 4(8/12) receive control register + * 0x84 R16_UEP5_T_LEN: Endpoint 5(13) transmission length register + * 0x86 R8_UEP5_TX_CTRL: Endpoint 5(13) transmit control register + * 0x87 R8_UEP5_RX_CTRL: Endpoint 5(13) receive control register + * 0x88 R16_UEP6_T_LEN: Endpoint 6(14) transmission length register + * 0x8a R8_UEP6_TX_CTRL: Endpoint 6(14) transmit control register + * 0x8b R8_UEP6_RX_CTRL: Endpoint 6(14) receive control register + * 0x8c R16_UEP7_T_LEN: Endpoint 7(15) transmission length register + * 0x8e R8_UEP7_TX_CTRL: Endpoint 7(15) transmit control register + * 0x8f R8_UEP7_RX_CTRL: Endpoint 7(15) receive control register + * + * CH567/CH568 USBHS DEVICE Related Registers : + * + * 0x10 UEP4_1_MOD: Endpoint 1/4 mode control register + * 0x11 UEP2_3_MOD: Endpoint 2/3 mode control register + * 0x14 UEP0_DMA: Endpoint 0 DMA buffer start address + * 0x18 UEP1_DMA: Endpoint 1 DMA buffer start address + * 0x1c UEP2_DMA: Endpoint 2 DMA buffer start address + * 0x20 UEP3_DMA: Endpoint 3 DMA buffer start address + * 0x24 UEP0_MAX_LEN: Endpoint 0 receive maximum length packet register + * 0x28 UEP1_MAX_LEN: Endpoint 1 receive maximum length packet register + * 0x2c UEP2_MAX_LEN: Endpoint 2 receive maximum length packet register + * 0x30 UEP3_MAX_LEN: Endpoint 3 receive maximum length packet register + * 0x34 UEP4_MAX_LEN: Endpoint 4 receive maximum length packet register + * 0x38 UEP0_T_LEN: Endpoint 0 transmission length register + * 0x3a UEP0_TX_CTRL: Endpoint 0 transmit control register + * 0x3b UEP0_RX_CTRL: Endpoint 0 receive control register + * 0x3c UEP1_T_LEN: Endpoint 1 transmission length register + * 0x3e UEP1_TX_CTRL: Endpoint 1 transmit control register + * 0x3f UEP1_RX_CTRL: Endpoint 1 receive control register + * 0x40 UEP2_T_LEN: Endpoint 2 transmission length register + * 0x42 UEP2_TX_CTRL: Endpoint 2 transmit control register + * 0x43 UEP2_RX_CTRL: Endpoint 2 receive control register + * 0x44 UEP2_T_LEN: Endpoint 3 transmission length register + * 0x46 UEP2_TX_CTRL: Endpoint 3 transmit control register + * 0x47 UEP2_RX_CTRL: Endpoint 3 receive control register + * 0x48 UEP4_T_LEN: Endpoint 4 transmission length register + * 0x4a UEP4_TX_CTRL: Endpoint 4 transmit control register + * 0x4b UEP4_RX_CTRL: Endpoint 4 receive control register + */ + +/* + * CH565/CH569 USBHS HOST Related Registers : + * + * 0x01 R8_UHOST_CTRL: USB host control register + * 0x11 R8_UH_EP_MOD: USB host endpoint mode register + * 0x1c R32_UH_RX_DMA: USB host receive buffer start address + * 0x3c R32_UH_TX_DMA: USB host transmit buffer start address + * 0x58 R16_UH_MAX_LEN: USB host reception maximum length packet register + * 0x78 R16_UH_EP_PID: USB host token setting register + * 0x7b R8_UH_RX_CTRL: USB host reception endpoint control register + * 0x7c R16_UH_TX_LEN: USB host transmission length register + * 0x7e R8_UH_TX_CTRL: USB host transmission endpoint control register + * 0x80 R16_UH_SPLIT_DATA: USB host transmit SPLIT packet data + * + * CH567/CH568 USBHS HOST Related Registers : + * + * 0x01 UHOST_CTRL: USB host control register + * 0x11 UH_EP_MOD: USB host endpoint mode register + * 0x1c UH_RX_DMA: USB host receive buffer start address + * 0x20 UH_TX_DMA: USB host transmit buffer start address + * 0x2c UH_RX_MAX_LEN: USB host reception maximum length packet register + * 0x3e UH_SETUP: USB host aux config register + * 0x40 UH_EP_PID: USB host token setting register + * 0x43 UH_RX_CTRL: USB host reception endpoint control register + * 0x44 UH_TX_LEN: USB host transmission length register + * 0x46 UH_TX_CTRL: USB host transmission endpoint control register + * 0x48 UH_SPLIT_DATA: USB host transmit SPLIT packet data + */ +struct usbhs_registers +{ + union + { + /* USB Global Registers */ + struct + { + union _usb_ctrl CTRL; + uint8_t stuff_01; + union _usb_int_en INT_EN; + uint8_t DEV_AD; + uint16_t FRAME_NO; + union _usb_suspend SUSPEND; + uint8_t resv_07; + union _usb_spd_type SPD_TYPE; + union _usb_mis_st MIS_ST; + union _usb_int_fg INT_FG; + union _usb_int_st INT_ST; + uint16_t RX_LEN; + }; + + /* USB DEVICE Related Registers */ + struct + { + uint32_t stuff_gr[4]; + union + { + uint8_t UEP_MOD[4]; + uint32_t R32_UEP_MOD; + }; +#ifdef SOC_SERIES_CH569 + union + { + struct + { + uint32_t UEP0_RT_DMA; + uint32_t stuff_rt[14]; + }; + struct + { + uint32_t UEP_RX_DMA[8]; // UEP_RX_DMA[0] NOT exist + uint32_t stuff_rx[7]; + }; + struct + { + uint32_t stuff_tx[7]; + uint32_t UEP_TX_DMA[8]; // UEP_TX_DMA[0] NOT exist + }; + }; +#else + struct + { + uint16_t reg; + uint16_t resv; + } UEP_DMA[4]; +#endif + struct + { + uint16_t reg; + uint16_t resv; + } UEP_MAX_LEN[UEP_ADDRESS_MAX + 1]; + struct + { + uint16_t t_len; // MSB 5 bits are fixed to 0 + union _uep_rt_ctrl TX_CTRL; + union _uep_rt_ctrl RX_CTRL; + } UEP_CTRL[UEP_ADDRESS_MAX + 1]; + }; + + /* USB HOST Related Registers */ +#ifdef SOC_SERIES_CH569 + struct + { + uint8_t stuff_00; + union _uhost_ctrl UHOST_CTRL; + uint8_t stuff_02[15]; + union _uh_ep_mod UH_EP_MOD; + uint8_t stuff_12[10]; + uint32_t UH_RX_DMA; + uint32_t stuff_20[7]; + uint32_t UH_TX_DMA; + uint32_t stuff_40[6]; + uint16_t UH_MAX_LEN; + uint16_t stuff_5a[15]; + union _uh_ep_pid UH_EP_PID; + uint8_t stuff_7a; + union _uh_rt_ctrl UH_RX_CTRL; + uint16_t UH_TX_LEN; + union _uh_rt_ctrl UH_TX_CTRL; + uint8_t stuff_7f; + uint16_t UH_SPLIT_DATA; + uint16_t stuff_82[7]; + }; +#else + struct + { + uint8_t stuff_00; + union _uhost_ctrl UHOST_CTRL; + uint8_t stuff_02[15]; + union _uh_ep_mod UH_EP_MOD; + uint8_t stuff_12[10]; + uint32_t UH_RX_DMA; + uint32_t UH_TX_DMA; + uint32_t stuff_24[2]; + uint16_t UH_MAX_LEN; + uint16_t stuff_2e[8]; + uint8_t UH_SETUP; + uint8_t stuff_3f; + union _uh_ep_pid UH_EP_PID; + uint8_t stuff_42; + union _uh_rt_ctrl UH_RX_CTRL; + uint16_t UH_TX_LEN; + union _uh_rt_ctrl UH_TX_CTRL; + uint8_t stuff_47; + uint16_t UH_SPLIT_DATA; + uint16_t stuff_4a; + }; +#endif + }; +} __packed; + +#ifdef SOC_SERIES_CH569 +CHECK_STRUCT_SIZE(struct usbhs_registers, 0x90); +#else +CHECK_STRUCT_SIZE(struct usbhs_registers, 0x4c); +#endif + +rt_inline void _uep_mod_set(volatile struct usbhs_registers *usbhs, + int ep_idx, uint8_t mod) +{ + int reg_n = uep_mod_offset(ep_idx); + int shift = uep_mod_shift(ep_idx); + int mask = 0x0f << shift; + + /* ep_idx must be 1 ~ UEP_ADDRESS_MAX */ + usbhs->UEP_MOD[reg_n] = (usbhs->UEP_MOD[reg_n] & ~mask) | (mod << shift); +} + +rt_inline uint8_t _uep_mod_get(volatile struct usbhs_registers *usbhs, int ep_idx) +{ + int reg_n = uep_mod_offset(ep_idx); + int shift = uep_mod_shift(ep_idx); + + /* ep_idx should be 1 ~ UEP_ADDRESS_MAX */ + return (usbhs->UEP_MOD[reg_n] >> shift) & 0x0f; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/soc.h b/bsp/wch/risc-v/Libraries/ch56x_drivers/soc.h index 01e5f6de39..e5fd9d7853 100644 --- a/bsp/wch/risc-v/Libraries/ch56x_drivers/soc.h +++ b/bsp/wch/risc-v/Libraries/ch56x_drivers/soc.h @@ -21,6 +21,10 @@ #define SOC_SERIES_CH569 #endif +#ifndef __packed +#define __packed __attribute__((packed)) +#endif + #define CHECK_STRUCT_SIZE(s, size) \ static_assert(sizeof(s) == size, #s " has wrong size") @@ -29,10 +33,10 @@ #define FLASH_BASE_ADDRESS 0x00000000 #define RAMS_BASE_ADDRESS 0x20000000 -#define RAMX_BASE_ADDRESS 0x20020000 #define BUS8_BASE_ADDRESS 0x80000000 #ifdef SOC_SERIES_CH569 +#define RAMX_BASE_ADDRESS 0x20020000 #define RAMS_SIZE 16 #else #define RAMS_SIZE 32 diff --git a/bsp/wch/risc-v/ch569w-evt/.config b/bsp/wch/risc-v/ch569w-evt/.config index de436382b8..1eaf24934c 100644 --- a/bsp/wch/risc-v/ch569w-evt/.config +++ b/bsp/wch/risc-v/ch569w-evt/.config @@ -38,9 +38,9 @@ CONFIG_RT_KSERVICE_USING_STDLIB=y # CONFIG_RT_USING_SEMAPHORE=y CONFIG_RT_USING_MUTEX=y -# CONFIG_RT_USING_EVENT is not set +CONFIG_RT_USING_EVENT=y CONFIG_RT_USING_MAILBOX=y -# CONFIG_RT_USING_MESSAGEQUEUE is not set +CONFIG_RT_USING_MESSAGEQUEUE=y # CONFIG_RT_USING_SIGNALS is not set # @@ -78,7 +78,7 @@ CONFIG_ARCH_RISCV=y # CONFIG_RT_USING_COMPONENTS_INIT=y CONFIG_RT_USING_USER_MAIN=y -CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_STACK_SIZE=1024 CONFIG_RT_MAIN_THREAD_PRIORITY=10 # CONFIG_RT_USING_LEGACY is not set CONFIG_RT_USING_MSH=y diff --git a/bsp/wch/risc-v/ch569w-evt/applications/SConscript b/bsp/wch/risc-v/ch569w-evt/applications/SConscript index 72c14ab8db..f99a1b878d 100644 --- a/bsp/wch/risc-v/ch569w-evt/applications/SConscript +++ b/bsp/wch/risc-v/ch569w-evt/applications/SConscript @@ -2,9 +2,11 @@ from building import * cwd = GetCurrentDir() +app = ARGUMENTS.get('app', "main") + src = Split(""" -main.c -""") +{}.c +""".format(app)) path = [cwd, str(Dir('#'))] diff --git a/bsp/wch/risc-v/ch569w-evt/applications/test.c b/bsp/wch/risc-v/ch569w-evt/applications/test.c index 4a6d114936..d77f121724 100644 --- a/bsp/wch/risc-v/ch569w-evt/applications/test.c +++ b/bsp/wch/risc-v/ch569w-evt/applications/test.c @@ -361,6 +361,52 @@ static void test_pwm(void) #define test_pwm() do {} while(0) #endif +#ifdef RT_USING_USB_DEVICE +#if !defined(RT_USING_EVENT) || !defined(RT_USING_MESSAGEQUEUE) + #error "event flag or message queue IPC not enabled" +#endif +static struct rt_thread *udvcom_thread; +static rt_device_t vcom; + +static void usbd_vcom_thread(void *param) +{ + char ch; + + while (1) + { + while (rt_device_read(vcom, 0, &ch, 1) != 1) + rt_thread_delay(1); + rt_kprintf("(%2d) %02x:%c\n", rt_device_write(vcom, 0, &ch, 1), ch, ch); + rt_pin_write(LED1_PIN, (ch & 1) ? PIN_LOW : PIN_HIGH); + } +} + +static void test_usbd() +{ + char name[] = "vcom"; + + vcom = rt_device_find(name); + if (vcom && rt_device_open(vcom, RT_DEVICE_FLAG_INT_RX) == RT_EOK) + { + rt_kprintf("%s opened\n", name); + + rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT); + rt_pin_write(LED1_PIN, PIN_LOW); + + udvcom_thread = rt_thread_create("udvcom", usbd_vcom_thread, vcom, + 512, 20, 50); + if (udvcom_thread != RT_NULL) + rt_thread_startup(udvcom_thread); + else + rt_kprintf("usvcom thread create failed !\n"); + + rt_device_write(vcom, 0, name, rt_strlen(name)); + } +} +#else + #define test_usbd() do {} while(0) +#endif + void main(void) { uint32_t wdog_timeout = 32; @@ -372,6 +418,7 @@ void main(void) test_hwtimer(); test_spi_master(); test_pwm(); + test_usbd(); rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT); rt_pin_write(LED0_PIN, led0 = PIN_LOW); diff --git a/bsp/wch/risc-v/ch569w-evt/board/linker_scripts/link.lds b/bsp/wch/risc-v/ch569w-evt/board/linker_scripts/link.lds index 41dce1bbea..b50b88dcfc 100644 --- a/bsp/wch/risc-v/ch569w-evt/board/linker_scripts/link.lds +++ b/bsp/wch/risc-v/ch569w-evt/board/linker_scripts/link.lds @@ -1,187 +1,189 @@ ENTRY( _start ) -__stack_size = 2048; +__stack_size = 1536; PROVIDE( _stack_size = __stack_size ); MEMORY { - FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 96K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K - RAMX (xrw) : ORIGIN = 0x20020000, LENGTH = 32K + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 96K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K + RAMX (xrw) : ORIGIN = 0x20020000, LENGTH = 32K } SECTIONS { - .init : - { - _sinit = .; - . = ALIGN(4); - KEEP(*(SORT_NONE(.init))) - . = ALIGN(4); - _einit = .; - } >FLASH AT>FLASH + .init : + { + _sinit = .; + . = ALIGN(4); + KEEP(*(SORT_NONE(.init))) + . = ALIGN(4); + _einit = .; + } >FLASH AT>FLASH .vector : { *(.vector); - . = ALIGN(64); + . = ALIGN(64); } >FLASH AT>FLASH - .text : - { - . = ALIGN(4); - *(.text) - *(.text.*) - *(.rodata) - *(.rodata*) - *(.glue_7) - *(.glue_7t) - *(.gnu.linkonce.t.*) - - /* section information for finsh shell */ - . = ALIGN(4); - __fsymtab_start = .; - KEEP(*(FSymTab)) - __fsymtab_end = .; - . = ALIGN(4); - __vsymtab_start = .; - KEEP(*(VSymTab)) - __vsymtab_end = .; - . = ALIGN(4); - - /* section information for initial. */ - . = ALIGN(4); - __rt_init_start = .; - KEEP(*(SORT(.rti_fn*))) - __rt_init_end = .; - . = ALIGN(4); - - /* section information for modules */ - . = ALIGN(4); - __rtmsymtab_start = .; - KEEP(*(RTMSymTab)) - __rtmsymtab_end = .; - . = ALIGN(4); - - } >FLASH AT>FLASH - - .fini : - { - KEEP(*(SORT_NONE(.fini))) - . = ALIGN(4); - } >FLASH AT>FLASH - - PROVIDE( _etext = . ); - PROVIDE( _eitcm = . ); - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >FLASH AT>FLASH - - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) - KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) - PROVIDE_HIDDEN (__init_array_end = .); - } >FLASH AT>FLASH - - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) - KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) - PROVIDE_HIDDEN (__fini_array_end = .); - } >FLASH AT>FLASH - - .ctors : - { - /* gcc uses crtbegin.o to find the start of - the constructors, so we make sure it is - first. Because this is a wildcard, it - doesn't matter if the user does not - actually link against crtbegin.o; the - linker won't look for a file to match a - wildcard. The wildcard also means that it - doesn't matter which directory crtbegin.o - is in. */ - KEEP (*crtbegin.o(.ctors)) - KEEP (*crtbegin?.o(.ctors)) - /* We don't want to include the .ctor section from - the crtend.o file until after the sorted ctors. - The .ctor section from the crtend file contains the - end of ctors marker and it must be last */ - KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) - } >FLASH AT>FLASH - - .dtors : - { - KEEP (*crtbegin.o(.dtors)) - KEEP (*crtbegin?.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - } >FLASH AT>FLASH - - .dalign : - { - . = ALIGN(4); - PROVIDE(_data_vma = .); - } >RAM AT>FLASH - - .dlalign : - { - . = ALIGN(4); - PROVIDE(_data_lma = .); - } >FLASH AT>FLASH - - .data : - { - *(.gnu.linkonce.r.*) - *(.data .data.*) - *(.gnu.linkonce.d.*) - . = ALIGN(8); - PROVIDE( __global_pointer$ = . + 0x800 ); - *(.sdata .sdata.*) - *(.sdata2.*) - *(.gnu.linkonce.s.*) - . = ALIGN(8); - *(.srodata.cst16) - *(.srodata.cst8) - *(.srodata.cst4) - *(.srodata.cst2) - *(.srodata .srodata.*) - . = ALIGN(4); - PROVIDE( _edata = .); - } >RAM AT>FLASH - - .bss : - { - . = ALIGN(4); - PROVIDE( _sbss = .); - *(.sbss*) - *(.gnu.linkonce.sb.*) - *(.bss*) - *(.gnu.linkonce.b.*) - *(COMMON*) - . = ALIGN(4); - PROVIDE( _ebss = .); - } >RAM AT>FLASH - - PROVIDE( _end = _ebss); - PROVIDE( end = . ); - - .dmadata : + .text : + { + . = ALIGN(4); + *(.text) + *(.text.*) + *(.rodata) + *(.rodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t.*) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(4); + + /* section information for modules */ + . = ALIGN(4); + __rtmsymtab_start = .; + KEEP(*(RTMSymTab)) + __rtmsymtab_end = .; + . = ALIGN(4); + + } >FLASH AT>FLASH + + .fini : + { + KEEP(*(SORT_NONE(.fini))) + . = ALIGN(4); + } >FLASH AT>FLASH + + PROVIDE( _etext = . ); + PROVIDE( _eitcm = . ); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH AT>FLASH + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH AT>FLASH + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH AT>FLASH + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >FLASH AT>FLASH + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >FLASH AT>FLASH + + .dalign : + { + . = ALIGN(4); + PROVIDE(_data_vma = .); + } >RAM AT>FLASH + + .dlalign : + { + . = ALIGN(4); + PROVIDE(_data_lma = .); + } >FLASH AT>FLASH + + .data : + { + *(.gnu.linkonce.r.*) + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.sdata2.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + . = ALIGN(4); + PROVIDE( _edata = .); + } >RAM AT>FLASH + + .bss : + { + . = ALIGN(4); + PROVIDE( _sbss = .); + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss*) + *(.gnu.linkonce.b.*) + *(COMMON*) + . = ALIGN(4); + PROVIDE( _ebss = .); + } >RAM AT>FLASH + + PROVIDE( _end = _ebss); + PROVIDE( end = . ); + + .dmadata : { - . = ALIGN(16); PROVIDE( _dmadata_start = .); + /* first 8 bytes are reserved for USB ep0 SETUP */ + . = . + 8; + . = ALIGN(16); *(.dmadata*) *(.dmadata.*) . = ALIGN(16); @@ -195,5 +197,5 @@ SECTIONS PROVIDE(_susrstack = . ); . = . + __stack_size; PROVIDE( _eusrstack = .); - } >RAM + } >RAM } diff --git a/bsp/wch/risc-v/ch569w-evt/rtconfig.h b/bsp/wch/risc-v/ch569w-evt/rtconfig.h index e24480f55d..9b894a1d99 100644 --- a/bsp/wch/risc-v/ch569w-evt/rtconfig.h +++ b/bsp/wch/risc-v/ch569w-evt/rtconfig.h @@ -25,7 +25,9 @@ #define RT_USING_SEMAPHORE #define RT_USING_MUTEX +#define RT_USING_EVENT #define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE /* Memory Management */ @@ -48,7 +50,7 @@ #define RT_USING_COMPONENTS_INIT #define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_STACK_SIZE 1024 #define RT_MAIN_THREAD_PRIORITY 10 #define RT_USING_MSH #define RT_USING_FINSH