<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Zephyr I2S: Next buffers not supplied on time</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/107049/zephyr-i2s-next-buffers-not-supplied-on-time</link><description>Hello, I am setting up a Zephyr project using custom hardware with the nRF52840 microcontroller. I am working from the Echo example (ncs/v2.5.0/zephyr/samples/drivers/i2s/echo/src/main.c), however, my application is TX direction only. My audio code is</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Fri, 12 Jan 2024 11:28:48 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/107049/zephyr-i2s-next-buffers-not-supplied-on-time" /><item><title>RE: Zephyr I2S: Next buffers not supplied on time</title><link>https://devzone.nordicsemi.com/thread/463959?ContentTypeID=1</link><pubDate>Fri, 12 Jan 2024 11:28:48 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:0c1631ab-6a54-4de9-bc88-bae96141c8f4</guid><dc:creator>ovrebekk</dc:creator><description>&lt;p&gt;Hi Chris&lt;/p&gt;
&lt;p&gt;It makes sense that you get the ENOMEM error if you try to read more often that data is being produced, yes. You should make sure that your code checks for this error and handles it accordingly.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If you can not afford to use a dedicated thread to tread to handle the I2S driver then I don&amp;#39;t think there is any way to get perfect synchronization between the consumer and producer, since there is no way to define a callback in the driver.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If you were to use the nrfx_i2s driver&amp;nbsp;directly then you can do it this way, and use the callback from the driver to synchronize everything, but then you also have to work with an API which is quite a bit more low level.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Best regards&lt;br /&gt;Torbjørn&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Zephyr I2S: Next buffers not supplied on time</title><link>https://devzone.nordicsemi.com/thread/463829?ContentTypeID=1</link><pubDate>Thu, 11 Jan 2024 16:11:14 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:1f8fc0ef-8ea6-4d2d-bc1b-61d0832a4d8d</guid><dc:creator>cfernandezruns</dc:creator><description>&lt;p&gt;Okay, thank you for the clarification. So as long as my audio thread is checking the state of the I2S buffer often enough that the buffer does not dry up, I should be fine to do other work in my audio thread. Is that correct?&lt;/p&gt;
&lt;p&gt;-------------&lt;br /&gt;&lt;br /&gt;I have updated my logic to attempt to write data to the I2S buffer periodically.&lt;br /&gt;My audio blocks are 200ms long.&lt;br /&gt;I am having my audio thread attempt to write data to the I2S buffer every 100ms, because I want to make sure that the audio buffer does not dry up.&lt;br /&gt;&lt;br /&gt;With this setup, I have found that my audio sounds good (no playback gaps), but&amp;nbsp;I am&amp;nbsp;regularly&amp;nbsp;getting&amp;nbsp;this error:&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; audio_task: Failed to allocate TX block 1: -12&lt;/p&gt;
&lt;p&gt;According to the &lt;a href="https://docs.zephyrproject.org/apidoc/latest/group__system__errno.html"&gt;Zephyr error number table&lt;/a&gt;, the -12 error code translates into &amp;quot;ENOMEM: Not enough core.&amp;quot; I am seeing this error about every other time that I call my function to add data to the I2S buffer. &lt;br /&gt;&lt;br /&gt;I think this all makes sense:&amp;nbsp;I&amp;#39;m trying to add a block to the I2S buffer every 100ms, but the I2S peripheral is only removing a block every 200ms. So the I2S buffer fills up, and every other time I attempt to write a block to the buffer, I get an error because there isn&amp;#39;t room for&amp;nbsp;the new block.&lt;/p&gt;
&lt;p&gt;I think this is fine - my thread attempts to add data to the I2S buffer, and if there is no room, it waits another 100ms and tries again.&lt;/p&gt;
&lt;p&gt;Ideally, I would only attempt to write a block of data when there is a space to add it. I could change my &amp;#39;Add to buffer&amp;#39; frequency to be 200ms as well, which should reduce the frequency of seeing this error. But I think, unless the timing is PERFECT between the buffer consumer and producer, I will always get some kind of buffer error:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If I add data to the I2S buffer faster than the data is being clocked out by the I2S peripheral, then eventually I will attempt to add data to the buffer when there isn&amp;#39;t room in the buffer, generating the &amp;quot;Failed to allocate TX block&amp;quot; error. (Acceptable, but the error is annoying)&lt;/li&gt;
&lt;li&gt;If I add data to the I2S buffer slower than the data is being clocked out, then eventually the buffer will dry up and I will have a gap in the audio playback. (Unacceptable)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I think the only way to get the timing perfectly in sync between the consumer and producer would be to use some kind of feedback from the I2S peripheral (like NEXT_BUFFERS_NEEDED) to signal that there is room for the next block. Any blind timer writing data to the I2S buffer will eventually have one of the two issues I listed, I believe.&lt;/p&gt;
&lt;p&gt;Can I safely ignore this &amp;quot;Failed to allocate TX block&amp;quot; error? Or is there a better approach I should use that would not generate this error?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Zephyr I2S: Next buffers not supplied on time</title><link>https://devzone.nordicsemi.com/thread/463807?ContentTypeID=1</link><pubDate>Thu, 11 Jan 2024 15:04:44 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:990363e4-9e41-419d-9abf-00c55549dcef</guid><dc:creator>ovrebekk</dc:creator><description>&lt;p&gt;Hi Chris&lt;/p&gt;
&lt;p&gt;My reply was probably a bit imprecise.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Any API that provides a timeout parameter can be used both in a blocking or a more asynchronous manner. To make an API call non blocking simply set the timeout to 0, and ensure you check the return value to see if the call timed out or not.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;For the I2S driver you define the timeout statically in the config, rather than provide it as an argument to every function call (like for many other API&amp;#39;s), but the basic principle in the same. In other words you can share the thread with other functions if you just make sure to use a small enough timeout.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;As for stack usage and threads keep in mind that each thread is separately configured, so the overall stack usage is not necessarily any larger when using multiple threads since a smaller thread doing less work would probably require a smaller stack, compared to a larger thread performing multiple tasks.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Best regards&lt;br /&gt;Torbjørn&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Zephyr I2S: Next buffers not supplied on time</title><link>https://devzone.nordicsemi.com/thread/463411?ContentTypeID=1</link><pubDate>Tue, 09 Jan 2024 16:21:02 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:44a01509-3fe2-4665-bbcf-6b4c7b750c14</guid><dc:creator>cfernandezruns</dc:creator><description>&lt;p&gt;Hi &lt;a href="https://devzone.nordicsemi.com/members/ovrebekk"&gt;ovrebekk&lt;/a&gt;&amp;nbsp;, thanks for the timely response.&lt;/p&gt;
&lt;p&gt;I am trying to keep my total number of threads to a minimum in order to avoid the overhead of having separate stacks for each thread. I&amp;#39;d like my audio thread to be able to do other work while waiting for the I2S buffer to free up space.&lt;/p&gt;
&lt;p&gt;If the Zephyr RTOS I2S driver is intended to use a blocking approach, then won&amp;#39;t this prevent any other work from happening in the thread that is managing the I2S interface?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Zephyr I2S: Next buffers not supplied on time</title><link>https://devzone.nordicsemi.com/thread/462473?ContentTypeID=1</link><pubDate>Wed, 03 Jan 2024 11:15:37 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:8241c132-78d2-4a91-b1b6-6ca685894a92</guid><dc:creator>ovrebekk</dc:creator><description>&lt;p&gt;Hi Chris&lt;/p&gt;
&lt;p&gt;The operation of the i2s driver in Zephyr is quite different to that of the nrfx driver. The nrfx driver is designed with a more bare metal approach in mind, and is based on asynchronous function calls and events. The i2s_driver on the other hand is designed to be used with the Zephyr RTOS, and uses a synchronous/blocking approach.&lt;/p&gt;
&lt;p&gt;Ideally you should be able to simply call the &lt;em&gt;i2s_write(..)&lt;/em&gt; function&amp;nbsp;in a loop from your audio thread, and whenever the buffers are full the call will simply be delayed until there is more room in the buffer, and at the same time the calling thread will yield so that other threads can run in the mean time.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;There is also a timeout parameter in the driver that allows you to configure a timeout on the write or read calls, making the function exit if there is no room in the buffer before the timeout occurs.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;For more details please read the &lt;a href="https://docs.zephyrproject.org/apidoc/latest/group__i2s__interface.html#ga01edf23acc6c16bbaf718dab8061a7a0"&gt;i2s_write(..) documentation&lt;/a&gt;.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Best regards&lt;br /&gt;Torbjørn&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>