Hello Kan
Thank you for the interest in the case.
I have attached a binary which can be loaded to the FRDM-KL43Z which shows the effect.
The CPU is clocked directly from IRC48M and the bus clock is 24MHz (divided by 2).
The software configures a USB audio device so when you connect it to a PC it will appear as a microphon and speaker: Playing any music at the PC should send it to the device.
The USB has a buffer or 32 x 96 bytes so that it can receive 32 isochronous packates of 48 x 16 bit PCM every 1ms from the host.
PIT0 is configured to run at exactly 48MHz and triggers a DAC conversion (since its source is the bus clock it should be synchronised to the USB clock).
When USB starts the DAC is enabled after 16 isochronous packets have been received so that there is a 16 packet (16ms) delay between the USB data and the DAC output, whereby each DAC conversion triggers DMA which performs continuous circular buffer transfers from the USB buffer to the DAC.
Connecting a speaker to the DAC output (PTE30 = J4-11), the music is heard and has good quality for usually 5 minues or so.
Occasionally (eg. roughly every 5 minutes) there is usually a period of around 10..20s where the music is badly distorted and there is a lot of noise - this happens when the DMA is copying the area in the USB buffer which is presently being filled by the USB reception. The original 16ms delay has either drifted to 32ms or reduced to 0ms to cause this.
PTC7 - J1-11 is driven by audio_USB_SOF_OUT so that the SOF on the USB bus can be monitored as reference.
PTD5 - (green LED) - J2-12 is initially at '1' but is set to 0 on the first USB buffer reception and then repeatedly each subsequent 32 buffers (once every 32ms).
The output is set to '1' each time the DMA circular buffer transfer completes (also every 32ms)
The result is that at USB connection there is a square wave with the falling edge indicating the first USB buffer reception and the rising edge the DMA buffer transfer completion. The falling edge (USB reception interrupt) is synchronous to the SOF output pulse (delayed by 84us).
If the USB host were perfectly synchronous to the IRC48M this square wave would remain stable overtime but this is not the case - the mark-space ratio drifts slightly with time - mainly in a certain direction with a gradual drift, although sometimes the drift speeds up for a short time and sometimes the drift changes direction for a short time too. Sometimes there are even quite long periods where the drift is virtually zero too.
Most of the time the circular buffer interrupt will drift 2ms slower every 14s and the drift is easily monitored with an oscillocope.
If I speed the PIT up slightly (0x1f2 instead of 0x1f3) the DMA buffer drifts faster at about +2ms every s.
If I slow the PIT slightly (0x1f4 instead of 0x1f3) the DMA buffer drifts slower at about -2ms every s.
The PIT clock is the bus clock and so is synchronous to IRC48M and this also shows that its 48kHz setting is optimal.
To do this experiment the memory modify command can be used in the I/O menu on the OpenSDA virtual COM port at 115200Baud:
"mm 40037100 l 1f3"
In fact it is quite simple to keep the USB synchronised with the audio output by using
"mm 40037100 l 1f2" or "mm 40037100 l 1f4" to cause a temporary drift to synchronise the signals before they drift to a critical phase.
Intially I thought that the DMA buffer interrupt, which needs to set up the next DMA buffer transfer, was the problem because it could lose a sample in the process (it must prepare the next transfer within 20.8us to ensure not missing a sample) but if it did always miss a sample it would result on a drift of 20us every 32ms (312us/s) and not the typical 140us/s. The fact that the drift sometimes stops and even goes in the opposite direction tends to confirm that this is not the case.
Another method of monitoring the drift is to use the "delta" command in the USB menu. This will show the present deviation (each time requested [repeat last command using the up-arrow]) from the ideal delay in us and thus also drifts between -16000us and +16000us. When the drift is at an extreme there can be noise and as long as it remains in the +-15000 range the music is of good quality.
Eg.
Command "delta" shows
Delta = -700us
The following are relevant configurations with regard to the crystal-less USB device operation:
SIM_SOPT2 |= (SIM_SOPT2_USBSRC | SIM_SOPT2_PLLFLLSEL_IRC48M); // set the source to IRC48M - value = 0x0404000
USB_CLK_RECOVER_IRC_EN = USB_CLK_RECOVER_IRC_EN_IRC_EN; // enable 48MHz IRC clock and clock recovery - value = 0x02
USB_CLK_RECOVER_CTRL = USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN; // value = 0x80
Finally, here is a screen shot of the USB registers when paused during the operation.

I can operate for long periods of time with the USB without any USB difficulties - the drift is the only problem. This tends to suggest that there is crystal-less synchronisation for reliable USB but the synchronisation is not adequate to actually lock the IRC48M to the host time base.
I look forward to your evaluation.
Regards
Mark