This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Running an lpc1768 as a USB device fails

This question is a follow up to this one:

https://community.arm.com/developer/tools-software/tools/f/keil-forum/47193/implementing-a-non-hanging-usb-listener/166340#166340

trying to narrow down the cause of USB blocking thread creation. 

I'm unable to find the implementation for the USBD_Initialize() and USBD_Connect() functions in app_main(), in main.c from  the "USB Device Virtual COM (MCB1700)" sample code:

main.c:

/*------------------------------------------------------------------------------
 * Example main module
 * Copyright (c) 2019 Arm Limited (or its affiliates). All rights reserved.
 *------------------------------------------------------------------------------
 * Name:    main.c
 * Purpose: Main module
 *----------------------------------------------------------------------------*/

#include "cmsis_os2.h"                  // ::CMSIS:RTOS2

#include "LPC17xx.h"                    // Device header
#include "Board_GLCD.h"                 // ::Board Support:Graphic LCD


extern       void           app_main (void *arg);
extern const osThreadAttr_t app_main_attr;

/*------------------------------------------------------------------------------
 * main function
 *----------------------------------------------------------------------------*/
int main(void) {

  SystemCoreClockUpdate ();                     // Update System Core Clock info
  GLCD_Initialize ();                           // Initialize Graphical LCD

  osKernelInitialize ();                        // Initialize CMSIS-RTOS2
  osThreadNew (app_main, NULL, &app_main_attr); // Create application main thread
  osKernelStart ();                             // Start thread execution

  for (;;) {}
}

app_main() contains the USB init/connect code and is defined in VirtualCom.c:

/*------------------------------------------------------------------------------
 * MDK Middleware - Component ::USB:Device
 * Copyright (c) 2004-2019 Arm Limited (or its affiliates). All rights reserved.
 *------------------------------------------------------------------------------
 * Name:    VirtualCOM.c
 * Purpose: USB Device - Virtual COM Port example
 *----------------------------------------------------------------------------*/

#include "rl_usb.h"                     // Keil.MDK-Pro::USB:CORE

#include "Board_GLCD.h"                 // ::Board Support:Graphic LCD
#include "GLCD_Config.h"                // Keil.MCB1700::Board Support:Graphic LCD

// Main stack size must be multiple of 8 Bytes
#define APP_MAIN_STK_SZ (1024U)
static uint64_t app_main_stk[APP_MAIN_STK_SZ / 8];
const osThreadAttr_t app_main_attr = {
  .stack_mem  = &app_main_stk[0],
  .stack_size = sizeof(app_main_stk)
};

extern GLCD_FONT GLCD_Font_6x8;
extern GLCD_FONT GLCD_Font_16x24;

__NO_RETURN void app_main (void *arg);

/*------------------------------------------------------------------------------
 *        Application
 *----------------------------------------------------------------------------*/
__NO_RETURN void app_main (void *arg) {
  (void)arg;

  GLCD_SetBackgroundColor (GLCD_COLOR_BLUE);
  GLCD_SetForegroundColor (GLCD_COLOR_WHITE);
  GLCD_ClearScreen        ();
  GLCD_SetFont            (&GLCD_Font_16x24);
  GLCD_DrawString         (0U, 0U*24U, "    USB Device      ");
  GLCD_DrawString         (0U, 1U*24U, "   CDC ACM Class    ");
  GLCD_DrawString         (0U, 2U*24U, " VirtualCOM Example ");
  GLCD_DrawString         (0U, 4U*24U, "   USB <-> UART1    ");
  GLCD_DrawString         (0U, 8U*24U, "  Keil Tools by ARM ");
  GLCD_DrawString         (0U, 9U*24U, "    www.keil.com    ");

  USBD_Initialize         (0U);         // USB Device 0 Initialization
  USBD_Connect            (0U);         // USB Device 0 Connect

  osThreadExit();
}

Where are USBD_Initialize() and USBD_Connect() implemented? Looking through the rest of the sample declarations can be found in

rl_usb.h:

/// \brief Initialize USB Device stack and controller
/// \param[in]     device               index of USB Device.
/// \return                             status code that indicates the execution status of the function as defined with \ref usbStatus.
extern usbStatus USBD_Initialize (uint8_t device);

extern usbStatus USBD_Connect (uint8_t device);

but I couldn't find a matching implementation file (F12 returns no matching function signatures); the only definitions found were
in USBD_lpc17xx.c:

/**
  \fn          int32_t USBD_Initialize (ARM_USBD_SignalDeviceEvent_t   cb_device_event,
                                        ARM_USBD_SignalEndpointEvent_t cb_endpoint_event)
  \brief       Initialize USB Device Interface.
  \param[in]   cb_device_event    Pointer to \ref ARM_USBD_SignalDeviceEvent
  \param[in]   cb_endpoint_event  Pointer to \ref ARM_USBD_SignalEndpointEvent
  \return      \ref execution_status
*/
static int32_t USBD_Initialize (ARM_USBD_SignalDeviceEvent_t   cb_device_event,
                                ARM_USBD_SignalEndpointEvent_t cb_endpoint_event) {

  if ((usb_state & USBD_DRIVER_INITIALIZED) != 0U) { return ARM_DRIVER_OK; }

  SignalDeviceEvent   = cb_device_event;
  SignalEndpointEvent = cb_endpoint_event;

  usb_role   =  ARM_USB_ROLE_DEVICE;

  if (USB_PinsConfigure () == -1) {
    usb_role = ARM_USB_ROLE_NONE;
    return ARM_DRIVER_ERROR;
  }

  usb_state |=  USBD_DRIVER_INITIALIZED;

  return ARM_DRIVER_OK;
}

where USB_PinsConfigure() is defined in OTG_lpc17xx.c:

/**
  \fn          int32_t USB_PinsConfigure (void)
  \brief       Configure USB pins
  \return                  result of pin configuration
               - value 0:  pins configured correctly
               - value -1: pins configuration has failed
*/
int32_t USB_PinsConfigure (void) {
#if defined (LPC177x_8x)
  volatile uint8_t U1_role = 0U;  // NOT DEFINED
  volatile uint8_t U2_role = 0U;  // NOT DEFINED
#endif

  if (usb_pin_cfg == 1U) { return 0U; }
  usb_pin_cfg = 0U;

#if   defined (LPC175x_6x)
  switch (usb_role) {
    // Host pins
    case ARM_USB_ROLE_HOST:
#if   (RTE_USB_PPWR_PIN_EN == 1)
      // P1.19 - USB_PPWR -- PIN NOT DEFINED
      if (PIN_Configure (1, 19, PIN_FUNC_2, PIN_PINMODE_PULLUP,   PIN_PINMODE_NORMAL) != 0) { return -1; }
#endif
#if   (RTE_USB_PWRD_PIN_EN == 1)
      // P1.22 - USB_PWRD -- PIN NOT DEFINED
      if (PIN_Configure (1, 22, PIN_FUNC_2, PIN_PINMODE_TRISTATE, PIN_PINMODE_NORMAL) != 0) { return -1; }
#endif
#if   (RTE_USB_OVRCR_PIN_EN == 1)
      // P1.27 - USB_OVRCR
      if (PIN_Configure (1, 27, PIN_FUNC_2, PIN_PINMODE_TRISTATE, PIN_PINMODE_NORMAL) != 0) { return -1; }
#endif
      break;

    // Device pins
    case ARM_USB_ROLE_DEVICE:
#if   (RTE_USB_CONNECT_PIN_EN == 1)
      // P2.9 SoftConnect
      if (PIN_Configure (2, 9,  PIN_FUNC_1, PIN_PINMODE_PULLDOWN, PIN_PINMODE_NORMAL) != 0) { return -1; } // NOT DEFINED
#endif
#if   (RTE_USB_VBUS_PIN_EN == 1)
      // P1.30 VBUS
      if (PIN_Configure (1, 30, PIN_FUNC_2, PIN_PINMODE_TRISTATE, PIN_PINMODE_NORMAL) != 0) { return -1; }
#endif
      break;

    default:
      return -1;
  }

  // Common pins configuration
#if   (RTE_USB_UP_LED_PIN_EN == 1)
  // P1.18 GoodLink
  if (PIN_Configure (1, 18, PIN_FUNC_1, PIN_PINMODE_PULLUP,   PIN_PINMODE_NORMAL) != 0) { return -1; }
#endif
  // P0.29 D+
  if (PIN_Configure (0, 29, PIN_FUNC_1, PIN_PINMODE_TRISTATE, PIN_PINMODE_NORMAL) != 0) { return -1; }
  // P0.30 D-
  if (PIN_Configure (0, 30, PIN_FUNC_1, PIN_PINMODE_TRISTATE, PIN_PINMODE_NORMAL) != 0) { return -1; }

  usb_pin_cfg = 1U;
  return 0U;

Pins 1.19 and 1.22 (USB host config) are not connected:

and in the sample file USB_User_CDC_ACM_UART.c:

// Called during USBD_Initialize to initialize the USB CDC class instance (ACM).
void USBD_CDC0_ACM_Initialize (void) {
  ptrUART->Initialize   (UART_Callback);
  ptrUART->PowerControl (ARM_POWER_FULL);
 
#ifdef USB_CMSIS_RTOS2
  cdc_acm_bridge_tid = osThreadNew (CDC0_ACM_UART_to_USB_Thread, NULL, &cdc0_acm_uart_to_usb_thread_attr); // NOT DEFINED
#else
  cdc_acm_bridge_tid = osThreadCreate (osThread (CDC0_ACM_UART_to_USB_Thread), NULL);
#endif
}

the later which is "called during USBD_Initialize to initialize USB CDC class instance (ACM)" but where USBD_Initialize defined?

I'm not using RTOS2; a thread is created at line (on RTOS):

cdc_acm_bridge_tid = osThreadCreate (osThread (CDC0_ACM_UART_to_USB_Thread), NULL);

How can I find the total number of threads that the firmware creates? On RTOS it's in RTX_Conf_CM.c:

//-------- <<< Use Configuration Wizard in Context Menu >>> -----------------
//
// <h>Thread Configuration
// =======================
//
//   <o>Number of concurrent running user threads <1-250>
//   <i> Defines max. number of user threads that will run at the same time.
//   <i> Default: 6; 
#ifndef OS_TASKCNT
 #define OS_TASKCNT     5
#endif

I'm not sure how many threads are created by either USBD_Initialize() and USBD_Connect(); at a glance, it's at least 1 in USBD_Initialize().
I already have 4 threads without the USB related code which makes a total of at least 5. Does RTOS2 specify a predefined number of threads?

At the moment, if USBD_Initialize() and USBD_Connect() are placed before any of the previous threads, a new COM port is created but the remaining threads
fail to launch. If placed after thread creation, no COM ports are created.

Is it possible to have the lpc1768 as a USB device listener while also performing logic?

If yes, how can I go about it?

The current USB examples in keil use RTOS2; where can I find code that uses RTOS?