RX Flexible Software Package Documentation  Release v1.0.0

 
Azure RTOS USBX Port (rm_usbx_port)

Functions

Refer to USB (r_usb_basic) for the common API (r_usb_basic) to be called from the application.

Overview

This USB driver works by combining USBX and r_usb_basic module.

How to Configuration

Using a class other than HMSC.

The following describes how to configure USBX using PCDC as an example.

rm_usbx_pcdc1.png
Select USB Device Class
rm_usbx_pcdc2.png
Select using USB Pipe
rm_usbx_pcdc3.png
Select using USB Pipe

Using HMSC.

Since HMSC is used in a different way from other USBX modules, the usage is described below.

rm_usbx_hmsc1.png
Select USB Device Class
rm_usbx_hmsc2.svg
FileX on USBX Stack

Note

HMSC uses FileX.

For more information on FileX, please refer to the following URL.

https://github.com/eclipse-threadx/rtos-docs/blob/main/rtos-docs/filex/index.md

Limitations

timer_ticks.png
Specify value of Timer Ticks Per Second
thread_priority.png
Specify value of Thread priority
rm_usbx_hmsc_filex.png
Check the fx checkbox

Descriptor

Templates for USBX descriptors can be found in rx/fsp/src/rm_usbx_port folder. Also, please be sure to use your vendor ID.
Change the descriptor.c.template file for each class as follows if High-speed mode is used.

Examples

USBX PCDC Example

PCDC loopback example is as follows.

#define VALUE_105 (105)
#define VALUE_2 (2)
#define VALUE_103 (103)
#define VALUE_93 (93)
/******************************************************************************
* Function Name : ux_cdc_device0_instance_activate
* Description : Get instance
* Arguments : void * cdc_instance : Pointer to the area store the instance pointer
* Return value : none
******************************************************************************/
static void ux_cdc_device0_instance_activate (void * cdc_instance)
{
/* Save the CDC instance. */
g_cdc = (UX_SLAVE_CLASS_CDC_ACM *) cdc_instance;
}
/******************************************************************************
* End of function ux_cdc_device0_instance_activate
******************************************************************************/
/******************************************************************************
* Function Name : ux_cdc_device0_instance_deactivate
* Description : Clear instance
* Arguments : void * cdc_instance : Pointer to area store the instance pointer
* Return value : none
******************************************************************************/
static void ux_cdc_device0_instance_deactivate (void * cdc_instance)
{
FSP_PARAMETER_NOT_USED(cdc_instance);
g_cdc = UX_NULL;
}
/******************************************************************************
* End of function ux_cdc_device0_instance_deactivate
******************************************************************************/
/******************************************************************************
* Function Name : apl_status_change_cb
* Description : USB callback function for USB status change
* Arguments : ULONG status : USB status
* Return value : UX_SUCCESS
******************************************************************************/
UINT apl_status_change_cb (ULONG status)
{
switch (status)
{
case UX_DEVICE_ATTACHED:
g_attach = USB_YES;
break;
case UX_DEVICE_REMOVED:
g_attach = USB_NO;
break;
default:
break;
}
return UX_SUCCESS;
}
/******************************************************************************
* End of function apl_status_change_cb
******************************************************************************/
/******************************************************************************
* Function Name : usbx_pcdc_sample
* Description : Application task (loopback processing)
* Arguments : none
* Return value : none
******************************************************************************/
void usbx_pcdc_sample (void)
{
fsp_err_t err;
uint32_t ret;
uint32_t size;
ux_system_initialize((CHAR *) g_ux_pool_memory, MEMPOOL_SIZE, UX_NULL, 0);
ux_device_stack_initialize(g_device_framework_hi_speed,
VALUE_103,
g_device_framework_full_speed,
VALUE_93,
g_string_framework,
VALUE_105,
g_language_id_framework,
VALUE_2,
apl_status_change_cb);
g_ux_device_class_cdc_acm0_parameter.ux_slave_class_cdc_acm_instance_activate = ux_cdc_device0_instance_activate;
g_ux_device_class_cdc_acm0_parameter.ux_slave_class_cdc_acm_instance_deactivate =
ux_cdc_device0_instance_deactivate;
ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name,
_ux_device_class_cdc_acm_entry,
1,
0x00,
(void *) &g_ux_device_class_cdc_acm0_parameter);
err = g_usb_on_usb.open(&g_basic0_ctrl, &g_basic0_cfg);
if (FSP_SUCCESS == err)
{
while (1)
{
if (USB_YES == g_attach)
{
while (g_cdc == UX_NULL)
{
;
}
ret = ux_device_class_cdc_acm_read(g_cdc, g_buf, DATA_LEN, &g_actual_length);
if (UX_SUCCESS == ret)
{
size = g_actual_length;
ux_device_class_cdc_acm_write(g_cdc, g_buf, size, &g_actual_length);
}
}
}
}
}
/******************************************************************************
* End of function usbx_pcdc_sample
******************************************************************************/

USBX HMSC Example

HMSC storage example is as follows. See usbx_hmsc_sample for the basic operation of HMSC. Also, please refer to usbx_hmsc_sample_format for the format of the USB memory.

#define UX_STORAGE_BUFFER_SIZE (64 * 1024)
#define EVENT_USB_PLUG_IN (1UL << 0)
#define EVENT_USB_PLUG_OUT (1UL << 1)
#define MEMPOOL_SIZE (63488)
#define DATA_LEN (2048)
#define VALUE_32 (32)
#define VALUE_100 (100)
#define VALUE_200 (200)
#define VALUE_256 (256)
#define VALUE_1024 (1024)
#define DEVICE_INSERTION (0x01U)
#define DEVICE_REMOVAL (0x02U)
static uint16_t g_read_buf[UX_STORAGE_BUFFER_SIZE];
static uint16_t g_write_buf[UX_STORAGE_BUFFER_SIZE];
static FX_FILE g_file;
static UCHAR g_fx_media0_media_memory[UX_STORAGE_BUFFER_SIZE];
static uint8_t g_ux_pool_memory[MEMPOOL_SIZE];
static FX_MEDIA * g_p_media = UX_NULL;
TX_EVENT_FLAGS_GROUP g_usb_plug_events;
UINT usb_host_plug_event_notification(ULONG usb_event, UX_HOST_CLASS * host_class, VOID * instance);
UINT ux_system_host_storage_fx_media_get(UX_HOST_CLASS_STORAGE * instance,
UX_HOST_CLASS_STORAGE_MEDIA ** p_storage_media,
FX_MEDIA ** p_fx_media);
static UINT apl_change_function (ULONG event, UX_HOST_CLASS * host_class, VOID * instance)
{
UINT status = UX_SUCCESS;
UX_HOST_CLASS * class;
UX_HOST_CLASS_STORAGE * storage;
UX_HOST_CLASS_STORAGE_MEDIA * storage_media;
/* Check if there is a device insertion. */
if (DEVICE_INSERTION == event)
{
status = ux_host_stack_class_get(_ux_system_host_class_storage_name, &class);
if (UX_SUCCESS != status)
{
return status;
}
status = ux_host_stack_class_instance_get(class, 0, (void **) &storage);
if (UX_SUCCESS != status)
{
return status;
}
if (UX_HOST_CLASS_INSTANCE_LIVE != storage->ux_host_class_storage_state)
{
return UX_ERROR;
}
storage_media = class->ux_host_class_media;
g_p_media = &storage_media->ux_host_class_storage_media;
tx_event_flags_set(&g_usb_plug_events, EVENT_USB_PLUG_IN, TX_OR);
}
else if (DEVICE_REMOVAL == event) /* Check if there is a device removal. */
{
g_p_media = UX_NULL;
tx_event_flags_set(&g_usb_plug_events, EVENT_USB_PLUG_OUT, TX_OR);
}
else
{
/* None */
}
return status;
}
/******************************************************************************
* Function Name : usbx_hmsc_sample
* Description : Application task (loopback processing)
* Arguments : none
* Return value : none
******************************************************************************/
void usbx_hmsc_sample (void)
{
ULONG actual_length = 0;
ULONG actual_flags;
UINT tx_return;
UINT fx_return;
uint16_t data_count = 0;
FX_MEDIA * p_media = UX_NULL;
CHAR volume[VALUE_32];
fx_system_initialize();
ux_system_initialize((CHAR *) g_ux_pool_memory, MEMPOOL_SIZE, UX_NULL, 0);
ux_host_stack_initialize(apl_change_function);
tx_event_flags_create(&g_usb_plug_events, (CHAR *) "USB Plug Event Flags");
g_usb_on_usb.open(&g_basic0_ctrl, &g_basic0_cfg);
while (1)
{
// Wait until device inserted.
tx_return = tx_event_flags_get(&g_usb_plug_events,
EVENT_USB_PLUG_IN,
TX_OR_CLEAR,
&actual_flags,
TX_WAIT_FOREVER);
if (TX_SUCCESS != tx_return)
{
tx_thread_sleep(TX_WAIT_FOREVER);
}
// Get the pointer to FileX Media Control Block for a USB flash device
p_media = g_p_media;
// Retrieve the volume name of the opened media from the Data sector
fx_return = fx_media_volume_get(p_media, volume, FX_DIRECTORY_SECTOR);
if (FX_SUCCESS == fx_return)
{
// Set the default directory in the opened media, arbitrary name called "firstdir"
fx_directory_default_set(p_media, "firstdir");
// Suspend this thread for 200 time-ticks
tx_thread_sleep(VALUE_100);
// Try to open the file, 'counter.txt'.
fx_return = fx_file_open(p_media, &g_file, "counter.txt", (FX_OPEN_FOR_READ | FX_OPEN_FOR_WRITE));
if (FX_SUCCESS != fx_return)
{
// The 'counter.txt' file is not found, so create a new file
fx_return = fx_file_create(p_media, "counter.txt");
if (FX_SUCCESS != fx_return)
{
break;
}
// Open that file
fx_return = fx_file_open(p_media, &g_file, "counter.txt", (FX_OPEN_FOR_READ | FX_OPEN_FOR_WRITE));
if (FX_SUCCESS != fx_return)
{
break;
}
}
// Already open a file, then read the file in blocks
// Set a specified byte offset for reading
fx_return = fx_file_seek(&g_file, 0);
if (FX_SUCCESS == fx_return)
{
fx_return = fx_file_read(&g_file, g_read_buf, DATA_LEN, &actual_length);
if ((FX_SUCCESS == fx_return) || (FX_END_OF_FILE == fx_return))
{
if (data_count == VALUE_1024)
{
// empty file
data_count = 0;
}
for (uint16_t data_max_count = data_count; data_count < (data_max_count + VALUE_256); data_count++)
{
g_write_buf[data_count] = data_count;
}
// Set the specified byte offset for writing
fx_return = fx_file_seek(&g_file, 0);
if (FX_SUCCESS == fx_return)
{
// Write the file in blocks
fx_return = fx_file_write(&g_file, g_write_buf, DATA_LEN);
if (FX_SUCCESS == fx_return)
{
}
else
{
tx_thread_sleep(TX_WAIT_FOREVER);
}
}
}
}
else
{
tx_thread_sleep(TX_WAIT_FOREVER);
}
// Close already opened file
fx_return = fx_file_close(&g_file);
if (FX_SUCCESS != fx_return)
{
tx_thread_sleep(TX_WAIT_FOREVER);
}
tx_thread_sleep(VALUE_200);
}
else
{
tx_thread_sleep(TX_WAIT_FOREVER);
}
/* flush the media */
fx_return = fx_media_flush(p_media);
if (FX_SUCCESS != fx_return)
{
tx_thread_sleep(TX_WAIT_FOREVER);
}
/* close the media */
fx_return = fx_media_close(p_media);
if (FX_SUCCESS != fx_return)
{
tx_thread_sleep(TX_WAIT_FOREVER);
}
// Wait for unplugging the USB
tx_event_flags_get(&g_usb_plug_events, EVENT_USB_PLUG_OUT, TX_OR_CLEAR, &actual_flags, TX_WAIT_FOREVER);
} // while(1)
}
void usbx_hmsc_sample_format (void)
{
ULONG actual_flags;
UINT tx_return;
UINT status = UX_SUCCESS;
FX_MEDIA * p_media = UX_NULL;
fx_system_initialize();
ux_system_initialize((CHAR *) g_ux_pool_memory, MEMPOOL_SIZE, UX_NULL, 0);
ux_host_stack_initialize(apl_change_function);
tx_event_flags_create(&g_usb_plug_events, (CHAR *) "USB Plug Event Flags");
g_usb_on_usb.open(&g_basic0_ctrl, &g_basic0_cfg);
// Wait until device inserted.
tx_return = tx_event_flags_get(&g_usb_plug_events, EVENT_USB_PLUG_IN, TX_OR_CLEAR, &actual_flags, TX_WAIT_FOREVER);
if (TX_SUCCESS != tx_return)
{
tx_thread_sleep(TX_WAIT_FOREVER);
}
// Get the pointer to FileX Media Control Block for a USB flash device
p_media = g_p_media;
memset(g_fx_media0_media_memory, 0x00, sizeof(g_fx_media0_media_memory));
status = fx_media_format(p_media, // Pointer to FileX media control block.
p_media->fx_media_driver_entry, // Driver entry
p_media->fx_media_driver_info, // Pointer to Block Media Driver
g_fx_media0_media_memory, // Media buffer pointer
p_media->fx_media_memory_size, // Media buffer size
"sample", // Volume Name
p_media->fx_media_number_of_FATs, // Number of FATs
p_media->fx_media_root_directory_entries, // Directory Entries
p_media->fx_media_hidden_sectors, // Hidden sectors
(ULONG) p_media->fx_media_total_sectors, // Total sectors
p_media->fx_media_bytes_per_sector, // Sector size
p_media->fx_media_sectors_per_cluster, // Sectors per cluster
p_media->fx_media_heads, // Heads (disk media)
p_media->fx_media_sectors_per_track);
if ((uint8_t) FX_SUCCESS != status)
{
__BKPT(0);
}
}