2025-12-08 2:48 AM
Hello,
I am trying to get Ethernet-over-USB working on a STM32U585. I want to be able to use both RNDIS and CDC-ECM, but I decided to start with RNDIS first. After a lot of trial and error and research, I am running out of ideas as to why my PC does not show any devices in USB Viewer on the port where I connected the circuit board. I am developing on a B-U585I-IOT02A.
I based my work on the following example: https://github.com/STMicroelectronics/stm32-usbx-examples/tree/main/Projects/STM32H735G-DK/Applications/USBX/Ux_Device_RNDIS
I provide my code here (if not mentioned it is generated by CubeMX). I did not touch files if code is not shown here:
main.c:
int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the System Power */
SystemPower_Config();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ICACHE_Init();
// HINT: this function is called later as in the example project
// MX_USB_OTG_FS_PCD_Init();
MX_ThreadX_Init();
while(1);
}app_usbx_device.c:
#include "app_usbx_device.h"
/* Private define ------------------------------------------------------------*/
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
/* Private variables ---------------------------------------------------------*/
static ULONG rndis_interface_number;
static ULONG rndis_configuration_number;
static UCHAR rndis_local_nodeid[UX_DEVICE_CLASS_RNDIS_NODE_ID_LENGTH];
static UCHAR rndis_remote_nodeid[UX_DEVICE_CLASS_RNDIS_NODE_ID_LENGTH];
static UX_SLAVE_CLASS_RNDIS_PARAMETER rndis_parameter;
static TX_THREAD ux_device_app_thread;
/* Private function prototypes -----------------------------------------------*/
static VOID app_ux_device_thread_entry(ULONG thread_input);
UINT MX_USBX_Device_Init(VOID *memory_ptr)
{
UINT ret = UX_SUCCESS;
UCHAR *device_framework_high_speed;
UCHAR *device_framework_full_speed;
ULONG device_framework_hs_length;
ULONG device_framework_fs_length;
ULONG string_framework_length;
ULONG language_id_framework_length;
UCHAR *string_framework;
UCHAR *language_id_framework;
UCHAR *pointer;
TX_BYTE_POOL *byte_pool = (TX_BYTE_POOL*)memory_ptr;
/* Allocate the stack for USBX Memory */
if (tx_byte_allocate(byte_pool, (VOID **) &pointer,
USBX_DEVICE_MEMORY_STACK_SIZE, TX_NO_WAIT) != TX_SUCCESS)
{
return TX_POOL_ERROR;
}
/* Initialize USBX Memory */
if (ux_system_initialize(pointer, USBX_DEVICE_MEMORY_STACK_SIZE, UX_NULL, 0) != UX_SUCCESS)
{
return UX_ERROR;
}
/* Get Device Framework High Speed and get the length */
device_framework_high_speed = USBD_Get_Device_Framework_Speed(USBD_HIGH_SPEED,
&device_framework_hs_length);
/* Get Device Framework Full Speed and get the length */
device_framework_full_speed = USBD_Get_Device_Framework_Speed(USBD_FULL_SPEED,
&device_framework_fs_length);
/* Get String Framework and get the length */
string_framework = USBD_Get_String_Framework(&string_framework_length);
/* Get Language Id Framework and get the length */
language_id_framework = USBD_Get_Language_Id_Framework(&language_id_framework_length);
/* Install the device portion of USBX */
if (ux_device_stack_initialize(device_framework_high_speed,
device_framework_hs_length,
device_framework_full_speed,
device_framework_fs_length,
string_framework,
string_framework_length,
language_id_framework,
language_id_framework_length,
UX_NULL) != UX_SUCCESS)
{
return UX_ERROR;
}
/* Initialize the rndis class parameters for the device */
rndis_parameter.ux_slave_class_rndis_instance_activate = USBD_RNDIS_Activate;
rndis_parameter.ux_slave_class_rndis_instance_deactivate = USBD_RNDIS_Deactivate;
/* Get RNDIS local MAC address */
USBD_RNDIS_GetMacAdd((uint8_t *)RNDIS_LOCAL_MAC_STR_DESC, rndis_local_nodeid);
/* Define RNDIS local node id */
rndis_parameter.ux_slave_class_rndis_parameter_local_node_id[0] = rndis_local_nodeid[0];
rndis_parameter.ux_slave_class_rndis_parameter_local_node_id[1] = rndis_local_nodeid[1];
rndis_parameter.ux_slave_class_rndis_parameter_local_node_id[2] = rndis_local_nodeid[2];
rndis_parameter.ux_slave_class_rndis_parameter_local_node_id[3] = rndis_local_nodeid[3];
rndis_parameter.ux_slave_class_rndis_parameter_local_node_id[4] = rndis_local_nodeid[4];
rndis_parameter.ux_slave_class_rndis_parameter_local_node_id[5] = rndis_local_nodeid[5];
/* Get RNDIS local MAC address */
USBD_RNDIS_GetMacAdd((uint8_t *)RNDIS_REMOTE_MAC_STR_DESC, rndis_remote_nodeid);
/* Define RNDIS remote node id */
rndis_parameter.ux_slave_class_rndis_parameter_remote_node_id[0] = rndis_remote_nodeid[0];
rndis_parameter.ux_slave_class_rndis_parameter_remote_node_id[1] = rndis_remote_nodeid[1];
rndis_parameter.ux_slave_class_rndis_parameter_remote_node_id[2] = rndis_remote_nodeid[2];
rndis_parameter.ux_slave_class_rndis_parameter_remote_node_id[3] = rndis_remote_nodeid[3];
rndis_parameter.ux_slave_class_rndis_parameter_remote_node_id[4] = rndis_remote_nodeid[4];
rndis_parameter.ux_slave_class_rndis_parameter_remote_node_id[5] = rndis_remote_nodeid[5];
rndis_parameter.ux_slave_class_rndis_parameter_vendor_id = USBD_VID;
rndis_parameter.ux_slave_class_rndis_parameter_driver_version = USBD_RNDIS_DRIVER_VERSION;
ux_utility_memory_copy(rndis_parameter.ux_slave_class_rndis_parameter_vendor_description,
USBD_PRODUCT_STRING, sizeof(USBD_PRODUCT_STRING));
/* Get rndis configuration number */
rndis_configuration_number = USBD_Get_Configuration_Number(CLASS_TYPE_RNDIS, 0);
/* Find rndis interface number */
rndis_interface_number = USBD_Get_Interface_Number(CLASS_TYPE_RNDIS, 0);
/* Initialize the device RNDIS */
if (ux_device_stack_class_register(_ux_system_slave_class_rndis_name,
ux_device_class_rndis_entry,
rndis_configuration_number,
rndis_interface_number,
&rndis_parameter) != UX_SUCCESS)
{
return UX_ERROR;
}
/* Perform the initialization of the network driver. This will initialize the
USBX network layer */
ux_network_driver_init();
/* Allocate the stack for device application main thread */
if (tx_byte_allocate(byte_pool, (VOID **) &pointer, UX_DEVICE_APP_THREAD_STACK_SIZE,
TX_NO_WAIT) != TX_SUCCESS)
{
return TX_POOL_ERROR;
}
/* Create the device application main thread */
if (tx_thread_create(&ux_device_app_thread, UX_DEVICE_APP_THREAD_NAME, app_ux_device_thread_entry,
0, pointer, UX_DEVICE_APP_THREAD_STACK_SIZE, UX_DEVICE_APP_THREAD_PRIO,
UX_DEVICE_APP_THREAD_PREEMPTION_THRESHOLD, UX_DEVICE_APP_THREAD_TIME_SLICE,
UX_DEVICE_APP_THREAD_START_OPTION) != TX_SUCCESS)
{
return TX_THREAD_ERROR;
}
return ret;
}
static VOID app_ux_device_thread_entry(ULONG thread_input)
{
MX_USB_OTG_FS_PCD_Init();
HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 0x200);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 0x80);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x80);
ux_dcd_stm32_initialize((ULONG)USB_OTG_FS, (ULONG)&hpcd_USB_OTG_FS);
if (HAL_PCD_Start(&hpcd_USB_OTG_FS) != HAL_OK) Error_Handler();
while(1);
}app_usbx_device.h:
* Includes ------------------------------------------------------------------*/
#include "ux_api.h"
#include "ux_device_rndis.h"
#include "ux_device_descriptors.h"
#include "app_azure_rtos_config.h"
#include "ux_dcd_stm32.h"
/* Private includes ----------------------------------------------------------*/
#include "usb_otg.h"
#include "ux_dcd_stm32.h"
/* Exported constants --------------------------------------------------------*/
#define USBX_DEVICE_MEMORY_STACK_SIZE 35840
#define UX_DEVICE_APP_THREAD_STACK_SIZE 2048
#define UX_DEVICE_APP_THREAD_PRIO 10
/* Exported functions prototypes ---------------------------------------------*/
UINT MX_USBX_Device_Init(VOID *memory_ptr);
#ifndef UX_DEVICE_APP_THREAD_NAME
#define UX_DEVICE_APP_THREAD_NAME "USBX Device App Main Thread"
#endif
#ifndef UX_DEVICE_APP_THREAD_PREEMPTION_THRESHOLD
#define UX_DEVICE_APP_THREAD_PREEMPTION_THRESHOLD UX_DEVICE_APP_THREAD_PRIO
#endif
#ifndef UX_DEVICE_APP_THREAD_TIME_SLICE
#define UX_DEVICE_APP_THREAD_TIME_SLICE TX_NO_TIME_SLICE
#endif
#ifndef UX_DEVICE_APP_THREAD_START_OPTION
#define UX_DEVICE_APP_THREAD_START_OPTION TX_AUTO_START
#endifI would be very grateful for any hints and tips.
Thank You!
K.S.