DAPLink (CMSIS-DAP) porting to Artery AT32F425, WCH CH32V203 and WCH CH32V305.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

486 lines
14 KiB

#include "NuMicro.h"
#include "vcom_serial.h"
#include "hid_transfer.h"
void HID_InitEP(int usbhs)
{
/* EPA ==> HID Interrupt IN endpoint */
HSUSBD_ConfigEp(EPA, HID_INT_IN_EP & 0x0F, HSUSBD_EP_CFG_TYPE_INT, HSUSBD_EP_CFG_DIR_IN);
HSUSBD_SetEpBufAddr(EPA, HID_INT_IN_BUF_BA, HID_INT_IN_BUF_SZ);
HSUSBD_SET_MAX_PAYLOAD(EPA, usbhs ? HID_INT_IN_SZ_HS : HID_INT_IN_SZ_FS);
HSUSBD_ENABLE_EP_INT(EPA, HSUSBD_EPINTEN_TXPKIEN_Msk);
/* EPB ==> HID Interrupt OUT endpoint */
HSUSBD_ConfigEp(EPB, HID_INT_OUT_EP & 0x0F, HSUSBD_EP_CFG_TYPE_INT, HSUSBD_EP_CFG_DIR_OUT);
HSUSBD_SetEpBufAddr(EPB, HID_INT_OUT_BUF_BA, HID_INT_OUT_BUF_SZ);
HSUSBD_SET_MAX_PAYLOAD(EPB, usbhs ? HID_INT_OUT_SZ_HS : HID_INT_OUT_SZ_FS);
HSUSBD_ENABLE_EP_INT(EPB, HSUSBD_EPINTEN_RXPKIEN_Msk);
/* EPC ==> CDC Interrupt IN endpoint */
HSUSBD_ConfigEp(EPC, CDC_INT_IN_EP & 0x0F, HSUSBD_EP_CFG_TYPE_INT, HSUSBD_EP_CFG_DIR_IN);
HSUSBD_SetEpBufAddr(EPC, CDC_INT_IN_BUF_BA, CDC_INT_IN_BUF_SZ);
HSUSBD_SET_MAX_PAYLOAD(EPC, usbhs ? CDC_INT_IN_SZ_HS : CDC_INT_IN_SZ_FS);
/* EPD ==> CDC Bulk IN endpoint */
HSUSBD_ConfigEp(EPD, CDC_BULK_IN_EP & 0x0F, HSUSBD_EP_CFG_TYPE_BULK, HSUSBD_EP_CFG_DIR_IN);
HSUSBD->EP[EPD].EPRSPCTL = HSUSBD->EP[EPD].EPRSPCTL & (~HSUSBD_EP_RSPCTL_MODE_MASK) | HSUSBD_EP_RSPCTL_MODE_MANUAL;
HSUSBD_SetEpBufAddr(EPD, CDC_BULK_IN_BUF_BA, CDC_BULK_IN_BUF_SZ);
HSUSBD_SET_MAX_PAYLOAD(EPD, usbhs ? CDC_BULK_IN_SZ_HS : CDC_BULK_IN_SZ_FS);
HSUSBD_ENABLE_EP_INT(EPD, HSUSBD_EPINTEN_TXPKIEN_Msk);
/* EPE ==> CDC Bulk OUT endpoint */
HSUSBD_ConfigEp(EPE, CDC_BULK_OUT_EP & 0x0F, HSUSBD_EP_CFG_TYPE_BULK, HSUSBD_EP_CFG_DIR_OUT);
HSUSBD_SetEpBufAddr(EPE, CDC_BULK_OUT_BUF_BA, CDC_BULK_OUT_BUF_SZ);
HSUSBD_SET_MAX_PAYLOAD(EPE, usbhs ? CDC_BULK_OUT_SZ_HS : CDC_BULK_OUT_SZ_FS);
HSUSBD_ENABLE_EP_INT(EPE, HSUSBD_EPINTEN_RXPKIEN_Msk);
}
void HID_Init(void)
{
HSUSBD_SET_ADDR(0);
/* Enable USB BUS, Control Endpoint and Endpoint A-E global interrupt */
HSUSBD_ENABLE_USB_INT(HSUSBD_GINTEN_USBIEN_Msk |
HSUSBD_GINTEN_CEPIEN_Msk |
HSUSBD_GINTEN_EPAIEN_Msk |
HSUSBD_GINTEN_EPBIEN_Msk |
HSUSBD_GINTEN_EPCIEN_Msk |
HSUSBD_GINTEN_EPDIEN_Msk |
HSUSBD_GINTEN_EPEIEN_Msk);
/* Enable Plug-In/Un-Plug and Reset bus interrupt */
HSUSBD_ENABLE_BUS_INT(HSUSBD_BUSINTEN_VBUSDETIEN_Msk |
HSUSBD_BUSINTEN_RSTIEN_Msk);
/* Control endpoint */
HSUSBD_SetEpBufAddr(CEP, EP0_BUF_BASE, EP0_BUF_SIZE);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_SETUPPKIEN_Msk |
HSUSBD_CEPINTEN_STSDONEIEN_Msk);
HID_InitEP(0);
}
void EPA_Handler(void) // HID Interrupt IN
{
HID_SetInReport();
}
void EPB_Handler(void) // HID Interrupt OUT
{
static uint8_t buff[1024];
int len = HSUSBD->EP[EPB].EPDATCNT & 0xFFFF;
for(int i = 0; i < len; i++)
buff[i] = HSUSBD->EP[EPB].EPDAT_BYTE;
HID_GetOutReport(buff, len);
}
void EPD_Handler(void) // CDC Bulk IN
{
Vcom.in_ready = 1;
}
void EPE_Handler(void) // CDC Bulk OUT
{
Vcom.out_bytes = HSUSBD->EP[EPE].EPDATCNT & 0xFFFF;
for(int i = 0; i < Vcom.out_bytes; i++)
Vcom.out_buff[i] = HSUSBD->EP[EPE].EPDAT_BYTE;
Vcom.out_ready = 1;
}
void USBD20_IRQHandler(void)
{
uint32_t usb_if, bus_if, ept_if;
usb_if = HSUSBD->GINTSTS & HSUSBD->GINTEN;
/* Bus Event */
if(usb_if & HSUSBD_GINTSTS_USBIF_Msk)
{
bus_if = HSUSBD->BUSINTSTS & HSUSBD->BUSINTEN;
if(bus_if & HSUSBD_BUSINTSTS_VBUSDETIF_Msk)
{
if(HSUSBD_IS_ATTACHED()) // USB Plug In
{
HSUSBD_ENABLE_USB();
}
else // USB Un-plug
{
HSUSBD_DISABLE_USB();
}
HSUSBD_CLR_BUS_INT_FLAG(HSUSBD_BUSINTSTS_VBUSDETIF_Msk);
}
if(bus_if & HSUSBD_BUSINTSTS_RSTIF_Msk)
{
HSUSBD_SwReset();
HSUSBD_SET_ADDR(0);
HID_InitEP(HSUSBD->OPER & HSUSBD_OPER_CURSPD_Msk);
HSUSBD_CLR_CEP_INT_FLAG(0x1FFC);
HSUSBD_CLR_BUS_INT_FLAG(HSUSBD_BUSINTSTS_RSTIF_Msk);
}
if(bus_if & HSUSBD_BUSINTSTS_SOFIF_Msk)
{
HSUSBD_CLR_BUS_INT_FLAG(HSUSBD_BUSINTSTS_SOFIF_Msk);
}
}
/* Control Endpoint */
if(usb_if & HSUSBD_GINTSTS_CEPIF_Msk)
{
ept_if = HSUSBD->CEPINTSTS & HSUSBD->CEPINTEN;
if(ept_if & HSUSBD_CEPINTSTS_SETUPPKIF_Msk)
{
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_SETUPPKIF_Msk);
HSUSBD_ProcessSetupPacket();
return;
}
if(ept_if & HSUSBD_CEPINTSTS_OUTTKIF_Msk)
{
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_OUTTKIF_Msk);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk);
return;
}
if(ept_if & HSUSBD_CEPINTSTS_INTKIF_Msk)
{
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_INTKIF_Msk);
if(!(ept_if & HSUSBD_CEPINTSTS_STSDONEIF_Msk))
{
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_TXPKIF_Msk);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_TXPKIEN_Msk);
HSUSBD_CtrlIn();
}
else
{
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_TXPKIF_Msk);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_TXPKIEN_Msk | HSUSBD_CEPINTEN_STSDONEIEN_Msk);
}
return;
}
if(ept_if & HSUSBD_CEPINTSTS_TXPKIF_Msk)
{
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk);
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR);
if(g_hsusbd_CtrlInSize)
{
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_INTKIF_Msk);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_INTKIEN_Msk);
}
else
{
if(g_hsusbd_CtrlZero == 1)
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_ZEROLEN);
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_SETUPPKIEN_Msk|HSUSBD_CEPINTEN_STSDONEIEN_Msk);
}
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_TXPKIF_Msk);
return;
}
if(ept_if & HSUSBD_CEPINTSTS_RXPKIF_Msk)
{
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_RXPKIF_Msk);
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_SETUPPKIEN_Msk|HSUSBD_CEPINTEN_STSDONEIEN_Msk);
return;
}
if(ept_if & HSUSBD_CEPINTSTS_STSDONEIF_Msk)
{
HSUSBD_UpdateDeviceState();
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_SETUPPKIEN_Msk);
return;
}
}
/* HID Interrupt IN */
if(usb_if & HSUSBD_GINTSTS_EPAIF_Msk)
{
ept_if = HSUSBD->EP[EPA].EPINTSTS & HSUSBD->EP[EPA].EPINTEN;
if(ept_if & HSUSBD_EPINTSTS_TXPKIF_Msk)
EPA_Handler();
HSUSBD_CLR_EP_INT_FLAG(EPA, ept_if);
}
/* HID Interrupt OUT */
if(usb_if & HSUSBD_GINTSTS_EPBIF_Msk)
{
ept_if = HSUSBD->EP[EPB].EPINTSTS & HSUSBD->EP[EPB].EPINTEN;
if(ept_if & HSUSBD_EPINTSTS_RXPKIF_Msk)
EPB_Handler();
HSUSBD_CLR_EP_INT_FLAG(EPB, ept_if);
}
/* CDC Interrupt IN */
if(usb_if & HSUSBD_GINTSTS_EPCIF_Msk)
{
ept_if = HSUSBD->EP[EPC].EPINTSTS & HSUSBD->EP[EPC].EPINTEN;
HSUSBD_CLR_EP_INT_FLAG(EPC, ept_if);
}
/* CDC Bulk IN */
if(usb_if & HSUSBD_GINTSTS_EPDIF_Msk)
{
ept_if = HSUSBD->EP[EPD].EPINTSTS & HSUSBD->EP[EPD].EPINTEN;
if(ept_if & HSUSBD_EPINTSTS_TXPKIF_Msk)
EPD_Handler();
HSUSBD_CLR_EP_INT_FLAG(EPD, ept_if);
}
/* CDC Bulk OUT */
if(usb_if & HSUSBD_GINTSTS_EPEIF_Msk)
{
ept_if = HSUSBD->EP[EPE].EPINTSTS & HSUSBD->EP[EPE].EPINTEN;
if(ept_if & HSUSBD_EPINTSTS_RXPKIF_Msk)
EPE_Handler();
HSUSBD_CLR_EP_INT_FLAG(EPE, ept_if);
}
if(usb_if & HSUSBD_GINTSTS_EPFIF_Msk)
{
ept_if = HSUSBD->EP[EPF].EPINTSTS & HSUSBD->EP[EPF].EPINTEN;
HSUSBD_CLR_EP_INT_FLAG(EPF, ept_if);
}
}
void HID_ClassRequest(void)
{
if(gUsbCmd.bmRequestType & 0x80)
{
/* Device to host */
switch(gUsbCmd.bRequest)
{
case GET_IDLE:
case GET_REPORT:
case GET_PROTOCOL:
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_STALLEN_Msk);
break;
case GET_LINE_CODE:
HSUSBD_PrepareCtrlIn((uint8_t *)&LineCfg, 7);
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_INTKIF_Msk);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_INTKIEN_Msk);
break;
default:
/* Setup error, stall the device */
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_STALLEN_Msk);
break;
}
}
else
{
/* Host to device */
switch(gUsbCmd.bRequest)
{
case SET_IDLE:
case SET_REPORT:
/* Status stage */
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk);
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk);
break;
case SET_PROTOCOL:
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_STALLEN_Msk);
break;
case SET_LINE_CODE:
HSUSBD_CtrlOut((uint8_t *)&LineCfg, 7);
/* Status stage */
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk);
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk);
break;
case SET_CONTROL_LINE:
Vcom.hw_flow = gUsbCmd.wValue;
/* Status stage */
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk);
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk);
break;
default:
/* Setup error, stall the device */
HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_STALLEN_Msk);
break;
}
}
}
extern uint8_t MS_OS_20_DescriptorSet[];
void WINUSB_VendorRequest(void)
{
uint16_t len;
if(gUsbCmd.bmRequestType & 0x80)
{
/* Device to host */
switch(gUsbCmd.bRequest)
{
case WINUSB_VENDOR_CODE:
switch(gUsbCmd.wIndex & 0xFF)
{
case 7:
len = Minimum(gUsbCmd.wLength, MS_OS_20_DescriptorSet[8] | (MS_OS_20_DescriptorSet[9] << 8));
HSUSBD_PrepareCtrlIn(MS_OS_20_DescriptorSet, len);
/* Status stage */
HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_INTKIF_Msk);
HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_INTKIEN_Msk);
return;
}
}
}
else
{
/* Host to device */
}
USBD_SetStall(0);
}
/***************************************************************/
#include "DAP_Config.h"
#include "DAP.h"
static volatile uint8_t USB_RequestFlag; // Request Buffer Usage Flag
static volatile uint32_t USB_RequestIn; // Request Buffer In Index
static volatile uint32_t USB_RequestOut; // Request Buffer Out Index
static volatile uint8_t USB_ResponseIdle = 1; // Response Buffer Idle Flag
static volatile uint8_t USB_ResponseFlag; // Response Buffer Usage Flag
static volatile uint32_t USB_ResponseIn; // Response Buffer In Index
static volatile uint32_t USB_ResponseOut; // Response Buffer Out Index
static uint8_t USB_Request [DAP_PACKET_COUNT][DAP_PACKET_SIZE]; // Request Buffer
static uint8_t USB_Response[DAP_PACKET_COUNT][DAP_PACKET_SIZE]; // Response Buffer
static uint16_t USB_ResponseSize[DAP_PACKET_COUNT]; // number of bytes in response
uint8_t usbd_hid_process(void)
{
uint32_t n, len;
if((USB_RequestOut != USB_RequestIn) || USB_RequestFlag)
{
USB_ResponseSize[USB_ResponseIn] = DAP_ProcessCommand(USB_Request[USB_RequestOut], USB_Response[USB_ResponseIn]);
// Update request index and flag
n = USB_RequestOut + 1;
if(n == DAP_PACKET_COUNT)
n = 0;
USB_RequestOut = n;
if(USB_RequestOut == USB_RequestIn)
USB_RequestFlag = 0;
if(USB_ResponseIdle)
{
USB_ResponseIdle = 0;
#ifdef DAP_FW_V1
len = DAP_PACKET_SIZE;
#else
len = USB_ResponseSize[USB_ResponseIn];
#endif
for(int i = 0; i < len; i++)
HSUSBD->EP[EPA].EPDAT_BYTE = USB_Response[USB_ResponseIn][i];
HSUSBD->EP[EPA].EPTXCNT = len;
}
else
{
n = USB_ResponseIn + 1;
if(n == DAP_PACKET_COUNT)
n = 0;
USB_ResponseIn = n;
if(USB_ResponseIn == USB_ResponseOut)
USB_ResponseFlag = 1;
}
return 1;
}
return 0;
}
void HID_GetOutReport(uint8_t *buf, uint32_t len)
{
if(buf[0] == ID_DAP_TransferAbort)
{
DAP_TransferAbort = 1;
return;
}
if(USB_RequestFlag && (USB_RequestIn == USB_RequestOut))
return; // Discard packet when buffer is full
// Store data into request packet buffer
USBD_MemCopy(USB_Request[USB_RequestIn], buf, len);
USB_RequestIn++;
if(USB_RequestIn == DAP_PACKET_COUNT)
USB_RequestIn = 0;
if(USB_RequestIn == USB_RequestOut)
USB_RequestFlag = 1;
}
void HID_SetInReport(void)
{
uint32_t len;
if((USB_ResponseOut != USB_ResponseIn) || USB_ResponseFlag)
{
#ifdef DAP_FW_V1
len = DAP_PACKET_SIZE;
#else
len = USB_ResponseSize[USB_ResponseOut];
#endif
for(int i = 0; i < len; i++)
HSUSBD->EP[EPA].EPDAT_BYTE = USB_Response[USB_ResponseOut][i];
HSUSBD->EP[EPA].EPTXCNT = len;
USB_ResponseOut++;
if (USB_ResponseOut == DAP_PACKET_COUNT)
USB_ResponseOut = 0;
if (USB_ResponseOut == USB_ResponseIn)
USB_ResponseFlag = 0;
}
else
{
USB_ResponseIdle = 1;
}
}