cancel
Showing results for 
Search instead for 
Did you mean: 

How to configure the packet memory area in STM32 USB controllers

FBL
ST Employee

Introduction

This guide explains the basic structure and organization of the packet memory area (PMA) in STM32 USB controllers operating in full speed. It covers how buffers are allocated and configured to support data transfers between the device and host. By understanding these concepts and following best practices, developers can improve the efficiency and reliability of USB communication in their applications.

Applicable STM32 products:

  • STM32H503/23/33/63/73, STM32G4, STM32U535/545, STM32C071, STM32U073/83 devices only,
  • STM32L4x2/x3, STM32L1, STM32L0x2/x3, STM32L5, STM32U3,
  • STM32F102/F103, STM32F0, STM32G0, STM32F3, STM32WB55/35

Note: This guide is not applicable for products embedding USB OTG controllers.

1. Packet memory area in STM32

1.1 Overview of packet memory area

The packet memory area (PMA) is a dedicated memory region within STM32 microcontrollers designed to buffer USB data packets during communication between the USB peripheral and the host. It enables efficient management of both incoming (OUT) and outgoing (IN) data to the STM32 USB device by organizing memory through a buffer description table. This table tracks buffer locations and sizes for each endpoint and direction. 

1.2 Structure of USB SRAM:

The buffer description table is a critical component that maps the packet memory area. Each entry in the table corresponds to a specific endpoint and direction (IN or OUT) and contains the following information:

  • Address register (ADDRn_TX/ADDRn_RX): Starting address of the buffer.
  • Count register (COUNTn_TX/COUNTn_RX): Number of bytes to be transferred or received.

Example reference: See figure 674 in the RM0440 G4 reference manual for examples of buffer description table locations.

The buffer descriptor table is located within the USB SRAM and acts as a configuration map for packet buffers. It defines the location and size of each buffer, enabling the USB peripheral to handle data packets effectively. 

1.3 USB SRAM on STM32 USB controllers

The USB SRAM register map consists of several registers; each associated with a specific channel or endpoint. These registers are used to configure packet buffers for data transmission and reception.

We have 2 versions of USB controllers,

  1. First version of USB controller:
    Applicable to STM32F102/F103, STM32L1, STM32F3, STM32F0, STM32L0x2/x3, STM32L4x2/x3, STM32L5, STM32G4, STM32WB55/35.

  2. Second version of USB controller:
    Applicable to STM32G0, STM32C071, STM32U535/545, STM32U3, STM32U073/83, STM32H503/23/33/63/73.

We can find differences in the mapping of two versions of controllers:

1.3.1 First version of USB controller

Registers in this version are 16-bit wide and include the following fields:

  • COUNTn_TX and COUNTn_RX [9:0]: Specifies the number of bytes to be transmitted/received.
  • ADDRn_TX and ADDRn_RX [15:0]: Points to the starting address of the transmission/reception buffer.
  • USB_BTABLE register: Specific to version 1 and not present in version 2:

 

FBL_0-1759313037742.png

 

Each register contains multiple bits, crucial for configuring the packet memory:

  • COUNT_TX [9:0]: Specifies the number of bytes to be transmitted.
  • ADDR_TX [15:0]: Points to the starting address of the transmission buffer.
  • COUNT_RX [9:0]: Indicates the number of bytes received.
  • ADDR_RX [15:0]: Points to the starting address of the reception buffer.
  • BLSIZE: Determines the block size for buffer allocation.
  • NUM_BLOCK [4:0]: Defines the number of blocks allocated for the buffer.

Below is a table showing the memory allocation for buffer sizes based on the values of NUM_BLOCK and BLSIZE. Ensure buffers are allocated correctly to avoid conflicts.

Value of NUM_BLOCK [4:0]

Memory allocated when BLSIZE = 0

Memory allocated when BLSIZE = 1

0

Not allowed

32 bytes

1

2 bytes

64 bytes

2

4 bytes

96 bytes

3

6 bytes

128 bytes

..

..

..

14

28 bytes

480 bytes

15

30 bytes

 

16

32 bytes

 

 

..

 

29

58 bytes

 

30

60 bytes

992 bytes

31

62 bytes

1023 bytes

 
The location and size of each buffer are specified in a buffer description table. Each table entry corresponds to an endpoint register of 16-bit. The start address of the buffer description table must be aligned to an 8-byte boundary. 
  • 2 bytes for Tx buffer address
  • 2 bytes for Tx byte count
  • 2 bytes for Rx buffer address
  • 2 bytes for Rx byte count

For USB version 1 devices, we distinguish between two types of access scheme:

For 2 x 16 bits/word access scheme devices (PMA_ACCESS=1) we recommend that buffer addresses are aligned to 1 byte (8 bit) boundaries for optimal performance. Or half-word (16-bit) accesses. Word (32-bit) access is not allowed.

For 1 x 16 bits/word access scheme devices (PMA_ACCESS = 2): To obtain the correct memory address value to be used in the application software while accessing the packet memory, the actual memory location address must be multiplied by two. So, every valid 16-bit data word is followed by a padding 16-bit word that is unused or reserved.

1.3.1.1 Transmission buffers

To configure a transmission buffer:

  1. Set the ADDR_TX field to the starting address of the buffer.
  •  Transmission buffer address n USB_ADDRn_TX address offset: [USB_BTABLE] + n*8 with maximum 1023 bytes (for 2x 16bit/word).
  • (For 1 x 16 bits/word access scheme) address offset: [USB_BTABLE] + n*16.
  1. Specify the number of bytes to be transmitted using COUNT_TX.
  •  Transmission byte count n USB_COUNTn_TX address offset: [USB_BTABLE] + n*8 + (for 2x 16bit/word.)
  • (For 1 x 16 bits/word access scheme) address offset: [USB_BTABLE] + n*16 + 4.
  1. Ensure that the buffer is word-aligned by setting the least significant bits to "00".

Note: In case of double-buffered or isochronous endpoints in the OUT/IN direction, this address location is referred to as USB_ADDRn_RX_0/USB_ADDRn_TX_0.

1.3.1.2 Reception buffers

To configure a reception buffer:

  1. Set the ADDR_RX field to the starting address of the buffer.
  • Reception buffer address n USB_ADDRn_RX address offset: [USB_BTABLE] + n*8 + 4 (for 2x 16bit/word)
  • (For 1 x 16 bits/word access scheme) address offset: [USB_BTABLE] + n*16 + 8 (we multiply by 2 if PMA_ACCESS=2)
  1. Use COUNT_RX to monitor the number of bytes received.
  • Reception byte count n USB_COUNTn_RX address offset: [USB_BTABLE] + n*8 + 6 (for 2x 16bit/word)
  • (For 1 x 16 bits/word access scheme) address offset: [USB_BTABLE] + n*16 + 12
  1. Configure BLSIZE and NUM_BLOCK to define the buffer size.

Note: In case of double-buffered or isochronous endpoints in the OUT/IN direction, this address location is referred to as USB_ADDRn_RX_1/USB_ADDRn_TX_1.

1.3.1.3 Practical tips

  • Ensure that buffers are half-word aligned to prevent data corruption.
  • Implement robust flow control mechanisms to handle buffer conflicts and prevent data loss.

1.3.2 Second version of USB controller

Registers in this version are 32-bit wide and include:

  • USB_CHEP_TXRXBD_n: Handles transmit buffer descriptors (and receive buffer in double-buffering mode).
  • USB_CHEP_RXTXBD_n: Handles receive buffer descriptors (and transmit buffer in double-buffering mode).
  • Alternate register in USB version 2 is used in double-buffering mode to be discussed later in the article.

Note: CHEP stands for Channel for host mode and EP for device mode.

The following figures illustrate packet buffer areas with examples of buffer description table locations for two versions of USB controllers with minor changes.

 

FBL_11-1759520495517.png

Figure 1 is extracted from Figure 674 in RM0440 and Figure 2 from Figure 790 in RM0481.

  • The diagram shows buffer descriptor registers (CHEP_TXRXBD_n) for endpoints 0 to 3, while support for buffer descriptors can be extended up to endpoint 7.
  • The buffer descriptor table starts at offset 0x00.
  • The packet buffers (actual data buffers) start from offset 0x40 in PMA.
  • The available buffer address range could be optimized starting from offset inferior to 0x40.

    0x40 is the worst case allocation.

  • Here is a quick comparison between register mapping for USB controller version 1 and 2.

Version 1: register

Version 1: field

Version 2: register

Version 2: field

USB_ADDRn_TX

ADDRn_TX[15:1]

CHEPn_ TXRXBD

ADDRn_TX[15:1]

 

USB_COUNTn_RX

BLSIZE

BLSIZE

NUM_BLOCK [4:0]

NUM_BLOCK [4:0]

COUNTn_RX[9:0]

COUNTn_RX[9:0]

USB_ADDRn_RX

ADDRn_RX[15:1]

CHEPn_ RXTXBD

ADDRn_RX[15:1]

USB_COUNTn_TX

COUNTn_TX[9:0]

COUNTn_TX[9:0]

  • This dedicated memory is memory mapped and can be directly accessed by software.

1.4 Types of buffer allocation

1.4.1 Single-buffered endpoints

Single-buffered endpoints can be used for control, bulk, isochronous, and interrupt transfers, where data is transferred in smaller, predictable amounts with lower performance requirements.

1.4.2 Double-buffered endpoints

Double buffered endpoints are available for bulk and isochronous transfers. They require two buffers (one for Tx and one for Rx). This mode allows one buffer to be filled or emptied from the bus while the other is processed, maximizing throughput. This is critical for isochronous transfers or some bulk transfers (also called double-buffered bulk transfers), which require the use of double-buffering mode.

1.5 Double-buffering mechanism

Double-buffering is a technique used to enhance data transfer efficiency by allowing simultaneous read and write operations. It involves toggling between two buffers, reducing wait times and increasing throughput. To implement double-buffering:

  1. Activate double-buffering by setting the appropriate bits in the USB_CHEPnR register.
  2. Use the DTOG and SW_BUF bits to manage buffer swapping.
  3. Ensure proper flow control by monitoring buffer availability and toggling the SW_BUF bit.

Toggle Bits (DTOG and SW_BUF) Manage buffer swapping. The USB peripheral toggles the DTOG bit upon completing a transaction, while the application software toggles the SW_BUF bit after processing the buffer.

The BLSIZE bit in the USB controller's buffer configuration register serves as an important indicator for buffer block sizing. When set to 1, it configures the buffer allocation in 32-byte blocks. This enables efficient handling of large USB packets up to the maximum packet size defined by the USB specification (for example, 1024 bytes). Conversely, when BLSIZE is cleared, the buffer is allocated in 2-byte blocks, optimizing memory usage for smaller packet transfers.  This design allows the USB peripheral and software stack to dynamically balance memory efficiency and transfer capability by selecting the appropriate block size granularity based on the expected packet size.

For more details, refer to Table 424: Bulk double-buffering memory buffers usage and Table 425: Isochronous memory buffers usage in RM0440. 

1.6 Practical tips

  • It is highly recommended to enable double-buffering mode for some bulk transfers to maximize throughput and for isochronous transfers to ensure functional operations and avoid any possible glitches.
  • Configure the USB peripheral with double-buffering where possible to reduce the CPU responsiveness required in managing data. This allows the USB peripheral to buffer data while the CPU prepares the next buffer.
  • Review the USB ISR and HAL USB driver code to ensure minimal processing inside ISR.
  • Avoid blocking calls or heavy computations.
  • In the RTOS context, use flags/semaphores to defer processing to lower priority tasks.

2. Managing packet buffers

2.1 Initialization

To initialize packet buffers, configure the buffer description table by setting the appropriate address and count registers. Ensure that the buffer addresses are aligned to 8-byte boundaries to optimize access speed and avoid conflicts.

2.2 Data transfer

  • IN transactions: Data is transmitted from the device to the host. The USB peripheral reads from the transmission buffer, and the application software must prepare data in advance.
  • OUT transactions: Data is received from the host. The USB peripheral writes to the reception buffer, and the application software must process the data promptly.

3. Buffer allocation recommendation

3.1 Proper alignment of PMA addresses

  • Ensure that PMA buffer addresses are aligned correctly to avoid memory conflicts and data corruption.
  • For USB controller V1, buffer addresses should be half-word (2 byte) aligned. In some cases (2 x 16 bits/word access scheme), 1-byte alignment may be optimal. Refer to the specific controller documentation.
  • For USB controller V2, all packet buffers must be word (4 byte) aligned.
  • The starting address of any data buffer in PMA must be aligned to an 8 byte boundary.

3.2 Buffer size allocation

  • Allocate buffer sizes based on the expected data transfer size to prevent buffer overruns or underruns.
  • For USB Full-Speed (FS) endpoints, typical supported sizes are 8, 16, 32, or 64 bytes for control and interrupt transfers. Ensure that endpoint buffer sizes comply with USB protocol requirements and STM32 USB controller capabilities

3.3 Managing buffer conflicts and flow control

  • Properly set and monitor DTOG and SW_BUF bits to manage buffer swapping and avoid conflicts.
  • Implement robust flow control mechanisms in software to handle buffer availability and prevent data loss.

3.4 Use of double-buffering managing 

  • Enable double-buffering for high-throughput applications such as audio, video, CDC, and MSC.
  • Double-buffering minimizes idle time by allowing simultaneous processing and data transfer, maximizing throughput and reducing CPU load.

3.5 Shared USB USRAM considerations 

  • For products embedding USB controller V1 that share USB SRAM with CAN peripherals, verify the amount of dedicated RAM available to avoid memory conflicts.

Conclusion

Understanding and managing the packet memory area is essential for efficient USB communication in STM32 microcontrollers. By following best practices and leveraging features like double-buffering, developers can significantly optimize data transfers and enhance the performance of their USB applications.  Building on this foundation, the following article provides practical examples and detailed guidance on configuring USB applications for various USB classes, including CDC, HID, MSC, and audio. This next step will help developers apply PMA concepts effectively in real-world scenarios to maximize USB communication efficiency.

Related links

Comments
gbm
Principal

1. A simple but important piece of information is missing from the article: Which microcontrollers have PMA_ACCESS=1 option and which ones PMA_ACCESS=2? The information may be (not always easily) found in RefMan but it clearly is missing from this text.

2. I am too dumb to understand this; compare these 2 paragraphs from the above article:

"For 2 x 16 bits/word access scheme devices (PMA_ACCESS=1) we recommend that buffer addresses are aligned to 1 byte (8 bit) boundaries for optimal performance. Or half-word (16-bit) accesses. Word (32-bit) access is not allowed."

"For USB controller V1, buffer addresses should be half-word (2 byte) aligned. In some cases (2 x 16 bits/word access scheme), 1-byte alignment may be optimal. Refer to the specific controller documentation."

So, the PMA addresses should be aligned to 2 but alignment to 1 may be needed for "optimal performance". Huh?!

Any location aligned to boundary of 2 or 4 is also aligned to a boundary of 1. So, alignment to 2 or 4 is also "alignment to 1 byte". This has nothing to do with the fact that no 32-bit access is allowed. The buffer address may still be aligned to 4. I believe that for OUT EPs, the buffer size must be the same as EP size, so why not to align it to 4? To save 2 bytes on IN EP buffer?

Why would anyone align the packet buffer to a boundary of 1 B instead of  2 B? Any rationale for that?

FBL
ST Employee

Hi @gbm 

Thank you for your feedback and questions. I appreciate the opportunity to clarify these important points regarding PMA access schemes and buffer alignment in first version of STM32 USB controllers.

  1. PMA_ACCESS scheme 1 is indeed MCU-specific and defined in the STM32 USB driver in the link provided. This scheme applies to certain STM32F3 MCUs (e.g., STM32F302xE, STM32F303xE) and is described in the reference manual as a 2 x 16 bits/word access scheme.
  2. In this scheme, the PMA memory is organized such that every valid 16-bit data word is followed by a 16-bit reserved padding word. It's to ensure your code matches this linear mapping model and avoid overlapping between the 2 blocks.

I hope it's clear! 

Version history
Last update:
‎2025-10-22 6:13 AM
Updated by: