Page 1 of 1

Tasks

PostPosted: Wed May 07, 2008 12:22 am
by aek
In a non-preemptive RTOS, if you release resources in the opposite order that you acquire them, and all tasks must acquire the shared resource before continuing, then you can't have deathlocks. Deathlocks are a fact of life in preemptive systems (and can be solved via mutexes, etc.), but are a non-issue with Salvo.

Salvo 4 for AVR does not use OSEnterCritical() and OSLeaveCritical() -- it uses OSDisableHook() and OSEnableHook(). It is certainly possible to mess things up with bad hooks, but the default hooks should be fine -- see the Salvo Compiler Reference Manual for more information on the default hooks.

In general, IF OSEnable|DisabelHook() control global interrupts (default, non-optimized) AND there is a problem with how they were implemented, THEN what usually manifests itself is that global interrupts will become permanently disabled. This causes any task that is dependent on interrupts (e.g. all delayed tasks, and tasks that are waiting for interrupt-driven events) to stop working (until a reset).

------------------

[This message has been edited by aek (edited May 07, 2008).]


Re: Tasks

PostPosted: Wed May 07, 2008 9:57 am
by Gerald
1.)
i do call OSEnterCritical(); + OSLeaveCritical();
and i implemented my own hook funtions...
i though OSEnterCritical will call OSDisableHook() and OSLeaveCritical will call OSEnableHook()?

code:
static uint8_t sreg;
void OSDisableHook()
{
sreg = SREG;
cli();
}

void OSEnableHook()
{
SREG = sreg;
}


2.) is it allowed to call OS_WaitMsg or OS_WaitEFlag in an ISR?

3.) how could i destroy a taskB inside of taskA?

i did:
OSDestroyTask(TASK_FUNCTIONLOGIC_P);

-> error: too few arguments to function 'OSDestroyTask'

in the documentation i saw:
Prototype: OStypeErr OSDestroyTask (
OStypeTcbP tcbP );

in salvotask3.c i saw:
#if OSENABLE_EVENTS
OStypeErr OSDestroyTask( OStypeTcbP tcbP,
OStypeID events )
#else
OStypeErr OSDestroyTask( OStypeTcbP tcbP )
#endif

what should i pass to OStypeID events? each task is waiting for more then 1 event...
must i call OSDestroyTask twice if taskA is waiting for 2 events?

if i do a test with:
OSDestroyTask(TASK_FUNCTIONLOGIC_P, 2); // waiting for 2 different events
OSDestroyTask(TASK_STEPPER_P, 2); // waiting for 2 different events
OSDestroyTask(TASK_ADC_P, 0); // waiting for no event

the result is:
.salvoLibGCCAVRlibsalvolgccavr-a.a(salvotask3.o): In function `OSDestroyTask':
salvotask3.c :(.text+0x16): undefined reference to `OSDelDelayQ'
salvotask3.c :(.text+0x38): undefined reference to `__mulhi3'

[This message has been edited by Gerald (edited May 08, 2008).]

[This message has been edited by aek (edited May 08, 2008).]


Re: Tasks

PostPosted: Wed May 07, 2008 11:01 am
by Gerald
Hi,

What must happen that a Task is not running any more? Is it a problem when using OSEnterCritical(); OSLeaveCritical(); ?

bye


Re: Tasks

PostPosted: Wed May 07, 2008 11:04 am
by Gerald
and is there a way to detect deathlocks?

how could i wait for messages or eflags in an interrup??

[This message has been edited by Gerald (edited May 07, 2008).]


Re: Tasks

PostPosted: Thu May 08, 2008 2:32 am
by Gerald
1.) what is the user allowed to call, if your not allowed to call OSEnter|LeaveCritical or OSDisable|EnableHook?

2.) what could i do for this situation? use a OSEnter|LeaveCritical() in the ISR?

3.) will test tomorrow!


Re: Tasks

PostPosted: Thu May 08, 2008 2:38 am
by aek
Hi Gerald.

1) The user doesn't call anything other than the Salvo API services .. the hooks etc. are not API services, but OSCreateTask() etc. is. IOW, when inspecting your Salvo application, there should not be any calls to OSDisableHook(), for example. See e.g. the various Salvo examples -- no calls to OSDisableHook() et. al. Those functions are called (only) by the Salvo code itself. In general, the only place that a user will make any calls that involve interrupts is to globally enable interrupts at the start of the application.

2) You can't wait on events in an ISR. This is typical of many (all?) RTOSes. Waiting is done only in tasks. Thinking another way, you can't block (in) an ISR, but you can block (only) in a task.

3) Let me know if it works for you.

------------------


Re: Tasks

PostPosted: Thu May 08, 2008 7:36 am
by aek
1) You confused me by saying that "you call" OSEnter|LeaveCritical() ... you don't call them -- they are part of Salvo 4, and they call the user hooks ...

But you should update OSDisableHook to look like this:

code:
static uint8_t sreg;
void OSDisableHook()
{
unit8_t sreg_local;

sreg_local = SREG;
cli();
sreg = sreg_local;
}


This guarantees that when OSDisableHook() in mainline code is preempted by OSDisableHook() called from an ISR (e.g. via an ISR call to OSSignalBinSem()), the sreg that is stored globally is the one that will be (re-)used when OSEnableHook() restores the global interrupt status.

2) No, never, as per the Salvo User Manual.

3) OSDestroyTask(tcbP, OSEVENTS). The documentation does not yet reflect this update to OSDestroyTask(). I assume you're doing a source-code build ... if so, the undefined reference is because you are missing a source module (salvoqdel.c).

------------------


Re: Tasks

PostPosted: Wed May 14, 2008 5:28 am
by Gerald
1.) if you cant wait for a message in an interrupt i have to use global variables! therefore i need a critical section to protect the variable between writing and reading between a task and an ISR. therefore its useful to use your OSDisableHook() OSEnableHook() function?

2.) is there a possiblity to look whether a message is full or empty in an ISR? OSTryMsg() seems not to be the right function...because it is like an OS_WaitMsg()...and i cant use waitmsg in an ISR.

3.) didnt have time to test;/

3.)


Re: Tasks

PostPosted: Wed May 14, 2008 8:56 am
by aek
1) One does not normally wait in an interrupt ... for a variety of reasons. See e.g. Chapter 9 in general and page 423 "The Fallacy of Avoiding Critical Sections at the Interrupt Level" in http://www.pumpkininc.com/content/doc/manual/SalvoUserManual.pdf for a general discussion. If you need to suppress an interrupt because a task is not ready for it, then you should be disabling the individual interrupt enable bit instead of trying to "wait" in the ISR. This lack of duality is in part due to the fact that interrupts ALWAYS have higher priority than any task.

Note that there are times when you pass information back and forth between tasks and ISRs -- e.g. in flag-setting and -clearing. In this case, if you can do the flag (i.e. bit) operation atomically, there's no need for interrupt control. Otherwise you need to control interrupts (either globally or peripheral-targeted) to avoid corruption of the global variable(s) (e.g. if a multi-byte counter is involved). But whatever the case, you would not use OSDisable|EnableHook() -- they are for Salvo's use exclusively. You must write your own routines (which can function just like OSDisable|EnableHook()), but they must be separate routines.

2) How about OSReadMsg()?

------------------