I am having problems with locking interrupts. I am doing this on a
power PC architecture. I created a watchdog timer to go off every 3
seconds. Then I wrote a code to lock task and then lock interrups. The
task locking works fine, but the interrupt locking does not seem to work
since the watchdog timer still goes off during a long print loop that
takes more than 3 seconds.
I even tested this with an external serial I/O interrupt and still does
not work. Can you tell me what the trick is. Here is a copy of my code
in case you wonder what I am doing.
Thanks.
#include "vxWorks.h"
#include "taskLib.h"
#include "semLib.h"
#include "stdio.h"
#include "stdlib.h"
#include "wdlib.h"
#include "time.h"
/* Globals */
int taskId1;
int taskId2;
SEM_ID semCounting;
SEM_ID semBinary;
WDOG_ID wdID;
/* Function Prototypes */
void taskNum1 ( void );
void taskNum2 ( void );
void wdISR ( void );
void Case_7 (void)
{
int taskCount = 0;
int sts;
/* Create a watchdog */
if ( ( wdID = wdCreate() ) == NULL)
{
printf ( "Error in creating watchdog\n" );
return;
}
/* Set the timer to go off after 10 seconds */
if ( wdStart ( wdID, sysClkRateGet() * 3, (FUNCPTR) wdISR, 0 ) ==
ERROR )
{
printf ( "Error in starting the watchdog timer\n" );
return;
}
/* Create a binary semaphore with semaphore available and queue tasks
on FIFO basis */
if ( ( semBinary = semBCreate ( SEM_Q_FIFO, SEM_FULL)) == NULL )
{
printf ( "Error in Creating Binary Semaphore\n");
return;
}
else
{
printf ( "Success in Creating Binary Semaphore\n");
}
/* Lock the semaphore for scheduling purposes */
semTake ( semBinary, WAIT_FOREVER );
/* spawn the 2 tasks starting with the highest priority task */
if ( taskId1 = taskSpawn ( "t1", 110, 0x100, 2000, (FUNCPTR)
taskNum1,0,0,0,0,0,0,0,0,0,0 ) == ERROR )
{
printf ( "Error in spawning taskNum1\n" );
return;
}
if ( taskId2 = taskSpawn ( "t2", 100, 0x100, 2000, (FUNCPTR)
taskNum2,0,0,0,0,0,0,0,0,0,0 ) == ERROR )
{
printf ( "Error in spawning taskNum2\n" );
return;
}
}
void taskNum1 ( void )
{
static int i = 0, j = 0, lock;
for ( j = 0; j < 3; j++ )
{
/* wait indefinitely for semaphore */
semTake ( semBinary, WAIT_FOREVER );
/* Adding a critical section that would prevent the higher priority
task to run until the locking task leaves the critical region */
if ( taskLock () == OK )
{
lock = intLock ();
/* A premitive delay to cause the wd to time out */
/* A test to see if intLock() works. The ISR should not go off */
for ( i = 0; i < 100; i++)
{
printf ( "taskNum1 Running in critical region\n" );
}
/* This delay would prove that no matter how long, VxWorks will
not permit any other tasks to run until execution is out of this
critical region. This is compared to the use of task delay in
task two which VxWorks would automatically schedules task one to
start running after a certain amount of delay. So for each task
delay call in taskNum2, taskNum1 gets to run also based on
VxWorks priority and internal schedulings. */
/*taskDelay ( 20 * sysClkRateGet()); */
intUnlock (lock);
taskUnlock ();
}
/* give up semaphore so the next task can run */
semGive ( semBinary );
}
}
void taskNum2 ( void )
{
static int i = 0, j = 0;
semGive ( semBinary );
for ( j = 0; j < 3; j++ )
{
/* wait indefinitely for semaphore */
semTake ( semBinary, WAIT_FOREVER );
for ( i = 0; i < 2; i++)
{
printf ( "taskNum2 Running\n" );
}
/* A delay to exercise for the binary semaphore
scheduling capability where without it, each task
will run untill finished based on their priorities
sequentially. */
taskDelay ( 2 * sysClkRateGet() );
/* give up semaphore so the other task can run */
semGive ( semBinary );
}
}
/* This routine goes off every 3 seconds */
void wdISR ( void )
{
printf ( "The watchdog timer expired after 3 seconds\n" );
/* Re-start timer to go off after 10 seconds */
if ( wdStart ( wdID, sysClkRateGet() * 3, (FUNCPTR) wdISR, 0 ) ==
ERROR )
{
printf ( "Error in starting the watchdog timer in wdISR\n" );
}
}
"Note that the timeout routine is invoked at interrupt level, rather than in
the context of the task. Thus, there are restrictions on what the routine
may do. Watchdog routines are constrained to the same rules as interrupt
service routines. For example, they may not take semaphores, issue other
calls that may block, or use I/O system routines like printf( )."
"PC User" <PCU...@hotmail.com> wrote in message
news:3bf9721a$0$30970$272e...@news.execpc.com...
> Hi Folks,
>
> I am having problems with locking interrupts. I am doing this on a
> power PC architecture. I created a watchdog timer to go off every 3
> seconds. Then I wrote a code to lock task and then lock interrups. The
> task locking works fine, but the interrupt locking does not seem to work
> since the watchdog timer still goes off during a long print loop that
> takes more than 3 seconds.
>
> (snip)
That's strange but yesterday I met the same problem on my PPC405 based
board. intLock() call does not lock interrupts (in fact, MSR[EE] is
not modified as it would have been).
I also tried to write my own intLock using the wrteei opcode and it
also fails modifying the MSR[EE] bit. I checked that the PPC is in
Supervisor mode.
Seems that we are two in the same case :-)
I suggest that the first one of us that obtain information tell it to
the other.
Matt
I have a beginning of answer for my case:
- intLock() executed from the target shell works fine, whereas...
- ...it does not work in the windsh, even with the @intLock call.
FYI, vxMsrGet() returns the MSR value (the register modified by
intLock()).
So, on the target shell it works well:
-> vxMsrGet
value = 168496 = 0x29230 = sysNvRamGet + 0x14c
-> intLock
value = 168496 = 0x29230 = sysNvRamGet + 0x14c
-> vxMsrGet /* MSR well
modified */
value = 4656 = 0x1230
-> intUnlock 0x29230
value = 168496 = 0x29230 = sysNvRamGet + 0x14c
When those same call are directly done in the wind shell, it does not
work. The MSR value returned is always 0x29230.
=> Calls from the windsh does not affect the MSR register for an
unknown reason for the moment and that's the reason why intLock() does
not work when called from the windsh.
So: do not call intLock() from the windsh directly (or do it through a
C function).
Hope that helps !
Matt
please see the comments between your code
"PC User" <PCU...@hotmail.com> wrote in message
news:3bf9721a$0$30970$272e...@news.execpc.com...
Just curious, but why did you not create the semaphore with SEM_EMPTY
instead of taking it manually?
>
> /* spawn the 2 tasks starting with the highest priority task */
You do it exactly the other way round than this comment states.
Except you do not consider higher priority to be more priviledged (and a
lower value).
> if ( taskId1 = taskSpawn ( "t1", 110, 0x100, 2000, (FUNCPTR)
> taskNum1,0,0,0,0,0,0,0,0,0,0 ) == ERROR )
> {
> printf ( "Error in spawning taskNum1\n" );
> return;
> }
>
> if ( taskId2 = taskSpawn ( "t2", 100, 0x100, 2000, (FUNCPTR)
> taskNum2,0,0,0,0,0,0,0,0,0,0 ) == ERROR )
> {
> printf ( "Error in spawning taskNum2\n" );
> return;
> }
>
> }
>
> void taskNum1 ( void )
> {
> static int i = 0, j = 0, lock;
>
> for ( j = 0; j < 3; j++ )
> {
> /* wait indefinitely for semaphore */
> semTake ( semBinary, WAIT_FOREVER );
>
> /* Adding a critical section that would prevent the higher priority
> task to run until the locking task leaves the critical region */
> if ( taskLock () == OK )
> {
> lock = intLock ();
>
> /* A premitive delay to cause the wd to time out */
> /* A test to see if intLock() works. The ISR should not go off */
>
> for ( i = 0; i < 100; i++)
> {
> printf ( "taskNum1 Running in critical region\n" );
printf is very likely to cause a task switch if some other task does I/O as
well or if you are using some kind of remote shell.
(Tornado host shell, Telnet, or whatsoever).
See the next comment for details.
> }
>
> /* This delay would prove that no matter how long, VxWorks will
> not permit any other tasks to run until execution is out of this
> critical region. This is compared to the use of task delay in
> task two which VxWorks would automatically schedules task one to
> start running after a certain amount of delay. So for each task
> delay call in taskNum2, taskNum1 gets to run also based on
> VxWorks priority and internal schedulings. */
> /*taskDelay ( 20 * sysClkRateGet()); */
No, when your task blocks (e. g. on a timeout, like above), the scheduler
will be invoked, too.
Afterwards, the state of the interrupts of that very task will be restored,
at least on platforms where this information is stored in the task control
block (TCB).
So you will end up running some other task, with interrupts re-enabled.
Finally, read the documentation intLock()
Here is the most important part - the warnings that come with intLock()
WARNINGS
Do not call VxWorks system routines with interrupts locked. Violating this
rule may re-enable interrupts unpredictably.
The routine intLock( ) can be called from either interrupt or task level.
When called from a task context, the interrupt lock level is part of the
task context. Locking out interrupts does not prevent rescheduling. Thus, if
a task locks out interrupts and invokes kernel services that cause the task
to block (e.g., taskSuspend( ) or taskDelay( )) or that cause a higher
priority task to be ready (e.g., semGive( ) or taskResume( )), then
rescheduling occurs and interrupts are unlocked while other tasks run.
Rescheduling may be explicitly disabled with taskLock( ). Traps must be
enabled when calling this routine.
As Dave already stated, you must not call printf() from interrupt context.
Unfortunately, this sometimes works.
But your machine will freeze if you have simultaneous calls to printf from
task and interrupt context.
(This happens at least on pc486 platform)
> }
> }
>
>
hth
Werner
This is because you _must_ not call any operating system functions with
interrupts locked.
When invoking intLock() from windSh, how do you expect that command to reach
the target?
It will be some kind of network or serial connection depending on your
target server configuration.
And _of_course_ this communication involves calling a whole lot of OS
functions in the target task / WDB agent.
Read the intLock() documentation.
It is designed to
lock interrupts
do something with your hardware, which must not be interrupted
but do NOT call _any_ VxWorks provided function, especially anything I/O
like
unlock interrupts
You should use intLock() carefully and rarely.
Usually someting is wrong with the overall design, when you find yourself
using intLock() too often.
hth
Werner
"Matthieu Sevestre" <matthieu...@yahoo.fr> wrote in message
news:d428158b.01112...@posting.google.com...
intLock()in your test do not realy lock the interrupts. You MSR value shows the
status of disabled interrupts.
You are not able to use the target shell (serial interface)with realy locked
interrupts.
You should not call VxWorks system routines with interrupts locked (see
documentation of intlock()). You do not know which function are called with your
shell-call.
test the call of:
void test(void)
{
intLock();
for (;;)
}
You see, that your intLock() works with a call from both shells correct.
>
>When those same call are directly done in the wind shell, it does not
>work. The MSR value returned is always 0x29230.
>
>=> Calls from the windsh does not affect the MSR register for an
>unknown reason for the moment and that's the reason why intLock() does
>not work when called from the windsh.
>
>So: do not call intLock() from the windsh directly (or do it through a
>C function).
>
>Hope that helps !
>Matt
--
__________________________________________________________
News suchen, lesen, schreiben mit http://newsgroups.web.de
Thanks again.
This is what you expect.... rtfm....
printf() will block because the serial port output fifo becomes full.
At this point you drop into the system idle loop - which will enable
interrupts.
The taskLock() will stop any other task being scheduled, but you are
still in the idle loop.
The serial port interrupt ISR has to run to re-enable your task.
The timer interrupt has to run to count 3 seconds.
If you want your system to lock up solid, use a polling output
routine for the serial port. If it is a 16550:
while (!(*(uart+5) & 0x40));
*uart=*msg++;
if (*(uart+5) & 1)
/* rx data - abort your infinite loop..... */
David
This is what you expect.... rtfm....
Seems that people still do not understand the scope of intLock(). It
works only for the task context that calls it. If that task blocks (or
exits), then interrupts will most probably be re-enabled. If the task
only blocked, when it resumes execution they will be locked again.
Why? Because the MSR (using PPC) is in the task context. You should
not block with interrupts locked (or, for that matter, after calling
taskLock() either). Switching to a different task, or the idle loop,
will re-enable the interrupts.
As for the wind shell (host shell), when you execute a command there,
the target agent spawns a task to call the function. So calling
intLock() from the wind shell results in a task on the target
executing intLock() and exiting. When the task exits, the scheduler
will be invoked and when the new task is selected, its value for the
MSR will be restored.
Does that make this any clearer? Search back a few days in the
archives for more on this subject... I posted a longer explanation not
so long ago.
John...
matthieu...@yahoo.fr (Matthieu Sevestre) wrote in message news:<d428158b.01112...@posting.google.com>...