Forums

RE: Re: CodeWarrior 4 Upgrading (bugs in version 5)

Started by wdhaan October 1, 2002
Dear Art,

Thank you for your mail. Of course I understand your solution/work
around, with disabling interrupts.
However this ought not to be necessary if a processor has an atomic
instruction for changing one bit in a port (I admit this is wishful
thinking when using Codewarrior).

You mentioned a "local variable bug inside a function". Which bug do
you exactly mean. Do you mean the bug/undocumented feature, that for
a function a kind of stack frame is built at addresses 0x30..0x3F (in
assembly called mr0..mr15). This stack frame is saved on stack at
next function entry.
Or do you mean the bug in the listing below?

Kind regards, Wim de Haan Exendis B.V.
W.J. de Haan
P.O.box 56, 6710 BB Ede
Keesomstraat 4, 6716 AB Ede
The Netherlands.
Tel: +31- 318 - 676305
/*
The following interrupt functions are not well compiled, as only the
registers used
by the interrupt function itself, are stored on stack.
However the registers used by library functions called from interrupt
functions
are not saved on stack.
This causes unpredictable strange effects for the main function were
those registers are used.
*/

void Bug1_interrupt_function(void);
void Bug2_interrupt_function(void);

unsigned U1, U2;
#pragma interrupt
void Bug1_interrupt_function(void)
{// At function entry the LA and LC registers are not saved

U1=U2%10;// This uses the ARTREMU16Z asm function,
// which uses "do" instruction, so LA and LC are destroyed
//Even if LA and LC were saved, HWS is not saved, so interrupt on
interrupt can cause
//hardware stack overflow
}

unsigned long L1, L2;
#pragma interrupt
void Bug2_interrupt_function(void) //EVEN MORE WORSE
{// At function entry the Y0, Y1, LA, LC registers are not saved

L1=L2/31;// This uses the ARTDIVU32UZ asm function,
// which uses Y0 and Y1 registers and "do" instruction, so
Y0, Y1, LA, LC are destroyed
//Even if Y0, Y1, LA, LC were saved, HWS is not saved, so interrupt
on interrupt can cause
//hardware stack overflow
} GLOBAL FBug1_interrupt_function
ORG P:
FBug1_interrupt_function:
lea (SP)+
move N,X:(SP)+
move Y0,X:(SP)+
move Y1,X:(SP)
movei #10,Y1
move X:FU2,Y0
jsr ARTREMU16Z
move Y0,X:FU1
pop Y1
pop Y0
pop N
rti GLOBAL FBug2_interrupt_function
ORG P:
FBug2_interrupt_function:
lea (SP)+
move N,X:(SP)+
move A0,X:(SP)+
move A1,X:(SP)+
move A2,X:(SP)+
move B0,X:(SP)
move B1,X:(SP)+
move B2,X:(SP)+
movei #0,B
movei #31,B0
push B0
push B1
move X:FL2+1,A
move X:FL2,A0
jsr ARTDIVU32UZ
pop
pop
move A1,X:FL1+1
move A0,X:FL1
pop B2
pop B1
pop B0
pop A2
pop A1
pop A0
pop N
rti

; From library file rtrem16.asm

ARTREMU16Z:

tstw y1
bge nohighbit2
cmp y1,y0
blo Done4
sub y1,y0
bra Done4
nohighbit2:
clr A ; clear A
move y0,a0 ; save dividend in a0
clr B
move y1,b1 ; Save divisor in B

do #16,endloop2
div y1,A ; form quotient in a0 remainder in a1
endloop2:
tst A
bge around4
add B,A ; fix
remainder
around4:
move a1,y0 ; save rem in y0
Done4:
rts ; From library file artdivu32uz.asm

ARTDIVU32UZ:
clr B ; clear register for resulting quotient
; bfset #$0100,omr ; make sure the CC bit is set

move a0,y0
move a1,y1 ; move A to y1:y0
move x:(sp-2),a
move x:(sp-3),a0 ; load divisor into A
bfclr #1,sr ; clear the carry bit

move #32,LC ; I don't know why I can't use
immediate #32
do LC,endloop
rol y0
rol y1
bcc notthisbit
asl B
bfset #1,b0
bra around
notthisbit:
asl B
around:
sub A,B ; If carry is clear,
sub was OK.
bcc nottoobig ; otherwise, restore B
add A,B
nottoobig:
bfchg #1,sr ; reverse cc bit
nop
nop
endloop:
rol y0
rol y1
move y1,A ; move result to A
move y0,a0

IF REV_B
; bfclr #$0100,omr ; set CC setting to 36 bits
ENDIF

rts

-----Original Message-----
From: Art Johnson [mailto:]
Sent: dinsdag 1 oktober 2002 15:22
To: wdhaan;
Cc: Kevin Ackerley (E-mail); Ed Baillie (E-mail); Greg Clark
Subject: RE: [motoroladsp] Re: CodeWarrior 4 Upgrading While I agree that CodeWarrior 5 produces poorer code than 4.0.2 in
this example, when changing data in any shared resource (like a GPIO
port or globally shared memory), one should never assume that the
compiler will generate code that performs the operation atomically
(ie as one indivisible operation). This is particularly important
when you are using a RealTime Operating System (RTOS) (we use the
DSPOS RTOS in all our applications).

The generally accepted way of coding to prevent this sort of problem
with a shared resource is shown by the following example from one of
our programs:

#define Sci0_Tx_Connect( ) \
{ \
register WORD interrupt; \
interrupt = Disable_Int(); \
g_p_dspregs->pwma.pmout &= ~SCI0_TX_ENABLE_BIT; \
Enable_Int(interrupt); \
}

#define Sci0_Tx_Disconnect( ) \
{ \
register WORD interrupt; \
interrupt = Disable_Int(); \
g_p_dspregs->pwma.pmout |= SCI0_TX_ENABLE_BIT; \
Enable_Int(interrupt); \
}

The functions Disable_Int() and Enable_Int() are provided by the
DSPOS library. In this example, we are using one output on PWMA to
control the Transmit Enable pin of an RS-485 transceiver for the SCI0
serial port.

In any case, as I mentioned before, the very serious bugs that exist
in CodeWarrior 4.x and earlier mean that you are taking a big risk of
having your program crash in an unpredictable manner. We stumbled
upon the "local variable bug inside a function" almost by accident.
It was discovered when we were tracking down a completely different
CodeWarrior bug. Our software could easily have been sent out with
this "time bomb" embedded in it.

For the above reasons, anyone with an older version of CodeWarrior
should upgrade to version 5.0 with the 5.0.2 patch.

I agree with you, that in my 26+ years experience I have never seen a
compiler as buggy as CodeWarrior. While no product this complex is
ever "perfect", the bugs we keep finding go way beyond what is
acceptable. The Metrowerks compiler writers apparently don't even
understand basic ANSI C concepts like the meaning of the
keywords "volatile" or "const". This is not exotic, high-level
stuff, it's basically kindergarten-level C programming. You might
expect these sorts of problems in Version 1.0 of some product, but
they should not exist in a "mature" product like Version 5.0 (which
we recently had to buy to get some other bugs fixed). They even
deliberately introduced a bug into Version 5.0 (Compiler/linker puts
const data into X RAM) that contravenes the ANSI C standard meaning
of "const". They refused to fix this bug (they think it's actually
a "new, improved feature"), but gave us a work-around that cost me
weeks of work to change every build target of every project we have
here.

I'm sure we'll never know how much all this extra time and effort has
cost our company (both in direct development costs and lost sales due
to delayed product launches), but I'm sure it's well over $100,000.
Forcing us to pay for an upgrade rather than issuing patches to
version 4.x is just adding insult to injury. Maybe that's the price
you have to pay to design in leading-edge devices ... Regards,

Art Johnson
Senior Systems Analyst
PMC Prime Mover Controls Inc.
3600 Gilmore Way
Burnaby, B.C., Canada
V5G 4R8
Phone: 604 433-4644
FAX: 604 433-5570
Email:
http://www.pmc-controls.com
-----Original Message-----
From: wdhaan [mailto:]
Sent: Tuesday, October 01, 2002 12:55 AM
To:
Subject: [motoroladsp] Re: CodeWarrior 4 Upgrading Hi,

Upgrade from Codewarrior 4 to 5?
I did it, but I returned to version 4.0.2, due to the following new
bug in version 5:

*********** C-listing

#define GPIOD_BASE 0x13E0 // Table 3-36 for DSP56F807
#define GPIO_D_DR *(WORD *) (0x1+GPIOD_BASE)
GPIO_D_DR |= 0x02; // set GPIO-D1 to 1

*********** Assembly listing Codewarrior version 4.0.2

orc #2,X:13e1

*********** Assembly listing Codewarrior version 5

movei #5089,R0
nop
move X:(R0),X0
orc #2,X0 ; <=== What happens
if here an interrupt occurs?
move X0,X:(R0)

The problem of this bug is not the additional memory nor the
additional execution time,
but the problem is if during the main program an interrupt function
occurs, which sets f.e. GPIO-D7.
In this case the main program resets the GPIO-D7 value, just set by
the interrupt function.
In this way you get software bugs, which are difficult to reproduce
and difficult to find!

This is only one bug of my Codewarrior bug collection (most of them
have not been solved in version 5). I have sent them to Metrowerks,
but only very few have been answered (some after half a year). I have
14 years experience in developing embedded software, but I have never
used a compiler with so many bugs as Codewarrior. We paid the full
price for Codewarrior version 4 and my supplier understood that I was
not willing to pay a cent for version 5, so I got the upgrade to
version 5 for free. However now I use version 4.0.2 for compilation
and version 5 for debugging

Kind regards, Wim de Haan Exendis B.V.
W.J. de Haan
P.O.box 56, 6710 BB Ede
Keesomstraat 4, 6716 AB Ede
The Netherlands.
Tel: +31- 318 - 676305