I received a comment that the USB port on the CY8CKit-059 is causing a timeout. This is from a Thesis. I looked at the student’s code, and it is slightly different from my implementation, so I suspect something is missing. I borrowed the code from the automatically generated API and fixed some issues with it, and released my changes GPL, with a proviso that previous licenses are not overridden.

I have not change previously posted code for USB. One of the readers of the blog who had issues traced their problems back to a bad board. There is a FreeRTOS on github under wmaxfield which is specific to the 059 board and good to use for a testbed.

During my work with the PSOC and USB, I was forced to document some of my issues for drivers within a file so I could easily recreate the environment on any new machines without having to do rediscovery. I hid it from myself in a file named Configuration.h. Nowhere close to USBSerial.c. Go figure.

Here is the text of Instructions to Myself (ITM) for the driver for a USB PSOC5 incarnation for windows 7 and Windows 10:

// The PSOC CY8CKit-059 is an (up to) 80mzh processor with built in USB.
// It also has a USB finger stub which can be broken off. 
//--Finger STUB:
//  *IF YOU KEEP IT ATTACHED* you can communicate over the finger stub with an
//  additional serial port.  With that port, you can use the UART on it with 
//  TeraTerm or Putty, or a Linux or Mac machine (using "screen" or some 
//other app).  It must be in Kitprog mode. CMSIS-DAP won't work for kitprog, 
//but will for kitprog2 updated to kitprog3.
//  Under Windows, the signed driver for the stub will automatically install
//  when it is plugged in.  In Linux or Mac, it will show up in 
//     /dev/tty (ls /dev/tty.*)
//  Macintosh 
//  The USB UART (micro-USB) connector on the CY8C-Kit059 is under 
//          /dev/tty.usbmodemxxxxx
//  or      /dev/cu.usbmodemxxxxx as a tty device.  
//  Linux:
//  The USB UART (micro-USB) connector on the CY8C-Kit059 is usually under 
//      /dev/ttyACM0. 
//  It can be under ttyACM1, ttyACM2,...ttyACM9.
//  To make world usable under Linux, then
//  create the following file as root: /etc/udev/rules.d/50-local.rules
//  using "sudo nano" to write the file,
//  with the following 2 lines
//   KERNEL=="ttyUSB[0-9]*",MODE="0666"
//   KERNEL=="ttyACM[0-9]*",MODE="0666"
//  this will make the plugin of the /dev/ttyACMx world usable without
//  running as root. Easiest is to reboot the linux machine to make this 
//  work.
//  You can restart the udev services rather than reboot.    
// Windows
//  The USB UART (micro-USB) driver is automatically created by PSOC Creator, 
//  and can be installed
//  under Windows 7 (unsigned driver) or under Windows 10 (signed).  See
//  the following information:  
// for a discussion of Windows 7 Driver,
//  or
//     Windows 10 driver info: (cypress page)
//      (infineon page:)
//   The knowledge base article is here: (cypress page)
//     ( )
//      (infineon page)
//  or
//    Windows 7 driver info:
//  After programming the PSoC, plug in the USBUART using a USB cable. 
//  You can interrupt the install, but that takes as long as waiting for the 
//  installer to give up talking to Windows Update Server.  Select the local 
//  file location option, and browse to the driver file in the PSOC directory 
//  in your project. It will be at:  
//     PROJECTNAME.cysdn\Generated_Source\PSOC5, 
//  assuming your project is named “PROJECTNAME.” Install that unsigned 
//  driver. 
//  You may have to Google allowing unsigned drivers for Windows 7. 
//  It should be functional after that. 
//    If not, try rebooting your VM if running under Mac or Linux or 
//    reboot your Windows machine if running natively.

Here is the FreeRTOS style code for using the USB port. Notice the “lineChanged” section to detect plug/unplugs:

  * SOCino 3d printer firmware, FreeRTOS version
 * Copyright 2020, Wade Maxfield
 * Written by Wade Maxfield
 * Commercial license Available.
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <>.
    This license does not override previous licenses

#include "main.h"
#include "Debug/TerminalDebug.h"
#include "Messages/MessageRouter.h"

#define USBFS_DEVICE (0)  // not sure why needed, is probably in future Cypress plans

const TickType_t xDelay = pdMS_TO_TICKS(1);
const TickType_t mDelay = pdMS_TO_TICKS(5000) ;

// these variables are modified at runtime to allow input from
// UART or from USB Serial.
// If this is to be standalone you MUST setup the Q here.
QueueHandle_t *USBMessageQPtr; // in the USB receive task 

SerialMessage *USBSerialRxBuffer[NUMBER_OF_MSG_BUFFERS+1];

int16_t currentBuffer;
/* The task that is created three times. */
static portTASK_FUNCTION_PROTO( vUSBSerialTask, pvParameters );
SemaphoreHandle_t USBMutex;
static int16_t qError;

// allow multiple task access through semaphores.
// Blocks until sends or a failure occurs.
// Fails silently
void USBport_putString( char *msg)
    int16 hold=0;
    if(0 == USBUART_GetConfiguration()) 
    // the following has to be checked more than once,
    // since at ~80mhz bus clock the USB can report
    // no activity between calls.
    // if 20 milliseconds have passed, the USB is 
    // probably unplugged.
    while (0==USBUART_CheckActivity()){
        if (++hold>20){
        vTaskDelay(xDelay);// wait 1 millisecond
    while(0 == USBUART_CDCIsReady()){
        // if an error in the uart, skip.
        if (++hold>10){

    if (USBUART_CDCIsReady())

// create the task and the serialization semaphore
void vStartUSBSerialTask( UBaseType_t uxPriority )
    /*Setup the mutex to control port access*/
    USBMutex = xSemaphoreCreateMutex();
	/* Spawn the task. */
	xTaskCreate( vUSBSerialTask, "USBSerial", USBSerialSTACK_SIZE, NULL, uxPriority, ( TaskHandle_t * ) &TaskMonitorArray[USB_SERIAL_TASK].taskHandle);

static portTASK_FUNCTION( vUSBSerialTask, pvParameters )
    uint16_t rxCount;
    uint16_t myTaskMsgBufferNumber=0;
    TaskMonitor_t *TaskMonitorPtr = &TaskMonitorArray[USB_SERIAL_TASK];
    static uint16_t firstTime=pdFALSE;
   	/* The parameters are not used. */
	( void ) pvParameters;
    int index;
    for (index=0; index < NUMBER_OF_MSG_BUFFERS; index++) {
        if (!USBSerialRxBuffer[index]) // did someone else handle?
            USBSerialRxBuffer[index]=(SerialMessage *) pvPortMalloc( sizeof(SerialMessage));   

    DebugPrintString("USBSerial Task Started..." CRLF);
    // allow queues to be set up, etc.
// This code provides a message router between uart and usb if needed
//    HandleMessageRoutingSetup();// sets up USBMessageQPtr

  //!!!!!!! WARNING  !!!!!!!!!!!!
  // set up the Queue pointer properly here if you do not have
  // an external message router.  In original code, this was
  // already done in HandleMessageRoutingSetup();

    /* Start the USB_UART */
    /* Start USBFS operation with 5-V operation. */
    // This, in theory, should be in HardwareInit.c
    firstTime = pdFALSE;
        /* Host can send double SET_INTERFACE request. */
        if (0u != USBUART_IsConfigurationChanged())
            /* Initialize IN endpoints when device is configured. */
            if (0u != USBUART_GetConfiguration())
                /* Enumeration is done, enable OUT endpoint to receive data 
                 * from host. */
        if(0 != USBUART_GetConfiguration()){  
            if (USBUART_IsLineChanged())
                firstTime = pdTRUE;
            if (firstTime){
                // every time a connect or change of baud, etc. occurs
                // print the signon string
                firstTime = pdFALSE;
                USBport_putString(START_STRING CRLF);
            /* Check for input data from host. */
            if (0u != USBUART_DataIsReady()){
                SerialMessage *ptr = USBSerialRxBuffer[myTaskMsgBufferNumber];
                /* Read received data and re-enable OUT endpoint. */
                rxCount = USBUART_GetAll(ptr->msg);
                // now post these bytes to the Debug Terminal Task
                ptr->ucMessageID = myTaskMsgBufferNumber++;
                ptr->msg[rxCount]=0;// terminate string just in case
                // if Message queue not assigned, don't use
                if (USBMessageQPtr){// see MessageRouter.c
                    // message will either post to GCodeCommandReceiverMessageQ (in GCodeHandlerTask.c)
                    // or TerminalSerialMessageQ (in TerminalDebug.c)
                    // General Message Flow:
                    // GCodeCommandReceiverMessageQ->GCodeHoldOffMessageQ->gMotorCommandQueue
                    if( QSend( *USBMessageQPtr,&ptr, pdMS_TO_TICKS(50),TaskMonitorPtr ) != pdPASS )
                			qError ++;
                            //try one more time
                            QSend( *USBMessageQPtr,&ptr, pdMS_TO_TICKS(50),TaskMonitorPtr);
                    if (myTaskMsgBufferNumber >= NUMBER_OF_MSG_BUFFERS)
                        myTaskMsgBufferNumber=0; // reset the ring
                /* Get and process inputs here */
            } else {
                // let someone else run, wait 50 milliseconds

        } else {
            // let someone else run, wait 50 milliseconds to see if event occurs

    } /*lint !e715 !e818 !e830 Function definition must be standard for task creation. */


// end of file



Add a Comment

Your email address will not be published. Required fields are marked *