Possible bug in LPCXpresso IDE - (Optimize for Size) and (ISR) and (INLINE code)

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Possible bug in LPCXpresso IDE - (Optimize for Size) and (ISR) and (INLINE code)

1,150 Views
billmather
Contributor I

Hi,

I have a project using CMSISv2p10_LPC13Uxx,FreeRTOS v8.2.2 and my code in an LPC1347.

The code compiles correctly and operates correctly in DEBUG mode, where optimization is default none (-O0).

In RELEASE, with default optimization - Optimize for size (-Os), the code fails, in a timer interrupt handler.

Tested: Setting the optimization for the ISR to either none (-O0) or most (-O3) results in correct program operation, compiled with both 7.5.0_254 on WinXP (the latest which works on WinXP) and 8.2.0_647 on Ubuntu32 14

The code is an ISR with volatile variables, one of which is cleared in another ISR (safe for race conditions, so no issue there), and it also contains a call to an INLINE function.

The purpose of the code is to set a SIGNAL, start a timer which when it times out, starts another operation. When the operation is complete, the timer is restarted, and when it times out, the SIGNAL is de-asserted, ie the SIGNAL wraps the other operation.

I have not investigated the reason for the failure - I have accepted that changing the optimization for the function removes the problem.

The code which performs incorrectly is attached, updated with optimize pragma, and with variable names changed:

volatile bool pending = false;

volatile bool isStartWait = false;

#define SIGNAL_ON()                             (LPC_GPIO->SET[0] = (1<<17))

#define SIGNAL_OFF()                            (LPC_GPIO->CLR[0] = (1<<17))

//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------

#pragma GCC push_options

#pragma GCC optimize ("O3")

void CT16B0_IRQHandler(void)

{

    if (isStartWait)

    {

        pending = true;

        isStartWait = false;

        NVIC_SetPendingIRQ(USART_IRQn);

    }

    else

    {

        LPC_CT16B0->TCR = TCR_CRST | TCR_CEN_DISABLE;   // stop timer, force output low

        SIGNAL_OFF();                                   // and turn signal off

    }

    LPC_CT16B0->IR = 0xff;                              // clear Int Flags set by transfer

}

#pragma GCC pop_options

Labels (1)
0 Kudos
4 Replies

624 Views
lpcxpresso_supp
NXP Employee
NXP Employee

So any details as to what the form of failure you see is when building with -Os?

And you say you don't see the issue at -O0 or -O3. But do you see it at -O1 or -O2?

And just to confirm, you see the same problem compiling with LPCXpresso IDE v8.2.0 as you did with v7.5.0 ?

Aside 1: Note that it is possible that there is an issue in the files insider the CMSISv2p10_LPC13Uxx project. There is a later version of the CMSIS and MCU headers available in the CMSIS_CORE_LPC13Uxx project. And of course all of this code was superseded by LPCOpen too.

Aside 2 : Probably not relevant in this case - but some background information on optimisation that might be useful in the future can be found in the FAQ : Compiler Optimization

Regards,

LPCXpresso Support

0 Kudos

624 Views
billmather
Contributor I

I confirm that testing included running the code generated by both v7.5.0 and v8.2.0, using a project exported as archive (our internal source version is g5p.a), with binaries put onto LPC1347 using USB MSC programming.

I have re-run the code compiled with v8.2.0 on Ubuntu. Re-checking, the code still fails on -Os, but does not fail when compiled with -O1, -O2 or -O3, where the code other than this function is compiled -Os.

Inserting the inline code from CMSIS directly into the function does not change the errant behaviour.

There are NO errors reported when compiling under either compiler at -Wall. At -Wextra, there are 48 warnings, consisting of:

  'static' is not at beginning of declaration [-Wold-style-declaration]

  comparison between signed and unsigned integer expressions [-Wsign-compare]

  suggest braces around empty body in an 'else' statement [-Wempty-body]  (no change when braces added)

  unused parameter 'xxx' [-Wunused-parameter]

plus 2 Infos in macros (in v8.2.0).

Noted that under v7.5.0, compiler acts on pragma optimize to give working code but gives warning (v7.5.0 & v8.2.0 both work fine and give no errors with __attribute__((optimize("O3"))) in the line before the function). Binary size Debug 41,416 bytes Release (original -Os Release 30,980 bytes, revised -Os/-O3 Release 30,496 bytes)

The Form of Failure.

The function is performing part of a task. The task is to manually turn the RTS SIGNAL on, and start a timer. When the timer fires its ISR, the UART is stuffed with characters to send (from a circular send buffer). When both the send buffer and the UART become empty, the timer is restarted (from inside the UART ISR), and when the timer fires its USR, the RTS SIGNAL is turned off. This code has passed some months of system test, so is presumed stable and valid. Code does handle case of a second transmission being triggered before first is complete.


The physical form of failure is that DATA sent through the UART to a DE controlled RS485 driver chip is not transmitted. Specifically, the DE line, instead of getting a pulse of length "front-porch-time" + "time to send 'n' chars" + "back-porch time", gets instead two very short pulses, one at the "front-porch-time", and one at the "back-porch-time". I did not investigate actual length or relationship of the two short pulses to the UART data to help pin down the actual code which is failing.

The CMSIS code has been used on other projects, and was therefore the choice of code base to use, and LPCOpen didn't seem as attractive at the time.

0 Kudos

624 Views
lpcxpresso_supp
NXP Employee
NXP Employee

I've spent some time looking at the disassembled object of the code you supplied, built both -Os and -O3, and can't see anything obviously wrong in the -Os output. All the same memory accesses to peripheral register and volatile variables are made in the same order, although the writes are more back to back in the -O3 output.

Can you confirm the actually build options being used to compile the file in your system as extracted from the build log (The Build Console  ) ?

And you mention uploading your code using USB MSC. I know there will be limitations due to the real time nature of your interrupts, but have you tried debugging at all?

As I can't spot anything in the code, I can't help feeling that you might be seeing some subtle timing issue in your logic, which the changes in the way the -Os code is structured just make it more likely to occur.  Or maybe an interrupt priority setting somewhere?

Regards,

LPCXpresso Support

0 Kudos

624 Views
billmather
Contributor I

I will go through and check all my code and test using debugger on -Os compilation and report back.
Development testbed uses LPCXpresso LPC1347, and the testbed allows probing.

0 Kudos