Interrupts Disabled After First Context Switch

Kirspel, Kevin {Engineering - Osmetech CCD} kevin.kirspel at osmetech.com
Fri Jan 6 15:01:20 UTC 2006


Actually I think it was 4.6.0pre4.  I do have an SH-3 ( sh7727 ) port
with the DSP functionality disabled.  When I added the SH-3 to the tree
I just cut and pasted the SH-4 port and made minor modifications.  I
also changed the Makefile.am, Makefile.in, and configure files manually
in the tree.  I don't know how to use the automake features so I just
modified the script files by cutting and pasting the sh-4 related lines
and modifying them.  My code set is based off the 4.6.0pre4 and I have
now manually added some of the problem reports ( up to 4.6.5 ).  So, my
code based is a combination of both releases.  In the future I could
take the 4.6.5 release and add my SH-3 stuff to it but I would need help
on how to do this properly.

Kevin Kirspel
Osmetech 
235 Hembree Park Drive
Roswell GA, 30076
770-510-4444 x4568


-----Original Message-----
From: Joel Sherrill <joel at OARcorp.com>
[mailto:joel.sherrill at OARcorp.com] 
Sent: Friday, January 06, 2006 10:48 AM
To: Kirspel, Kevin {Engineering - Osmetech CCD}
Cc: Ian Caddy; rtems-users at rtems.com
Subject: Re: Interrupts Disabled After First Context Switch

Kirspel, Kevin {Engineering - Osmetech CCD} wrote:
> 4.6.0
> 
> I see that the 4.6.5 version does not have the disable. I will upgrade
> my rtems today.

Checking cvsweb, I don't see two _ISR_Disable calls in the version 
shipped.  Are you sure you don't have some local modifications?

Also you are on an SH-3.  Are there any CPU related patches that you
have that are not in the tree?

--joel


> Kevin Kirspel
> Osmetech 
> 235 Hembree Park Drive
> Roswell GA, 30076
> 770-510-4444 x4568
> 
> 
> -----Original Message-----
> From: Joel Sherrill <joel at OARcorp.com>
> [mailto:joel.sherrill at OARcorp.com] 
> Sent: Friday, January 06, 2006 8:21 AM
> To: Ian Caddy
> Cc: Kirspel, Kevin {Engineering - Osmetech CCD}; rtems-users at rtems.com
> Subject: Re: Interrupts Disabled After First Context Switch
> 
> Ian Caddy wrote:
> 
>>Hi Kevin,
>>
>>Which version of RTEMS are you running.  We have been looking through 
>>watchdoginsert.c for another problem and in my version, which is from 
>>4.6.5 there is no _ISR_Disable( level ) after the restart.
> 
> 
> Ditto for the code on the head of CVS.  Which version of RTEMS is
this?
> Or which CVS Id is watchdoginsert.c?
> 
> 
> 
>>That definitely looks wrong to me.  You can not have 2 disables
> 
> without 
> 
>>an enable in between them.  In fact looking through that code, if the 
>>restart is invoked, you will get more _ISR_Disable( level ) than just 
>>the 2 as well.
> 
> 
> Right.
> 
> 
> 
>>The cpukit/score/src/watchdoginsert.c in the 4.6.5 release is correct
> 
> if 
> 
>>you want to have a look at that.
>>
>>regards,
>>
>>Ian Caddy
>>
>>
>>Kirspel, Kevin {Engineering - Osmetech CCD} wrote:
>>
>>
>>>I'm not sure this is a bug but I tracked down my problem to
>>>_Watchdog_Insert().  Below is the relevant code snippet. Upon
> 
> entering
> 
>>>watchdog insert the routine disables interrupts.  This sets my
> 
> interrupt
> 
>>>level to 15 ( which blocks all interrupts ).  The returned interrupt
>>>level from the _ISR_Disable() call shows that the previous interrupt
>>>level to be zero.  This is correct.  It then disables the interrupts
>>>again right after the restart label.  Since the interrupt level is
>>>current 15 the returned interrupt level from the _ISR_Disable() is
> 
> now
> 
>>>15.  When it finally enables interrupts at the end, the level is set
> 
> to
> 
>>>15 masking all interrupts. To fix the problem I commented out the
>>>_ISR_Disable() right below the restart label.  Is this a bug or is
> 
> rtems
> 
>>>intended to work this way?
>>>
>>>void _Watchdog_Insert(
>>>  Chain_Control         *header,
>>>  Watchdog_Control      *the_watchdog
>>>)
>>>{
>>>  ISR_Level          level;
>>>  Watchdog_Control  *after;
>>>  unsigned32         insert_isr_nest_level;
>>>  Watchdog_Interval  delta_interval;
>>>
>>>
>>>  insert_isr_nest_level   = _ISR_Nest_level;
>>>
>>>    _ISR_Disable( level );
>>>
>>>  /*
>>>   *  Check to see if the watchdog has just been inserted by a
>>>   *  higher priority interrupt.  If so, abandon this insert.
>>>   */
>>>
>>>  if ( the_watchdog->state != WATCHDOG_INACTIVE ) {
>>>    _ISR_Enable( level );
>>>    return;
>>>  }
>>>
>>>  the_watchdog->state = WATCHDOG_BEING_INSERTED;
>>>
>>>  _Watchdog_Sync_count++;
>>>
>>>restart:
>>>  delta_interval = the_watchdog->initial;
>>>
>>>  _ISR_Disable( level ); //I commented this Disable to fix problem
>>>
>>>for ( after = _Watchdog_First( header ) ;
>>>        ;
>>>        after = _Watchdog_Next( after ) ) {
>>>
>>>     if ( delta_interval == 0 || !_Watchdog_Next( after ) )
>>>       break;
>>>
>>>     if ( delta_interval < after->delta_interval ) {
>>>       after->delta_interval -= delta_interval;
>>>       break;
>>>     }
>>>
>>>     delta_interval -= after->delta_interval;
>>>
>>>     /*
>>>      *  If you experience problems comment out the _ISR_Flash line.
>>>      *  3.2.0 was the first release with this critical section
>>>redesigned.
>>>      *  Under certain circumstances, the PREVIOUS critical section
>>>algorithm
>>>      *  used around this flash point allowed interrupts to execute
>>>      *  which violated the design assumptions.  The critical section
>>>      *  mechanism used here WAS redesigned to address this.
>>>      */
>>>
>>>     _ISR_Flash( level );
>>>
>>>     if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) {
>>>       goto exit_insert;
>>>     }
>>>
>>>     if ( _Watchdog_Sync_level > insert_isr_nest_level ) {
>>>       _Watchdog_Sync_level = insert_isr_nest_level;
>>>       goto restart;
>>>     }
>>>  }
>>>
>>>  _Watchdog_Activate( the_watchdog );
>>>
>>>  the_watchdog->delta_interval = delta_interval;
>>>
>>>  _Chain_Insert_unprotected( after->Node.previous,
> 
> &the_watchdog->Node
> 
>>>);
>>>
>>>  the_watchdog->start_time = _Watchdog_Ticks_since_boot;
>>>
>>>exit_insert:
>>>  _Watchdog_Sync_level = insert_isr_nest_level;
>>>  _Watchdog_Sync_count--;
>>>  _ISR_Enable( level );
>>>}
>>>
>>>
>>>
>>>Kevin Kirspel
>>>Osmetech 235 Hembree Park Drive
>>>Roswell GA, 30076
>>>770-510-4444 x4568
>>>
>>>
>>>-----Original Message-----
>>>From: Joel Sherrill <joel at OARcorp.com>
>>>[mailto:joel.sherrill at OARcorp.com] Sent: Thursday, January 05, 2006 
>>>4:44 PM
>>>To: Kirspel, Kevin {Engineering - Osmetech CCD}
>>>Cc: rtems-users at rtems.com
>>>Subject: Re: Interrupts Disabled After First Context Switch
>>>
>>>Kirspel, Kevin {Engineering - Osmetech CCD} wrote:
>>>
>>>
>>>>During _Thread_Dispatch() I was printing the state of the SR
> 
> register.
> 
>>>
>>>I
>>>
>>>
>>>>found that by the third context switch the interrupts were disabled
>>>>going into _Thread_Dispatch().  So when _ISR_Disable() is called it
>>>>returns the SR register with interrupts disabled.  Since the
>>>>_ISR_Enable() routine just sets the SR register with the given
> 
> level,
> 
>>>>interrupts are disabled even after the _ISR_Enable() call.  Is it
>>>>possible to enter the _Thread_Dispatch() routine while interrupts
> 
> are
> 
>>>>disable ( i.e. _ISR_Disable() was called prior to _Thread_Dispatch()
>>>
>>>
>>>)?
>>>
>>>Yes.  Interrupt level is maintained across context switches on a per 
>>>thread basis.
>>>
>>>I suspect that the third context switch you see is actually from 
>>>__ISR_Dispatch and that the level is somehow not being maintained
> 
> across
> 
>>>a preemption from ISR.
>>>
>>>The sequence should be something like this for your test:
>>>
>>>   (1) 1st context switch (initialization to 1st thread)
>>>   (2) 1st thread to IDLE (wake after)
>>>     ... clock tick isrs
>>>   (3) IDLE to 1st thread FROM ISR!!
>>>
>>>The FROM ISR on (3) is critical.  That puts you through the tail of 
>>>__ISR_Handler and possibly needing some magic.  On other CPUs, that
>>>code is tricky.  The SH code is straightforward but might be missing
>>>something on the SH3/4.
>>>
>>>
>>>
>>>
>>>>Kevin Kirspel
>>>>Osmetech 235 Hembree Park Drive
>>>>Roswell GA, 30076
>>>>770-510-4444 x4568
>>>>
>>>>
>>>>-----Original Message-----
>>>>From: Joel Sherrill <joel at OARcorp.com>
>>>>[mailto:joel.sherrill at OARcorp.com] Sent: Thursday, January 05, 2006 
>>>>1:04 PM
>>>>To: Kirspel, Kevin {Engineering - Osmetech CCD}
>>>>Cc: rtems-users at rtems.com
>>>>Subject: Re: Interrupts Disabled After First Context Switch
>>>>
>>>>Kirspel, Kevin {Engineering - Osmetech CCD} wrote:
>>>>
>>>>
>>>>
>>>>>1) Renesas SH-3 but it's pretty much the same as the SH-4.
>>>>>
>>>>>2) the rtems_interrupt_disable() routine returns the value in the
> 
> SR
> 
>>>>>register of the sh-3/4.  The SR register contains a BL bit that
> 
> masks
> 
>>>>>interrupts.  It also contains an interrupt level mask that prevents
>>>>
>>>>
>>>>any
>>>>
>>>>
>>>>
>>>>>interrupt lower than the level in the SR register from executing.
> 
> The
> 
>>>>>SH4 port sets the interrupt level to 15 to mask all interrupts (
>>>>>rtems_interrupt_disable ).  Upon the printf statement below, the
>>>>>interrupt level in the SR register is set to 15 masking all
>>>>
>>>>
>>>>interrupts.
>>>>
>>>>
>>>>
>>>>>3)Yes.
>>>>>
>>>>>Case 1: using interrupt mask level 15 to disable interrupts. (
>>>>
>>>>
>>>>interrupt
>>>>
>>>>
>>>>
>>>>>masks bits are bits 4-7 which is 0 before and F after).
>>>>>INT BEFORE: 0x40001000
>>>>>INT AFTER:  0x400011F1
>>>>>
>>>>>Case 2: using interrupt BL bit to disable interrupts. ( interrupt
> 
> BL
> 
>>>>
>>>>bit
>>>>
>>>>
>>>>
>>>>>is bit 28 which is 0 before and 1 after).
>>>>>INT BEFORE: 0x40001000
>>>>>INT AFTER:  0x50001101
>>>>
>>>>
>>>>
>>>>Is BL implicitly modified by an interrupt?  I don't know the SH well
> 
> 
>>>>enough to trace the code in my head but since you are doing a 
>>>>delaying/blocking wake_after, there will be a context switch to
> 
> IDLE, 
> 
>>>>then some clock tick ISRs, then a preempt of IDLE via the
>>>
>>>
>>>__ISR_Handler
>>>
>>>
>>>>routine in cpu_asm.c.  If the BL bit is not preserved across the (a)
> 
> 
>>>>context switch or (b) interrupt preemption, then it might be what
> 
> you 
> 
>>>>are seeing.
>>>>
>>>>I do not think it is (a) because that is a simple load/store of the
>>>
>>>
>>>sr.
>>>
>>>
>>>>The __ISR_Handler code is always tricky to get right but I don't see
>>>
>>>
>>>how
>>>
>>>
>>>>it could be messed up either.
>>>>
>>>>To eliminate some possibilities and assuming this is a single task
>>>
>>>
>>>test,
>>>
>>>
>>>>change the wake after(100) to wake after(0).  And do not print until
> 
> 
>>>>after all of the interrupt level changes.  I suspect it is the
>>>
>>>
>>>interrupt
>>>
>>>
>>>>context switch somehow.  Just a guess.
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>>Kevin Kirspel
>>>>>Osmetech 235 Hembree Park Drive
>>>>>Roswell GA, 30076
>>>>>770-510-4444 x4568
>>>>>
>>>>>
>>>>>-----Original Message-----
>>>>>From: Joel Sherrill <joel at OARcorp.com>
>>>>>[mailto:joel.sherrill at OARcorp.com] Sent: Thursday, January 05, 2006
> 
> 
>>>>>11:20 AM
>>>>>To: Kirspel, Kevin {Engineering - Osmetech CCD}
>>>>>Cc: rtems-users at rtems.com
>>>>>Subject: Re: Interrupts Disabled After First Context Switch
>>>>>
>>>>>Kirspel, Kevin {Engineering - Osmetech CCD} wrote:
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>>Upon entering a task, the interrupts at the hardware level are
>>>>>
>>>>>
>>>>>enabled.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>>After a call to rtems_task_wake_after() the interrupts are
> 
> disabled
> 
>>>>>
>>>>>and
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>>remain disabled while the task is running.  What part of the code
>>>>>
>>>>>
>>>>>should
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>>I look at to diagnose this issue? It seems that interrupts get
>>>>>
>>>>>
>>>>>disabled
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>>before the task switch is performed.
>>>>>>
>>>>>>The code sample below illustrates what I am doing. At the first
>>>>>>printf(), the interrupts are enabled.  After the second printf(),
> 
> the
> 
>>>>>>interrupts are disabled.
>>>>>>
>>>>>>rtems_task GUITask ( rtems_task_argument ignored )
>>>>>>{
>>>>>>//Local Varaibles
>>>>>>rtems_interrupt_level level;
>>>>>>
>>>>>>/* Wait 100ms til everyone is up and running */
>>>>>>rtems_interrupt_disable(level);
>>>>>>rtems_interrupt_enable(level);
>>>>>>printf( "\r\nINT BEFORE: %08lX", level );
>>>>>>rtems_task_wake_after( 10 );
>>>>>>rtems_interrupt_disable(level);
>>>>>>rtems_interrupt_enable(level);
>>>>>>printf ( "\r\nINT AFTER: %08lX", level );
>>>>>>}
>>>>>
>>>>>
>>>>>
>>>>>I have more questions than answers.
>>>>>
>>>>>rtems_interrupt_enable/disable are implemented as inline assembly 
>>>>>language routines.  They are port specific which leads to
>>>>>
>>>>>(1) Which CPU are you using?
>>>>>
>>>>>There is no guarantee on the contents of level after calling enable
>>>>>so
>>>>>
>>>>>(2) are you sure they are really off?
>>>>>
>>>>>(3) can you print out the status register or whatever it is on this
>>>>
>>>>
>>>>CPU
>>>>
>>>>
>>>>>and we really check?
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>>Kevin Kirspel
>>>>>>Osmetech 235 Hembree Park Drive
>>>>>>Roswell GA, 30076
>>>>>>770-510-4444 x4568
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>>
>>>
> 
> 


-- 
Joel Sherrill, Ph.D.             Director of Research & Development
joel at OARcorp.com                 On-Line Applications Research
Ask me about RTEMS: a free RTOS  Huntsville AL 35805
    Support Available             (256) 722-9985




More information about the users mailing list