USB Component  Version 6.6
MDK-Professional Middleware for USB Device and Host
 All Data Structures Functions Variables Enumerations Enumerator Groups Pages
USB Host Custom Class

This example application shows how to connect USB to serial RS232 adapter with Prolific PL2303 UART-to-USB bridge chip to a development board. It is a simple demonstration on how to send data from the USB Host via the USB to serial RS232 adapter to an attached serial terminal. Here, the USB Host sends "Test!" to the USB to serial RS232 adapter and stores all incoming messages from the device in the variable receive_buf. This example is using the Custom Class because the PL2303 is not USB CDC ACM compliant.

The following picture shows an exemplary connection of the development board and an PL2303 based Device. The PL2303 Device is connected to a PC via RS232 to check incoming messages.

usbh_cust_pl2303_example_setup.png

Create the "USB Host Custom Class PL2303" Project

Create a new project in MDK. In this example, we are using the MCBSTM32F400 board with the STM32F407IGHx device. In the Manage Run-Time Environment window, select the following components:

  • USB:Host:Custom Class
  • CMSIS Driver:USB Host (API):Full-speed
  • CMSIS Driver:USART (API):PL2303
  • Board Support:LED (API):LED (Variant MCBSTM32F400)

Click the Resolve button and then OK.

Before continuing to add the required source code, you need to add a template file called USBH_PL2303.c:

  • Right-click on Source Group 1 and select Add New Item to Group 'Source Group 1'....
  • Click on User Code Template and scroll down on the left side, until you see the USB component with two template files.
  • Choose USB Host Prolific 2303
  • Click on Add.

Finally, your Project should look like this:

usbh_cust_example_proj_window.png
USB Host Custom Class PL2303 Project Structure

Source Files

  • Right-click on Source Group 1 and select Add New Item to Group 'Source Group 1'....
  • Click on C File (.c) and enter main in the Name box.
  • Copy the following code into the main.c file:
    #include <stdio.h>                      /* Standard I/O .h-file               */
    #include <ctype.h>                      /* Character functions                */
    #include <string.h>                     /* String and memory functions        */
     
    #include "cmsis_os.h"                   /* CMSIS RTOS definitions             */
    #include "rl_usb.h"                     /* RL-USB function prototypes         */
     
    #include "Terminal.h"
    #include "Board_LED.h"
     
    #include "Driver_USART.h"
     
    #include "stm32f4xx_hal.h"
     
    extern bool USBH_Serial_GetDeviceStatus (void);
     
    /* UART Driver */
    extern ARM_DRIVER_USART       Driver_USART9;
    #define ptrUART_USB         (&Driver_USART9)
     
    osThreadId  con_discon_thread_id;
    bool        connected;
     
    extern uint32_t os_time;
     
    uint32_t HAL_GetTick(void) {
      return os_time;
    }
     
    /* System Clock Configuration */
    void SystemClock_Config(void) {
      RCC_OscInitTypeDef RCC_OscInitStruct;
      RCC_ClkInitTypeDef RCC_ClkInitStruct;
     
      /* Enable Power Control clock */
      __PWR_CLK_ENABLE();
     
      /* The voltage scaling allows optimizing the power consumption when the
         device is clocked below the maximum system frequency (see datasheet). */
      __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
     
      /* Enable HSE Oscillator and activate PLL with HSE as source */
      RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
      RCC_OscInitStruct.HSEState = RCC_HSE_ON;
      RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
      RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
      RCC_OscInitStruct.PLL.PLLM = 25;
      RCC_OscInitStruct.PLL.PLLN = 336;
      RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
      RCC_OscInitStruct.PLL.PLLQ = 7;
      HAL_RCC_OscConfig(&RCC_OscInitStruct);
     
      /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
         clocks dividers */
      RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 |
                                    RCC_CLOCKTYPE_PCLK2;
      RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
      RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
      RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
      RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
      HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
    }
     
    /*------------------------------------------------------------------------------
     *        UART Done Callback
     *----------------------------------------------------------------------------*/
    void UART_Done (uint32_t event) {
      switch (event) {
        case ARM_USART_EVENT_SEND_COMPLETE:
          LED_On(1);
          break;
        case ARM_USART_EVENT_RECEIVE_COMPLETE:
          LED_On(2);
          break;
      }
    }
     
    /*------------------------------------------------------------------------------
     *        USB Host Serial Receive Thread
     *----------------------------------------------------------------------------*/
    void USBH_Serial_ReceiveThread (void const *arg) {
      uint8_t receive_buf[64];
      while (1) {
        ptrUART_USB->Receive (receive_buf, 64);
      }
    }
    osThreadDef(USBH_Serial_ReceiveThread, osPriorityNormal, 1, NULL);
     
    /*------------------------------------------------------------------------------
     *        USB Host Thread
     *----------------------------------------------------------------------------*/
    void USBH_Thread (void const *arg) {
      static bool con = false;
     
      USBH_Initialize (0);                        /* Initialize USB Host 0        */
     
      while (1) {
        if (USBH_CustomClass_GetDeviceStatus(0) ^ con) {
          if (!con) {
            con = true;
            LED_On(0);
            osDelay(1000);
     
            /* Initialize and configure UART <-> USB Bridge */
            ptrUART_USB->Initialize  (UART_Done);
            ptrUART_USB->PowerControl(ARM_POWER_FULL);
            ptrUART_USB->Control     (ARM_USART_MODE_ASYNCHRONOUS |
                                      ARM_USART_DATA_BITS_8       |
                                      ARM_USART_PARITY_NONE       |
                                      ARM_USART_STOP_BITS_1       |
                                      ARM_USART_FLOW_CONTROL_NONE ,
                                      115200                      );
            ptrUART_USB->Control     (ARM_USART_CONTROL_TX, 1);
            ptrUART_USB->Control     (ARM_USART_CONTROL_RX, 1);
            ptrUART_USB->Send        ("Test!\r\n", 7);
            osThreadCreate (osThread(USBH_Serial_ReceiveThread), NULL);
          } else {
            con = false;
            LED_Off(0);
          }
        } else {
          osDelay(1000);
        }
      }
    }
    osThreadDef(USBH_Thread, osPriorityNormal, 1, NULL);
     
    /*------------------------------------------------------------------------------
     *        Application
     *----------------------------------------------------------------------------*/
    int main (void) {
     
      HAL_Init();                                 /* Initialize the HAL Library   */
      SystemClock_Config();                       /* Configure the System Clock   */
      LED_Initialize           ();
     
      con_discon_thread_id =   osThreadCreate (osThread(USBH_Thread), NULL);
     
      while (1) {
        osDelay(100);
      }
    }
    
  • Right-click on Source Group 1 and select Add New Item to Group 'Source Group 1'....
  • Click on Header File (.h) and enter Terminal in the Name box.
  • Copy the following code into the Terminal.h file:
    /*------------------------------------------------------------------------------
     * MDK Middleware
     * Copyright (c) 2004-2014 ARM Germany GmbH. All rights reserved.
     *------------------------------------------------------------------------------
     * Name:    Terminal.h
     * Purpose: File manipulation example terminal definitions
     *----------------------------------------------------------------------------*/
     
    #include <stdbool.h>
     
    enum {BACKSPACE = 0x08, 
          LF        = 0x0A, 
          CR        = 0x0D, 
          CNTLQ     = 0x11, 
          CNTLS     = 0x13, 
          ESC       = 0x1B, 
          DEL       = 0x7F };
     
    /* External functions */
    extern bool getline  (char *buf, int bufsz);
    

Before building the project, you need to edit these configuration files:

  • Double-click RTE_Device.h and enable USB OTG Full-speed.
  • Double-click USBH_Config_0.c and set
    • Maximum concurrent Pipes in system to 4
    • Maximum concurrent Transfers in system to 3
  • Double-click RTX_Conf_CM.c and set
    • Default Thread stack size to 1024
    • Main Thread stack size to 1024
    • Number of threads with user-provided stack size to 4
    • Total stack size [bytes] for threads with user-provided stack size to 2048
    • RTOS Kernel Timer input clock frequency [Hz] to 168000000

Before building and downloading the project to the target, make sure that the correct debugger is set in the Options for Target dialog (ALT + F7). You may then build and download the example project to the evaluation board using the µVision commands:

  • Project –> Build target (F7)
  • Flash   –> Download (F8)
  • Debug –> Start/Stop Debug Session (Ctrl + F5)
  • Debug –> Run (F5)

After these steps, the project should start executing on your evaluation kit. In case of errors, refer to the Evaluation Board User's Guide for configuration information.

Using the "USB Host Custom Class PL2303" Project

Hardware Setup

  • Verify all jumper settings on the target hardware.
  • Connect an USB to serial RS232 adapter using the Prolific PL2303 to the development board's USBFS connector.
  • Connect the serial line to a PC and open a terminal using 115200 baud data rate.
  • You should see the message "Test!" in the terminal window. You can also send messages from the PC to the microcontroller device. For that, please check the receive_buf buffer called by the ->Receive function.