Are util/delay.h-methods independent of whether being run or not?

Go To Last Post
12 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Confusing question maybe, what I mean is, on a threaded time-shared system where an individual process might be preempted by another, will the delay-methods perform accurately or not? I read the documentation in the util/delay-file but it didn't mention anything, but I do see some "ticks"-macros, so maybe it keeps track of the CPU and not just numbers in a loop..?

 

Help is very much appreciated.

sol i sinne - brun inne

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

First, you should make clear which toolchain and version you are using.  Does the mention of "util/delay.h" imply GCC of some vintage for some AVR flavour?

 

It is good to see your thread.  It has been some weeks since this "much ado about nothing" topic has been resurrected.  In short, delay function is of limited use in any real AVR application.  No real AVR application is going to sit in one place for an indeterminate time wasting all the CPU cycles.  Indeed, you also mentioned "threaded".  ???  Take a pencil and paper and list out the instructions in a particular sequence...how does that list get affected by task switch in the middle of counting delay loops?

 

The mention of "ticks" is probably the clue.  You make a master counter if some kind of timed interval; call that your tick.  Then all timekeeping is done in relation to that tick counter.

 

We can leave "maximum service time" for another day.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you look at the library source code you'll see it is a software delay. Thus, in a preemptive system, the delays using these functions may be longer than expected. I was going to mention this regarding your posts in my tutorial thread, but i couldn't make sense of what point you were trying to make, so i refrained.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks guys, yeah I get confused a lot. It's just that, I'm programming an EDF-scheduler for my preemptive kernel, and if delay would've worked regardless of it being processed or not that would really help in setting accurate deadlines, for testing purposes.

 

Time is really a confusing concept when you think about it, especially when it comes to programming. I'm not very proficient in C so I might need your help, I will return if so.

sol i sinne - brun inne

Last Edited: Sun. Jan 11, 2015 - 03:51 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have timers available. You can use the compare features to give you a system tick as well as sub microsecond times. Have the timer free run (no ctc mode) and using uint16 vars, you can add the future compare time to the output compare register (assuming a 16 bit timer). Normally you might add 10ms for your system tick but if you wanted say,180us, the add 180us worth of time and set you flag/state so you know the next interrupt is special rather than your system tick.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Soft delays are of no use in a (preemptive) RTOS but think about it - your tasks are being switched in/out on a timer (probably 10ms or 100ms or something) anyway so the simplistic way to get a task to delay() is simply to have it make some kind of "yield and now don't call me for N ticks" mechanism. So if the task wants a 150ms delay and your task switching tick is 10ms the task just needs to be "put to sleep" for 15 ticks. Maybe add a "sleep_count" field added to the TCB for each task and when one calls delay(150) you set sleep_count to 150/10 (where 10 is the tick rate) and then on subsequent scheduling ticks you just decrement any non-0 sleep_count fields and perhaps priortize things so that for any task where sleep_count makes the last 1 to 0 transition it is then scheduled in next.

 

For example see:

 

http://www.freertos.org/vtaskdel...

Last Edited: Mon. Jan 12, 2015 - 10:19 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Wow that's really insightful, thanks! I hope I can implement it in some fashion, so far my attempts at making a task scheduler have been in vain, the round-robin scheme works much better haha, two days wasted.

 

Instead of just blindly switching between tasks I've at least tried to infer some type of priority based on deadlines, I'm not sure it makes sense the way I've implemented it nor tested it. Uh I'm so not used to languages with side effects :P And pointers lol, what were they thinking

sol i sinne - brun inne

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Again there's a lot of "prior art" on all this. RTOS prioritization is well researched. Look again at the FreeRTOS site - they have a walkthrough of the implementation and the one they happen to explain is the AVR one.

 

Ultimately you have a regular ticker interrupt and every time it ticks (typically 10ms..100ms) you interrupt and "put away" the task that was executing then you "unpack" and set up to continue running the next one in the list. The choice of "which one should I run next" is basically a question of prioritization.

 

One way to do that (for example) would be to have each task have a counter. When the timer "ticks" you decrement all the counters and any that hit 0 you then schedule in to run. You then reload the counter with a "priority" so the ones with the lowest numbers actually have a high priority. Say you had two tasks. One set to "priority" 3 and one to priority 7 then you start each with their max priority value: one set to 3 one to 7. Then ticks occur:
 

tick  1 2 3 4 5 6 7 8 9 10 11 12...

task  3 2 1 0 3 2 1 0 3 2  1  0 ...
task  7 6 5 4 3 2 1 0 7 6  5  4 ...

so the top task counts down its priority from 3 and when it hits 0 it runs and then sets the count back to 3. The other task does it with 7. As you can see the prio=3 taks gets more CPU time than the prio 7 one.

 

Of course this scheme is not great as there's some time slots where nothing runs so maybe you should add a rule that "if nothing hits 0 in a time slot go back round and decrement all their timers until one does.

 

Of course this could be affected by something like the delay thing I suggested above. If a task is in a "wait 10 ticks before you run" delay then that takes priority over anything affecting actual task priority. but when it's delay counter reaches 0 perhaps it's priority countdown should also be set immediately to 0 so it runs as soon as possible?

 

This is all just simplistic example and needs some thinking about but it just illustrates the kind of approach you could think about. Far better though is to search out the prior work on this. I'm sure there are examples codes, articles and books all to be found on the internet where "best solutions" are explored so I'd examine those first.

 

One fairly well known pre-emptive RTOS is called Linux and it has a ./doc/ directory that contains a lot of files that explain how various parts of it works. If that has something on how the task scheduling works I'll bet that could be a VERY interesting read!

 

EDIT: yup Google finds things like this: http://en.wikipedia.org/wiki/Com... and http://en.wikipedia.org/wiki/Sch... I'd then follow links there to find out more about what "fair scheduling" and things are.

Last Edited: Mon. Jan 12, 2015 - 04:49 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I will read everything in a minute, I'll just do some prototyping of my own first. Thanks for the elaborate answer!

sol i sinne - brun inne

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Alright guys, good news! Your brilliant tip (or just the realization of my stupidity) has payed off, I now have a working preemptive context switching kernel with the ability to postpone execution of threads! I did try to prioritize threads in regards to their deadline, but that's scrapped now because it simply didn't work , I will start fresh again (: Here's a video link to youtube (sorry for the video quality, if you can even call it quality.. Read the description if you can't see what's going on).

 

https://www.youtube.com/watch?v=...

 

Instead of using _delay_ms() to blink an led for instance, I simply make a method that turns it on, one that turns it off, and within them both spawn the corresponding method but with a postponed execution equivalent to the _delay_ms()! No wasted cpu cycles!

sol i sinne - brun inne

Last Edited: Mon. Jan 12, 2015 - 08:20 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why not just a sleep() call to your rtos? The task gets suspended for x ticks.
Seems like you need to read
http://books.google.com.au/books/about/MicroC_OS_II.html?id=exHUsQoEgD4C

There's also books by the guy who did minix
These should give you a good grounding in o/s concepts and implementation.

Last Edited: Tue. Jan 13, 2015 - 04:13 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
There's also books by the guy who did minix
Andrew Tanenbaum.  "The nice thing about standards is that there are so many to choose from."

http://en.wikipedia.org/wiki/Andrew_S._Tanenbaum

 

Some good talks on YT as well:

https://www.youtube.com/results?search_query=andrew+s+tanenbaum

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]