Re: [nRF52 HAL I2C] Possible 'probe' issue?

2016-12-26 Thread Kevin Townsend
BTW, an easy workaround for this would just be rejecting any requests 
that aren't in the 0x8..0x77 range on the nRF52. That's valid on any 
chip, to be honest, though only an issue on the nRF52.


I'll see if I spot anything on the logic analyzer tomorrow, though, but 
I think this is internal to the peripheral block itself inside the chip 
and so it won't likely appear just looking at the I2C transactions. But 
I'll let you know once I have it hooked up again.



On 27/12/16 01:51, will sanfilippo wrote:

What I am going to say is obvious, but has anyone hooked up an i2c analyzer to 
see what is actually going on in the two cases? I dont see why the peripheral 
would act differently based on the address itself; something must be happening 
on the bus causing the peripheral to act differently.

When I was messing around with the nrf i2c peripheral I used the probe API but 
only for the address I was expecting.

The way we are programming the nrf peripheral might indeed be an issue here but 
without knowing more about how devices act and more about the i2c protocol 
itself I dont think I can offer anything intelligent here :-)

I dont have an analyzer with me but if no one can get a hold of one and test it 
out, I will try to get something set up later in the week.





Re: [nRF52 HAL I2C] Possible 'probe' issue?

2016-12-26 Thread Kevin Townsend
I'll hook a logic analyzer up again tommorow with and without the 
invalid address range and see what the difference is, but it seems like 
a single incorrect address usage is sending the I2C block into the weeds 
for some reason. Nordic's SDK has the same behaviour with the SD and 
their drivers.



On 27/12/16 01:51, will sanfilippo wrote:

What I am going to say is obvious, but has anyone hooked up an i2c analyzer to 
see what is actually going on in the two cases? I dont see why the peripheral 
would act differently based on the address itself; something must be happening 
on the bus causing the peripheral to act differently.

When I was messing around with the nrf i2c peripheral I used the probe API but 
only for the address I was expecting.

The way we are programming the nrf peripheral might indeed be an issue here but 
without knowing more about how devices act and more about the i2c protocol 
itself I dont think I can offer anything intelligent here :-)

I dont have an analyzer with me but if no one can get a hold of one and test it 
out, I will try to get something set up later in the week.





Re: [nRF52 HAL I2C] Possible 'probe' issue?

2016-12-26 Thread will sanfilippo
What I am going to say is obvious, but has anyone hooked up an i2c analyzer to 
see what is actually going on in the two cases? I dont see why the peripheral 
would act differently based on the address itself; something must be happening 
on the bus causing the peripheral to act differently.

When I was messing around with the nrf i2c peripheral I used the probe API but 
only for the address I was expecting.

The way we are programming the nrf peripheral might indeed be an issue here but 
without knowing more about how devices act and more about the i2c protocol 
itself I dont think I can offer anything intelligent here :-)

I dont have an analyzer with me but if no one can get a hold of one and test it 
out, I will try to get something set up later in the week.


> On Dec 26, 2016, at 3:34 PM, Kevin Townsend  wrote:
> 
> And just to highlight the point, here is the results
> using 0x03 at the starting point on an identical setup:
> 
>   i2cscan
>   9116:Scanning I2C bus 0
> 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
>   00:  -- -- -- -- -- -- -- -- -- -- -- -- --
>   10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
>   20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
>   30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
>   40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
>   50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
>   60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
>   70: -- -- -- -- -- -- -- --
>   Found 0 devices on I2C bus 0
> 
> The peripheral shouldn't die because of a faulty addr,
> though, and it isn't a behaviour I've seen before. :)
> 
> That sounds suspiciously like a silicon level problem with
> the I2C peripheral itself, though it would need further
> testing to confirm.
> 



Re: [nRF52 HAL I2C] Possible 'probe' issue?

2016-12-26 Thread Kevin Townsend

And just to highlight the point, here is the results
using 0x03 at the starting point on an identical setup:

   i2cscan
   9116:Scanning I2C bus 0
 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
   00:  -- -- -- -- -- -- -- -- -- -- -- -- --
   10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   70: -- -- -- -- -- -- -- --
   Found 0 devices on I2C bus 0

The peripheral shouldn't die because of a faulty addr,
though, and it isn't a behaviour I've seen before. :)

That sounds suspiciously like a silicon level problem with
the I2C peripheral itself, though it would need further
testing to confirm.



Re: [nRF52 HAL I2C] Possible 'probe' issue?

2016-12-26 Thread Kevin Townsend

Hi Greg,

Well, unexpected but the problem is indeed the faulty address
requests at the beginning and correctly setting the start
address to 0x08 causes the LSM303 to respond:

   133728:Scanning I2C bus 0
 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
   00: -- -- -- -- -- -- -- --
   10: -- -- -- -- -- -- -- -- -- 19 -- -- -- -- 1e --
   20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
   70: -- -- -- -- -- -- -- --
   Found 2 devices on I2C bus 0

The code is below:

   static int
   shell_i2cscan_cmd(int argc, char **argv)
   {
uint8_t addr;
int32_t timeout = OS_TICKS_PER_SEC / 10;
uint8_t dev_count = 0;

console_printf("Scanning I2C bus 0\n"
   " 0  1  2  3  4  5  6  7  8  9 a  b  c  d 
   e  f\n"

   "00: ");

/* Scan all valid I2C addresses (0x03..0x77) */
for (addr = 0x08; addr < 0x78; addr++) {
int rc = hal_i2c_master_probe(0, addr, timeout);
/* Print addr header every 16 bytes */
if (!(addr % 16)) {
  console_printf("\n%02x: ", addr);
}
/* Display the addr if a response was received */
if (!rc) {
console_printf("%02x ", addr);
dev_count++;
} else {
console_printf("-- ");
}
}
console_printf("\nFound %u devices on I2C bus 0\n", dev_count);

return 0;
   }

However, this does still point to a design issue with the I2C
peripheral, and other ICs with identical code combined with this
particular sensor don't exhibit the same behaviour.

Perhaps at a minimum we should check the address in the probe
function and return an appropriate error code if the requested
address is < 0x08, or reject /any/ I2C transaction where the
address is invalid on the nRF52?

Kevin


On 27/12/16 00:15, Greg Stein wrote:

Hey Kevin, all,

I've done quite a bit of I2C, and Sterling pointed out this thread for me
to add some thoughts.

First up, the probe should start scanning at 0x08 (rather than 0x03). Per
the I2C spec, Rev 6, Section 3.1.12, the first and last 8 addresses (in
7-bit addressing) are reserved. Thus 0x08 to 0x77.

Second, the fact that more addresses show up is very disconcerting. For
example, given the 0x29 address for the TCS3472x, how does 0x2a show up?
That is *two* bits changing on the bus. I could see noise introducing one
bit... but two?

And lastly, it seems very weird that the STOP bit is at issue. The N/ACK
occurs before the STOP event is sent. I could possibly imagine bus
weirdness, and parts' state machines going off track, but if the bus is run
properly, then those state machines should be working fine. I'd expect way
more problems when you stop sending that STOP event.

I haven't dug into the code. Is the probe using hardware, or bit banging?
And if hardware, what is the master in your scenario? I found the
microcontroller on the original RPi cannot do repeated starts. So masters
*do* have bugs. Hooking up that scope would be great, to see if your master
is properly obeying the I2C protocol. Particularly given the double-bit
ghost appearance of new nodes.

Cheers,
-g


On Thu, Dec 22, 2016 at 4:54 PM, Kevin Townsend  wrote:


As a follow up to the unexpected I2C scan issue with the LSM303DLHC, I
looked at the errata for the nRF52832 and it may be related to this issue
described below (since the scan problem is unique to the nRF52). A second
STOP bit may be causing problem with the LSM303DLHC inside the probe
function. I'll have to look on a scope to see whether this is happening or
not. There were no other likely errata issues listed in the latest document.

Source: http://infocenter.nordicsemi.com/pdf/nRF52832_Rev_1_Errata_v
1.3.pdf

*3.22 [83] TWIS: STOPPED event occurs twice if the STOP task is triggered
during a transaction*

This anomaly applies to IC Rev. Rev 1, build codes QFAA-B00, QFAB-B00,
CIAA-B00. It was inherited from the previous IC revision Engineering C.

*Symptoms**
*STOPPED event is set after clearing it.

*Conditions**
*The STOP task is triggered during a transaction.

*Consequences**
*STOPPED event occurs twice: When the STOP task is fired and when the
master issues a stop condition on the bus. This could provoke an extra
interrupt or a failure in the TWIS driver.

*Workaround**
*The last STOPPED event must be accounted for in software.



On 19/12/16 14:37, Kevin Townsend wrote:


While adding a test driver for the new sensor API, we've been trying to
debug an issue where a specific sensor (the LSM303DLHC) doesn't show up in
an I2C bus scan (using the 'probe' command in the I2C HAL), using the
following shell 

Re: [nRF52 HAL I2C] Possible 'probe' issue?

2016-12-26 Thread Greg Stein
Hey Kevin, all,

I've done quite a bit of I2C, and Sterling pointed out this thread for me
to add some thoughts.

First up, the probe should start scanning at 0x08 (rather than 0x03). Per
the I2C spec, Rev 6, Section 3.1.12, the first and last 8 addresses (in
7-bit addressing) are reserved. Thus 0x08 to 0x77.

Second, the fact that more addresses show up is very disconcerting. For
example, given the 0x29 address for the TCS3472x, how does 0x2a show up?
That is *two* bits changing on the bus. I could see noise introducing one
bit... but two?

And lastly, it seems very weird that the STOP bit is at issue. The N/ACK
occurs before the STOP event is sent. I could possibly imagine bus
weirdness, and parts' state machines going off track, but if the bus is run
properly, then those state machines should be working fine. I'd expect way
more problems when you stop sending that STOP event.

I haven't dug into the code. Is the probe using hardware, or bit banging?
And if hardware, what is the master in your scenario? I found the
microcontroller on the original RPi cannot do repeated starts. So masters
*do* have bugs. Hooking up that scope would be great, to see if your master
is properly obeying the I2C protocol. Particularly given the double-bit
ghost appearance of new nodes.

Cheers,
-g


On Thu, Dec 22, 2016 at 4:54 PM, Kevin Townsend  wrote:

> As a follow up to the unexpected I2C scan issue with the LSM303DLHC, I
> looked at the errata for the nRF52832 and it may be related to this issue
> described below (since the scan problem is unique to the nRF52). A second
> STOP bit may be causing problem with the LSM303DLHC inside the probe
> function. I'll have to look on a scope to see whether this is happening or
> not. There were no other likely errata issues listed in the latest document.
>
> Source: http://infocenter.nordicsemi.com/pdf/nRF52832_Rev_1_Errata_v
> 1.3.pdf
>
> *3.22 [83] TWIS: STOPPED event occurs twice if the STOP task is triggered
> during a transaction*
>
> This anomaly applies to IC Rev. Rev 1, build codes QFAA-B00, QFAB-B00,
> CIAA-B00. It was inherited from the previous IC revision Engineering C.
>
> *Symptoms**
> *STOPPED event is set after clearing it.
>
> *Conditions**
> *The STOP task is triggered during a transaction.
>
> *Consequences**
> *STOPPED event occurs twice: When the STOP task is fired and when the
> master issues a stop condition on the bus. This could provoke an extra
> interrupt or a failure in the TWIS driver.
>
> *Workaround**
> *The last STOPPED event must be accounted for in software.
>
>
>
> On 19/12/16 14:37, Kevin Townsend wrote:
>
>> While adding a test driver for the new sensor API, we've been trying to
>> debug an issue where a specific sensor (the LSM303DLHC) doesn't show up in
>> an I2C bus scan (using the 'probe' command in the I2C HAL), using the
>> following shell command on the nRF52, but it DOES work on other targets:
>>
>> // Command handler prototype declaration
>> static int shell_i2cscan_cmd(int argc, char **argv);
>>
>> // Shell command struct
>> static struct shell_cmd shell_i2cscan_cmd_struct = {
>> .sc_cmd = "i2cscan",
>> .sc_cmd_func = shell_i2cscan_cmd
>> };
>>
>> // i2cscan command handler
>> static int
>> shell_i2cscan_cmd(int argc, char **argv)
>> {
>> uint8_t addr;
>> int32_t timeout = OS_TICKS_PER_SEC / 10;
>> uint8_t dev_count = 0;
>>
>> console_printf("Scanning I2C bus 0\n"
>>" 0  1  2  3  4  5  6  7  8  9  a  b c  d
>>  e  f\n"
>>"00:  ");
>>
>> /* Scan all valid I2C addresses (0x03..0x77) */
>> for (addr = 0x03; addr < 0x78; addr++) {
>> int rc = hal_i2c_master_probe(0, addr, timeout);
>> /* Print addr header every 16 bytes */
>> if (!(addr % 16)) {
>>   console_printf("\n%02x: ", addr);
>> }
>> /* Display the addr if a response was received */
>> if (!rc) {
>> console_printf("%02x ", addr);
>> dev_count++;
>> } else {
>> console_printf("-- ");
>> }
>> }
>> console_printf("\nFound %u devices on I2C bus 0\n", dev_count);
>>
>> return 0;
>> }
>>
>> The HW (https://www.adafruit.com/product/1120 or
>> https://www.adafruit.com/products/1714) has been used on about 20
>> different MCUs by me, and it's usually one of the first drivers I write so
>> I'm confident the HW is good.
>>
>> What is unusual is that the LSM303DLHC is the only sensor that doesn't
>> show up. We have 5 other I2C sensors connected to the test system that show
>> up fine.
>>
>> I thought it might be a HW issue we haven't seen before since we have
>> 5V/3V level shifting, but checking the LSM303DLHC datasheet I'm quite
>> confident the HW breakout is fine and we are using the recommended values
>> (10K pullups on SCL/SDA, 

Re: Schedule task with strict fixed timing and variable workload

2016-12-26 Thread will sanfilippo
I think there was some discussion re: HAL PWM but I cannot quite recall the end 
result. Maybe that this would be a driver instead of a HAL? I agree; PWM is 
very commonly used so having PWM support (in either driver or HAL form) should 
be added.


> On Dec 26, 2016, at 10:26 AM, Kevin Townsend  wrote:
> 
> Hi Will,
> 
> Thanks for the feedback.
> 
>> 1) Unless you are the highest priority task, other tasks can run which could 
>> cause delays, and thus you are not waking up at the desired time.
> Yeah, everything is based on the assumption that priority is resolved by 
> design, and that the scheduling constraints are realistic and well understood 
> in the system.
>> 2) Using os_time_delay() and os_callout_reset() gives you a 1 os time tick 
>> resolution, so if your ticks are 10 msecs, you will be off by up to 9 msecs. 
>> A 1 msec ticker gets you off by up to 1 msec.
>> 
>> Using a task to post another task is a bit heavyweight; I would use a timer 
>> or a callout to do this. A timer would solve your “tick resolution” issue 
>> but would not solve the problem of a task wake up getting delayed.
> A timer would be a valid solution as well, yes. I haven't looked seriously at 
> the timer HAL yet, but I'll have a look right now and give it a try just to 
> familiarize myself with it.
> 
> I saw earlier today that there wasn't PWM support and wanted to see if that 
> was something that could be easily added to the timer HAL since it's a common 
> requirement that should probably be included (motor control, dimming control, 
> etc.). Different issue though!
>> It would not be hard to add an API to os_callout.c that could be used for 
>> this. Something like “os_callout_reset_at” or “os_callout_reset_tick” which 
>> you could pass in a specified os tick. Not sure what the API should do if 
>> you missed the os tick (return -1 and not post the task)? This would be 
>> simple code to use; just add the sample rate to the last time and call the 
>> new os_calllout API.
> Personally, I think this would make a lot of sense and solve what is bound to 
> be a common problem, and perhaps you can have a flag to define the behaviour 
> when you miss the delay. Either you return an error code, OR you fire the 
> task as soon as you can (though ideally still with a flag of some sort to 
> know you're late), but having the option between the two should solve some 
> problems.
> 
> K.



Re: Schedule task with strict fixed timing and variable workload

2016-12-26 Thread Kevin Townsend

Hi Will,

Thanks for the feedback.


1) Unless you are the highest priority task, other tasks can run which could 
cause delays, and thus you are not waking up at the desired time.
Yeah, everything is based on the assumption that priority is resolved by 
design, and that the scheduling constraints are realistic and well 
understood in the system.

2) Using os_time_delay() and os_callout_reset() gives you a 1 os time tick 
resolution, so if your ticks are 10 msecs, you will be off by up to 9 msecs. A 
1 msec ticker gets you off by up to 1 msec.

Using a task to post another task is a bit heavyweight; I would use a timer or 
a callout to do this. A timer would solve your “tick resolution” issue but 
would not solve the problem of a task wake up getting delayed.
A timer would be a valid solution as well, yes. I haven't looked 
seriously at the timer HAL yet, but I'll have a look right now and give 
it a try just to familiarize myself with it.


I saw earlier today that there wasn't PWM support and wanted to see if 
that was something that could be easily added to the timer HAL since 
it's a common requirement that should probably be included (motor 
control, dimming control, etc.). Different issue though!

It would not be hard to add an API to os_callout.c that could be used for this. 
Something like “os_callout_reset_at” or “os_callout_reset_tick” which you could 
pass in a specified os tick. Not sure what the API should do if you missed the 
os tick (return -1 and not post the task)? This would be simple code to use; 
just add the sample rate to the last time and call the new os_calllout API.
Personally, I think this would make a lot of sense and solve what is 
bound to be a common problem, and perhaps you can have a flag to define 
the behaviour when you miss the delay. Either you return an error code, 
OR you fire the task as soon as you can (though ideally still with a 
flag of some sort to know you're late), but having the option between 
the two should solve some problems.


K.


Re: Schedule task with strict fixed timing and variable workload

2016-12-26 Thread will sanfilippo
There is nothing in the OS to delay until a specific OS time or to cause the 
scheduler to periodically wake up at a certain rate. There are different ways 
to go about doing this and it really depends on what you want. Using a task to 
guarantee timing can be tricky. Some things to be aware of (which I am sure you 
all are):

1) Unless you are the highest priority task, other tasks can run which could 
cause delays, and thus you are not waking up at the desired time.
2) Using os_time_delay() and os_callout_reset() gives you a 1 os time tick 
resolution, so if your ticks are 10 msecs, you will be off by up to 9 msecs. A 
1 msec ticker gets you off by up to 1 msec.

Using a task to post another task is a bit heavyweight; I would use a timer or 
a callout to do this. A timer would solve your “tick resolution” issue but 
would not solve the problem of a task wake up getting delayed.

It would not be hard to add an API to os_callout.c that could be used for this. 
Something like “os_callout_reset_at” or “os_callout_reset_tick” which you could 
pass in a specified os tick. Not sure what the API should do if you missed the 
os tick (return -1 and not post the task)? This would be simple code to use; 
just add the sample rate to the last time and call the new os_calllout API.

Will

> On Dec 26, 2016, at 6:30 AM, Kevin Townsend  wrote:
> 
> Hi Fabio,
> 
> Thanks for the feedback and suggestion.
> 
> I didn't think to have separate sync and read tasks. It does add a decent 
> amount of code when this could be solved with one or two lines and a built in 
> helper class, but it's a workable and reliable solution today.
> 
> I also tested the code below but there are several potential problems with it:
> 
>   static void
>   blinky_task_handler(void *arg)
>   {
>static os_time_t start;
>static os_time_t stop;
>hal_gpio_init_out(LED_BLINK_PIN, 1);
> 
>while (1) {
>/* Measure the starting tick */
>start = os_time_get();
> 
>/* Toggle the LED */
>hal_gpio_toggle(LED_BLINK_PIN);
> 
>/* Measure the ending tick */
>stop = os_time_get();
> 
>/* Check for overflow in tick counter */
>if (stop >= start) {
>os_time_delay(OS_TICKS_PER_SEC/BLINKY_RATE_HZ - (stop -
>   start));
>} else {
>/* Overflow occured */
>os_time_delay(OS_TICKS_PER_SEC/BLINKY_RATE_HZ - stop +
>(UINT_MAX - start) );
>}
>}
>   }
> 
> This doesn't account for situations where the read event might run /over/ the 
> desired rate either, which will require a check before the overflow test if 
> 'stop-start > OS_TICKS_PER_SECOND/BLINKY_RATE_HZ', at which point you 
> probably want to flag the timing overrun and maybe get a new sample right 
> away. There are likely other issues I'm not seeing as well, such as making 
> sure we don't exceed 1/2 the OS time epoch in our delay.
> 
> Having a single helper function would let you encapsulate all these edge 
> cases in one call might be useful, but perhaps someone has a suggestion about 
> the naming or some other helpers that are worth considering ... or disagrees 
> that this should be included in the core at all!?
> 
> FreeRTOS, for example, has vTaskDelayUntil(): 
> http://www.freertos.org/vtaskdelayuntil.html
> 
> K.
> 



Podling Report Reminder - January 2017

2016-12-26 Thread johndament
Dear podling,

This email was sent by an automated system on behalf of the Apache
Incubator PMC. It is an initial reminder to give you plenty of time to
prepare your quarterly board report.

The board meeting is scheduled for Wed, 18 January 2017, 10:30 am PDT.
The report for your podling will form a part of the Incubator PMC
report. The Incubator PMC requires your report to be submitted 2 weeks
before the board meeting, to allow sufficient time for review and
submission (Wed, January 04).

Please submit your report with sufficient time to allow the Incubator
PMC, and subsequently board members to review and digest. Again, the
very latest you should submit your report is 2 weeks prior to the board
meeting.

Thanks,

The Apache Incubator PMC

Submitting your Report

--

Your report should contain the following:

*   Your project name
*   A brief description of your project, which assumes no knowledge of
the project or necessarily of its field
*   A list of the three most important issues to address in the move
towards graduation.
*   Any issues that the Incubator PMC or ASF Board might wish/need to be
aware of
*   How has the community developed since the last report
*   How has the project developed since the last report.

This should be appended to the Incubator Wiki page at:

https://wiki.apache.org/incubator/January2017

Note: This is manually populated. You may need to wait a little before
this page is created from a template.

Mentors
---

Mentors should review reports for their project(s) and sign them off on
the Incubator wiki page. Signing off reports shows that you are
following the project - projects that are not signed may raise alarms
for the Incubator PMC.

Incubator PMC


Re: Schedule task with strict fixed timing and variable workload

2016-12-26 Thread Kevin Townsend

Hi Fabio,

Thanks for the feedback and suggestion.

I didn't think to have separate sync and read tasks. It does add a 
decent amount of code when this could be solved with one or two lines 
and a built in helper class, but it's a workable and reliable solution 
today.


I also tested the code below but there are several potential problems 
with it:


   static void
   blinky_task_handler(void *arg)
   {
static os_time_t start;
static os_time_t stop;
hal_gpio_init_out(LED_BLINK_PIN, 1);

while (1) {
/* Measure the starting tick */
start = os_time_get();

/* Toggle the LED */
hal_gpio_toggle(LED_BLINK_PIN);

/* Measure the ending tick */
stop = os_time_get();

/* Check for overflow in tick counter */
if (stop >= start) {
os_time_delay(OS_TICKS_PER_SEC/BLINKY_RATE_HZ - (stop -
   start));
} else {
/* Overflow occured */
os_time_delay(OS_TICKS_PER_SEC/BLINKY_RATE_HZ - stop +
(UINT_MAX - start) );
}
}
   }

This doesn't account for situations where the read event might run 
/over/ the desired rate either, which will require a check before the 
overflow test if 'stop-start > OS_TICKS_PER_SECOND/BLINKY_RATE_HZ', at 
which point you probably want to flag the timing overrun and maybe get a 
new sample right away. There are likely other issues I'm not seeing as 
well, such as making sure we don't exceed 1/2 the OS time epoch in our 
delay.


Having a single helper function would let you encapsulate all these edge 
cases in one call might be useful, but perhaps someone has a suggestion 
about the naming or some other helpers that are worth considering ... or 
disagrees that this should be included in the core at all!?


FreeRTOS, for example, has vTaskDelayUntil(): 
http://www.freertos.org/vtaskdelayuntil.html


K.



Re: Schedule task with strict fixed timing and variable workload

2016-12-26 Thread Fabio Utzig
Hi Kevin,

One pattern I have used for solving the problem would be to create one
extra task simply signaling the first task and looping on the required
timeout. That guarantees to some extent that the first task is always
waken up at a fixed rate. Something on the lines of (disclaimer:
non-tested code!):

static struct os_eventq timeout_evq;
static struct os_event timeout_evt;

static void
poller_handler(void *arg)
{
os_eventq_init(_evq);

while (1) {
/* will wait here for waking up signal from other task! */
os_eventq_get(_evq);
read_my_sensor();
}
}

static void
timeout_handler(void *arg)
{
/* Wait for eventq initialization */
while (!os_eventq_inited(_evq)) {
os_time_delay(OS_TICKS_PER_SEC / 100);
}

while (1) {
/* wake up the other thread regularly */
os_eventq_put(_evq, _evt);
os_time_delay(timeout);
}
}

This should probably work but having the functionality in the OS would
be cool!

Cheers,
Fabio Utzig

On Mon, Dec 26, 2016, at 09:01 AM, Kevin Townsend wrote:
> Is there a mechanism in the scheduler to fire a task at a specific 
> interval, where the task execution time itself might be variable and 
> 'os_time_delay' might not work.
> 
> For example, assume we need to fire the task reliably at 50hz (within 
> scheduler limits) then push data into a time sensitive algorithm, but 
> the task workload has a variable execution time. This won't work:
> 
> void my_task_func(void *arg) {
>  /* The task is a forever loop that does not return */
>  while (1) {
>  /* Sample data at 50Hz */
>  os_time_delay( OS_TICKS_PER_SEC/50);
> 
>  /* Variable time task to get data */
>  do_something_with_variable_delay()
>  }
> }
> 
> If we knew the time for 'do_something' this would be easy, but if not we 
> need to get the timestamp before execution, and then delay for the 
> required timespan minus execution time, taking into account timer 
> rollover, task overrun, etc. That doesn't seem very elegant.
> 
> I was wondering if some mechanism to do something like this exists 
> already in the system, perhaps in another form like indicating a fixed 
> delay when the task is created:
> 
> void my_50hz_func(void *arg) {
>  static uint32_t a, b;
> 
>  while (1) {
>  a = GET_CURRENT_TIMESTAMP; /* Imaginary macro for discussion 
> purposes! */
> 
>  /* Variable time task to get data */
>  do_something_with_variable_delay()
> 
>  /* Delay until the 20ms interval has passed */
> *os_time_delay_until(a + OS_TICKS_PER_SEC/50);**
> ***}
> }
> 
> Alternatively if something like delay_until is a bad approach (?), can 
> you initialize a task somehow with a fixed delay, saying fire this every 
> 20ms for example, and then just put the task to sleep once the read is 
> done and you've sent the data to the time sensitive algorithm?
> 
> Sorry if I'm missed something obvious looking through the scheduler, 
> task and time documentation.