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.
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.
Ah... yes... the silly line of code was a memcpy which in my case was memcopying the 16bit I2S buffer, which was a 16bit pointer, but was case to uint8_t without multiplying the length by 2. Easy done while playing bug whack-a-mole
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.
Tell me about it. I sat idle in work for a month. Then once the code freeze looms all these people appear with demands. Nothing, nothing, nothing, PANIC! NEED IT TOMORROW!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.
Yes.are you using the same usb buffer and SAI output?
Audio stream is 48 kHz / 16 bit (in two bytes), 2 channels, EP bInterval = 1, so 24 bytes per microframe. EP data size in the usb descriptor = 28 bytes.Also what is the EP data size buffer size in the usb descriptor?
Definitely. SAI part is taken from another project that works well.Are you sure about the buffer and transfer alignments?
I can hear pure sound but it's like just a part. Anyway that does not influence "Incomplete isochronous OUT transfer" interrupts I get.Slow/fast jumpy playback, clicking, phase crashes etc. etc.
It is realized in the ST example I referrenced and it works well.One thing that made 24 and 32 bit stand out...
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.
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
(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
It is possible to use different datasize in SAI to what host sends so it is not necessarily "of course".Yes, of course.
The incomplete isochronous out transfer interrupt happens in device and host is not aware of it. So it does not appear in Windows UAC2 logs.Some Windows USBAudio2 driver log messages
(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.
Those are Windows UAC2 driver internal buffers. Number of samples per packet can vary (+-1 samples) so that may explain the size.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.
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.Also the linear buffer position is only moving by 460bytes for each 1920Bytes?
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.It is possible to use different datasize in SAI to what host sends so it is not necessarily "of course".
Yes. 480 bytes are transfered every 10 ms.buffer advances 480 bytes in 10 ms.
As it can be seen 3 buffers are used interleaved. I think each of them contains data for both channels.I assume there is one buffer per channel
You have to remember that I know precious little about your implementation.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.
🙂 Good answer!You have to remember that I know precious little about your implementation.
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.
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.
- Home
- Source & Line
- Digital Line Level
- UAC2.0 on STM32