How to configure the packet memory area in STM32 USB controllers
- October 22, 2025
- 2 replies
- 593 views
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.
- Introduction
- 1. Packet memory area in STM32
- 1.1 Overview of packet memory area
- 1.2 Structure of USB SRAM:
- 1.3 USB SRAM on STM32 USB controllers
- 1.3.1 First version of USB controller
- 1.3.1.1 Transmission buffers
- 1.3.1.2 Reception buffers
- 1.3.1.3 Practical tips
- 1.3.2 Second version of USB controller
- 1.4 Types of buffer allocation
- 1.4.1 Single-buffered endpoints
- 1.4.2 Double-buffered endpoints
- 1.5 Double-buffering mechanism
- 1.6 Practical tips
- 2. Managing packet buffers
- 2.1 Initialization
- 2.2 Data transfer
- 3. Buffer allocation recommendation
- 3.1 Proper alignment of PMA addresses
- 3.2 Buffer size allocation
- 3.3 Managing buffer conflicts and flow control
- 3.4 Use of double-buffering managing
- 3.5 Shared USB USRAM considerations
- Conclusion
- Related links
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,
-
First version of USB controller:
Applicable to STM32F102/F103, STM32L1, STM32F3, STM32F0, STM32L0x2/x3, STM32L4x2/x3, STM32L5, STM32G4, STM32WB55/35. -
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:
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 |
- 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:
- 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.
- Specify the number of bytes to be transmitted using COUNT_TX.
- Transmission byte count n USB_COUNTn_TX address offset: [USB_BTABLE] + n*8 + 2 (for 2x 16bit/word.)
- (For 1 x 16 bits/word access scheme) address offset: [USB_BTABLE] + n*16 + 4.
- 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:
- 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)
- 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
- 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.

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:
- Activate double-buffering by setting the appropriate bits in the USB_CHEPnR register.
- Use the DTOG and SW_BUF bits to manage buffer swapping.
- 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.
