freeRTOS with usb issue

I have a problem with the usb_serial interrupt with the freertos os, i tried to create a task handle the usb requests and used a binary semaphore technique between the Handler and the task, and once the xTaskNotify technique and all didn’t work.

Be more precise. What exactly “does not work”?

the usb didn’t configured successfully on the device manager(unknown usb device (Device Descriptor Request Failed)) and all the tasks stop running, despite the same usb handling doing well in while(1) system. @RAc

well, if “all tasks stop running,” you might have run into a fault that halted the system. In that case you need to locate the fault cause and debug it.

You need to figure out in which state the system is before proceeding.

If you publish your code here, we can look over it and point,out possible problems. If you can’t, you will need to provide MUCH more detailed information such as the system state if you expect useful input.

You may also want to check with the USB driver vendor if the code is designed to work with RTOS.

@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”);
    }
    }

what do task1 and task2 do?

Again, what exactly “does not work?” Does your code enter the infinite loop in your usb task at all, and if yes, how far does it get? Is your system basically alive, ie does your sys tick interrupt get invoked regularly? Does your usb isr get invoked? you appear to be mixing interrupt driven and polling usb driving, normally the two are mutually exclusive.

1 Like

@RAc the tasks1,2 just sending a word via UART every specific time, and they doing well before creating the 3rd usb_task.
And yes the sys_tick handler was fired continuously in the debug session, but the usb didn’t initialized well as device com port serial, the 2 tasks stop sending via uart.
Also, i put break points inside the tasks but the tasks stop running especially after
USBFS_Device_Init (ENABLE, PWR_VDD_SupplyVoltage());
how i can get the system fault details if one occurred?

well, a lot of this is guess work as you are using platform/eco system provided functions that, as @aggarg pointed out, may or may not be designed to work with RTOSs, so it would be a good idea to reach out to the driver vendor.

My shot in the dark is that your USBFS_Device_Init function enables interrupts which is a nono (interrupts must be disabled until vTaskStartScheduler enables them). Try delegating it into a “root task” that first creates the usb task then initializes the driver (or into the USB task prior to its infinite loop). But again, it’s as good a guess as anyone’s.

About fault hunting: That is extremly platform and tool dependent.

1 Like

Other thing that I notice is that you are using suspend/resume which is generally not a good idea. Consider using semaphore or task notifications.

1 Like