RT600/1170 UAC change OUT endpoint interval methods
1. Abstract
When using the RT600 SDK USB composite example, the customer found that the default HS interval was 125us, and the code was: mimxrt685audevk_dev_composite_hid_audio_unified_bm.
However, in actual applications, the 125us packet interval for data transmission will cause a large interrupt load on the CPU, so the customer hopes to change the interval to a larger during, such as 1ms. After changing interval to 1ms, it is found that the data packet can be sent to the RT chip, but there is indeed a problem with the playback on the RT side, speaker no voice. Changing it to 500us in synchronous mode is possible work, but at 500us, the customer's CPU load still reaches more than 80%, which is not convenient for subsequent application code expansion, so it is still hoped to achieve a 1ms method.
This article will give the transmission of different intervals of UAC and provide a solution for 1ms intervals.
2. Test situation
Board:MIMXRT685-AUD-EVK
SDK:SDK_2_15_000_MIMXRT685-AUD-EVK
USB Analyzer:Lecroy USB-TOS2-A01-X
2.1 Platform connection situation
First, given the connection between MIMXRT685-AUD-EVK, USB analyzer and audio source. This article mainly tests the RT685 UAC speaker function, that is, USB transmits audio source data to RT685, and plays the audio source through a player (which can be headphones), or speaker. The J7 USB port of EVK is connected to the A port of Lecroy, and the B port of Lecroy is connected to the audio source, which can be a PC or a mobile phone. If using a PC, the speaker needs to be selected as USB AUDIO+HID DEMO, because the name of the board after UAC enumeration is USB AUDIO+HID DEMO.
The other end of Lecroy is connected to the PC for transmitting USB bus data. The specific connection diagram is as follows:
Fig 1 EVK USB analyzer connection
2.2 Different audio interval data package situation
This chapter gives the modifications under different intervals, as well as the results of USB analyzer packet capture. The clock system of the audio synchronous/isochronous audio endpoint can be synchronized through SOF. The USB 1.0 sampling rate must be locked to the 1ms SOF beat. The USB2.0 high-speed HS endpoint can be locked to the 125us SOF beat. If you want to change the interval, it is usually a multiple of 125us, that is, it can be 250us, 500us, 1ms, etc. The modification method is usually to directly modify the USB stack's usb_audio_config.h:
#define HS_ISO_OUT_ENDP_INTERVAL (0x01)
The relationship between HS_ISO_OUT_ENDP_INTERVAL and the real during time is: 125us*2^( HS_ISO_OUT_ENDP_INTERVAL -1)
So:
HS_ISO_OUT_ENDP_INTERVAL=1 : 125us
HS_ISO_OUT_ENDP_INTERVAL=2 : 250us
HS_ISO_OUT_ENDP_INTERVAL=3 : 500us
HS_ISO_OUT_ENDP_INTERVAL=4 : 1000us
The following are the four situations mentioned above respectively through USB analyzer packet capture test.
2.2.1 125us interval packet situation
#define HS_ISO_OUT_ENDP_INTERVAL (0x01)
Fig 2 125us interval
It can be seen that when the interval is configured to 125us, the SOF beat interval in front of each OUT packet is 125us, and the length of the OUT data packet is 24Byte. The data in this 24Byte packet is the actual audio data.
In this case, the playback is normal
2.2.2 250us interval packet situation
#define HS_ISO_OUT_ENDP_INTERVAL (0x02)
The packet capture configured as 250us is shown in the figure below. It can be seen that the SOF beat interval in front of the two OUT packets is 250us, and the length of the OUT data packet is 48 Byte. In other words, as the interval increases, the length of the data packet also increases proportionally, that is, the transmission time is longer, but a packet contains more data packets. At this time, the RT side also needs to provide more USB receiving buffers to receive data.
Fig 3 250us interval
This situation, the speaker play normally, have the audio sound.
2.2.3 500us interval packet situation
#define HS_ISO_OUT_ENDP_INTERVAL (0x03)
Fig 4 500us interval SYNC mode
At this time, you can see that the data packet has become 96 Bytes, and the data content is also normal audio data, but the playback has problems and no sound can be heard.
However, if you configure:
#define USB_DEVICE_AUDIO_USE_SYNC_MODE (0U)
It is not the SYNC mode, it can hear the audio sound, the packet situation is:
Fig 5 500us interval no SYNC mode
However, the asynchronous mode also has problems. After a long period of operation, it may become out of sync and the playback may become stuck. Therefore, it is still necessary to use the 1ms method in the synchronous mode.
2.2.4 1ms interval packet situation
#define HS_ISO_OUT_ENDP_INTERVAL (0x04)
Fig 6 interval 1ms
It can be seen that the data packet length has become 192 bytes, and the SOF beat interval in front of the OUT packet has indeed become 1ms. The audio data packet also looks like normal audio data, so the audio data here is successfully transmitted from USB to RT. However, the playback is abnormal and no sound can be heard.
3. 1ms interval solution
Now let's debug the project to find the problem. Because the USB analyzer can show that the audio data of the USB bus is actually transmitted, we must first check whether the USB receives the data packet in the kUSB_DeviceAudioEventStreamRecvResponse event in USB_DeviceAudioCompositeCallback of audio_unified.c, whether the data packet length is correct, and whether the data content looks like audio data. The following is the debug result:
Fig 7 data packet received situation
So from this point of view, the USB interface data packet is received, and the data looks like real audio data. If it is abnormal data, it is either all 0 or irregular data that changes, but the test result cannot be played.
So now to check the I2S playback function, composite.h file, TxCallback function:
Fig 8 I2S play data buffer
We can see, the real data transfer to the I2S data buffer are always 0, and the reality should be
g_composite.audioUnified.startPlayFlag none zero, and also use:
s_TxTransfer.dataSize = g_composite.audioUnified.audioPlayTransferSize;
s_TxTransfer.data=audioPlayDataBuff + g_composite.audioUnified.tdReadNumberPlay;
But, after testing, audioPlayDataBuff data are also 0. So the issue should be the USB received side, receive the data, but when save the data to the audioPlayDataBuff have issues, go back to audio_unified.c
Fig 9 USB_DeviceAudioCompositeCallback
Fig10 USB_AudioSpeakerPutBuffer
After testing, in the Fig 9, audioUnified.tdWriteNumberPlay never larger than
g_deviceAudioComposite->audioUnified.audioPlayTransferSize * AUDIO_CLASS_2_0_HS_LOW_LATENCY_TRANSFER_COUNT=192*6
#define AUDIO_CLASS_2_0_HS_LOW_LATENCY_TRANSFER_COUNT \
(0x06U) /* 6 means 6 mico frames (6*125us), make sure the latency is smaller than 1ms for sync mode */
The low latency here is a delay buffer. Therefore, the USB cache data must at least be able to hold the delayed data packet. Unit 1 represents an interval frame. Now it is changed to an interval of 1ms, 6 delay units, which means that the delay here is 6ms. Here, the receiving buffer size needs to be larger, which is related to the following definition:
Fig 11 USB device callback
g_composite.audioUnified.audioPlayBufferSize =
AUDIO_PLAY_BUFFER_SIZE_ONE_FRAME * AUDIO_SPEAKER_DATA_WHOLE_BUFFER_COUNT;
#define AUDIO_PLAY_BUFFER_SIZE_ONE_FRAME AUDIO_OUT_TRANSFER_LENGTH_ONE_FRAME
#define AUDIO_OUT_FORMAT_CHANNELS (0x02U)
#define AUDIO_OUT_FORMAT_SIZE (0x02)
#define AUDIO_OUT_SAMPLING_RATE_KHZ (48)
/* transfer length during 1 ms */
#define AUDIO_OUT_TRANSFER_LENGTH_ONE_FRAME \
(AUDIO_OUT_SAMPLING_RATE_KHZ * AUDIO_OUT_FORMAT_CHANNELS * AUDIO_OUT_FORMAT_SIZE)
#define AUDIO_SPEAKER_DATA_WHOLE_BUFFER_COUNT \
(2U) /* 2 units size buffer (1 unit means the size to play during 1ms) */
Here, try to set larger AUDIO_SPEAKER_DATA_WHOLE_BUFFER_COUNT, let it should be at least can put 6ms data, as 1 unit is 1ms play data size, and it needs to have more than 6ms, so, set to 12 unit, the modified definition:
#define AUDIO_SPEAKER_DATA_WHOLE_BUFFER_COUNT 12
Build the project and download it, now capture the USB bus data again:
Fig 12 1ms interval data packet play successfully
This data waveform is the data that can be played normally.
Below is the video of the MIMXRT685-AUD-EVK test.
The attachment provides two demos of RT685 and RT1170, both modified to 1ms interval, and the modification method of RT1170 is exactly the same
4. Summarize
Whether it is RT600, RT1170, or more precisely the UAC code of the entire RT series, if you need to modify the interval, the main focus is on the following macros in usb_audio_config.h, the following is for 1ms interval:
#define HS_ISO_OUT_ENDP_INTERVAL (0x04)//(0x01)//(0X04)
#define AUDIO_CLASS_2_0_HS_LOW_LATENCY_TRANSFER_COUNT \
(0x06U) /* 6 means 16 mico frames (6*125us), make sure the latency is smaller than 1ms for ehci high speed */
#define AUDIO_SPEAKER_DATA_WHOLE_BUFFER_COUNT \
(12U)//(2U) /* 2 units size buffer (1 unit means the size to play during 1ms) */
Test video:
- Chapters
- descriptions off, selected
- subtitles settings, opens subtitles settings dialog
- subtitles off, selected
- en (Main), selected
This is a modal window.
Beginning of dialog window. Escape will cancel and close the window.
End of dialog window.
This is a modal window. This modal can be closed by pressing the Escape key or activating the close button.