<?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>Recommended best practice for a multithreaded sensor</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/92202/recommended-best-practice-for-a-multithreaded-sensor</link><description>Hi Nordic. This is a general question and could as easily have been posted to stack overflow but I have found the members and staff of this community so helpful and adept in explaining things such that even I understand them and thus I hope this is a</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Thu, 22 Sep 2022 13:28:58 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/92202/recommended-best-practice-for-a-multithreaded-sensor" /><item><title>RE: Recommended best practice for a multithreaded sensor</title><link>https://devzone.nordicsemi.com/thread/387521?ContentTypeID=1</link><pubDate>Thu, 22 Sep 2022 13:28:58 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:bf696297-c924-46e0-af54-709bc6eeeb3d</guid><dc:creator>nWre</dc:creator><description>&lt;p&gt;Thank you both Simon and witc for your time and expertise. I have some reading and thinking to do. I hope we can keep this thread open if any big picture questions should arise, it might be a good help for other developers if I am not the only one who is scared and confused.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Recommended best practice for a multithreaded sensor</title><link>https://devzone.nordicsemi.com/thread/387456?ContentTypeID=1</link><pubDate>Thu, 22 Sep 2022 10:36:31 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:ca02d502-5c86-4395-b501-40637254789b</guid><dc:creator>Simon</dc:creator><description>&lt;p&gt;Using&amp;nbsp;k_msgq_get() and&amp;nbsp;&lt;span&gt;k_msgq_get() like&amp;nbsp;&lt;a href="https://devzone.nordicsemi.com/members/witc"&gt;witc&lt;/a&gt;&amp;nbsp;recommended seems like a good approach.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Down below I&amp;#39;ll copy in a reply I provided in a private ticket a month ago, which explains different approaches to manage different threads in Zephyr/NCS:&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;em&gt;&amp;quot;I would recommend you to look at the applications under nrf/applications, they are more complex than the simple samples under nrf/samples, and demonstrate how to handle states/program flow in NCS/Zephyr.&lt;/em&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;em&gt;For example the examples nrf5340_audio and&amp;nbsp;asset_tracker_v2 uses&amp;nbsp;k_msgq_get inside a while(true) loop. For example, the audio app calls it through&amp;nbsp;nrf5340_audio\src\main.c--&amp;gt;main()--&amp;gt;streamctrl_event_handler()--&amp;gt;ctrl_events_get()--&amp;gt;k_msgq_get().&lt;/em&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;em&gt;So it will&amp;nbsp;wait at&amp;nbsp;k_msgq_get() until&amp;nbsp;k_msgq_put() is called from somewhere else, and handle it accordingly. While waiting at&amp;nbsp;k_msgq_get() I think the thread where it&amp;#39;s called from (main thread in this case) is suspended and the idle thread can run (similar to what happens when&amp;nbsp;&lt;a href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.0.0/zephyr/kernel/services/threads/index.html#:~:text=a%20thread%20can%20prevent%20itself%20from%20executing%20for%20a%20specified%20period%20of%20time%20using%20k_sleep()"&gt;k_sleep()&lt;/a&gt;&amp;nbsp;is called).&lt;/em&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;em&gt;The applications nrf_desktop,&amp;nbsp;machine_learning and&amp;nbsp;connectivity_bridge uses the&amp;nbsp;&lt;a href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.0.0/nrf/libraries/others/app_event_manager.html"&gt;Application Event Manager&lt;/a&gt;.&amp;nbsp;In this library, events are submitted by modules and other modules can subscribe and react to them. I&amp;#39;m not sure how it works in details, but it seems like whenever an event is submitted, the&amp;nbsp;&lt;a href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.0.0/zephyr/kernel/services/threads/workqueue.html"&gt;Work queue&lt;/a&gt;&amp;nbsp;(see&amp;nbsp;&lt;a href="https://github.com/nrfconnect/sdk-nrf/blob/v2.0.2/subsys/app_event_manager/app_event_manager.c#L222"&gt;_event_submit()&lt;/a&gt;) is used to execute the appropriate function calls. So whenever&amp;nbsp;&lt;a href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.0.0/zephyr/kernel/services/threads/workqueue.html#:~:text=a%20thread%20that%20processes%20the%20work%20items%20in%20the%20queue.%20"&gt;the thread that processes the work items in the queue&lt;/a&gt;&amp;nbsp;has done it&amp;#39;s work, it will get suspended and the idle thread will run and put the chip to sleep.&lt;/em&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;em&gt;There are many more ways of going about this, for example you can use work queues directly and whenever an event happens, like a button press, you can put the response off to the work queue (for example blink an LED). Here is an example made by a colleague of mine where this approach is used:&amp;nbsp;&lt;a href="https://github.com/too1/ncs-peripheral-uart-adc/blob/d575cdb9a2e0d7e5f0984a6a228bcb0d3a6f1a7c/src/main.c#L564"&gt;https://github.com/too1/ncs-peripheral-uart-adc/blob/d575cdb9a2e0d7e5f0984a6a228bcb0d3a6f1a7c/src/main.c#L564&lt;/a&gt;. So when the&amp;nbsp;&lt;a href="https://github.com/too1/ncs-peripheral-uart-adc/blob/d575cdb9a2e0d7e5f0984a6a228bcb0d3a6f1a7c/src/main.c#L627"&gt;adc_sample_event() is called&lt;/a&gt;&amp;nbsp;it&amp;nbsp;&lt;a href="https://github.com/too1/ncs-peripheral-uart-adc/blob/d575cdb9a2e0d7e5f0984a6a228bcb0d3a6f1a7c/src/main.c#L624"&gt;will run&lt;/a&gt;&amp;nbsp;the&amp;nbsp;&lt;a href="https://github.com/too1/ncs-peripheral-uart-adc/blob/d575cdb9a2e0d7e5f0984a6a228bcb0d3a6f1a7c/src/main.c#L528"&gt;adc_sample() function&lt;/a&gt;. In&amp;nbsp;&lt;a href="https://devzone.nordicsemi.com/f/nordic-q-a/74617/config_assert-cause-code-to-crash/307651"&gt;this sample&lt;/a&gt;, I just used k_sem_take() inside a while true loop, and the chip will sleep while waiting for the semaphore.&amp;quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Best regards,&lt;/p&gt;
&lt;p&gt;Simon&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Recommended best practice for a multithreaded sensor</title><link>https://devzone.nordicsemi.com/thread/387399?ContentTypeID=1</link><pubDate>Thu, 22 Sep 2022 07:04:12 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:fdef8f3e-1029-4cfa-ba42-0686599700bc</guid><dc:creator>nWre</dc:creator><description>&lt;p&gt;Thanks for the example! I will try it out and get back to you. Very much appreciated!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Recommended best practice for a multithreaded sensor</title><link>https://devzone.nordicsemi.com/thread/387395?ContentTypeID=1</link><pubDate>Thu, 22 Sep 2022 06:52:46 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:6824d04d-b8bf-4cad-9241-03fbb037ca69</guid><dc:creator>witc</dc:creator><description>&lt;p&gt;I mean threads (I do not know terminology - I am used to FreeRTOS).&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Task1:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;Common data structure for all queues in the system:
typedef struct {
	uint32_t cmd;
	uint32_t data;
	uint8_t temp8[20];
}dataQueue;

/* cmds constant table*/
#define NEW_DATA_FROM_SENZOR  1
#define NEW_DATA_FROM_ADC     2
...

/* Create queue */
char __aligned(4) queueCore[10 * sizeof(dataQueue)];
struct k_msgq my_msgq;
K_MSGQ_DEFINE(my_msgq, sizeof(dataQueue), 16, 4);

/*Read data from senzor */
dataXYZ[3] = getNewSenzorValue();
/*Send data to the queue */
dataQueue sendData;
sendData.cmd=NEW_DATA_FROM_SENZOR;
memcpy(sendData.temp8,dataXYZ,sizeof(sendData.temp8));
while (k_msgq_put(&amp;amp;my_msgq, &amp;amp;sd, K_NO_WAIT) != 0) {
          /* message queue is full: purge old data &amp;amp; try again */
          // k_msgq_purge(&amp;amp;my_msgq);
        }&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;and reading data in different task:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;dataQueue rxd;
k_msgq_get(&amp;amp;my_msgq, &amp;amp;rxd, K_FOREVER);
if(rxd.cmd == NEW_DATA_FROM_SENZOR)
{
    /* new data are in rxd.temp8 */
}&lt;/pre&gt;&lt;/p&gt;
&lt;div class="jfk-bubble gtx-bubble" style="top:186px;"&gt;
&lt;div id="bubble-4" class="jfk-bubble-content-id"&gt;
&lt;div id="gtx-host" style="max-width:400px;"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="jfk-bubble-closebtn-id jfk-bubble-closebtn"&gt;&lt;/div&gt;
&lt;div class="jfk-bubble-arrow-id jfk-bubble-arrow jfk-bubble-arrowdown" style="left:15px;"&gt;
&lt;div class="jfk-bubble-arrowimplbefore"&gt;&lt;/div&gt;
&lt;div class="jfk-bubble-arrowimplafter"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Recommended best practice for a multithreaded sensor</title><link>https://devzone.nordicsemi.com/thread/387394?ContentTypeID=1</link><pubDate>Thu, 22 Sep 2022 06:43:21 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:38328bbe-34e4-4010-8c60-f99a1c0dbc1b</guid><dc:creator>nWre</dc:creator><description>&lt;p&gt;I think I understand if you mean tasks are threads(?). Or maybe you can show me a pseudo example, however it sounds interesting. I am at the limits of the nrf9160 doing this, it is just barely fast enough to keep up (when an event is triggered, ftp-thread is sleeped as to give more cpu to sd-card-thread and sensor-thread)&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Recommended best practice for a multithreaded sensor</title><link>https://devzone.nordicsemi.com/thread/387391?ContentTypeID=1</link><pubDate>Thu, 22 Sep 2022 06:37:14 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:4467bb2c-fff3-4091-adbc-b354c4059ede</guid><dc:creator>witc</dc:creator><description>&lt;p&gt;Hi, In my case I would you Queue to communicate between Tasks. In Task 1 you can read the values from senzor, then send it to the queue and in Task2 you can read it. It is safe, maybe it will not be fast enought - but it deppends on your needs. Queues are safe.&lt;/p&gt;
&lt;p&gt;Do you understand? Just read it from senzor and send info aout it to the another task..&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>