AnsweredAssumed Answered

Compiler/Optimisation error CW10.2 (Kinetis)

Question asked by Butcher on Dec 6, 2013
Latest reply on Dec 13, 2013 by Butcher

Hi All

 

The following code (simplified to a minimum from original case but simple to reproduce) fails from optimisation for size -O2 (is OK for -0-and -O1). If the code is simplified - eg. removing inner if () level, the problem no longer occurs.

Since the working project is almost complete and tested I can't upgated to CW10.5 (yet) but maybe someone would like to see whether it has been solved there (?)

 

#define NUMBER_OF_ANALOGUE_INPUTS 8

signed short diInput1[NUMBER_OF_ANALOGUE_INPUTS];

 

static const int ADC0channel[8] = {0,1,2,3,4,5,6,7}; // in reality the numbers may be mixed around

static const int ADC1channel[8] = {0,1,2,3,4,5,6,7};

 

void function(void)

{

static int iDinIndex = 0; // multiplexed input index (counts 0,1,2,3,4,5,6,7,8,9,10,11)

 

diInput1[ADC0channel[iDinIndex]] = (signed short)0x0080; // fixed ADC values

diInput1[ADC1channel[iDinIndex]] = (signed short)0x0080;

 

if (iDinIndex & 0x01) { // every even sample

register signed short sSample = diInput1[ADC0channel[iDinIndex]]; // ADC input sample

register iADC;

 

for (iADC = 0; iADC < 2; iADC++) { // for each ADC (2 digital channels)

fnDebugHex(sSample, (sizeof(sSample) | WITH_LEADIN | WITH_CR_LF));

usSample = diInput1[ADC1channel[iDinIndex]]; // ADC1 input sample (ADC1)

}

 

if (++iDinIndex >= 8) {

iDinIndex = 0;

}

}

else { // odd samples

++iDinIndex;

}

}

 

 

fnDebugHex() can be replaced by printf() and shows the following incorrect output (the function needs to eb called twice since it jumps the loop on every odd call) but can be called from any code in an operating project environment that can display the output.

Without the debug output the error can also be seen by stepping the code with debugger.


0xff80  <- incorrect

0x0080 <- correct

 

When the following is inserted before the debug output line it is then correct (2 x 0x0080).

if (iADC == 0) {

sSample = diInput1[ADC0channel[iDinIndex]];

}

 

That means that loading the value before the loop is bad but inside the loop is good.

 

The problem can be seen in the assembler code generated:

- inside the loop ldrsh r7,[r6,r3,lsl #0x1]    <- sign extends from a half-word (correct)

- before the loop ldrsb r0,[r6,r2,lsl #0x1]    <- this sign extends from a byte (incorrect)

 

Regards

 

Mark

 


Outcomes