Pumpkin, Inc.

Pumpkin User Forums

calling user services from ISR

If you can't make Salvo do what you want it to do, post it here.

calling user services from ISR

Postby mfan » Wed Mar 29, 2006 8:11 am

Hi, this is still based on the tut6 tutorial project.
I am trying to add user services into the ISR. Can I add code into the existing ISR?...see below.

void interrupt IntVector( void )
{
if ( T0IE && T0IF ) {
T0IF = 0;
TMR0 -= TMR0_RELOAD;

OSTimer();
}

//Can I add these lines ???
if ( RC1IE && RC1IF ) {
OSSignalMsg(...);
}
}

mfan
 
Posts: 11
Joined: Thu Mar 23, 2006 12:00 am

Re: calling user services from ISR

Postby aek » Wed Mar 29, 2006 8:24 am

Yes, you can, but you need to review the Salvo Reference Manual for your compiler to understand the requirements when you signal from ISRs. This is a compiler issue because the HI-TECH compilers are not reentrant.

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

-------
aek
aek
 
Posts: 1888
Joined: Sat Aug 26, 2000 11:00 pm

Re: calling user services from ISR

Postby jmurphy » Tue Aug 07, 2007 5:03 am

okay, I am still evaluating the software but here is a big issue that spins off this topic, from i admit a not-very-experienced programmer (me)...

(i did a quick search for 'multiple calls' in the archives of the forum and did not get any meaningful hits to this question - sorry if it is something already answered ad nauseum)

as stated somewhere in the docs, you of course can't context switch into or out of an ISR, but you are _apparently_ allowed to signal from within an ISR.

however... if you do this, and this is _not_ compiler-dependent really as I would bet a fair chunk of embedded apps run on non-reentrant compilers, here is the risk you run (and this is also spelled out in the Salvo User manual chapter 2 RTOS fundamentals section on re-entrancy as a problem so I do not see why there is not a clearer work-around)...

you are executing code from the main execution tree and begin a signal by calling the signal function (ie OSSigBinSem()) from within the main execution tree (ie a task). the salvo code for the signal function begins executing and sets up its registers and local vars etc. along comes an interrupt with the isr also signalling. now the isr calls into the same salvo function (ie OSSigBinSem()) to signal and, viola, all the previous local vars etc inside that salvo function got wiped because the compiler (like many, many) is not re-entrant and the salvo signal function appears not to be defined as re-entrant (which would be an option perhaps). when you return from the interupt it is quite likely that the wiped out local vars in the main tree execution of the signal function will cause unpredictable behaviour.

given salvo is clearly familiar with this issue as they have a description of exectly this phenomenon _not_ pertaining to their RTOS code in the manual introduction see Salvo User manual chapter 2 RTOS fundamentals - the section on re-entrancy), I do not really get why they would have a work-around.

so I think I am missing something or mis-understanding something. possible, I am not a very experienced programmer.

any ideas on how to work around this? i do not mind so much the Keil BL51 warning message WARNING L15: MULTIPLE CALL TO SEGMENT but i do mind the real issue that if i try to signal from inside an isr and also use the same signal function (service) from the main execution tree i am going to have problems.

one way i see is to raise a flag in the isr and do the call in the main loop checking for the isr flag between OSSched()... but that seems really clunky.

jmurphy
 
Posts: 4
Joined: Mon Aug 06, 2007 11:00 pm

Re: calling user services from ISR

Postby jmurphy » Tue Aug 07, 2007 5:23 am

okay... never mind... i see some info on salvo config in rm-kc51 that makes it clear what is going on (just fyi if you have not got this far yet - there are switches, 'variants', in the salvocfg.h and which .lib file you select which enable or disable calling of services from inside an isr probably for the reasons stated)
jmurphy
 
Posts: 4
Joined: Mon Aug 06, 2007 11:00 pm

Re: calling user services from ISR

Postby aek » Tue Aug 07, 2007 8:51 am

Yep, you got it
-------
aek
aek
 
Posts: 1888
Joined: Sat Aug 26, 2000 11:00 pm

Re: calling user services from ISR

Postby aek » Tue Aug 07, 2007 8:54 am

BTW, this does notwork:
quote:
one way i see is to raise a flag in the isr and do the call in the main loop checking for the isr flag between OSSched()... but that seems really clunky.
for fundamental reasons.

The only way to prevent corruption of global vars (which is what happens when functions accessing those non-stack vars are preempted) is to prevent the preemption in the first place. This can / must be done by disabling interrupts around the access to the global variables.

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

-------
aek
aek
 
Posts: 1888
Joined: Sat Aug 26, 2000 11:00 pm

Re: calling user services from ISR

Postby jmurphy » Wed Nov 07, 2007 11:13 am

Back after a long hiatus...

I would like to set up a ring buffer for the 8051 uart in a similar way to the examples you give. However, if I want to use putchar() and _getkey() custom versions to retain the stdio functionality I wonder if I am hosed. Since putchar() and _getkey() are not tasks I am unable to use Salvo user services (waits and signals) from inside those functions.

Is there a way I just have not yet grasped to make putchar and getkey into tasks? Or is there another way around this?

(the concept being use the uart ISR to stuff chars into a rxBuff and pull chars out of a txBuff, then use putchar to stuff the txBuff and getkey to pull from the rxBuff)

I had blithely started down the path of doing this when I realized I was breaking a Salvo golden rule by calling services from a non-task routine.

jmurphy
 
Posts: 4
Joined: Mon Aug 06, 2007 11:00 pm

Re: calling user services from ISR

Postby aek » Thu Nov 08, 2007 8:36 am

You can still place putchar and getkey in tasks -- it just means that you will be wasting cycles in those tasks that can only be used by ISRs ...

I would suggest you simply go ahead and do it first, and see how it works. The (slight) delays -- particularly with putchar -- may be perfectly acceptable.

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

-------
aek
aek
 
Posts: 1888
Joined: Sat Aug 26, 2000 11:00 pm

Re: calling user services from ISR

Postby PresbyopticProgrammer » Wed Nov 21, 2007 4:15 am

So (Keil C51) one can call Salvo services such as context-switching from a function, which is not itself a task, provided that the function is itself called from a task?

e.g. if one makes a custom putchar() to use a semaphore to control access to a ring buffer it is a function and not a task but this is okay so long as any calls to printf() or whatever Keil uses to access putchar() are only made from tasks?

This seems contrary to the concept that only tasks can context-switch, which I had naively thought was due to a compiler constraint or something rather than a run-time constraint. So I apologize for beating this repeatedly but I'd like to be sure I understand this concept.

PresbyopticProgrammer
 
Posts: 14
Joined: Wed Nov 21, 2007 12:00 am
Location: Fort Valley, VA, USA

Re: calling user services from ISR

Postby aek » Wed Nov 21, 2007 8:57 am

The only thing you can't call from a called function is one of Salvo's context-switching functions.

I.e. you can call OSSignalBinSem() all day long from anywhere in your code. But you can only call OS_Delay() directly at the task level. To do cooperative (or preemptive) task switching at the level of called functions, you need individual task stacks, and they consume RAM like no tomorrow, and RAM is especially precious on the 8051.

So, for example, if your putchar() waits in a loop on the outgoing Tx buffer to free up, then that's perfectly OK, but you can't use OS_WaitXyz() or OS_Delay() or any "OS_" services inside of putchar().

Let's say you're talking at 4800 baud and your putchar() simply waits for the Tx register to be empty before putting another character. Assuming 4800,N,8,1, that's 2ms per character, so worst-case putchar() will have to loop locally on checking Tx empty flag for 2ms before it can place another character into the Tx buffer for transmission. Since putchar() cannot use OS_Delay(), etc. to do a "multitasking wait", how does that affect your application?

Well, it means that for 2ms all you can do is loop for Tx buffer to be empty inside of putchar(), AND service interrupts. All multitasking is blocked during this time. Assuming your Salvo system tick is 10ms, then since 10 >> 2, single character waits won't have much of an impact on timer services. So, this situation may or may not be acceptable to you in terms of overall system performance. Note that if you're running at 115,200 bps, then we're talking 9us per character, and the putchar() delay would likely be not noticeable at all. But at 2ms, it may be. You'll need to decide whether that's OK or not ...

The point is that task switching at arbitrary levels has the unavoidable requirement of large amounts of RAM for task stacks. It varies by processor, but function parameters, return addresses, return values and all local / auto variables live on the stack, and so task stacks are often quite large even if the call depth is just a few levels. Salvo was designed to give you powerful multitasking with a few restrictions, the main one being that you can only task-switch at the task level. But tasks can call any functions without restrictions.

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

[This message has been edited by aek (edited November 21, 2007).]

-------
aek
aek
 
Posts: 1888
Joined: Sat Aug 26, 2000 11:00 pm

Next

Return to Coding

Who is online

Users browsing this forum: No registered users and 1 guest

cron