<?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>AD7794 long delay</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/36369/ad7794-long-delay</link><description>Hi, 
 I&amp;#39;m trying to write a quick driver for the AD7794 on nrf51822. This works on a special SPI: the MISO line is alse the &amp;quot;data ready&amp;quot; line. So when I want to read a value, I need first to ask to read the right channel, then to wait for a value, and</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Mon, 20 Aug 2018 19:18:27 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/36369/ad7794-long-delay" /><item><title>RE: AD7794 long delay</title><link>https://devzone.nordicsemi.com/thread/144992?ContentTypeID=1</link><pubDate>Mon, 20 Aug 2018 19:18:27 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:89a180de-9557-4cf8-99be-cd6f2aa65f6a</guid><dc:creator>Hugo</dc:creator><description>&lt;p&gt;Thank you Stian,&lt;/p&gt;
&lt;p&gt;I&amp;#39;m actually&amp;nbsp; in vacation. My turn ;)&lt;br /&gt;I&amp;#39;ll try this WFE() function within a month.&lt;br /&gt;&lt;br /&gt;But atbout OS and scheduler, not every OS has a scheduler, and a scheduler might not be an OS. This is because there is no precise definition of OS. An OS a is just a toolset that can handle hardware. . So saying that the softdevice, which is an OS in my opinion, is not an OS, is not an excuse of providing a nice scheduler or a less good one.&lt;br /&gt;I&amp;#39;m happy to know that the scheduler cannot do what I need, the way I need, because it&amp;#39;s a step further. I&amp;#39;m quite scared to use both softdevice which has a scheduler used by bluetooth runtime, and an other scheduler, as they need &amp;quot;to share&amp;quot; interupts from a timer, and they might interract.&amp;nbsp; I&amp;#39;ll check if it&amp;#39;s possible, when I&amp;#39;ll come back.&lt;br /&gt;Thanks for your answer.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: AD7794 long delay</title><link>https://devzone.nordicsemi.com/thread/144922?ContentTypeID=1</link><pubDate>Mon, 20 Aug 2018 11:39:08 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:cce6fe1f-c6e5-4e9b-a2f2-d85d704b1b60</guid><dc:creator>Stian R&amp;#248;ed Hafskjold</dc:creator><description>&lt;p&gt;The scheduler is very simple, it does not provide this functionality. It&amp;#39;s basically just for transferring execution from interrupt context to main context. You put the event handler in a queue in the ISR, and you execute the handler in main context. That&amp;#39;s all. FreeRTOS, linux etc which you mentioned earlier are OS&amp;#39;s. If you want similar functionality you can use freeRTOS on the nRF chip, but I think this is a bit too much just for an SPI driver.&lt;/p&gt;
&lt;p&gt;A clean and nice solution is to use flag in the GPIOTE interrupt handler and wait for it in the SPI function. Did you try the following?&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;bool data_ready = 0;

void gpiote_interrupt(){
    //got a MISO falling edge interrupt
    data_ready = 1;
}

void SPI_read_sensor(){
    spi_send_command();
    deinit_spi(); // SPI lines cannot be configured while SPI is enabled
    configure_gpiote_interrupt_on_MISO();
    while(!data_ready){
        __WFE(); //wait for event. CPU sleeps until event
    }
    data_ready = 0;
    deinit_gpiote();
    init_spi();
    spi_read_data();
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Note that you cannot reconfigure the GPIO pins while SPI is enabled.&lt;/p&gt;
&lt;p&gt;Another thing you should be careful with is whether or not the spi_read/write calls are blocking. For example: If the &amp;quot;spi_read_data()&amp;quot; call above is non-blocking, the function will return instantly and the scheduler might continue execute the next function in the queue before the SPI data has actually been read. Or similarly, if the &amp;quot;spi_read_command()&amp;quot; call is non-blocking it will enter the waiting loop before the spi read command is sent.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: AD7794 long delay</title><link>https://devzone.nordicsemi.com/thread/144131?ContentTypeID=1</link><pubDate>Tue, 14 Aug 2018 10:28:35 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:a37bd4f4-a15d-4aa3-ab04-bf5faee72f0b</guid><dc:creator>Hugo</dc:creator><description>&lt;p&gt;Great, it tooks me, 1mninute&amp;nbsp;on google to deal with it on 3 different scheduler, I still don&amp;#39;t know how to do it with the nordic softdevice scheduler. Can you name a function to &amp;quot;&lt;span&gt;wait/block/suspend on a flag/mutex/semaphore&amp;quot;? can you&amp;nbsp;link me an exemple? or the best can you ask me to read the manual, but with a link to the right page of the manual? this would be lovely, and thank you in advance :)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: AD7794 long delay</title><link>https://devzone.nordicsemi.com/thread/144121?ContentTypeID=1</link><pubDate>Tue, 14 Aug 2018 09:49:03 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b005052d-3816-407a-941e-f96c75d044b0</guid><dc:creator>Susheel Nuguru</dc:creator><description>[quote userid="9573" url="~/f/nordic-q-a/36369/ad7794-long-delay/144098"]In an other hand, I fully agree that the while loop is really ugly and is a great way to block the CPU and everything including the softdevice[/quote]
&lt;p&gt;The while loop does not block softdevice from interrupting your app. That is what we believe is the source of this problem.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;There is a solution as I wrote earlier, instead of waiting for the pin state change, your app needs to wait/block/suspend on a flag/mutex/semaphore. Make sure that the flag/mutex/semaphore change their state in the gpio ISR which is making sure that you do not loose this info. I do not see any other way to do this a failproof way.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: AD7794 long delay</title><link>https://devzone.nordicsemi.com/thread/144098?ContentTypeID=1</link><pubDate>Tue, 14 Aug 2018 08:30:09 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c703e784-6ba5-4dbd-8365-857e3edb0a24</guid><dc:creator>Hugo</dc:creator><description>&lt;p&gt;Hin thanks, and congratulation, you found the bug.&lt;br /&gt;Actually, as you see in the 1st screenshot, asking and waiting for a measurement takes 4ms.&amp;nbsp;&lt;br /&gt;When the while loop explodes, the 4ms are not done yet, wich means that if I was waiting for an interrupt, the interrupt woudn&amp;#39;t have been called yet.&lt;br /&gt;Maybe you are right, and this is cleaner, but I&amp;#39;m quite sure it won&amp;#39;t work, would it?&lt;br /&gt;&lt;br /&gt;In an other hand, I fully agree that the while loop is really ugly and is a great way to block the CPU and everything including the softdevice. I&amp;#39;m looking for a softer function, such as:&lt;br /&gt;void no_breaking_delay_ms( int delay_time);&lt;br /&gt;or&lt;br /&gt;void wait_quietly_for_an_event_enjoying_a_mojito_on_the_beach_watching_all_the_other_thread_are_still_running(event_t event_name);&lt;br /&gt;If both functions exist, it would be even better.&lt;br /&gt;&lt;br /&gt;As Stian, and I said, there is an other way: cut the function into 3 function, the beginning, the interrup, the end. And of course, cut any function that need to read the adc in two too. Let&amp;#39;ts try to avoid this, please. Lingchi is a programming technic which leads the code to death.&lt;br /&gt;&lt;br /&gt;In linux, there is &amp;quot;sleep&amp;quot; and &amp;quot;mutex&amp;quot;&lt;br /&gt;In chibios there is &amp;quot;&lt;a class="el" href="http://chibios.sourceforge.net/html/group__threads.html#ga8b10a49e2ec522a5ddecabdc453afcab"&gt;chThdSleep&lt;/a&gt;&lt;span&gt;&amp;nbsp;(&lt;/span&gt;&lt;a class="el" href="http://chibios.sourceforge.net/html/group__types.html#gae3e32a98d431a02106616da3071832dd"&gt;systime_t&lt;/a&gt;&lt;span&gt;&amp;nbsp;time)&lt;/span&gt;&amp;quot; and &lt;a class="el" href="http://chibios.sourceforge.net/html/group__events.html#ga77651e22578713ebe355c1213286c2e9"&gt;chEvtWaitOne&lt;/a&gt;&lt;span&gt;&amp;nbsp;(&lt;/span&gt;&lt;a class="el" href="http://chibios.sourceforge.net/html/group__types.html#gabff0c32475baf20ea8c5c710d6e8b708"&gt;eventmask_t&lt;/a&gt;&lt;span&gt;&amp;nbsp;mask)&lt;br /&gt;&lt;/span&gt;In freeRTOS there is &amp;quot;vTaskDealy&amp;quot; and eventGroups&lt;br /&gt;etc...&lt;br /&gt;&lt;br /&gt;Maybe, there is just no solution, is it?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: AD7794 long delay</title><link>https://devzone.nordicsemi.com/thread/144079?ContentTypeID=1</link><pubDate>Tue, 14 Aug 2018 07:38:48 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:aff00d95-337d-47d6-8b3d-f3ea3e239da5</guid><dc:creator>Susheel Nuguru</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;I see atleast one deadlock scenario here. At the below line in your code&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;    //set the MISO line as input
    nrf_gpio_cfg_input(BSP_SPI_SD0, NRF_GPIO_PIN_NOPULL  );
    //wait fot the line to be down (! ! ! )
    while(nrf_gpio_pin_read(BSP_SPI_SD0)!=0);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;You are assuming that your application will be active and able to catch the pin toggle to low in that while loop. But on a multi context system (when using softdevice or scheduler or any other RTOS) it is possible that some other context is running other than your app. I think this is what is happening in your application&amp;nbsp;&lt;/p&gt;
&lt;p&gt;1) you set MISO as input&lt;/p&gt;
&lt;p&gt;2) wait for pin to go low.&lt;/p&gt;
&lt;p&gt;3) something interrupts your app (softdevice or interrupt)&amp;nbsp;&lt;/p&gt;
&lt;p&gt;4) When something else is running other than your app, then the MISO pin toggles to 0 and toggles back to 1&lt;/p&gt;
&lt;p&gt;5) your application gets control back from (softdevice or interrupt) and it has missed the toggle it waits for and sees that the pin is still at 1 and continues the while loop.&lt;/p&gt;
&lt;p&gt;5) Since your app is stuck in this loop it is not sending read commands to the sensor and hence the MISO pin will not toggle anymore.&lt;/p&gt;
&lt;p&gt;This is clearly a deadlock in your app.&lt;/p&gt;
&lt;p&gt;You need to make sure that when your app is in the background and something else is running, then the pin toggle is captured somehow. It is wise to configure the pin to generate interrupt at this time when the pin goes low and then set a flag in the interrupt. You can wait for this flag in the while loop instead of waiting for pin to toggle. If you set the flag the the interrupt then you make sure that this toggle is not lost and captured as a flag value change in ISR.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: AD7794 long delay</title><link>https://devzone.nordicsemi.com/thread/143961?ContentTypeID=1</link><pubDate>Mon, 13 Aug 2018 12:46:31 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c87361b1-8761-42ba-a451-7a146ae94120</guid><dc:creator>Hugo</dc:creator><description>&lt;p&gt;Hi,&lt;br /&gt;The function is called by a app_timer (from app_timer_create), depending of the state of the bluetooth state machine(if connected, timer is on fast, if off, it&amp;#39;s on slow). So the main tread, on the main loop just check the scheduler and low power the module.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;    for (;;)
    {
        app_sched_execute();
        power_manage();
    }&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;For now, I use the timeout of the timer as interrupt, but the reading rate is just ok (5ms/measure so 33Hz). &lt;br /&gt;On every scheduler I ever met, there was a function &amp;quot;delay&amp;quot; and &amp;quot;wait_for_event&amp;quot;, and even on linux, there is mutexs, and and non-crashing &amp;quot;sleep&amp;quot; function for threads. That&amp;#39;s all what I want :&lt;br /&gt;-Or a way to create and wait for an event&lt;br /&gt;-Or a way to wait for some specific time, but without limit but max value of an integer. &lt;br /&gt;-Or both&lt;br /&gt;And if they don&amp;#39;t exist:&lt;br /&gt;-whats the limit of time, for a function called on a timer, without any hulk risk, and why, and how to change it, if it&amp;#39;s possible?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: AD7794 long delay</title><link>https://devzone.nordicsemi.com/thread/143942?ContentTypeID=1</link><pubDate>Mon, 13 Aug 2018 12:15:29 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:ad818c41-91c5-4844-b1a0-75f73bc9581a</guid><dc:creator>Stian R&amp;#248;ed Hafskjold</dc:creator><description>&lt;p&gt;If you want to wait quietly for something, the way to do it is to exit the function, return to idle, and wait for an interrupt. This interrupt could be the GPIOTE telling you SPI driver that data is ready, or an app_timer continuously polling the SPI lines. Blocking the main thread waiting in a for loop is generally not a good idea, so why it asserts is hard to say, it would require some debugging to know exactly why it fails.&lt;/p&gt;
&lt;p&gt;If these sensor readings are something you do continuously, I would suggest to use the app_timer to trigger the reading instead of the scheduler. Also if the time it takes for the MISO line to go low after the command has been issued is somewhat deterministic (i.e. you can say that it is always less than 12ms) maybe it&amp;#39;s better to hard code the waiting time using the app_timer and initiate a read sequence in the app_timer timeout interrupt.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: AD7794 long delay</title><link>https://devzone.nordicsemi.com/thread/143317?ContentTypeID=1</link><pubDate>Wed, 08 Aug 2018 08:48:40 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:49f348b1-f1eb-4967-b6c6-162b2a544f3d</guid><dc:creator>Hugo</dc:creator><description>&lt;p&gt;thanks for your answer.&lt;br /&gt;I can do this but I must split my function at least into 2 parts. I don&amp;#39;t like it.&lt;br /&gt;look this is want to be able to do:&lt;br /&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;void my_lovely_function()
{
  uint32_t summer_temperature[6];
  uint8_t i;
  what_a_nice_day();
  I_love_summer();
  let_s_enable_temperature_sensors();
  let_s_wait_a_delay_to_stabilise_them();
  for(i=0;i&amp;lt;6;i++)
    summer_temperature[i]=check_ext_adc(i);
  switch_temperature_sensor_down();
  if(do_I want_to_send_this_temperature_by_bluetooth(summer_temperature))
    send_bt_data(summer_temperature);
  this_was_my_pleasure_to_deal_with_you();
  thanks_for_reading_all_this();
  return;
}&lt;/pre&gt;&lt;br /&gt;&lt;span&gt;If I split &amp;quot;check_ext_adc&amp;quot;, I still must wait for its result, which will still break the scheduler.&lt;br /&gt;I can make some ugly stuffs, but I love code that I can understand without comment and&amp;nbsp;&lt;/span&gt;&lt;span&gt; chart.&lt;br /&gt;What&amp;#39;s the max time lengh of a function and why? How can I say in a function, &amp;quot;let&amp;#39;s pause and wait quietly for something (time, event, whatever)&amp;quot;? what&amp;#39;s the min time I should free the scheduler for it to be happy? (bluetooth connected).&lt;br /&gt;Kind regards,&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: AD7794 long delay</title><link>https://devzone.nordicsemi.com/thread/143242?ContentTypeID=1</link><pubDate>Tue, 07 Aug 2018 13:55:09 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c81ee30b-dc67-40f0-a95a-44c15b502ae8</guid><dc:creator>Stian R&amp;#248;ed Hafskjold</dc:creator><description>&lt;p&gt;Hi, sorry for the late response. Vacation time.. What if you do it like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Initialize SPI&lt;/li&gt;
&lt;li&gt;Do the SPI write sequence&lt;/li&gt;
&lt;li&gt;De-initialize SPI&lt;/li&gt;
&lt;li&gt;Set up GPIOTE on the MISO line and trigger on falling edge.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then in the GPIOTE event handler:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Initialize SPI again&lt;/li&gt;
&lt;li&gt;Do the SPI read sequence&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This will also be a more power efficient solution as the CPU is running in a while loop, and is not blocking other things from running.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: AD7794 long delay</title><link>https://devzone.nordicsemi.com/thread/140281?ContentTypeID=1</link><pubDate>Mon, 16 Jul 2018 18:09:43 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e2be7eb5-3fd8-4524-8844-bc62adedc3da</guid><dc:creator>Hugo</dc:creator><description>&lt;p&gt;I found and wrote a very very ugly solution:&lt;br /&gt;-I create an init function, which request a value to the AD7794&lt;br /&gt;-I schedule a function that read the value, switch to the next one, and request it. Then just stop&lt;br /&gt;I read the value every 4ms+wait for slave select. This is extra quite short, if it happens.&lt;br /&gt;&lt;br /&gt;the good things are:&lt;br /&gt;-I can read the 6 values and send a packet every 6 of them.&lt;br /&gt;-I can be in power save during the wait (saving energy is important for me)&lt;br /&gt;the bad things are:&lt;br /&gt;-This is really ugly&lt;br /&gt;-I can&amp;#39;t just read a selected value when I want&lt;br /&gt;-I can&amp;#39;t schedule is as: &amp;quot;get the 6 values as fast as I can, then shout it on bluetooth&amp;quot;, all this every n ms.&lt;br /&gt;-if it happens that a value arrives like 8ms after request, the chip falls into a broken state.&lt;br /&gt;-if I want to mix ready order, or add other sensor, it might be mind-blowing.&lt;br /&gt;&lt;br /&gt;So I&amp;#39;m still interested to know the official way to do it&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: AD7794 long delay</title><link>https://devzone.nordicsemi.com/thread/140058?ContentTypeID=1</link><pubDate>Fri, 13 Jul 2018 11:45:04 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c404e955-d47f-4e65-bce0-c761972d11fd</guid><dc:creator>Hugo</dc:creator><description>&lt;p&gt;Some precision, all is actually working with the softdevice, the problem is when it&amp;#39;s called from scheduler timer.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>