Design Article
Do you have questions about uC/OS-III? Or RTOSs in general?
11/25/2009 10:26 AM EST
At the conclusion of the webinar, many questions were asked. Some were answered live, but time did not permit all questions to be answered. So Mr. Labrosse took the time to respond to those questions that time did not allow for.
Question: How large is a typical task's stack?
Answer: That really depends on what the task needs to do. In fact, sizing the stack is not obvious and generally you need to take an educated guess and give your tasks way more stack space than they need. The good news is that uC/OS-III performs run-time stack sizing and thus, it's possible to know how much stack space your tasks actually use. You can then go back and make adjustments. You obviously don't want to set the stack size exactly as measured but instead, give yourself 25% to 100% more space.
Question: As an alternative to using mutexes, could I simply disable interrupts when accessing shared resources?
Answer: Yes and no. Technically speaking, you can obviously disable interrupts while accessing a critical section. But you want to make sure that you do so for as short as possible. C/OS-III disables interrupts to access some internal data structures but we keep that to a minimum.
Accessing a couple of variables by first surrounding them with OSMutexPend()/OSMutexPost() will most certainly create more overhead than you'd want. However, you need to be certain that the access time to those variables is indeed very short. It would be acceptable to disable/enable interrupts when you are only "copying" variables but not when you're performing complex arithmetic operations on them while interrupts are disabled.
So, if you can ensure that access is very short and won't affect interrupt latency of your system as a whole, then I'd say that disabling/enabling interrupts is acceptable.
Question: You mentioned that ISRs should be kept as short as possible. What sorts of problems can lengthy ISRs cause?
Answer: For one thing, ISRs are generally hard to debug. The simpler the ISRs, the better. If you have long ISRs and you don't allow for interrupt nesting, then you stand a chance of missing other interrupts. If you allow for nesting, you further complicate the debugging of ISRs. Also, ISRs are meant to capture asynchronous events to prevent the processor from having to poll I/O devices. The hardware typically prioritizes these I/O devices which may not correspond to the same priority as what you'd want to give them in your system. In other words, you may prefer to rearrange the priority of servicing these interrupts and that's where the kernel comes in.
Question: In the discussion of synchronization, you said that each task has a built-in semaphore. What advantages do these semaphores offer over standard semaphores?
Answer: There are two main advantages—performance and simplicity. In many cases, you know which task will be servicing a certain I/O device and thus, there's no need to create an "intermediate" object for that purpose. With the built-in semaphore, you simply signal that task. With the external semaphore, you need to first create the semaphore. When the task responsible for servicing the device depends on the semaphore, that task is placed on the wait list of that semaphore. If it's the only task pending on the semaphore, it's wasteful to go through that overhead.
Question: The message queue example involved a single task and an ISR. Can multiple tasks retrieve messages from a queue?
Answer: That depends what queue mechanism you use. Obviously, if you send a message "directly" to the task's internal queue, then only that task will get the message. However, if you prefer to implement an external message queue, then multiple tasks can receive messages. In fact, either the highest priority task waiting on the external message queue will get the message, or the ISR can post the message to all tasks waiting using a "broadcast" mechanism.



