DSPRelated.com
Forums

modulus (%) affects interrupts?

Started by Corey, Rick April 5, 2004
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



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:]
Sent: Monday, April 05, 2004 5:51 PM
To: '
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:

To Post:

To Leave:

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

_____

> .


Hi William
 
Ouch!  I thought I read somewhere that simple "multiply" is a run-time library function.  I wish I could recall where I read that.  I see nothing in the "MSL C" doc.  I see 13 "multiply" instructions listed in family RefMan (which makes sense, for a DSP).  IMACUU provides a 32-bit result.  Maybe I'm wrong about "*" being a run-time lib function.  Hope so!
 
The CW online manual has this to say about "certain computations":
"Intrinsic functions let you pass in data to perform specific optimized computations. For example, some calculations may be inefficient if coded in C because the compiler has to follow ANSI C rules to represent data, and this may cause the program to jump to runtime math routines for certain computations. In such cases, it probably is better to code these calculations using assembly language instructions and intrinsic functions. "
 
The intrinsic multiply functions I found were all for fractional math, not integer.
 
I didn't even have the modulus operator in my ISR - it was in the main loop.  I understand that if it isn't thread-safe, some other math in the ISR could break it ... I would have expected less-repeatable results.
 
The "fanciest" math inside my ISR is:
    increment a variable (I think they are all ushorts, but I'll search for longs)
    mask a ushort variable using  "var & mask" 
    mask-and-shift register contents, then assign to another variable (for byte-swapping)
    mask a register value, then use it in a comparison
 
On a quick look-through, I don't even see any "multiply"s remaining, but I suppose pointer arithmetic might use one implicitly.  I'll look several more times.  I had better look through the ASM produced to look for calls to lib functions.
 
I share your paranoia.  Thanks!
 
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: 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

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


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:]
Sent: Wednesday, April 07, 2004 11:00 AM
To: '
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:]
Sent: Monday, April 05, 2004 5:51 PM
To: '
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:

To Post:

To Leave:

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:

To Post:

To Leave:

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

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

Yahoo! Groups Links


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'; '
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:]
Sent: Wednesday, April 07, 2004 11:00 AM
To: '
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:]
Sent: Monday, April 05, 2004 5:51 PM
To: '
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:

To Post:

To Leave:

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:

To Post:

To Leave:

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

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

Yahoo! Groups Links


HI Rick and William,

32-bit multiply instructions take two 16-bit values and generated a 32-bit
result. This is not useful by itself for doing 32x32-bit multiplication.
This is why a runtime library is called for.

16-bit math is not done in a library.

For 5683xx/5685x we have more instruction support and inline much of these
user select "optimize for speed". 5680x and 5682x families have a more
limited instruction and registers set here.

All FP math is done in a library. (no FPU on the processor)

Regarding being ISR safe. This is addressed as long as the routine calling
these functions have one of the following:

1. "#pragma interrupt" For use only at top level ISR. Recommended when
there are not too many subroutine calls

2. "#pragma interrupt saveall" For use only at top level ISR recommended
when there will be many subroutine calls

3. "#pragma interrupt called" for use in case #1. Must be placed on C
functions called by interrupt routine (unless saveall option was used)

One problem you point out is that the compiler does not emit an error if
pragma in case 3 is left off. We don not have a solution to offer this
shortcoming.

If its not guarded by these #pragma's it will clobber volatile registers
used by the library. This ABI approach is a solid performance tradeoffs.
We have many volatile registers because, it would really slow things down if
more were treated as non-volatile. > Hi William
>
> Ouch! I thought I read somewhere that simple "multiply" is a run-time
> library function. I wish I could recall where I read that. I see nothing
> in the "MSL C" doc. I see 13 "multiply" instructions listed in family
> RefMan (which makes sense, for a DSP). IMACUU provides a 32-bit result.
> Maybe I'm wrong about "*" being a run-time lib function. Hope so!
>
> The CW online manual has this to say about "certain computations":
> "Intrinsic functions let you pass in data to perform specific optimized
> computations. For example, some calculations may be inefficient if coded in
> C because the compiler has to follow ANSI C rules to represent data, and
> this may cause the program to jump to runtime math routines for certain
> computations. In such cases, it probably is better to code these
> calculations using assembly language instructions and intrinsic functions. "
>
> The intrinsic multiply functions I found were all for fractional math, not
> integer.
>
> I didn't even have the modulus operator in my ISR - it was in the main loop.
> I understand that if it isn't thread-safe, some other math in the ISR could
> break it ... I would have expected less-repeatable results.
>
> The "fanciest" math inside my ISR is:
> increment a variable (I think they are all ushorts, but I'll search for
> longs)
> mask a ushort variable using "var & mask"
> mask-and-shift register contents, then assign to another variable (for
> byte-swapping)
> mask a register value, then use it in a comparison
>
> On a quick look-through, I don't even see any "multiply"s remaining, but I
> suppose pointer arithmetic might use one implicitly. I'll look several more
> times. I had better look through the ASM produced to look for calls to lib
> functions.
>
> I share your paranoia. Thanks!
>
> Rick Corey > -----Original Message-----
> From: Yochum, William [mailto:]
> Sent: Wednesday, April 07, 2004 11:00 AM
> To: '
> Cc: Corey, Rick
> Subject: 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
>

--
Free Download - New Version Released
CodeWarrior Development Studio for HC(S)12 Microcontrollers v3.1
Offers "emulator-like" debugging support for HCS12 derivatives
http://www.metrowerks.com/MW/Develop/Embedded/HC12/Default.htm Ron Liechty - - http://www.metrowerks.com


Rick Corey wrote:

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

An ISR will not call any function in the main loop or be affected by it in
anyway. The ISR should run to completion before going back to the main loop.

The engineers that looked at this are guessing that the time to complete the
ISR you wrote might depend on some data structure that could be corrupted by
something done in the mainloop. The mod library itself would not do this.
It is likely something in your code. Perhaps the modulus operation is just
a red herring?

Ron

--
Free Download - New Version Released
CodeWarrior Development Studio for HC(S)12 Microcontrollers v3.1
Offers "emulator-like" debugging support for HCS12 derivatives
http://www.metrowerks.com/MW/Develop/Embedded/HC12/Default.htm Ron Liechty - - http://www.metrowerks.com


Hi Ron

The modulus problem is not a red herring. I have weeks of testing where:
'without the % it works fine for days" and 20-30 cycles of "add the % and
break it - remove the % and it works fine for as long as I run the test".
The most recent test is "make both arguments ushorts and run overnight" vs.
"if either is a long it will crash very quickly". This is conclusive. The
two variables used in the % statement are not used anywhere else in the
program and are local to the routine that uses them. It is not a red
herring.

Rick Corey
-----Original Message-----
From: MW Ron [mailto:]
Sent: Wednesday, April 07, 2004 5:10 PM
To:
Cc: Corey, Rick
Subject: Re: [motoroladsp] modulus (%) affects interrupts?
Importance: Low Rick Corey wrote:

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

An ISR will not call any function in the main loop or be affected by it in
anyway. The ISR should run to completion before going back to the main loop.

The engineers that looked at this are guessing that the time to complete the
ISR you wrote might depend on some data structure that could be corrupted by
something done in the mainloop. The mod library itself would not do this.
It is likely something in your code. Perhaps the modulus operation is just
a red herring?

Ron

--
Free Download - New Version Released
CodeWarrior Development Studio for HC(S)12 Microcontrollers v3.1
Offers "emulator-like" debugging support for HCS12 derivatives
http://www.metrowerks.com/MW/Develop/Embedded/HC12/Default.htm Ron Liechty - - http://www.metrowerks.com



Hi Ron

First, I'll just mention that even blocking interrupts entirely around that
modulus code did not seem to solve the problem either! I used:
"#define __EI3() { asm(bfset #0x0300,SR); }" and
"#define __EI0() { asm(bfclr #0x0300,SR); }
I added such long delays elsewhere in the main loop that blocking IRQs
during the % code wouldn't cause problems. It still died when I used a long
constant, and worked when I used a short. Tentatively I would think that
this means that "ISR-safety" is not the only issue.

Sorry, but I have several points of substantial disagreement with your post:

(1) First, you said:
"Regarding being ISR safe. This is addressed as long as the routine
calling
these functions have one of the following: ..."

Ron, that means that these are absolutely *NOT* ISR-safe in ANY sense,
since they need to have complete ISR protection wrapped around them.

You said:
"as long as the routine calling these functions have ..."
Please tell me how one would add ISR protection like "#pragma interrupt
called" to "main", which is where this happened to bite me. Then I could
test the theory that "% long" is merely not ISR-safe, as opposed to having
other problems as well.

I'm also puzzled about how "#pragma interrupt called" can protect the
inside of a function, if it does not block IRQs when the function is not
called from inside an ISR. It seems to me that the "protected" function (or
main, in my case) would save its context, then start running, then reach the
math code, then be interrupted by an ISR, and break things. When you put
"#pragma interrupt called" around a function that is NOT called from inside
an iSR, does it block IRQs as well as SAVEALL? This is puzzling.

Even if that is sufficient, are you saying that ANY non-ISR routine that
uses any floating point math, or any math function, or any 32-bit multiply
needs to have "#pragma interrupt called" around it, even if it is NOT
called from inside any ISR? That's a brutal efficiency hit! Would the same
rule apply to any function that uses the modulus operator with a long
(32-bit) variable? I understand that floating point math will be slow
(that's understandable) but not having to save and restore the whole context
just to do a 32-bit multiply or modulus!

The most scary thing is that these are not explicit library functions like
"sin" or "log" ... these are just the ANSII C operators "*" and "%".
Modulus isn't ISR-safe with longs in your compiler - or maybe it just
occasionally works wrong with longs altogether, I don't know. When I change
the "unsigned short" to a "unsigned long" it breaks my code.

One excellent consultant we work with pointed to FPE_state as a possible
culprit, and I'll test that eventually - he suggests that it should be part
of your SAVEALL and RESTOREALL macros for ISRs to work correctly with math. (2) Next, you said:
>> 16-bit math is not done in a library. <<

I think this is incorrect. Here's the ASM you generate:
- - - -
if (!(NumMsgsSent % 100)) // 0xFF))
P:00000EBA: B57C move.w X:(SP-4),Y0
P:00000EBB: 87470064 move.w #100,Y1
P:00000EBD: E254126D jsr 0x00126d
P:00000EBF: 8F05 tst.w Y0
P:00000EC0: A211 bne main+0xd0 (0xed2) ; 0x000772
- - - -

The jsr jumps to the following, which the debugger says comes from
"C:\program files\Metrowerks\CW6\M56800E Support\math
support\Rtrem16\ARTREMU16Z.asm". This looks like a library to me.
"Modulus" is math, and both the operands are ushorts (16 bits). It seems to
be "16 bit math done in a library" ... but at least it doesn't seem to
destroy my code.

tst.w y1 ; Check on high bit, should be zero
P:0000126D: 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:0000126E: A51B blt @DummyFn1+0x1d (0x128a) ; 0x000953
P:0000126F: E700 nop

lsr16 y0,b ; Copy dividend to b0 no sign
extension
P:00001270: 7CD7 lsr16 Y0,B

;;;;;;;;;;;;;;;; 4-bit division ;;;;;;;;;;;;;;;;
div y1,b ; form quotient in b0
P:00001271: 78FF div Y1,B

<big snip>

;;;;;;;;;;;;;;; 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:0000128A: 8105 move.w Y0,B
sub y1,y0 ; REM valid if y0 >= y1 (quotient =
1)
P:0000128B: 7AF1 sub Y1,Y0
tcc y0,b ; if quotient = 1, REM = y0-y1
P:0000128C: 709F tcc Y0,B

rtsd ; delay return after nxt 3 instr
P:0000128D: E70C rtsd
move.w b1,y0 ; move REM value into return register
P:0000128E: 8511 move.w B1,Y0
nop ; filler
P:0000128F: E700 nop
nop ; filler
P:00001290: E700 nop

- - - - - -

(3) Finally, you said:
"If its not guarded by these #pragma's it will clobber volatile registers
used by the library. This ABI approach is a solid performance tradeoffs.
We have many volatile registers because, it would really slow things down if
more were treated as non-volatile."

I never heard that, before, as a reason to ship non-re-entrant math
libraries for a microcontroller. The tendency to use those with interrupts
usually makes re-entrancy an absolute requirement for usability.

How could making your libraries re-entrant slow things down as much as
forcing the user to wrap "SAVEALL" and "RESTOREALL" around every single
routine that uses any math?

Rick Corey
-----Original Message-----
From: MW Ron [mailto:]
Sent: Wednesday, April 07, 2004 5:06 PM
To:
Subject: Re: [motoroladsp] RE: modulus (%) affects interrupts?
Importance: Low HI Rick and William,

32-bit multiply instructions take two 16-bit values and generated a 32-bit
result. This is not useful by itself for doing 32x32-bit multiplication.
This is why a runtime library is called for.

16-bit math is not done in a library.

For 5683xx/5685x we have more instruction support and inline much of these
user select "optimize for speed". 5680x and 5682x families have a more
limited instruction and registers set here.

All FP math is done in a library. (no FPU on the processor)

Regarding being ISR safe. This is addressed as long as the routine calling
these functions have one of the following:

1. "#pragma interrupt" For use only at top level ISR. Recommended when
there are not too many subroutine calls

2. "#pragma interrupt saveall" For use only at top level ISR recommended
when there will be many subroutine calls

3. "#pragma interrupt called" for use in case #1. Must be placed on C
functions called by interrupt routine (unless saveall option was used)

One problem you point out is that the compiler does not emit an error if
pragma in case 3 is left off. We don not have a solution to offer this
shortcoming.

If its not guarded by these #pragma's it will clobber volatile registers
used by the library. This ABI approach is a solid performance tradeoffs.
We have many volatile registers because, it would really slow things down if
more were treated as non-volatile. > Hi William
>
> Ouch! I thought I read somewhere that simple "multiply" is a run-time
> library function. I wish I could recall where I read that. I see nothing
> in the "MSL C" doc. I see 13 "multiply" instructions listed in family
> RefMan (which makes sense, for a DSP). IMACUU provides a 32-bit result.
> Maybe I'm wrong about "*" being a run-time lib function. Hope so!
>
> The CW online manual has this to say about "certain computations":
> "Intrinsic functions let you pass in data to perform specific optimized
> computations. For example, some calculations may be inefficient if coded
in
> C because the compiler has to follow ANSI C rules to represent data, and
> this may cause the program to jump to runtime math routines for certain
> computations. In such cases, it probably is better to code these
> calculations using assembly language instructions and intrinsic functions.
"
>
> The intrinsic multiply functions I found were all for fractional math, not
> integer.
>
> I didn't even have the modulus operator in my ISR - it was in the main
loop.
> I understand that if it isn't thread-safe, some other math in the ISR
could
> break it ... I would have expected less-repeatable results.
>
> The "fanciest" math inside my ISR is:
> increment a variable (I think they are all ushorts, but I'll search for
> longs)
> mask a ushort variable using "var & mask"
> mask-and-shift register contents, then assign to another variable (for
> byte-swapping)
> mask a register value, then use it in a comparison
>
> On a quick look-through, I don't even see any "multiply"s remaining, but I
> suppose pointer arithmetic might use one implicitly. I'll look several
more
> times. I had better look through the ASM produced to look for calls to
lib
> functions.
>
> I share your paranoia. Thanks!
>
> Rick Corey > -----Original Message-----
> From: Yochum, William [mailto:]
> Sent: Wednesday, April 07, 2004 11:00 AM
> To: '
> Cc: Corey, Rick
> Subject: 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
>

--
Free Download - New Version Released
CodeWarrior Development Studio for HC(S)12 Microcontrollers v3.1
Offers "emulator-like" debugging support for HCS12 derivatives
http://www.metrowerks.com/MW/Develop/Embedded/HC12/Default.htm Ron Liechty - - http://www.metrowerks.com
_____________________________________
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:

To Post:

To Leave:

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

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

Yahoo! Groups Links



Corey, Rick wrote:

> Hi Ron
>
> The modulus problem is not a red herring. I have weeks of testing where:
> 'without the % it works fine for days" and 20-30 cycles of "add the % and
> break it - remove the % and it works fine for as long as I run the test".
> The most recent test is "make both arguments ushorts and run overnight" vs.
> "if either is a long it will crash very quickly". This is conclusive. The
> two variables used in the % statement are not used anywhere else in the
> program and are local to the routine that uses them. It is not a red
> herring.

Please open a Service Request on this and let me know when you do. We need
a reproducible case.

Ron

>
>
> -----Original Message-----
> From: MW Ron [mailto:]
> Sent: Wednesday, April 07, 2004 5:10 PM
> To:
> Cc: Corey, Rick
> Subject: Re: [motoroladsp] modulus (%) affects interrupts?
> Importance: Low > Rick Corey wrote:
>
>> Can anyone imagine a way that a modulus operator (%) in the main loop
> could
>> slow down an ISR? I'm stumped.
>
> An ISR will not call any function in the main loop or be affected by it in
> anyway. The ISR should run to completion before going back to the main loop.
>
> The engineers that looked at this are guessing that the time to complete the
> ISR you wrote might depend on some data structure that could be corrupted by
> something done in the mainloop. The mod library itself would not do this.
> It is likely something in your code. Perhaps the modulus operation is just
> a red herring?
>
> Ron
>
> --
> Free Download - New Version Released
> CodeWarrior Development Studio for HC(S)12 Microcontrollers v3.1
> Offers "emulator-like" debugging support for HCS12 derivatives
> http://www.metrowerks.com/MW/Develop/Embedded/HC12/Default.htm > Ron Liechty - - http://www.metrowerks.com >
>
> _____________________________________
> 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:
>
> To Post:
>
> To Leave:
>
> Archives: http://www.yahoogroups.com/group/motoroladsp
>
> More Groups: http://www.dsprelated.com/groups.php3
>
> Yahoo! Groups Links

--
Free Download - New Version Released
CodeWarrior Development Studio for HC(S)12 Microcontrollers v3.1
Offers "emulator-like" debugging support for HCS12 derivatives
http://www.metrowerks.com/MW/Develop/Embedded/HC12/Default.htm Ron Liechty - - http://www.metrowerks.com