UAC2.0 on STM32

Are you sure about the buffer and transfer alignments? That is the kind of behaviour I got when I had miss matches between the DMA transfer sizes and the buffer. Slow/fast jumpy playback, clicking, phase crashes etc. etc. In one case it turned out to be a single innocent looking line of code which didn't do what it was meant to.

It's easy to do what with some of the relative functions taking a pointer and a byte length and others, DMA for instance, taking a "number of transfers" based on their transfer word size. I2S adds more word size absractions, IIRC.

One thing that made 24 and 32 bit stand out as something I will tackle next time, is that you no longer get a complete set of stereo samples in one frame. In 24bit it depends on the format as to whether you get a 32bit left and a 32bit right in 2 frames or you get 16MSB+16MSB and 16LSB+16LSB. Similar in 32bit, but in 24bit you need to know which 8 bits are zeroed in hardware also. Another reason why I'm trying to catch up here, so excuse me if I'm a bit off.
 
  • Like
Reactions: 1 user
My understanding of USB is you either frame duplicate/drop or you provide endpoint feedback in the SOF event. As to how to get the later working from HAL or even the LL code ... I'm still working that out.

You can maybe see why I am very seriously considering moving ALL USB endpoints to hardware ICs. That does present a distinct lack of easy Jelly bean ICs as 99% of them only do UAC1. DVD quality. However I got an Atmel+XLinx USB Bridge in the post from China to try. It does everything I2S up to 384/32 AND... if you enable the DS On pin it supports all the DS512/1024 for DTS and multi-channel theatre audio. I'm quite likely to end up running it at way, way less than that :)

On searching around the HAL bugs I mostly ran into people having low level issues the H7 chips. Some of them have a nasty hardware bug that catches people out though I think there was a work around.

That H bug is due to that chip having 3 matrix “domains” connected by bridges, so depending where the data source and destination is set it may not have visibility for DMA.
The F bug is that the USB’s own DMA doesn’t understand that the memory location is cached in the CPU by default, even adjusting the MCU memory map and disabling the data cache for that memory area doesn’t work. The only way is to globally disable the data cache. Instead it’s faster to leave the data cache enabled and don’t use the USB DMA. The SAI DMA seems content but as mentioned the DMA systems and buffers don’t like misalignment.

Interesting point on the transactions I assume DATA0..DATAx but from my understanding the ISO doesn’t really worry about the DATA transactions as the ISO is not ack’d or rate controlled independently for transactions.

I have to admit, the day job got in the way over the last few weeks as all the programmes are attempting to get releases in before the xmas production freezes.
 
Are you sure about the buffer and transfer alignments?
Definitely. SAI part is taken from another project that works well.

Slow/fast jumpy playback, clicking, phase crashes etc. etc.
I can hear pure sound but it's like just a part. Anyway that does not influence "Incomplete isochronous OUT transfer" interrupts I get.

One thing that made 24 and 32 bit stand out...
It is realized in the ST example I referrenced and it works well.
 
So correct sound just incomplete. It has to be that you are only filling the first half of each buffer, which still points to a "length" or offset issue between 2 bytes words and 32bit words. (or 8 bit words).

The error ... could it be that the otherside is only sending you half the buffer? You could be asking for N bytes, the other ends sends N/2 bytes and the USB layer throws that interrupt.
 
Some Windows USBAudio2 driver log messages

(OUT): [ notificationCount=2 requestedSize=3840
(0x01): calling AllocatePagesForMdl for 3840 bytes
(0x01): MDL: ByteCount=4096 bytes ByteOffset=0 bytes
Cyclic buffer for PCM ch=2 sz=16/16 sr=48000 is: 2 x 1920 = 3840 bytes, 2 x 1 XFERs
(0x01): DATA Isoch Buffers: BufferCount=3 PacketsPerBuffer=88 MillisecondsPerBuffer=11 IsochPacketsPerUsbFrame=8 BytesPerPacket=28
(OUT): ] actualSize=3840
(OUT)
(OUT): [ KSSTATE_ACQUIRE
(0x04): ClockSource SET 48000
(0x04): ClockSource locked to 48000 by InputTerminal ID=0x01
(0x04): LockedFrequency=48000 TerminalCount=1
(0x01): Interface 0x01 set to AltSetting 0x01
(OUT): ] STATUS_SUCCESS
(OUT): [ KSSTATE_PAUSE
(OUT): ] STATUS_SUCCESS


Data transfer

(OUT): os=0 smp ts=5181196749315
(OUT): packetNumber=1 flags=0x00000000 eosPacketLength=1920
(0x01): COMPL OUT buf 0 CurrenLinearPosition=480 EVENT
(OUT): 1
(OUT): pos=0 smp ts=5181196891413
(OUT): packetNumber=2 flags=0x00000000 eosPacketLength=1920
(0x01): COMPL OUT buf 1 CurrenLinearPosition=960 EVENT
(OUT): pos=432 smp ts=5181196991135
(OUT): packetNumber=3 flags=0x00000000 eosPacketLength=1920
(0x01): COMPL OUT buf 2 CurrenLinearPosition=1440 EVENT
(OUT): packetNumber=4 flags=0x00000000 eosPacketLength=1920
(0x01): COMPL OUT buf 0 CurrenLinearPosition=1920 EVENT
(OUT): packetNumber=5 flags=0x00000000 eosPacketLength=1920
(0x01): COMPL OUT buf 1 CurrenLinearPosition=2400 EVENT
(OUT): packetNumber=6 flags=0x00000000 eosPacketLength=1920
(0x01): COMPL OUT buf 2 CurrenLinearPosition=2880 EVENT
.................................................................................................................................
EP 0x01 OUT stream running at PCM ch=2 sz=16/16 sr=48000

and so on
 
(0x01): DATA Isoch Buffers: BufferCount=3 PacketsPerBuffer=88 MillisecondsPerBuffer=11 IsochPacketsPerUsbFrame=8 BytesPerPacket=28

Emm. How does any of that create 1920 byte USB frames?

I2S 48K @ 16 bit is 192 bytes per millisecond. 11 milliseconds per buffer, nor bytes per packet * packets per frame total to 1920.

What am I missing?

Also the linear buffer position is only moving by 460bytes for each 1920Bytes? Either the person who wrote the logs needs slapped or there is "hidden" knowledge to interpret them.
 
Emm. How does any of that create 1920 byte USB frames?

I2S 48K @ 16 bit is 192 bytes per millisecond. 11 milliseconds per buffer, nor bytes per packet * packets per frame total to 1920.
Those are Windows UAC2 driver internal buffers. Number of samples per packet can vary (+-1 samples) so that may explain the size.
Also the linear buffer position is only moving by 460bytes for each 1920Bytes?
Actually 480 bytes. If the timestamps were included you could see that those log events are written every 10 ms. I assume there is one buffer per channel so each buffer advances 480 bytes in 10 ms.
 
  • Like
Reactions: 1 user
It is possible to use different datasize in SAI to what host sends so it is not necessarily "of course".
I know about different SAI settings. But you ask about particular SAI usage in particular application. So I check my SAI code (which is being used for several years and works well) one more time, check SAI registers by means of debugger. And then give you an answer. So there is nothing wrong with "of course" here.
 
I know about different SAI settings. But you ask about particular SAI usage in particular application. So I check my SAI code (which is being used for several years and works well) one more time, check SAI registers by means of debugger. And then give you an answer. So there is nothing wrong with "of course" here.
You have to remember that I know precious little about your implementation.
 
  • Like
Reactions: 1 user
After some experiments and searching it is found out that source of data loss is odd / even frame bits (USB_OTG_DOEPCTL_SODDFRM / USB_OTG_DOEPCTL_SD0PID_SEVNFRM) in the endpoint DOEPCTL register. By default frame bits were changed in "USB_EPStartXfer(...)" function called through a long chain of other calls. And it seems to be meaningless because by the time bits are changed frame has also already changed. So only part of data is received. I moved odd / even frame bits changing code to USB_ISR (HAL_PCD_IRQHandler) in the place of SOF Interrupt handling. Situation changed. Now "Incomplete isochronous OUT transfer" interrupts rise not as often as before but they do rise. I can hear more, the whole melody but with distortions.
I am sure the reason (may be it's not the only one) of data loss is loss of some odd / even frames, wich in it's turn depends on changing corresponding bits. It's like the bits are changed too late sometimes. Thinking of possible solutions.