Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Real time embedded FreeRTOS mailing list 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT Training




Loading

xxxxFromISR?

Posted by Neil Bradley on April 29, 2008
Curiosity question -

In all other RTOSes I've worked with, getting any kernel object that may (or may not) block only had a single API, whether called from an interrupt or from foreground code and would return an "invalid context" error message if an attempt to block was made.

In FreeRTOS, there are regular kernel object functions that have both ISR and non ISR versions. Why not make them a single API with the checking inside the kernel object functions? That way I don't have to manually check it myself. It's not as if checking a boolean or a counter is a major (or even minor) time consumer compared to the rest of the functionality of the code, and it'd save me from having to manually check for interrupt vs. non-interrupt time. ;-) Sorry - just seems like it should be a kernel capability.

RE: xxxxFromISR?

Posted by Richard on April 29, 2008
You raise some interesting questions, for which I'm not going to say "my way is the best way", just give an opinion. The queue send and receive functions are really the most complex part of the system. This is to ensure they cover all cases - there are many more of which than might be immediately obvious. The 'FromISR' versions are much smaller and simpler in many ways, so its not just the overhead of checking one status variable. Also from a portability and maintainability point of view, doing it the other way might require additional code in the portable layer to indicate the context from which the functions are being called.

Regards.

RE: xxxxFromISR?

Posted by Neil Bradley on April 29, 2008
To be clear, I wasn't suggesting getting rid of the guts of the functions themselves. What I was suggesting was adding in a check "if (in interrupt) { call ISR version} else {call foreground version}" and eliminating the xxxFromISR. Doesn't FreeRTOS already have at least a boolean or some other variable to know what context it's in?

RE: xxxxFromISR?

Posted by incrediball on April 29, 2008
The xxxFromISR routines are probably too different from the regular versions to combine them into one. For example xQueueReceive will block for xTicksToWait ticks if nothing is available in the queue whereas xQueueReceiveFromISR cannot possibly do this. Additionally xQueueReceiveFromISR returns information about whether a task was woken and xQueueReceive does not.

RE: xxxxFromISR?

Posted by Richard Damon on April 30, 2008
Actually, FreeRTOS does NOT know (in general) if an interrupt has occurred, as there is not code automatically inserted into every interrupt. FreeRTOS is a very lightweight general system and does not claim to be a full kernel, so interrupt go directly to the users interrupt service routines, which are kernel level procedures, and need to work under different rules than user level procedures (like use the ISR versions of routines).

Also the idea of an
if(in interrupt) fun_isr() else fun_task()
statement is almost certainly going to lead to bugs, as the ISR version needs to use external tracking of a possible context switch needed on return, and possible need somewhat to handle the error when the function refuses the operation if for example the queue is full on an insert. You probably want to have some way to record that information was lost.

RE: xxxxFromISR?

Posted by Neil Bradley on April 30, 2008
Well, I can see what you guys are saying, but I'll point out that ThreadX and uCOS-II (a couple of the biggest RTOSes out there that I have extensive experience with) do this with absolutely no issues and in practice, no problems.

To your point about that statement leading to bugs, that's false. Depositing messages into queues, etc... can be done from ISRs or from foreground code from either source and it's perfectly valid programming, also as evidenced by FreeRTOS supporting two versions. The fact that I have to check and call one of two different routines instead of the kernel (which should already know it) is just something I've come to expect in RTOSes. It's a strange departure from all other RTOSes I've encountered. There's an opportunity here to have the kernel take away possible problematic operation from the implementor.

The whole "lightweight" argument I don't attach any value to. Adding in an increment/decrement for the # of times it's in an ISR and checking it is not any significant nor appreciable overhead, no matter the CPU. I don't buy that argument.

Part of FreeRTOS's appeal is it being free, and a better way to help propagate the project is to ensure it has what those who use RTOSes extensively expect, so I do plan on nudging Richard from time to time to help the project along. ;-) It was only recently that counting semaphores were added - something that is quite standard in all other RTOSes. I submitted some timer code (in FreeRTOS's highly configurable style and spirit) well over a year ago and it hasn't been added in any form (again, something I've come to expect out of an RTOS). I'm also in need of event flags which FreeRTOS doesn't have, so I'm hoping that either Richard will be receptive to me adding it, or has plans to do so.


RE: xxxxFromISR?

Posted by Richard on April 30, 2008
> The fact that I have to check and
> call one of two different
> routines instead of the kernel (which should already know it)
> is just something
> I've come to expect in RTOSes.

What type of function call are you making both from task level and from an ISR?

Original FreeRTOS.org design decisions came from my own usage scenarios, that is true. My preference is to 'defer' interrupt processing to the task level. Therefore interrupts do nothing other than service the interrupting peripheral (gather data [if necessary], clear the interrupt), then post the data and status to a task for post processing. The task can be what I call a 'handler' task whereby it runs at a priority above any application tasks. Doing this ensures that the interrupt returns directly to the handler task, therefore ensuring processing is contiguous in time just as if all the processing had been done in the ISR - assuming there are no higher priority handler tasks already executing. Hence you can see where the model originally came from. Current developments are driven by users, not by my own usage, so things are changing.

> It's a strange departure from
> all other RTOSes
> I've encountered.

Strange as it may seem, I have never used wither uCOS-II or ThreadX. This probably has positive and negative effects. On the positive side, I have a clean sheet design and can be sure that nobody can ever make any claims over code I issue as open source. On the negative side, maybe I have missed some tricks, but note the comment just made about other people making claims over the FreeRTOS.org code.


>There's an opportunity here to have the
> kernel take away possible
> problematic operation from the implementor.
>
> The whole "lightweight" argument I don't attach any value to.
> Adding in
> an increment/decrement for the # of times it's in an ISR and
> checking it is
> not any significant nor appreciable overhead, no matter the
> CPU. I don't buy
> that argument.

There are minor portability and maintenance issues though.

I have very recently been working on a SafeRTOS implementation that adds in (in a backward compatible way) a method of allowing different interrupt priorities for different API calls. For example, queues can be used from interrupts of higher priority than the tick. At some point this will get migrated into the FreeRTOS.org code too. That might be an opportunity to add in your suggestion, but I would see this as being done on a port by port basis on a 'who shouts loudest' basis.


> Part of FreeRTOS's appeal is it being free, and a better way
> to help propagate
> the project is to ensure it has what those who use RTOSes
> extensively expect,
> so I do plan on nudging Richard from time to time to help the
> project along.
> ;-)

... which is good, this type of debate is very useful to me. Most of the recent developments have been user driven. I am just preparing my classes for the Microchip Masters conference this year, and comparing the code to that presented last year I have been amazed how things have come on in just 12 months.


>It was only recently that counting semaphores were added
> - something that
> is quite standard in all other RTOSes.

This is an example of what I mentioned at the top of this post. I see counting semaphores to be of little value to small embedded systems, but people asked for them (over and over again) so I added them in.

The recursive semaphore feature was for one particular customer who needed it to facilitate their implementation of some communications stacks. It’s a bit of an oddity (although posix I think has them).

The V5.0.0 change to the xQueueSendFromISR() was the result of user requests - it did in fact fix a badly constructed API function so I was pleased to make the change but a little nervous of the backward compatibility issue.

> I submitted some timer
> code (in FreeRTOS's
> highly configurable style and spirit) well over a year ago
> and it hasn't been
> added in any form
> (again, something I've come to expect out
> of an RTOS). I'm
> also in need of event flags which FreeRTOS doesn't have, so
> I'm hoping that
> either Richard will be receptive to me adding it, or has
> plans to do so.


Three things here:

1) Thanks for your contribution.

2) I have a whole library of ports and suggestions that people have sent me. I would like to create an 'unofficial' archive of such things that people can download. This is a little tricky with respect to maintainability, as people will often send something, then two days later they will send it again with a fix, etc. Also as previously mentioned I have to be VERY careful with publishing things for which the origin is unknown by me. If I unknowingly published something that was basically taken out of another OS then this would cause big trouble. Don't underestimate how big an issue this is. FreeRTOS.org is licensed to make it as easy as possible to use in commercial applications, so it is a regular occurrence for (big company) users to get their legal departments involved. This is just the way life is now. Its a fine balance between maintaining the open source ethos, and maintaining users ability to use the code with confidence.

3) I think we have discussed a couple of times the issues regarding event flags, and to a lesser extent timers, readers can search through the forum for this so I won't repeat it here....but basically I am unhappy with including code that searches lists in an undeterministic way from within an interrupt. I have not come up with an event flag implementation yet that gets around this. Timers are less of a problem, and my preferred implementation is to use a switch statement to switch on an incrementing value. My implementation is faster, your implementation is much more user friendly.

Maybe we could add in some documentation on the FreeRTOS.org site about the timer implementation? I could write one page showing my (very basic) implementation, and then you could have a page (with due credits given) showing your more generic and user friendly approach - with a link to the source code. I would be happy to do this, provided we also included a paragraph on the pros and cons of each approach.

One of my next targets is to improve the time it takes to select the next task. This is currently fast and deterministic when moving from a low priority task to a high priority task (the critical case), but could be improved when moving from a high to low priority task.

Thanks for everybody's inputs. We of course all have different opinions, but that is what makes a good debate.

Regards.

RE: xxxxFromISR?

Posted by Neil Bradley on May 1, 2008
> What type of function call are you making both from task level and from an ISR?

I've got a perfect example for that - I have a windowing system that I've written that has two sources of stimulus. One is foreground code, that expires a timer or an asynchornous programmed event that causes a window region to be updated (message queue based). The other is an interrupt based event for pointer/stylus events that causes window regions to be updated as well (also the same message queue). So I'm depositing messages into the same queue from two different contexts, and there's a single WindowDepositMessage() API that I call that allocates a message, fills in appropriate detail, and deposits the message. Yeah, I know I could create two different call points, but this is something the OS could do for me quite easily so I (and others doing so) wouldn't have to. ;-)

> My preference is to 'defer' interrupt processing to the task level.

Sure (this is how I'm using it), and this doesn't negate that.

> On the negative side, maybe I have missed some tricks, but note the comment just made about other people making claims over the FreeRTOS.org code.

I don't know about the other claims that you mention (I didn't see the post), but the most appropriate phrase I can think of is "know thy enemy". ;-) I think it all depends upon what you want FreeRTOS to end up being. After being used to several other RTOSes (ThreadX/uCOS-II being the most prominent in my experience), there were simply several aspects of FreeRTOS (missing features) that I needed, so I didn't use FreeRTOS (I bought uCOS-II licenses instead for the last two projects). If you're interested in making FreeRTOS ubiquitous and attractive to other users of RTOSes, I strongly recommend looking at least at their APIs, because anyone approaching FreeRTOS as an option are likely going to be coming from the perspective of "How do I do x like I do on RTOS y?".

I'm one of the last individuals to recommend "do it like someone else", but in a few cases here, doing it like other OSes is exactly the right thing to do. APIs and approaches that ThreadX/uCOS-II use have been battle hardened 15-20 years now, and there's a LOT to be learned from their examples.

>For example, queues can be used from interrupts of higher priority than the tick. At some point this will get migrated into the FreeRTOS.org code too. That might be an opportunity to add in your suggestion, but I would see this as being done on a port by port basis on a 'who shouts loudest' basis.

Well, here's an example of expectations and implementation that differ. ;-) Based on my experience, I expected FreeRTOS to already handle nested interrupts and know when it's in an interrupt context. Based on that, the xxxFromISR procedures just seemed odd. It seemed like a relatively simple, attainable goal that is of direct benefit to the consumer (which is why I brought it up).

>This is an example of what I mentioned at the top of this post. I see counting semaphores to be of little value to small embedded systems, but people asked for them (over and over again) so I added them in.

Case in point. ;-) I don't think people would repeatedly ask for them if there weren't a need, and as I mentioned above, they are an expected feature in other RTOSes. I've used semaphores for more than just binary purposes, specifically in one case where I had a dual CPU situation. The slave CPU would interrupt the master to "come get" the info from it, but it was low priority, and we had realtime requirements that made servicing the slave CPU unacceptable at interrupt time. We wanted to use FreeRTOS to do it, but at the time didn't have counting semaphores, so we bought uCOS-II (for a few other reasons as well as this was not our only criteria) and used its counting semaphores to wake a high priority task up when it needed to be serviced.

>The recursive semaphore feature was for one particular customer who needed it to facilitate their implementation of some communications stacks. It’s a bit of an oddity (although posix I think has them).

They're probably using it as a mutex. I can't recall (but I don't think) that mutexes existed at the last point where I worked with FreeRTOS, so I can understand the need.

>2) I have a whole library of ports and suggestions that people have sent me. I would like to create an 'unofficial' archive of such things that people can download. This is a little tricky with respect to maintainability, as people will often send something, then two days later they will send it again with a fix, etc. Also as previously mentioned I have to be VERY careful with publishing things for which the origin is unknown by me.

Totally understood, and agreed. In the case of timers, this gets back to what I'd consider to be an expected feature. And the module I submitted to you I mentioned I was writing from scratch in FreeRTOS's style and that you were free to use it as is for whatever purposes you want. I needed the functionality, and I've seen others ask for it on the message boards as well. I'm still just surprised that there isn't an OS-based timer function that's available to the user.

>3) I think we have discussed a couple of times the issues regarding event flags, and to a lesser extent timers, readers can search through the forum for this so I won't repeat it here....but basically I am unhappy with including code that searches lists in an undeterministic way from within an interrupt.

The code I had submitted wasn't nondeterministic (or maybe we're using the word slightly differently). It would only decrement timers based on if they were running (if they weren't, there was no penalty), and only timers that were running would get searched.

But I really do need to ask the question, since I've seen it before, is the concern over microoptimizations like searching lists really all that big of a deal? Let's assume for a second that we have a paltry 10Mhz ARM, with a timer tick that fires once every millisecond. That timer tick is going to fire no matter if a user timer is running (because of the scheduler). Let's also assume that each instruction takes 100ns to execute, and that to "skip" a node, it would require 4 instructions, or 400ns (this isn't unrealistic). Let's say there are 10 timers that aren't running, but allocated. So, that means it takes 4usec per timer tick, or .4% of the CPU. So even with exaggerated/unrealistic examples, it's still less than .4% of the overall CPU execution time, and in practice it only goes down from there. Why is this such a large concern, considering that all other operations will absolutely dwarf it?

While I certainly understand and respect the concept of optimization, I don't think that avoiding such a feature to gain another .4% (or less) of the CPU in terms of performance is worth the extra work other consumers of FreeRTOS would have to go through to work around a lack of timers.

> I have not come up with an event flag implementation yet that gets around this.

Maybe you and I have differnt ideas in mind. Only one thread can block on an event flag, and the only time that there's any check at all is when something posts to the event flag mask.

> Timers are less of a problem, and my preferred implementation is to use a switch statement to switch on an incrementing value. My implementation is faster, your implementation is much more user friendly.

I'd argue that it's "faster by insigificant amounts". I cannot imagine that a timer handler would be of any appreciable CPU time in practice. Context switches and other operations' execution are orders of magnitude longer.

> I could write one page showing my (very basic) implementation, and then you could have a page (with due credits given) showing your more generic and user friendly approach - with a link to the source code. I would be happy to do this, provided we also included a paragraph on the pros and cons of each approach.

I guess we could, but I just have a hard time believing that the "user friendly" way is of a detriment to anyone in practice.

>One of my next targets is to improve the time it takes to select the next task. This is currently fast and deterministic when moving from a low priority task to a high priority task (the critical case), but could be improved when moving from a high to low priority task.

Before I share my experiences with my own RTOS implementations, in practice is this really a significant time sink?

Anyway, not sure how this is going to come across conceptually, but here's what I did:

* Kept an array of pointers to the head and tail of all TCBs of a given priority - one index per priority (32 at the time I think)
* Kept an array of pointers to the heads/tails of all TCBs of a given priority in the "ready to run" linked list
* Two prior/next pointers were kept in each TCB - one when it was in the "ready to run" linked list, and one that was linked to its TCB priority prior/next list
* Kept a head pointer to a "ready to run" linked list of TCBs. That way any task waking up was an instant pointer dereference.
* When a task was finished and was put back to sleep, it got removed from the head of the "ready to run" list and put back at the tail of that task's priority, and removed from the "ready to run" list

I'm probably not doing a very good job of describing this, but I found that the implementation was worse than a linear search of the "ready to run list" approach for anything less than 12 tasks.

Anyway, not sure if it's helpful, but hopefully it'll get the creative juices flowing. ;-)

RE: xxxxFromISR?

Posted by Richard Damon on May 6, 2008
Neil,
One danger I see with your example of WindowDepositMessage() is that what does this API do if the queue is full? (And while maybe you have things setup so this can't happen, I would guess that most situations like this would be hard to make it a certainty that this can never happen). I likely desired goal is that from task level that the API would block waiting for room, but that case is NOT available to the interrupt routine.

Yes, it could be done right, but by the same token, you could add a wrapper to implement your idea, just define a function/macro for entry and exit of ISRs that keep track of the context, and functions/macros that select between the ISR/Task level routines.

RE: xxxxFromISR?

Posted by Neil Bradley on May 6, 2008
It returns an error, and inside the ISR it just ignores it and waits for the next message. In this specific environment, if the queue is full, it'd just return, and it means that a message inside

>Yes, it could be done right, but by the same token, you could add a wrapper to implement your idea, just define a function/macro for entry and exit of ISRs that keep track of the context, and functions/macros that select between the ISR/Task level routines.

Yes, I'm aware of what I could do, but as I said in my prior emails, this is standard operating procedure for all other RTOSes I've worked with, some of which are 10-15 years old by now (and older), and I'm asserting very vehemently that the OS should do this work for you and not burden the user with it. Just like event flags and timers. ;-)

This is one of the aspects of FreeRTOS that is frustrating to me. I sometimes feel like people go out of their way to look for excuses for the existing design rather than taking the advice/input from those of us with decades of experience. Kinda like trying to explain red to a color blind person. There was quite a bit of talk about FreeRTOS at the Embedded Systems Conference this spring, and the common complaints from those I talked to had to do with lack of counting semaphores (no longer true, which I corrected them on), no event flags, no timers, and "oddball APIs" (xxxFromISR being one). I'd like to see FreeRTOS become more pervasive, and I evangelized as much as I could.

Don't get me wrong - I appreciate Richard's most excellent efforts, but I'd like to see FreeRTOS be all it can be. That's why I'm a bit whiny. I bring these topics up specifically because I HAVE been listening to other embedded systems engineers, and I'd like to have FreeRTOS be the evangelized solution for everyone. The fewer things it's missing, the more apt it is to be adapted. And I'm also a selfish bastard who wants to see these features myself, as I use them in all other RTOSes.


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) 2004-2010 Richard Barry. Copyright (C) 2010-2016 Real Time Engineers Ltd.
Any and all data, files, source code, html content and documentation included in the FreeRTOSTM distribution or available on this site are the exclusive property of Real Time Engineers Ltd.. See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Real Time Engineers Ltd.

Latest News:

FreeRTOS V9.0.0 is now available for download.


Free TCP/IP and file system demos for the RTOS


Sponsored Links

⇓ Now With No Code Size Limit! ⇓
⇑ Free Download Without Registering ⇑


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Renesas Electronics Gold Alliance RTOS Partner.jpg

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Atmel RTOS partner supporting ARM Cortex-M3 and AVR32 microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Xilinx Microblaze and Zynq partner

Silicon Labs low power RTOS partner

Altera RTOS partner for Nios II and Cortex-A9 SoC

Freescale Alliance RTOS Member supporting ARM and ColdFire microcontrollers

Infineon ARM Cortex-M microcontrollers

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

Cypress RTOS partner supporting ARM Cortex-M3

Fujitsu RTOS partner supporting ARM Cortex-M3 and FM3

Microsemi (previously Actel) RTOS partner supporting ARM Cortex-M3

Atollic Partner

IAR Partner

Keil ARM Partner

Embedded Artists