5.29 USBFSD Guide
This chapter covers the files of the N32H49x full-speed USB device (USBFSD) driver, the source of its interfaces, and its 12 examples. USBFSD uses the standalone driver firmware/n32h49x_usbfsd_driver shipped with the SDK, so it is not part of the standard peripheral library; the examples cover the HID, CDC, MSC, and Printer device classes and composite devices. Read it together with the “Universal serial bus full-speed device interface (USB_FS_Device)” chapter of the user manual for the USB clock, the packet buffer, and the endpoint configuration.
5.29.1 Related files
| Relative path | Purpose |
|---|---|
firmware/n32h49x_usbfsd_driver/inc/ |
Driver header directory: usbfsd_core.h declares the control-transfer state machine and the standard request handlers, usbfsd_init.h, usbfsd_sil.h, usbfsd_mem.h, and usbfsd_int.h declare device initialization, low-level transfer, buffer copy, and interrupt handling functions, usbfsd_type.h, usbfsd_regs.h, and usbfsd_def.h define the types, registers, and descriptor structures, and usbfsd_lib.h aggregates all headers |
firmware/n32h49x_usbfsd_driver/src/ |
Driver source directory: usbfsd_core.c, usbfsd_init.c, usbfsd_sil.c, usbfsd_mem.c, usbfsd_int.c, and usbfsd_regs.c implement the interfaces above |
projects/n32h49x_EVAL/examples/USBFSD/ |
USBFSD example root, containing 12 examples: HID_CDC_Composite, HID_Customer, HID_Keyboard, HID_Keyboard_Xtal_Less, HID_MSC_Composite, JoyStickMouse, Mass_Storage, MSC_CDC_Composite, Printer, Virtual_COM_Port, Virtual_COM_Port_LoopBack, and Virtual_COM_Port_LoopBack_Composite |
projects/n32h49x_EVAL/examples/USBFSD/HID_Keyboard/ |
Layout of this example project: MDK-ARM/, EWARM/, inc/, src/, and readme.txt |
projects/n32h49x_EVAL/bsp/ |
Board support files referenced by the HID keyboard, HID customer, HID plus CDC composite, and HID plus MSC composite examples: inc/bsp_eval.h defines the board selection and the LED and key pin macros, and src/bsp_eval.c provides the LED and key initialization functions |
5.29.2 API reference
The USBFSD interfaces come from the standalone driver firmware/n32h49x_usbfsd_driver, which is not part of the standard peripheral library, so they are not listed in the API entry form used for the library. The examples include all the driver headers at once through usbfsd_lib.h; usbfsd_core.h, usbfsd_init.h, usbfsd_sil.h, usbfsd_mem.h, and usbfsd_int.h together declare 23 functions available to applications.
By header: usbfsd_core.h declares the control-transfer state machine and the standard request handlers (USB_ProcessSetup0, USB_ProcessPost0, USB_ProcessIn0, USB_ProcessOut0, Standard_GetConfiguration, Standard_SetConfiguration, Standard_GetInterface, Standard_SetInterface, Standard_GetDescriptorData, Standard_GetStatus, Standard_ClearFeature, Standard_SetEndPointFeature, Standard_SetDeviceFeature, USB_SetDeviceAddress, USB_ProcessNop); usbfsd_init.h declares USB_Init; usbfsd_sil.h declares the low-level transfer functions USB_SilInit, USB_SilWrite, and USB_SilRead; usbfsd_mem.h declares the packet buffer copy functions USB_CopyUserToPMABuf and USB_CopyPMAToUserBuf; usbfsd_int.h declares the interrupt handlers USB_CorrectTransferLp and USB_CorrectTransferHp.
The base types, registers, and descriptor structures are defined in usbfsd_type.h, usbfsd_regs.h, and usbfsd_def.h; the device-class implementations of each example (descriptors, endpoints, properties, and wakeup callbacks) live under that example project’s inc/ and src/ folders and are not part of the driver itself.
5.29.3 Demo descriptions
This section describes the 12 USBFSD examples, covering an HID keyboard, an HID customer device, HID plus CDC composite, HID plus MSC composite, a virtual COM port, and its loopback variants.
5.29.3.1 HID_CDC_Composite HID and CDC composite device
Example directory: projects/n32h49x_EVAL/examples/USBFSD/HID_CDC_Composite/
Configure USBFS pins as alternate function→Start the USB device clock and initialize the device→Wait for host enumeration and the configured state→Report an HID report on a key press through the IN endpoint→Host OUT endpoint data drives three LEDs→Forward data both ways between the virtual COM port and USART1
| Item | Source analysis |
|---|---|
| Function | The same USB device provides both an HID interface and a CDC interface: HID reports keystrokes and receives host commands to drive the LEDs, while CDC forwards data both ways with USART1. |
| Source files | src/main.c main loop and HID reports;src/hw_config.c and inc/hw_config.h USB clock, GPIO, interrupt, and USART configuration;src/usbfsd_desc.c, src/usbfsd_endp.c, src/usbfsd_prop.c, src/usbfsd_istr.c, and src/usbfsd_pwr.c composite descriptors, endpoints, properties, interrupts, and wakeup;readme.txt features and usage;MDK-ARM/ and EWARM/ Keil and IAR projects. |
| Key configuration | System clock 240MHz, HSE 16MHz, USB clock 48MHz; KEY2 is PA15, LED1 is PA3, LED2 is PB3, and LED3 is PA8; USART1 is PA9 (TX) and PA10 (RX) at 115200 baud. |
| Program and data path | main initializes the board LEDs and keys, the USBFS pins, and the interrupts, then configures and starts the USB device with the 240MHz system clock and waits for the host to reach the configured state;the main loop reads KEY2 when PrevXferComplete is true, writes the two-byte HID report to the endpoint 1 IN buffer, and sets it valid;OUT data from the host drives LED1 to LED3 through the endpoint callback, and USART1 forwards data both ways with the virtual COM port. |
| Main APIs | USB_Config, USB_Init, USBFS_IO_Configure, USB_Interrupts_Config, USB_SilWrite, SetEPTxStatus, CDC_Receive_DATA, CDC_Send_DATA |
| Verification | After download and reset, connect the host through the J4 port, which enumerates a COM port and an HID device; pressing KEY2 reports the keystroke through the IN endpoint; sending 0x01, 0x02, or 0x03 plus 0x00 or 0x01 from the host through the OUT endpoint turns LED1 to LED3 off or on respectively; the virtual COM port and USART1 can exchange data both ways. |
| Use note | When the on-board serial tool is not used, disconnect TX and RX from NSLINK; the HID report is two bytes long and byte 0 is fixed at 0x05; the development environment is KEIL MDK-ARM V5.34 or IAR EWARM 8.50.1. |
Core-code walkthrough and porting
This example combines HID and CDC into one device, then reports keystrokes on the HID channel and forwards serial data on the CDC channel.
Data path: projects/n32h49x_EVAL/examples/USBFSD/HID_CDC_Composite/src/main.c
1. Initialize board and USB resources. First initialize the on-board LEDs and keys, then configure the USBFS pin alternate function and the USB interrupts.
Hardware_Board_Led_Init();
Hardware_Board_Key_Init();
USBFS_IO_Configure();
USB_Interrupts_Config();
2. Configure and start the USB device. Configure USB with the 240MHz system clock, initialize the device on success, and wait for host enumeration.
if(USB_Config(system_clock) == SUCCESS)
{
USB_Init();
while (bDeviceState != CONFIGURED)
{
}
3. Report keystrokes in the main loop. After the previous transfer completes, read KEY2 and write the two-byte HID report to the IN endpoint and set it valid.
if(PrevXferComplete)
{
Sendbuffer[0] = 0x05;
if (KEY_Press_Status_Read(LEFT_BUTTON_AND_2) == SET)
{
Sendbuffer[1] = 0x01;
}
else
{
Sendbuffer[1] = 0x00;
}
USB_SilWrite(EP1_IN, Sendbuffer, 2);
SetEPTxStatus(ENDP1, EP_TX_VALID);
PrevXferComplete = 0;
}
Corresponding source files: src/main.c
5.29.3.2 HID_Customer custom HID device
Example directory: projects/n32h49x_EVAL/examples/USBFSD/HID_Customer/
Configure USBFS pins and interrupts→Start the USB device clock and initialize the device→Wait for host enumeration and the configured state→Send a two-byte report on a key press through the IN endpoint→Host OUT endpoint data drives three LEDs
| Item | Source analysis |
|---|---|
| Function | A custom HID device: KEY2 reports a keystroke to the host, and the device also receives LED control commands that the host sends through the OUT endpoint. |
| Source files | src/main.c main loop and HID reports;src/hw_config.c and inc/hw_config.h USB clock, GPIO, and interrupt configuration;src/usbfsd_desc.c, src/usbfsd_endp.c, src/usbfsd_prop.c, src/usbfsd_istr.c, and src/usbfsd_pwr.c custom HID descriptors, endpoints, properties, interrupts, and wakeup;readme.txt features and usage;MDK-ARM/ and EWARM/ Keil and IAR projects. |
| Key configuration | System clock 240MHz, HSE 16MHz, USB clock 48MHz; KEY2 is PA15, LED1 is PA3, LED2 is PB3, and LED3 is PA8. |
| Program and data path | main initializes the board LEDs and keys, the USBFS pins, and the interrupts, then configures and starts the USB device with the 240MHz system clock and waits for the host to reach the configured state;the main loop sets report byte 0 to 0x05 when PrevXferComplete is true, sets byte 1 to 0x01 or 0x00 by the KEY2 level, writes the report to the endpoint 1 IN buffer, and sets it valid;OUT data from the host is decoded in the endpoint callback into LED1 to LED3 on or off commands. |
| Main APIs | USB_Config, USB_Init, USBFS_IO_Configure, USB_Interrupts_Config, USB_SilWrite, SetEPTxStatus |
| Verification | After download and reset, connect the host through the J4 port, which enumerates an HID device; pressing KEY2 reports the keystroke through the IN endpoint; sending 0x01, 0x02, or 0x03 plus 0x00 or 0x01 from the host through the OUT endpoint turns LED1 to LED3 off or on respectively. |
| Use note | The HID report is two bytes long and byte 0 is fixed at 0x05; changing the report format requires updating the report descriptor in the example; the development environment is KEIL MDK-ARM V5.34 or IAR EWARM 8.50.1. |
Core-code walkthrough and porting
This example implements a custom HID device: the main loop reports the key state and the endpoint callback receives the LED control commands from the host.
Data path: projects/n32h49x_EVAL/examples/USBFSD/HID_Customer/src/main.c
1. Initialize board and USB resources. First initialize the on-board LEDs and keys, then configure the USBFS pin alternate function and the USB interrupts.
Hardware_Board_Led_Init();
Hardware_Board_Key_Init();
USBFS_IO_Configure();
USB_Interrupts_Config();
2. Configure and start the USB device. Configure USB with the 240MHz system clock, initialize the device on success, and wait for host enumeration.
if(USB_Config(system_clock) == SUCCESS)
{
USB_Init();
while (bDeviceState != CONFIGURED)
{
}
3. Report keystrokes in the main loop. After the previous transfer completes, assemble the two-byte report from the KEY2 level, write it to the IN endpoint, and set it valid.
if(PrevXferComplete)
{
Sendbuffer[0] = 0x05;
if (KEY_Press_Status_Read(LEFT_BUTTON_AND_2) == SET)
{
Sendbuffer[1] = 0x01;
}
else
{
Sendbuffer[1] = 0x00;
}
USB_SilWrite(EP1_IN, Sendbuffer, 2);
SetEPTxStatus(ENDP1, EP_TX_VALID);
PrevXferComplete = 0;
}
Corresponding source files: src/main.c
5.29.3.3 HID_Keyboard USB keyboard
Example directory: projects/n32h49x_EVAL/examples/USBFSD/HID_Keyboard/
Configure USBFS pins and interrupts→Start the USB device clock and initialize the device→Wait for host enumeration and the configured state→Poll keys to build a key code into the endpoint buffer→Send an 8-byte key report through the IN endpoint→Drive LEDs to show the CapsLock and NumLock state
| Item | Source analysis |
|---|---|
| Function | Turns the evaluation board into a USB HID keyboard: KEY1, KEY2, and KEY3 type a, b, and c respectively, and the matching LED turns on or off when the host toggles CapsLock or NumLock. |
| Source files | src/main.c main loop, key codes, and keyboard LEDs;src/hw_config.c and inc/hw_config.h USB clock, GPIO, and interrupt configuration, including the keyboard LED macros;src/usbfsd_desc.c, src/usbfsd_endp.c, src/usbfsd_prop.c, src/usbfsd_istr.c, and src/usbfsd_pwr.c HID keyboard descriptors, endpoints, properties, interrupts, and wakeup;readme.txt features and usage;MDK-ARM/ and EWARM/ Keil and IAR projects. |
| Key configuration | System clock 240MHz, HSE 16MHz, USB clock 48MHz; KEY1 is PC13, KEY2 is PA15, and KEY3 is PB4, all keyboard inputs; keyboard LED D1 is PA3 and D2 is PB3. |
| Program and data path | main initializes the board LEDs and keys, the USBFS pins, and the interrupts, then configures and starts the USB device with the 240MHz system clock and waits for the host to reach the configured state;the main loop sets key_buffer[2] to the key code by the KEY1, KEY2, and KEY3 pressed state when PrevXferComplete is true, writes the 8-byte report to the endpoint 1 IN buffer, sets it valid, and clears the key code;keyboard LED commands from the host drive D1 and D2 on or off. |
| Main APIs | USB_Config, USB_Init, USBFS_IO_Configure, USB_Interrupts_Config, USB_SilWrite, SetEPTxStatus |
| Verification | After download and reset, connect the host through the J4 port, which enumerates a keyboard; pressing KEY1, KEY2, and KEY3 types a, b, and c on the host; toggling CapsLock and NumLock from another keyboard turns D1 and D2 on or off accordingly. |
| Use note | Key codes 0x04, 0x05, and 0x06 are a, b, and c respectively; the keyboard LEDs are driven by the example keyboard LED callback and their pins are defined in the board header; the development environment is KEIL MDK-ARM V5.34 or IAR EWARM 8.50.1. |
Core-code walkthrough and porting
This example turns the evaluation board into a USB HID keyboard: the main loop polls the keys for a key code and the endpoint callback handles the host keyboard LED commands.
Data path: projects/n32h49x_EVAL/examples/USBFSD/HID_Keyboard/src/main.c
1. Initialize board and USB resources. First initialize the on-board LEDs and keys, then configure the USBFS pin alternate function and the USB interrupts.
Hardware_Board_Led_Init();
Hardware_Board_Key_Init();
USBFS_IO_Configure();
USB_Interrupts_Config();
2. Configure and start the USB device. Configure USB with the 240MHz system clock, initialize the device on success, and wait for host enumeration.
if(USB_Config(system_clock) == SUCCESS)
{
USB_Init();
while (bDeviceState != CONFIGURED)
{
}
3. Write the key report and set the endpoint valid. Once the key code is assembled, write the 8-byte report to the IN endpoint, set it valid, and clear the key code for the next report.
USB_SilWrite(EP1_IN, key_buffer, 8);
SetEPTxStatus(ENDP1, EP_TX_VALID);
key_buffer[2] = 0;
PrevXferComplete = 0;
}
Corresponding source files: src/main.c
5.29.3.4 HID_Keyboard_Xtal_Less crystal-less USB keyboard
Example directory: projects/n32h49x_EVAL/examples/USBFSD/HID_Keyboard_Xtal_Less/
Configure USBFS pins and interrupts→Start the USB device from an internal clock source→Wait for host enumeration and the configured state→Detect the suspend state and support remote wakeup→Poll keys and send a key report through the IN endpoint→Drive LEDs to show the CapsLock and NumLock state
| Item | Source analysis |
|---|---|
| Function | A USB HID keyboard in crystal-less mode: when no external crystal is used, the internal clock supplies the USB clock, and the keys and LEDs behave as in HID_Keyboard. |
| Source files | src/main.c main loop, suspend and wakeup, and key handling;src/hw_config.c and inc/hw_config.h USB clock, GPIO, and interrupt configuration;src/usbfsd_desc.c, src/usbfsd_endp.c, src/usbfsd_prop.c, src/usbfsd_istr.c, and src/usbfsd_pwr.c HID keyboard descriptors, endpoints, properties, interrupts, and wakeup;readme.txt features and usage;MDK-ARM/ and EWARM/ Keil and IAR projects. |
| Key configuration | The system clock is 240MHz when USE_USBFSD_XTALLESS is not defined and SystemCoreClock when it is;HSE 16MHz and USB clock 48MHz; KEY1 is PC13, KEY2 is PA15, and KEY3 is PB4, and keyboard LED D1 is PA3 and D2 is PB3. |
| Program and data path | main initializes the board LEDs, the keys, and the key interrupt, then configures the USBFS pins and interrupts, selects the system clock by the macro, and configures and starts the USB device;in the suspend state the main loop compares the SOF count of two consecutive frames to decide whether the bus woke up and restores the configured state; when configured and not remote-woken it builds the key code from KEY1, KEY2, and KEY3, writes it to the endpoint 1 IN buffer, and sets it valid. |
| Main APIs | USB_Config, USB_Init, USBFS_IO_Configure, USB_Interrupts_Config, USB_SilWrite, SetEPTxStatus, Set_System, Cfg_KeyInterrupt |
| Verification | After download and reset, connect the host through the J4 port, which enumerates a keyboard; pressing KEY1, KEY2, and KEY3 types a, b, and c on the host; toggling CapsLock and NumLock from another keyboard turns D1 and D2 on or off accordingly. |
| Use note | This example compares the SOF count in the suspend state to decide on wakeup, adding remote-wakeup handling beyond HID_Keyboard; key codes 0x04, 0x05, and 0x06 are a, b, and c respectively; the development environment is KEIL MDK-ARM V5.34 or IAR EWARM 8.50.1. |
Core-code walkthrough and porting
This example adds crystal-less mode and remote wakeup to the HID keyboard: after the host suspends, the SOF count decides whether the bus woke up.
Data path: projects/n32h49x_EVAL/examples/USBFSD/HID_Keyboard_Xtal_Less/src/main.c
1. Initialize board, key interrupt, and USB resources. First initialize the LEDs, the keys, and the key interrupt, then configure the USBFS pin alternate function and the USB interrupts.
Hardware_Board_Led_Init();
Hardware_Board_Key_Init();
Cfg_KeyInterrupt();
Set_System();
USBFS_IO_Configure();
USB_Interrupts_Config();
2. Select the system clock and start the device. Take 240MHz when the crystal-less macro is not defined and the core clock when it is, then configure and start the USB device.
#ifndef USE_USBFSD_XTALLESS
#if defined (N32H49X)
system_clock = SYSCLK_VALUE_240MHz;
#endif
#else
system_clock = SystemCoreClock;
#endif /* USE_USBFSD_XTALLESS */
if(USB_Config(system_clock) == SUCCESS)
{
USB_Init();
while (bDeviceState != CONFIGURED)
{
}
3. Decide on wakeup after suspend. Record the current SOF count, wait for a while, and if the count changed the bus is still active, so restore the configured state.
if (bDeviceState == SUSPENDED)
{
LastIntPackSOF = bIntPackSOF;
for (i = 0; i < 0xffff; i++);
if (LastIntPackSOF != bIntPackSOF)
{
bDeviceState = CONFIGURED;
}
}
Corresponding source files: src/main.c
5.29.3.5 HID_MSC_Composite HID and MSC composite device
Example directory: projects/n32h49x_EVAL/examples/USBFSD/HID_MSC_Composite/
Initialize the SPI FLASH as a storage medium→Configure USBFS pins and interrupts→Start the USB device clock and initialize the device→Wait for host enumeration and the configured state→Host OUT data drives three LEDs→Read and write the SPI FLASH through the USB mass-storage interface
| Item | Source analysis |
|---|---|
| Function | An HID and MSC composite device: the device appears as both an HID device and a mass-storage device, the storage is emulated with the on-board SPI FLASH, and HID reports keystrokes and receives LED control commands. |
| Source files | src/main.c storage medium init and main loop;src/hw_config.c and inc/hw_config.h USB clock, GPIO, and interrupt configuration;src/usbfsd_desc.c, src/usbfsd_endp.c, src/usbfsd_prop.c, src/usbfsd_istr.c, and src/usbfsd_pwr.c composite descriptors, endpoints, properties, interrupts, and wakeup;readme.txt features and usage;MDK-ARM/ and EWARM/ Keil and IAR projects. |
| Key configuration | System clock 240MHz, HSE 16MHz, USB clock 48MHz; SPI NSS is PA15, SCK is PB3, MISO is PD11, and MOSI is PD12, connected to the W25Q128; KEY2 is PA15, LED1 is PA3, LED2 is PB3, and LED3 is PA8. |
| Program and data path | main first initializes the SPI FLASH storage medium, then the USBFS pins and interrupts, and configures and starts the USB device with the 240MHz system clock;after the host reaches the configured state the main loop writes the HID report to the endpoint 1 IN buffer by the KEY2 state and sets it valid; the host drives LED1 to LED3 through the OUT endpoint, and mass-storage read and write requests are handled by the MSC callback over the SPI FLASH. |
| Main APIs | USB_Config, USB_Init, MAL_Config, USBFS_IO_Configure, USB_Interrupts_Config, USB_SilWrite, SetEPTxStatus |
| Verification | After download and reset, connect the host through the J4 port, which enumerates both a mass-storage device and an HID device; pressing KEY2 reports the keystroke through the IN endpoint; sending 0x01, 0x02, or 0x03 plus 0x00 or 0x01 from the host through the OUT endpoint turns LED1 to LED3 off or on respectively. |
| Use note | The mass-storage device must be formatted on first mount and can then be used as a USB drive; on the N32H49XZEL7_EVB V1.1 board a jumper must connect J20; the development environment is KEIL MDK-ARM V5.34 or IAR EWARM 8.50.1. |
Core-code walkthrough and porting
This example combines HID and MSC into one device: the HID channel reports keystrokes and receives LED control, and the MSC channel emulates a USB drive with the SPI FLASH.
Data path: projects/n32h49x_EVAL/examples/USBFSD/HID_MSC_Composite/src/main.c
1. Initialize the storage medium, board, and USB resources. First initialize the on-board LEDs and keys, then the SPI FLASH storage medium, the USBFS pins, and the interrupts.
Hardware_Board_Led_Init();
Hardware_Board_Key_Init();
MAL_Config();
USBFS_IO_Configure();
USB_Interrupts_Config();
2. Configure and start the USB device. Configure USB with the 240MHz system clock, initialize the device on success, and wait for host enumeration.
if(USB_Config(system_clock) == SUCCESS)
{
USB_Init();
while (bDeviceState != CONFIGURED)
{
}
3. Report keystrokes in the main loop. After the previous transfer completes, read KEY2 and write the two-byte HID report to the IN endpoint and set it valid.
if(PrevXferComplete)
{
Sendbuffer[0] = 0x05;
if (KEY_Press_Status_Read(LEFT_BUTTON_AND_2) == SET)
{
Sendbuffer[1] = 0x01;
}
else
{
Sendbuffer[1] = 0x00;
}
USB_SilWrite(EP1_IN, Sendbuffer, 2);
SetEPTxStatus(ENDP1, EP_TX_VALID);
PrevXferComplete = 0;
}
Corresponding source files: src/main.c
5.29.3.6 JoyStickMouse USB joystick mouse
Example directory: projects/n32h49x_EVAL/examples/USBFSD/JoyStickMouse/
Configure USBFS pins and interrupts→Start the USB device clock and initialize the device→Wait for host enumeration and the configured state→Poll the up, down, left, and right key directions→Send a mouse movement report through the IN endpoint
| Item | Source analysis |
|---|---|
| Function | Treats the evaluation board keys as a mouse: WKUP, KEY1, KEY2, and KEY3 move the mouse up, down, left, and right. |
| Source files | src/main.c main loop and mouse reports;src/hw_config.c and inc/hw_config.h USB clock, GPIO, and interrupt configuration;src/usbfsd_desc.c, src/usbfsd_endp.c, src/usbfsd_prop.c, src/usbfsd_istr.c, and src/usbfsd_pwr.c HID mouse descriptors, endpoints, properties, interrupts, and wakeup;readme.txt features and usage;MDK-ARM/ and EWARM/ Keil and IAR projects. |
| Key configuration | System clock 240MHz, HSE 16MHz, USB clock 48MHz; up is WKUP (PA0), down is KEY1 (PC13), left is KEY2 (PA15), and right is KEY3 (PB4). |
| Program and data path | main initializes the board LEDs and keys, the USBFS pins, and the interrupts, then configures and starts the USB device with the 240MHz system clock;in the configured state the main loop writes a mouse movement report to the endpoint send buffer whenever the direction state is non-zero and the previous transfer has completed. |
| Main APIs | USB_Config, USB_Init, USBFS_IO_Configure, USB_Interrupts_Config, JoyState, Joystick_Send |
| Verification | After download and reset, connect the host through the J4 port, which enumerates a mouse; pressing WKUP, KEY1, KEY2, and KEY3 moves the mouse up, down, left, and right respectively. |
| Use note | The mouse movement report is generated by the example from the key directions; the development environment is KEIL MDK-ARM V5.34 or IAR EWARM 8.50.1. |
Core-code walkthrough and porting
This example treats the evaluation board keys as a mouse: the main loop polls the direction state and writes a movement report to the endpoint for the interrupt to send.
Data path: projects/n32h49x_EVAL/examples/USBFSD/JoyStickMouse/src/main.c
1. Initialize board and USB resources. First initialize the on-board LEDs and keys, then configure the USBFS pin alternate function and the USB interrupts.
Hardware_Board_Led_Init();
Hardware_Board_Key_Init();
USBFS_IO_Configure();
USB_Interrupts_Config();
2. Configure and start the USB device. Configure USB with the 240MHz system clock and initialize the device on success.
if(USB_Config(system_clock) == SUCCESS)
{
USB_Init();
}
3. Send movement reports in the main loop. In the configured state, send a mouse report whenever the direction state is non-zero and the previous transfer has completed.
while (1)
{
if (bDeviceState == CONFIGURED)
{
if ((JoyState() != 0) && (PrevXferComplete))
{
Joystick_Send(JoyState());
}
}
}
Corresponding source files: src/main.c
5.29.3.7 Mass_Storage mass-storage device
Example directory: projects/n32h49x_EVAL/examples/USBFSD/Mass_Storage/
Initialize the SPI FLASH as a storage medium→Configure USBFS pins and interrupts→Start the USB device clock and initialize the device→Wait for host enumeration and the configured state→Read and write the SPI FLASH through the USB mass-storage interface
| Item | Source analysis |
|---|---|
| Function | Emulates a USB drive with the on-board SPI FLASH: the host enumerates the device as a mass-storage device and can read and write files. |
| Source files | src/main.c storage medium init and main loop;src/hw_config.c and inc/hw_config.h USB clock, GPIO, and interrupt configuration;src/usbfsd_desc.c, src/usbfsd_endp.c, src/usbfsd_prop.c, src/usbfsd_istr.c, and src/usbfsd_pwr.c MSC descriptors, endpoints, properties, interrupts, and wakeup;readme.txt features and usage;MDK-ARM/ and EWARM/ Keil and IAR projects. |
| Key configuration | System clock 240MHz, HSE 16MHz, USB clock 48MHz; SPI NSS is PA15, SCK is PB3, MISO is PD11, and MOSI is PD12, connected to the W25Q128. |
| Program and data path | main first initializes the SPI FLASH storage medium, then the USBFS pins and interrupts, and configures and starts the USB device with the 240MHz system clock and waits for the host to reach the configured state;after mounting, mass-storage read and write requests are handled by the MSC callback over the SPI FLASH. |
| Main APIs | USB_Config, USB_Init, MAL_Config, USBFS_IO_Configure, USB_Interrupts_Config |
| Verification | After download and reset, connect the host through the J4 port, which enumerates a USB drive that can then be read and written normally. |
| Use note | The mass-storage device must be formatted on first mount and can then be used as a USB drive; on the N32H49XZEL7_EVB V1.1 board a jumper must connect J20; the development environment is KEIL MDK-ARM V5.34 or IAR EWARM 8.50.1. |
Core-code walkthrough and porting
This example emulates a USB drive with the on-board SPI FLASH: the main program mounts the FLASH as a storage medium, then starts the device and waits for host access.
Data path: projects/n32h49x_EVAL/examples/USBFSD/Mass_Storage/src/main.c
1. Initialize the storage medium and USB resources. First initialize the SPI FLASH storage medium, then configure the USBFS pin alternate function and the USB interrupts.
MAL_Config();
USBFS_IO_Configure();
USB_Interrupts_Config();
2. Configure and start the USB device. Configure USB with the 240MHz system clock, initialize the device on success, and wait for host enumeration.
if(USB_Config(system_clock) == SUCCESS)
{
USB_Init();
while (bDeviceState != CONFIGURED)
{
}
}
3. Wait in an empty loop for mass-storage access. After the configured state the main loop is empty and all read and write requests are handled by the MSC callback.
while(1)
{
}
Corresponding source files: src/main.c
5.29.3.8 MSC_CDC_Composite storage and serial composite device
Example directory: projects/n32h49x_EVAL/examples/USBFSD/MSC_CDC_Composite/
Initialize the SPI FLASH as a storage medium→Configure USBFS pins and interrupts→Start the USB device clock and initialize the device→Wait for host enumeration and the configured state→Read and write the SPI FLASH through the USB mass-storage interface→Forward data both ways between the virtual COM port and USART1
| Item | Source analysis |
|---|---|
| Function | An MSC and CDC composite device: the device appears as both a mass-storage device and a COM port, the storage is emulated with the on-board SPI FLASH, and the COM port forwards data both ways with USART1. |
| Source files | src/main.c storage medium init and main loop;src/hw_config.c and inc/hw_config.h USB clock, GPIO, interrupt, and USART configuration;src/usbfsd_desc.c, src/usbfsd_endp.c, src/usbfsd_prop.c, src/usbfsd_istr.c, and src/usbfsd_pwr.c composite descriptors, endpoints, properties, interrupts, and wakeup;readme.txt features and usage;MDK-ARM/ and EWARM/ Keil and IAR projects. |
| Key configuration | System clock 240MHz, HSE 16MHz, USB clock 48MHz; SPI NSS is PA15, SCK is PB3, MISO is PD11, and MOSI is PD12, connected to the W25Q128; USART1 is PA9 (TX) and PA10 (RX) at 115200 baud. |
| Program and data path | main first initializes the SPI FLASH storage medium, then the USBFS pins and interrupts, and configures and starts the USB device with the 240MHz system clock and waits for the host to reach the configured state;USART1 forwards data both ways with the virtual COM port, and mass-storage read and write requests are handled by the MSC callback over the SPI FLASH. |
| Main APIs | USB_Config, USB_Init, MAL_Config, USBFS_IO_Configure, USB_Interrupts_Config |
| Verification | After download and reset, connect the host through the J4 port, which enumerates both a COM port and a mass-storage device; the virtual COM port and USART1 can exchange data both ways. |
| Use note | The mass-storage device must be formatted on first mount and can then be used as a USB drive; on the N32H49XZEL7_EVB V1.1 board a jumper must connect J20; the development environment is KEIL MDK-ARM V5.34 or IAR EWARM 8.50.1. |
Core-code walkthrough and porting
This example combines MSC and CDC into one device: the MSC channel emulates a USB drive with the SPI FLASH and the CDC channel exchanges data with USART1.
Data path: projects/n32h49x_EVAL/examples/USBFSD/MSC_CDC_Composite/src/main.c
1. Initialize the storage medium and USB resources. First initialize the SPI FLASH storage medium, then configure the USBFS pin alternate function and the USB interrupts.
MAL_Config();
USBFS_IO_Configure();
USB_Interrupts_Config();
2. Configure and start the USB device. Configure USB with the 240MHz system clock, initialize the device on success, and wait for host enumeration.
if(USB_Config(system_clock) == SUCCESS)
{
USB_Init();
while (bDeviceState != CONFIGURED)
{
}
}
3. Wait in an empty loop for data forwarding. After the configured state the main loop is empty and the mass-storage and serial transfers are handled by the MSC and CDC callbacks.
while(1)
{
}
Corresponding source files: src/main.c
5.29.3.9 Printer USB printer
Example directory: projects/n32h49x_EVAL/examples/USBFSD/Printer/
Configure USBFS pins and interrupts→Start the USB device clock and initialize the device→Wait for host enumeration and the configured state→Receive host print data through the bulk endpoint→Forward the received data in the endpoint callback
| Item | Source analysis |
|---|---|
| Function | A USB printer device: the host enumerates the device as USB printing support, and the device receives the print data the host sends through the bulk endpoint. |
| Source files | src/main.c send flow and main loop;src/hw_config.c and inc/hw_config.h USB clock, GPIO, and interrupt configuration;src/usbfsd_desc.c, src/usbfsd_endp.c, src/usbfsd_prop.c, src/usbfsd_istr.c, and src/usbfsd_pwr.c printer descriptors, endpoints, properties, interrupts, and wakeup;readme.txt features and usage;MDK-ARM/ and EWARM/ Keil and IAR projects. |
| Key configuration | System clock 240MHz, HSE 16MHz, USB clock 48MHz. |
| Program and data path | main initializes the USBFS pins and interrupts, then configures and starts the USB device with the 240MHz system clock and waits for the host to reach the configured state;when the main loop sees the receive flag it clears it and passes the last received bulk data back to the send flow; print data from the host is received by the bulk endpoint callback. |
| Main APIs | USB_Config, USB_Init, USBFS_IO_Configure, USB_Interrupts_Config |
| Verification | After download and reset, connect the host through the J4 port, which enumerates USB printing support; setting a breakpoint in the bulk endpoint callback shows that host data is received normally. |
| Use note | The print data is received on the bulk endpoint and can be observed with a breakpoint in the endpoint callback; the development environment is KEIL MDK-ARM V5.34 or IAR EWARM 8.50.1. |
Core-code walkthrough and porting
This example turns the evaluation board into a USB printer: the bulk endpoint receives the print data from the host and the main loop passes the received data back to the send flow.
Data path: projects/n32h49x_EVAL/examples/USBFSD/Printer/src/main.c
1. Initialize USB resources. Configure the USBFS pin alternate function and the USB interrupts.
USBFS_IO_Configure();
USB_Interrupts_Config();
2. Configure and start the USB device. Configure USB with the 240MHz system clock, initialize the device on success, and wait for host enumeration.
if(USB_Config(system_clock) == SUCCESS)
{
USB_Init();
while (bDeviceState != CONFIGURED)
{
}
}
3. Forward the received data in the main loop. When the receive flag is seen, clear it and call the send flow to return the last received data.
while (1)
{
if (m_rx_flag)
{
m_rx_flag = 0;
m_BulkData_send(m_rx_buf, m_rx_len);
}
}
Corresponding source files: src/main.c
5.29.3.10 Virtual_COM_Port virtual COM port
Example directory: projects/n32h49x_EVAL/examples/USBFSD/Virtual_COM_Port/
Configure USBFS pins and interrupts→Start the USB device clock and initialize the device→Wait for host enumeration and the configured state→Forward data both ways between the virtual COM port and USART1
| Item | Source analysis |
|---|---|
| Function | A USB virtual COM port device: the host enumerates the device as a COM port, and the virtual COM port forwards data both ways with the on-board USART1. |
| Source files | src/main.c main loop;src/hw_config.c and inc/hw_config.h USB clock, GPIO, interrupt, and USART configuration;src/usbfsd_desc.c, src/usbfsd_endp.c, src/usbfsd_prop.c, src/usbfsd_istr.c, and src/usbfsd_pwr.c CDC descriptors, endpoints, properties, interrupts, and wakeup;readme.txt features and usage;MDK-ARM/ and EWARM/ Keil and IAR projects. |
| Key configuration | System clock 240MHz, HSE 16MHz, USB clock 48MHz; USART1 is PA9 (TX) and PA10 (RX) at 115200 baud. |
| Program and data path | main initializes the USBFS pins and interrupts, then configures and starts the USB device with the 240MHz system clock and waits for the host to reach the configured state;data received by USART1 is forwarded to the virtual COM port through the endpoint 1 IN buffer, and data sent by the virtual COM port is transmitted on USART1. |
| Main APIs | USB_Config, USB_Init, USBFS_IO_Configure, USB_Interrupts_Config |
| Verification | After download and reset, connect the host through the J4 port, which enumerates a new COM port in Device Manager; with USART1 wired to a serial tool, data sent from the virtual COM port is received by the tool and data sent by the tool is received by the virtual COM port. |
| Use note | The transfer length is limited by the example buffer size; when the on-board serial tool is not used, disconnect TX and RX from NSLINK; the development environment is KEIL MDK-ARM V5.34 or IAR EWARM 8.50.1. |
Core-code walkthrough and porting
This example turns the evaluation board into a USB virtual COM port: after device initialization the virtual COM port forwards data both ways with the on-board USART1.
Data path: projects/n32h49x_EVAL/examples/USBFSD/Virtual_COM_Port/src/main.c
1. Initialize USB resources. Configure the USBFS pin alternate function and the USB interrupts.
USBFS_IO_Configure();
USB_Interrupts_Config();
2. Configure and start the USB device. Configure USB with the 240MHz system clock, initialize the device on success, and wait for host enumeration.
if(USB_Config(system_clock) == SUCCESS)
{
USB_Init();
while (bDeviceState != CONFIGURED)
{
}
}
3. Wait in an empty loop for serial forwarding. After the configured state the main loop is empty and forwarding is handled entirely by the endpoint callbacks.
while(1)
{
}
Corresponding source files: src/main.c
5.29.3.11 Virtual_COM_Port_LoopBack virtual COM port loopback
Example directory: projects/n32h49x_EVAL/examples/USBFSD/Virtual_COM_Port_LoopBack/
Configure USBFS pins and interrupts→Start the USB device clock and initialize the device→Wait for host enumeration and the configured state→Read data received on the virtual COM port→Echo it back through the IN endpoint unchanged
| Item | Source analysis |
|---|---|
| Function | USB virtual COM port loopback: the device sends data received on the virtual COM port back to the host unchanged. |
| Source files | src/main.c main loop and loopback logic;src/hw_config.c and inc/hw_config.h USB clock, GPIO, and interrupt configuration;src/usbfsd_desc.c, src/usbfsd_endp.c, src/usbfsd_prop.c, src/usbfsd_istr.c, and src/usbfsd_pwr.c CDC descriptors, endpoints, properties, interrupts, and wakeup;readme.txt features and usage;MDK-ARM/ and EWARM/ Keil and IAR projects. |
| Key configuration | System clock 240MHz, HSE 16MHz, USB clock 48MHz; the virtual COM port is 115200, 8 data bits, 1 stop bit, no parity. |
| Program and data path | main initializes the USBFS pins and interrupts, then configures and starts the USB device with the 240MHz system clock;after the configured state the loop reads the virtual COM port and, once a non-zero length is received and the previous send has completed, echoes the same data back. |
| Main APIs | USB_Config, USB_Init, USBFS_IO_Configure, USB_Interrupts_Config, CDC_Receive_DATA, CDC_Send_DATA |
| Verification | After download and reset, connect the host through the J4 port, which enumerates a new COM port in Device Manager; open that virtual COM port with a serial tool and send data, and the same data is received back immediately. |
| Use note | The loopback does not go through USART1 but only through the virtual COM port itself; the development environment is KEIL MDK-ARM V5.34 or IAR EWARM 8.50.1. |
Core-code walkthrough and porting
This example turns the evaluation board into a virtual COM port loopback: the main loop keeps reading the virtual COM port and echoes the received data back to the host unchanged.
Data path: projects/n32h49x_EVAL/examples/USBFSD/Virtual_COM_Port_LoopBack/src/main.c
1. Initialize USB resources. Configure the USBFS pin alternate function and the USB interrupts.
USBFS_IO_Configure();
USB_Interrupts_Config();
2. Configure and start the USB device. Configure USB with the 240MHz system clock and initialize the device on success.
if(USB_Config(system_clock) == SUCCESS)
{
USB_Init();
3. Read and echo in the main loop. In the configured state read the virtual COM port and echo the same data back once a non-zero length is received and the previous send has completed.
while(1)
{
if (bDeviceState == CONFIGURED)
{
CDC_Receive_DATA();
/*Check to see if we have data yet */
if (Receive_length != 0)
{
if (packet_sent == 1)
{
CDC_Send_DATA ((unsigned char*)Receive_Buffer,Receive_length);
}
Receive_length = 0;
}
}
}
Corresponding source files: src/main.c
5.29.3.12 Virtual_COM_Port_LoopBack_Composite multi-port virtual COM loopback
Example directory: projects/n32h49x_EVAL/examples/USBFSD/Virtual_COM_Port_LoopBack_Composite/
Configure USBFS pins and interrupts→Start the USB device clock and initialize the device→Wait for host enumeration and the configured state→Read data received on two virtual COM ports→Echo it back through each corresponding IN endpoint unchanged
| Item | Source analysis |
|---|---|
| Function | Multi-port virtual COM loopback: the device provides several virtual COM ports, and each echoes the received data back to the host unchanged. |
| Source files | src/main.c main loop and multi-port loopback logic;src/hw_config.c and inc/hw_config.h USB clock, GPIO, and interrupt configuration;src/usbfsd_desc.c, src/usbfsd_endp.c, src/usbfsd_prop.c, src/usbfsd_istr.c, and src/usbfsd_pwr.c multi-port CDC descriptors, endpoints, properties, interrupts, and wakeup;readme.txt features and usage;MDK-ARM/ and EWARM/ Keil and IAR projects. |
| Key configuration | System clock 240MHz, HSE 16MHz, USB clock 48MHz; the number of virtual COM ports is set by an example macro and each port keeps its own receive buffer; the virtual COM port is 115200, 8 data bits, 1 stop bit, no parity. |
| Program and data path | main first initializes the send and receive flags of each port by the port count, then the USBFS pins and interrupts, and configures and starts the USB device with the 240MHz system clock;after the configured state the loop reads each virtual COM port and echoes the data of every port with non-zero length back unchanged. |
| Main APIs | USB_Config, USB_Init, USBFS_IO_Configure, USB_Interrupts_Config, CDC_Receive_DATA, CDC_Send_DATA |
| Verification | After download and reset, connect the host through the J4 port, which enumerates a new COM port in Device Manager; open a virtual COM port with a serial tool and send data, and the same data is received back immediately. |
| Use note | The loopback does not go through USART1 but only through the virtual COM port itself; each port uses its own receive buffer and endpoint and the count is set by an example macro; the development environment is KEIL MDK-ARM V5.34 or IAR EWARM 8.50.1. |
Core-code walkthrough and porting
This example provides several virtual COM ports and loops each of them back: the main program initializes the flags by the port count and the main loop reads and echoes each port in turn.
Data path: projects/n32h49x_EVAL/examples/USBFSD/Virtual_COM_Port_LoopBack_Composite/src/main.c
1. Initialize USB resources. Configure the USBFS pin alternate function and the USB interrupts.
USBFS_IO_Configure();
USB_Interrupts_Config();
2. Configure and start the USB device. Configure USB with the 240MHz system clock and initialize the device on success.
if(USB_Config(system_clock) == SUCCESS)
{
USB_Init();
3. Read and echo each port in the main loop. In the configured state read every virtual COM port in turn and then echo the received data of the matching port back unchanged.
while(1)
{
if (bDeviceState == CONFIGURED)
{
CDC_Receive_DATA();
/*Check to see if we have data yet */
Corresponding source files: src/main.c
5.29.4 Notes and troubleshooting
| Scenario | Check & action | Source |
|---|---|---|
| USB clock configuration | With USB_FS_Device the PLLCLK must be 48MHz, 96MHz, 144MHz, 192MHz, or 240MHz, otherwise the module cannot work; the APB1 bus clock must be greater than 8MHz, otherwise the data buffers may overflow or underflow; the USB registers and the module SRAM can only be accessed after the USB module clock is enabled. |
User manual |
| Application access to Packet Buffer Memory | Access from the APB1 bus to the packet buffer must be 32-bit aligned and use 16-bit reads and writes, not 8-bit or 32-bit access; the buffer descriptor table start address must lie inside the packet buffer and be 8-byte aligned. |
User manual |
| Enabling USB after reset | Every time USB is enabled after a system or power-on reset, the D+ line pull-up resistor must be configured; after the USB reset interrupt, software must enable the endpoint 0 transfers within 10ms and set the USB_ADDR.EFUC bit and initialize the endpoint 0 registers and its packet buffer. |
User manual |
| Suspend and resume | After the device enters suspend it must still detect the RESET signal; the USB_CTRL.RESUM bit can only be set when USB_CTRL.FSUSPD is 1; entering low-power mode requires setting FSUSPD first and then USB_CTRL.LP_MODE. |
User manual |
| SETUP transactions on the control endpoint | After receiving a SETUP token the device must not reply with a NAK or STALL handshake, only with ACK; even when the endpoint 0 receive status is STALL or NAK, the module can still receive a SETUP token; when USB_EP0.CTRS_RX is 1 and another SETUP token arrives, the module discards the packet and returns no handshake. |
User manual |
| Endpoint receive overflow and double buffering | When received data exceeds the receive endpoint buffer size, the hardware stops writing, replies STALL, and sets the buffer overflow error but raises no interrupt; a double-buffered bulk endpoint sets NAK only on a buffer access conflict; an isochronous endpoint status can only be VALID or DISABLED, and setting STALL or NAK is illegal. |
User manual |