Forums

RE: [Bulk E-Mail] RE: RE: modulus (%) affects inte rrupts?

Started by Ebersman, Howard April 7, 2004
If you use up all available processing power, which can happen very quickly if you use frequent library calls, strange things often happen in your code.
 
Sometimes what appears to be a "crash" might just be a big backlog of processing stuff that never gets cleared out and prevents the console or other operations from running.
 
It is often a good idea to set an I/O line low during your idle "process" and high otherwise and use a scope to figure out how many spare cycles you have available before all heck breaks loose.
 
Howard
-----Original Message-----
From: Corey, Rick [mailto:r...@dpconline.com]
Sent: Wednesday, April 07, 2004 4:35 PM
To: 'm...@yahoogroups.com'
Subject: [Bulk E-Mail] RE: [motoroladsp] RE: modulus (%) affects interrupts?

FWIW, I just noticed that my #defined constants for "ONE_K" and "TEN_K" were
#defined as longs ... so the problem I saw may have been with
modulus-for-longs.  I've run for 5-8 minutes at a time just now with ushorts
... will try overnight.

Rick Corey

-----Original Message-----
From: Corey, Rick
Sent: Wednesday, April 07, 2004 3:20 PM
To: 'Yochum, William'; 'm...@yahoogroups.com'
Cc: Corey, Rick
Subject: RE: [motoroladsp] RE: modulus (%) affects interrupts?I tried throwing ISR protection around my "modulus code" but that didn't
help much.  It still died, but maybe took a little longer than it used to.

I used the P.E. macros :
#define __EI0() { asm(bfclr  #0x0300,SR); }   /* Enable interrupts of level
0,1,2,3 */
#define __EI3() { asm(bfset  #0x0300,SR); }   /* Enable interrupts of level
3 only (NMI) */

I  _think_  that this rules out the theory that the only problem with
modulus is that it isn't interrupt-safe ... but what is left?Rick Corey

-----Original Message-----
From: Yochum, William [mailto:w...@microwavedata.com]
Sent: Wednesday, April 07, 2004 11:00 AM
To: 'm...@yahoogroups.com'
Cc: Corey, Rick
Subject: [motoroladsp] RE: modulus (%) affects interrupts?I've seen something even worse in an earlier version of Code Warrior.

I was also attempting to do "simple" math in an ISR.

The math in my ISR was written as a standard C expression, but the compiler
implemented this as a call to a run-time library function.  So far, so good
... but the run-time library function was NOT INTERRUPT SAFE!  It corrupted
registers which manifested itself as random failures in background code.
This was a VERY insidious problem and took quite a while to find.

William C. Yochum               Microwave Data Systems Inc.
Principal Eng./Software        175 Science Parkway
Phone: (585) 242-8319           Rochester, NY 14620
FAX:   (585) 241-5590           USA-----Original Message-----
From: Corey, Rick [mailto:r...@dpconline.com]
Sent: Monday, April 05, 2004 5:51 PM
To: 'm...@yahoogroups.com'
Subject: [Bulk E-Mail] [motoroladsp] modulus (%) affects interrupts?Hi

Can anyone imagine a way that a modulus operator (%) in the main loop could
slow down an ISR?  I'm stumped. 

There's a lot of "div"s in the library function, and two "rtsd"s .  I'm
using the 6.0.2 CW for 56800E (568357).  I turned on Processor Expert to
create the project, then turned PE off.  Any suggestions or speculation
would be appreciated, even if derived from experience with CW 5.1.

I had some durable FlexCAN code that broke when I added a modulus operator
to my main loop.  I just wanted to blink some LEDs so I could see fast TX
and RX occur without a scope.

The symptom seems to be partial or intermittent blocking of the FlexCAN
mailbox interrupt - or possibly slowing down the servicing of that
interrupt.  If it was only slowing down the main loop, I should never see
this symptom.  It acts as if it is preventing the FlexCAN ISR from being
serviced promptly. 

I can see a few packets (around 8, instead of 96) go out after a one-second
delay that should have fully restored the pool, but despite waiting long
enough to TX 7,000 packets, I only find that 8 or so have been clocked out.It seems as if, once this "bad thing" happens, CAN TX is permanently slowed
down by a very large factor - maybe around 1,000 times too slow - but not
stopped entirely.

I normally set up to send almost as fast as the packets can go over the
wire.  Then I blink an LED every 100 messages (every 300 CAN packets) - in
some tests, I also blink other LEDs every 1,000 or 10,000 messages.

The symptom is running low on TX packet buffers - as if the ISR is being
prevented from running as soon as it should, or as fast as it should.  (If
the TX ISR ran normally, all the packet buffers would be restored to the
pool before I took another 30 buffers out.)

Strangely, adding a one-second delay every time I detect "low buffer pool"
does not return the chip to full-speed sending, as it should once the pool
is full again.   Further, the lengths of time it takes to exhaust the pool
will be consistent for each test case, but range from 20 seconds to several
minutes to overnight.

I normally send 30 packets, wait 4 milliseconds, then send another 30.  The
4 mSec plus the main loop itself is long enough for the packets to go out -
if I count the number of times my ToTxList goes empty, it is equal to the
number of batches of packets, so the pool normally gets empty every 4
milliseconds.  The test also fails if I run with 10 mSec delays, or 50 mSec
- it just takes longer to fail.  With the 4 mSec delay and no "%"s, it runs
over a weekend.

I read the error counters every few packets, and they never exceed "1".  I
trigger an interrupt and trap on any FCSTATUS error bit.  None seen.

CODE SAMPLES:

Worst case code, with unsigned long, breaks in 20 seconds:
                    if (!(NumMsgsSent % 100))
                        {
                        LED1_Toggle();
                        if (!(NumMsgsSent % ONE_K))
                            {
                            LED2_Toggle();
                            if (!(NumMsgsSent % TEN_K))
                                LED3_Toggle();
                            }
                        }

Bad-enough case, even with an unsigned short, it breaks overnight:
It also breaks if I use if ( 0 == (NumMsgsSent % 100) ), instead of    if
(!(NumMsgsSent % 100))  .
// not OK with an ushort, either, but it runs for much longer before dying
                    if (!(NumMsgsSent % 100))                 
                        LED1_Toggle();

This runs fine overnight, without any "%" modulus:
                if (NumMsgsSent >= 256)
                    {
                    NumMsgsSent = 0;
                    LED2_Toggle();  
                    }Note that instances of   (var % 256)  get turned by the compiler into  (var
& 256),  so those don't do any messy math.  I've used that for months
without problems.

LIBRARY CODE, from "mixed source" screen:

Here's the asm library function that is JSRed to for   if (!(NumMsgsSent %
100)) .  I notice that different code is used for % 1,000 or   %10,000, but
the problem occurs even when I only do  % 100  :

if (!(NumMsgsSent % 100))      jsr  01238      ARTREMU16Z.asm
support/runtime56800E/math_support
       tst.w           y1              ; Check on high bit, should be zero
. . .

P:00001238: 8F07                tst.w    Y1
                                       ; Required carry bit is cleard too!
       blt             High_bit_present ; If bit 15 on, result is either 1
or 0
P:00001239: A51B                blt      @DummyFn1+0x1d (0x1255) ; 0x000938
P:0000123A: E700                nop
       lsr16           y0,b            ; Copy dividend to b0 no sign
extension
P:0000123B: 7CD7                lsr16    Y0,B
;;;;;;;;;;;;;;;; 4-bit division ;;;;;;;;;;;;;;;;
       div             y1,b            ; form quotient in b0
P:0000123C: 78FF                div      Y1,B
       div             y1,b
P:0000123D: 78FF                div      Y1,B
       div             y1,b
P:0000123E: 78FF                div      Y1,B
       div             y1,b
P:0000123F: 78FF                div      Y1,B
;;;;;;;;;;;;;;;; 4-bit division ;;;;;;;;;;;;;;;;
       div             y1,b            ; form quotient in b0

P:00001240: 78FF                div      Y1,B
       div             y1,b                                
P:00001241: 78FF                div      Y1,B
       div             y1,b
P:00001242: 78FF                div      Y1,B
       div             y1,b                                
P:00001243: 78FF                div      Y1,B
;;;;;;;;;;;;;;;; 4-bit division ;;;;;;;;;;;;;;;;
       div             y1,b            ; form quotient in b0
P:00001244: 78FF                div      Y1,B
       div             y1,b
P:00001245: 78FF                div      Y1,B
       div             y1,b
P:00001246: 78FF                div      Y1,B
       div             y1,b
P:00001247: 78FF                div      Y1,B
;;;;;;;;;;;;;;;; 4-bit division ;;;;;;;;;;;;;;;;
       div             y1,b            ; form quotient in b0
P:00001248: 78FF                div      Y1,B
       div             y1,b
P:00001249: 78FF                div      Y1,B
       div             y1,b
P:0000124A: 78FF                div      Y1,B
       div             y1,b
P:0000124B: 78FF                div      Y1,B      
;;;;;;;;;;;;;;;; check sign of quotient and adjust accordingly  
       tst             b               ; Result sign in N bit of SR
P:0000124C: 70BB                tst      B
       bge             Positive_rem    ; if remainder is positive, ok
P:0000124D: A403                bge      @DummyFn1+0x19 (0x1251) ; 0x00092a
P:0000124E: E700                nop      
Fix_required_remainder:
       add             y1,b            ; restored remainder, b is negative
P:0000124F: 78F0                add      Y1,B
P:00001250: E700                nop                                       ;
y1-b
Positive_rem:      
       rtsd                            ; delay return after nxt 3 instr
P:00001251: E70C                rtsd
       move.w          b1,y0           ; move result value into return
register
P:00001252: 8511                move.w   B1,Y0
       nop                             ; filler
P:00001253: E700                nop
       nop                             ; filler
P:00001254: E700                nop      
;;;;;;;;;;;;;;; Quotient result is either be 1 (REM = y0-y1) or 0 (REM = y0)
High_bit_present:
       move.w          y0,b            ; set REM to dividend, y0, for
quotient = 0
P:00001255: 8105                move.w   Y0,B
       sub             y1,y0           ; REM valid if y0 >= y1 (quotient =
1)
P:00001256: 7AF1                sub      Y1,Y0
       tcc             y0,b            ; if quotient = 1, REM = y0-y1
P:00001257: 709F                tcc      Y0,B      
       rtsd                            ; delay return after nxt 3 instr
P:00001258: E70C                rtsd
       move.w          b1,y0           ; move REM value into return register
P:00001259: 8511                move.w   B1,Y0
       nop                             ; filler
P:0000125A: E700                nop
       nop                             ; filler
P:0000125B: E700                nop

FWIW, here's what I use for LEDs, borrowed from P.E.:
#define LED6_Toggle() (changeRegBits(*GPIO_D_DR,128))
#define LED1_Off()    (clrRegBits(*GPIO_C_DR,1))

The inner loop of my delay function reads the timers as often as it can, but
does 32-bit arithmetic:
    while ( NowTick < DoneTick )              
        TMRD3D2_TICKS_LONG ( NowTick );

where the macro is:
#define  TMRD3D2_TICKS_LONG( LongVar ) {  \
      LongVar   = (*TMR_D2_CNTR);           \
      LongVar <<= 16;                       \
      LongVar  += (*TMR_D3_HOLD); }

Is it conceivable that reading a timer too frequently is somehow stalling an
ISR?  The HOLD register?  Long arithmetic??

Rick Corey
Senior Software Engineer
DPC Instrument Systems Division
_____________________________________
Note: If you do a simple "reply" with your email client, only the author of
this message will receive your answer.  You need to do a "reply all" if you
want your answer to be distributed to the entire group.

_____________________________________
About this discussion group:

To Join:  m...@yahoogroups.com

To Post:  m...@yahoogroups.com

To Leave: m...@yahoogroups.com

Archives: http://www.yahoogroups.com/group/motoroladsp
<http://www.yahoogroups.com/group/motoroladsp>

More Groups: http://www.dsprelated.com/groups.php3
<http://www.dsprelated.com/groups.php3

  _____ 

> .

_____________________________________
Note: If you do a simple "reply" with your email client, only the author of
this message will receive your answer.  You need to do a "reply all" if you
want your answer to be distributed to the entire group.

_____________________________________
About this discussion group:

To Join:  m...@yahoogroups.com

To Post:  m...@yahoogroups.com

To Leave: m...@yahoogroups.com

Archives: http://www.yahoogroups.com/group/motoroladsp

More Groups: http://www.dsprelated.com/groups.php3

Yahoo! Groups Links


_____________________________________
Note: If you do a simple "reply" with your email client, only the author of this message will receive your answer.  You need to do a "reply all" if you want your answer to be distributed to the entire group.

_____________________________________
About this discussion group:

To Join:  m...@yahoogroups.com

To Post:  m...@yahoogroups.com

To Leave: m...@yahoogroups.com

Archives: http://www.yahoogroups.com/group/motoroladsp

More Groups: http://www.dsprelated.com/groups.php3