I2S buffer handling

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

I2S buffer handling

2,039 Views
scottm
Senior Contributor II

Is there a description somewhere of the I2S driver's buffer handling and status callbacks? I'm working on porting an audio processing project from Kinetis to the LPC55S69 and on Kinetis I was using my own I2S DMA driver and I need to figure out which pieces of my driver I can replace with the MCUX SDK driver - or if I should just skip it and adapt my own driver to the new hardware.

From what I can tell from the sparse SDK docs, it looks like the driver has a queue that takes I2S_NUM_BUFFERS (4) entries. It doesn't mention any size limits so I'm assuming that queue is just taking four pointers.

All of the provided example projects use only a single, fixed buffer. They'll queue the same buffer twice in a row to avoid gaps in the playback, but they don't illustrate how to manage multiple buffers. The loopback examples have the sender and receiver using the same buffer, so the contents are changing, but there's no synchronization mechanism of any kind - they simply rely on the fact that both are clocked together and won't ever pause or experience desynchronization. The demos only change the contents, not the buffer being sent, which isn't safe for most real-world applications.

There's a callback of i2s_transfer_callback_t, which provides a parameter "completionStatus" of type status_t, but status_t is simply typedef'd to int32_t  with no documentation of the values it can return.

There is an anonymous enum with BufferComplete, Done, and Busy values - but nothing to explicitly that these are used in the callback. I'm assuming these are the values for status_t and that BufferComplete means a single buffer has been sent, and Done means all of them are done. It'd be nice to know in advance if the final buffer generates both a BufferComplete and a Done, or if it's just Done.

That's provided in the basic I2S driver. In the I2S_DMA driver there's a separate I2S_DMACallback. It doesn't appear to be documented at all in the manual. From the code, it looks like this is strictly an internal function used by the ISR. Is that correct? Is there some way to distinguish in the SDK docs what's an exported function and what's only used internally? Or maybe exclude the internal stuff entirely if it's not relevant?

I assume the completion callback happens when the DMA transfer completes? Or is there a callback when the I2S FIFO empties? My application doesn't normally send audio continuously so I need to know when to shut down the I2S transmitter without cutting off the last transmission. (Kudos to the hardware designers for letting you select whether an idle I2S transmitter sends zeroes or repeats the last value - that's one of those little touches that really makes things easier. I have applications that need it both ways.)

Edit: My main concern right now is figuring out with certainty which buffer just completed. The callback doesn't seem to specify, the user data is associated with the handle and not the individual transfer, and the DMA handle data is private. First in, first out is an obvious assumption but I'm trying to avoid the possibility of buffer desynchronization if a transfer is aborted or something.

Thanks,

Scott

0 Kudos
Reply
6 Replies

2,008 Views
CarlosGarabito
NXP TechSupport
NXP TechSupport

Hi @scottm the examples that we have you can find in SDK_X.X.X_LPCXpresso55S69\boards\lpcxpresso55s69\driver_examples\i2s, we no have more examples with i2s

0 Kudos
Reply

1,995 Views
scottm
Senior Contributor II

OK, what about the rest of my questions?

How do you determine which buffer was just sent? I'm concerned that if the application misses a deadline servicing the completion callback that it'll get desynchronized. With four buffers in rotation it can miss one or two and not interrupt the transmission, but only if there's a way to tell which buffers have been sent.

When are the callbacks generated? Does the final buffer generate both a "buffer sent" and "done" callback?

What are the possible values for status_t?

And how do you get a callback for completion of the whole I2S transmission, so you can shut down the transmitter?

I've got my basic functionality working, but it's hard to guarantee a complete and robust implementation without knowing the details.

Thanks,

Scott

1,936 Views
CarlosGarabito
NXP TechSupport
NXP TechSupport

I suggest you read the i2c manual (https://community.nxp.com/pwmxy87654/attachments/pwmxy87654/nxp-designs/931/1/UM10204.pdf) and use breakpoints and watch variables in your code to determine all the information that you need

 

these links are also interesting

https://mcuoneclipse.com/2020/06/29/mcuxpresso-sdk-tutorial-using-i2c-driver-on-okdo-e1-board/

https://mcuoneclipse.com/2012/12/04/a-generic-i2c-high-level-driver/

0 Kudos
Reply

1,926 Views
scottm
Senior Contributor II

Carlos,

Please reread my questions. You'll see that my post is about I2S, which is a synchronous serial audio interface that's unrelated to the I2C protocol. None of the links you provided have any relevance to I2S or to my questions.

I'm attempting to use the MCUX SDK driver because it's supposedly NXP's recommended solution. I wrote my own driver for Kinetis but I'm trying to take advantage of the code that NXP already provides for this purpose rather than writing something for LPC from scratch.

It sounds like you're telling me the only way to get the information I need is to reverse-engineer the MCUX code. Setting breakpoints doesn't tell me what values are possible. I did that just now and the completion callback gets a value of 0xa8c. What exactly does that tell me? There's no way to look that up, or to see what other values are possible and what they indicate, short of tracing back through the driver.

Reading back through I2S_DMACallback(), it looks like there is no provided mechanism for determining which buffer was just sent. That information is kept in a private handle marked "Members not to be accessed / modified outside of the driver."

Don't get me wrong, I'd be happy to spend my days reading, testing, documenting, and improving MCUX SDK driver code - if NXP wants to negotiate an appropriate salary.

The questions I'm asking are things that would need to be answered for any reliable, non-trivial use of the I2S driver in real-world applications. If NXP isn't able to provide answers then I have to assume the code was never tested in real-world applications and shouldn't be considered complete or safe. Is that the case?

Scott

1,854 Views
CarlosGarabito
NXP TechSupport
NXP TechSupport

Sorry for the confusion of a quick reading, suddenly the work is loaded and to give a quick answer made me confused, I comment that each code was developed by specialists in the corresponding area, so each code was not made by one person, but by a group of people with different knowledge, so that, although it may have some errors (we all have them), I believe that if you can trust the code.

 

On the other hand, we do not have much documentation on this code, and I am currently looking for your information, but due to the lack of info on this code, I do not think I can give you a quick answer, and for what you tell me, well, I am not the one offering vacancies, although if you are an expert on the subject, we would not mind an expert in I2S and other related topics, so if you want to be part of our team, you can look for a vacancy and apply for it.

https://www.nxp.com/company/about-nxp/careers:CAREERS

0 Kudos
Reply

1,664 Views
devel
Contributor III

Carlos, you gotta be kidding. Right?

0 Kudos
Reply