@RAc @aggarg
Firstly, Thank you for your replies and contributing. The WCH offer examples modularity for what the mcu can do with. i implemented a large system based on while(1) polling design—> that means the usb with isr perform well(i use it stablish a Microshell on the ch32x035 mcu for easy communicating with the user later).the WCH also offer an example module for the freeRTOS. i pulled it and follow the standards of freertos with the interrupts. the wch usb_device_SimulateCDC_example: ch32x035/EVT/EXAM/USB/USBFS/DEVICE/SimulateCDC at main · openwch/ch32x035 · GitHub
FreeRTOS_example: https://github.com/openwch/ch32x035/tree/main/EVT/EXAM/FreeRTOS/FreeRTOS_Corea
snippet code for my first integrating project (USB + freeRTOS) :
void USB_task (void *pvParameters) {
printf ("usb_inintialized......\r\n");
while (1) {
uint8_t intflag = USBFSD->INT_FG;
uint8_t intst = USBFSD->INT_ST;
uint8_t errflag;
uint16_t len;
if (intflag & USBFS_UIF_TRANSFER) {
switch (intst & USBFS_UIS_TOKEN_MASK) {
case USBFS_UIS_TOKEN_IN:
switch (intst & (USBFS_UIS_TOKEN_MASK | USBFS_UIS_ENDP_MASK)) {
case USBFS_UIS_TOKEN_IN | DEF_UEP0:
if (USBFS_SetupReqLen == 0) {
USBFSD->UEP0_CTRL_H = (USBFSD->UEP0_CTRL_H & ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_TOG | USBFS_UEP_R_RES_ACK;
}
if ((USBFS_SetupReqType & USB_REQ_TYP_MASK) != USB_REQ_TYP_STANDARD) {
// Non-standard request
} else {
switch (USBFS_SetupReqCode) {
case USB_GET_DESCRIPTOR:
len = USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen;
memcpy (USBFS_EP0_4Buf, pUSBFS_Descr, len);
USBFS_SetupReqLen -= len;
pUSBFS_Descr += len;
USBFSD->UEP0_TX_LEN = len;
USBFSD->UEP0_CTRL_H ^= USBFS_UEP_T_TOG;
break;
case USB_SET_ADDRESS:
USBFSD->DEV_ADDR = (USBFSD->DEV_ADDR & USBFS_UDA_GP_BIT) | USBFS_DevAddr;
break;
}
}
break;
case USBFS_UIS_TOKEN_IN | DEF_UEP1:
USBFSD->UEP1_CTRL_H ^= USBFS_UEP_T_TOG;
USBFSD->UEP1_CTRL_H = (USBFSD->UEP1_CTRL_H & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_NAK;
USBFS_Endp_Busy[DEF_UEP1] = 0;
break;
case USBFS_UIS_TOKEN_IN | DEF_UEP3:
USBFSD->UEP3_CTRL_H ^= USBFS_UEP_T_TOG;
USBFSD->UEP3_CTRL_H = (USBFSD->UEP3_CTRL_H & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_NAK;
USBFS_Endp_Busy[DEF_UEP3] = 0;
break;
}
break;
case USBFS_UIS_TOKEN_OUT:
switch (intst & (USBFS_UIS_TOKEN_MASK | USBFS_UIS_ENDP_MASK)) {
case USBFS_UIS_TOKEN_OUT | DEF_UEP0:
len = USBFSD->RX_LEN;
if (intst & USBFS_UIS_TOG_OK) {
if ((USBFS_SetupReqType & USB_REQ_TYP_MASK) != USB_REQ_TYP_STANDARD) {
USBFS_SetupReqLen = 0;
}
if (USBFS_SetupReqLen == 0) {
USBFSD->UEP0_TX_LEN = 0;
USBFSD->UEP0_CTRL_H = (USBFSD->UEP0_CTRL_H & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK;
}
}
break;
case USBFS_UIS_TOKEN_OUT | DEF_UEP2:
USBFSD->UEP2_CTRL_H ^= USBFS_UEP_R_TOG;
len = USBFSD->RX_LEN;
for (uint16_t i = 0; i < len; i++) {
char c = USBFS_EP2_Buf[i];
if (c == '\r') {
RxBuffer[RxIndex] = '\0';
ProcessBufferFlag = 1;
} else if (RxIndex < BUFFER_SIZE - 1) {
RxBuffer[RxIndex++] = c;
Queue_Enqueue (&input_queue, c);
}
}
break;
}
break;
case USBFS_UIS_TOKEN_SETUP:
USBFSD->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_NAK | USBFS_UEP_R_TOG | USBFS_UEP_R_RES_NAK;
USBFS_SetupReqType = pUSBFS_SetupReqPak->bRequestType;
USBFS_SetupReqCode = pUSBFS_SetupReqPak->bRequest;
USBFS_SetupReqLen = pUSBFS_SetupReqPak->wLength;
USBFS_SetupReqValue = pUSBFS_SetupReqPak->wValue;
USBFS_SetupReqIndex = pUSBFS_SetupReqPak->wIndex;
len = 0;
errflag = 0;
if ((USBFS_SetupReqType & USB_REQ_TYP_MASK) != USB_REQ_TYP_STANDARD) {
if (USBFS_SetupReqType & USB_REQ_TYP_CLASS) {
switch (USBFS_SetupReqCode) {
case CDC_GET_LINE_CODING:
case CDC_SET_LINE_CODING:
case CDC_SET_LINE_CTLSTE:
case CDC_SEND_BREAK:
errflag = 0xff;
break;
}
} else {
errflag = 0xFF;
}
} else {
switch (USBFS_SetupReqCode) {
case USB_GET_DESCRIPTOR:
switch ((uint8_t)(USBFS_SetupReqValue >> 8)) {
case USB_DESCR_TYP_DEVICE:
pUSBFS_Descr = MyDevDescr;
len = DEF_USBD_DEVICE_DESC_LEN;
break;
case USB_DESCR_TYP_CONFIG:
pUSBFS_Descr = MyCfgDescr;
len = DEF_USBD_CONFIG_DESC_LEN;
break;
case USB_DESCR_TYP_STRING:
switch ((uint8_t)(USBFS_SetupReqValue & 0xFF)) {
case DEF_STRING_DESC_LANG:
pUSBFS_Descr = MyLangDescr;
len = DEF_USBD_LANG_DESC_LEN;
break;
case DEF_STRING_DESC_MANU:
pUSBFS_Descr = MyManuInfo;
len = DEF_USBD_MANU_DESC_LEN;
break;
case DEF_STRING_DESC_PROD:
pUSBFS_Descr = MyProdInfo;
len = DEF_USBD_PROD_DESC_LEN;
break;
case DEF_STRING_DESC_SERN:
pUSBFS_Descr = MySerNumInfo;
len = DEF_USBD_SN_DESC_LEN;
break;
default:
errflag = 0xFF;
break;
}
break;
default:
errflag = 0xFF;
break;
}
if (USBFS_SetupReqLen > len) {
USBFS_SetupReqLen = len;
}
len = (USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE) ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen;
memcpy (USBFS_EP0_4Buf, pUSBFS_Descr, len);
pUSBFS_Descr += len;
break;
case USB_SET_ADDRESS:
USBFS_DevAddr = (uint8_t)(USBFS_SetupReqValue & 0xFF);
break;
case USB_GET_CONFIGURATION:
USBFS_EP0_4Buf[0] = USBFS_DevConfig;
if (USBFS_SetupReqLen > 1)
USBFS_SetupReqLen = 1;
break;
case USB_SET_CONFIGURATION:
USBFS_DevConfig = (uint8_t)(USBFS_SetupReqValue & 0xFF);
USBFS_DevEnumStatus = 0x01;
break;
case USB_CLEAR_FEATURE:
if ((USBFS_SetupReqType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_DEVICE) {
if ((uint8_t)(USBFS_SetupReqValue & 0xFF) == USB_REQ_FEAT_REMOTE_WAKEUP) {
USBFS_DevSleepStatus &= ~0x01;
}
} else if ((USBFS_SetupReqType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_ENDP) {
if ((uint8_t)(USBFS_SetupReqValue & 0xFF) == USB_REQ_FEAT_ENDP_HALT) {
switch ((uint8_t)(USBFS_SetupReqIndex & 0xFF)) {
case (DEF_UEP_IN | DEF_UEP1):
USBFSD->UEP1_CTRL_H = USBFS_UEP_T_RES_NAK;
break;
case (DEF_UEP_OUT | DEF_UEP2):
USBFSD->UEP2_CTRL_H = USBFS_UEP_R_RES_ACK;
break;
case (DEF_UEP_IN | DEF_UEP3):
USBFSD->UEP3_CTRL_H = USBFS_UEP_T_RES_NAK;
break;
default:
errflag = 0xFF;
break;
}
} else {
errflag = 0xFF;
}
} else {
errflag = 0xFF;
}
break;
case USB_SET_FEATURE:
if ((USBFS_SetupReqType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_DEVICE) {
if ((uint8_t)(USBFS_SetupReqValue & 0xFF) == USB_REQ_FEAT_REMOTE_WAKEUP) {
if (MyCfgDescr[7] & 0x20) {
USBFS_DevSleepStatus |= 0x01;
} else {
errflag = 0xFF;
}
} else {
errflag = 0xFF;
}
} else if ((USBFS_SetupReqType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_ENDP) {
if ((uint8_t)(USBFS_SetupReqValue & 0xFF) == USB_REQ_FEAT_ENDP_HALT) {
switch ((uint8_t)(USBFS_SetupReqIndex & 0xFF)) {
case (DEF_UEP_IN | DEF_UEP1):
USBFSD->UEP1_CTRL_H = (USBFSD->UEP1_CTRL_H & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_STALL;
break;
case (DEF_UEP_OUT | DEF_UEP2):
USBFSD->UEP2_CTRL_H = (USBFSD->UEP2_CTRL_H & ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_RES_STALL;
break;
case (DEF_UEP_IN | DEF_UEP3):
USBFSD->UEP3_CTRL_H = (USBFSD->UEP3_CTRL_H & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_STALL;
break;
default:
errflag = 0xFF;
break;
}
} else {
errflag = 0xFF;
}
} else {
errflag = 0xFF;
}
break;
case USB_GET_INTERFACE:
USBFS_EP0_4Buf[0] = 0x00;
if (USBFS_SetupReqLen > 1)
USBFS_SetupReqLen = 1;
break;
case USB_SET_INTERFACE:
break;
case USB_GET_STATUS:
USBFS_EP0_4Buf[0] = 0x00;
USBFS_EP0_4Buf[1] = 0x00;
if ((USBFS_SetupReqType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_DEVICE) {
if (USBFS_DevSleepStatus & 0x01) {
USBFS_EP0_4Buf[0] = 0x02;
}
} else if ((USBFS_SetupReqType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_ENDP) {
switch ((uint8_t)(USBFS_SetupReqIndex & 0xFF)) {
case (DEF_UEP_IN | DEF_UEP1):
if ((USBFSD->UEP1_CTRL_H & USBFS_UEP_T_RES_MASK) == USBFS_UEP_T_RES_STALL) {
USBFS_EP0_4Buf[0] = 0x01;
}
break;
case (DEF_UEP_OUT | DEF_UEP2):
if ((USBFSD->UEP2_CTRL_H & USBFS_UEP_R_RES_MASK) == USBFS_UEP_R_RES_STALL) {
USBFS_EP0_4Buf[0] = 0x01;
}
break;
case (DEF_UEP_IN | DEF_UEP3):
if ((USBFSD->UEP3_CTRL_H & USBFS_UEP_T_RES_MASK) == USBFS_UEP_T_RES_STALL) {
USBFS_EP0_4Buf[0] = 0x01;
}
break;
default:
errflag = 0xFF;
break;
}
} else {
errflag = 0xFF;
}
if (USBFS_SetupReqLen > 2)
USBFS_SetupReqLen = 2;
break;
default:
errflag = 0xFF;
break;
}
}
if (errflag == 0xff) {
USBFSD->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_STALL | USBFS_UEP_R_TOG | USBFS_UEP_R_RES_STALL;
} else {
if (USBFS_SetupReqType & DEF_UEP_IN) {
len = (USBFS_SetupReqLen > DEF_USBD_UEP0_SIZE) ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen;
USBFS_SetupReqLen -= len;
USBFSD->UEP0_TX_LEN = len;
USBFSD->UEP0_CTRL_H = (USBFSD->UEP0_CTRL_H & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK;
} else {
if (USBFS_SetupReqLen == 0) {
USBFSD->UEP0_TX_LEN = 0;
USBFSD->UEP0_CTRL_H = (USBFSD->UEP0_CTRL_H & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK;
} else {
USBFSD->UEP0_CTRL_H = (USBFSD->UEP0_CTRL_H & ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_TOG | USBFS_UEP_R_RES_ACK;
}
}
}
break;
case USBFS_UIS_TOKEN_SOF:
break;
}
USBFSD->INT_FG = USBFS_UIF_TRANSFER;
} else if (intflag & USBFS_UIF_BUS_RST) {
USBFS_DevConfig = 0;
USBFS_DevAddr = 0;
USBFS_DevSleepStatus = 0;
USBFS_DevEnumStatus = 0;
USBFSD->DEV_ADDR = 0;
USBFS_Device_Endp_Init();
USBFSD->INT_FG = USBFS_UIF_BUS_RST;
} else if (intflag & USBFS_UIF_SUSPEND) {
USBFSD->INT_FG = USBFS_UIF_SUSPEND;
Delay_Us (10);
if (USBFSD->MIS_ST & USBFS_UMS_SUSPEND) {
USBFS_DevSleepStatus |= 0x02;
} else {
USBFS_DevSleepStatus &= ~0x02;
}
} else {
USBFSD->INT_FG = intflag;
}
vTaskSuspend (NULL); // suspend itself
}
}
void USBFS_IRQHandler (void) attribute ((interrupt (“WCH-Interrupt-fast”)));
void USBFS_IRQHandler (void) {
BaseType_t xYieldRequired;
// Resume the suspended task.
xYieldRequired = xTaskResumeFromISR (USB_Task_Handler);
// We should switch context so the ISR returns to a different task.
// NOTE: How this is done depends on the port you are using. Check
// the documentation and examples for your port.
portYIELD_FROM_ISR (xYieldRequired);
// printf ("USB_USB_USB\r\n");
}
/*********************************************************************
- @fn main
- @brief Main program.
- @return none
/
int main (void) {
NVIC_PriorityGroupConfig (NVIC_PriorityGroup_1);
Delay_Init();
USART_Printf_Init (115200);
printf (“SystemClk:%d\r\n”, SystemCoreClock);
printf (“FreeRTOS Kernel Version:%s\r\n”, tskKERNEL_VERSION_NUMBER);
USBFS_RCC_Init();
USBFS_Device_Init (ENABLE, PWR_VDD_SupplyVoltage());
/create two task test the FreeRTOS*/
printf (“1\r\n”);
xTaskCreate ((TaskFunction_t)task2_task,
(const char *)“task2”,
(uint16_t)TASK2_STK_SIZE,
(void *)NULL,
(UBaseType_t)TASK2_TASK_PRIO,
(TaskHandle_t *)&Task2Task_Handler);
printf (“2\r\n”);
xTaskCreate ((TaskFunction_t)task1_task,
(const char *)“task1”,
(uint16_t)TASK1_STK_SIZE,
(void *)NULL,
(UBaseType_t)TASK1_TASK_PRIO,
(TaskHandle_t *)&Task1Task_Handler);
printf (“4\r\n”);
xTaskCreate ((TaskFunction_t)USB_task,
(const char *)“usbTASK”,
(uint16_t)USB_STK_SIZE,
(void *)NULL,
(UBaseType_t)USB_TASK_PRIO,
(TaskHandle_t *)&USB_Task_Handler);
vTaskStartScheduler();
printf (“3\r\n”);
while (1) {
printf (“shouldn’t run at here!!\n”);
}
}