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
This commit is contained in:
parent
9cfb864068
commit
a38b39ac25
|
@ -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']
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 <rthw.h>
|
||||
#include <rtdebug.h>
|
||||
#include <drivers/usb_common.h>
|
||||
#include <drivers/usb_device.h>
|
||||
#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();
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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('#'))]
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue