This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

"#pragma diag_suppress" fails to suppress error 1358 ("intrinsic _bic_SR_register_on_exit() only available within interrupt routines")

Other Parts Discussed in Thread: MSP430F5528

First, some context: we're compiling our application with CCS compiler version 4.2.1 for an MSP430F5528. I have also tested this with version 4.3.3 and see the same behavior.

Our application uses a lightweight scheduler to manage the power state of the hardware. Tasks request service from an interrupt context, and it's the scheduler's responsibility to exit low power mode if appropriate. By design, the scheduler will only attempt to exit low power mode from an interrupt context.

To manage our low power state, we use methods similar to the following:

#include <intrinsics.h>

static void schedulerSleep(void)
{
    _bis_SR_register(LPM3_bits);
    _no_operation();
}

static void schedulerWakeup(void)
{
    if (schedulerIsSleeping()) {
        _bic_SR_register_on_exit(LPM3_bits);
        _no_operation();
    }
}

Again, I should reiterate that our design guarantees that schedulerIsSleeping() returns true iff called from an interrupt context.

This code does not compile. It fails with the error:

error #1358: intrinsic (_bic_SR_register_on_exit) only available within interrupt routines

Through some trial-and-error engineering, we have found that the only way to avoid this compiler error is to include the _bic_SR_register_on_exit call within the ISR. (If wrapped in a #define, the code compiles, but wrapped in an inline function - even with the FUNC_ALWAYS_INLINE #pragma - compilation fails.)

According to "MSP430 Optimizing C/C++ Compiler v4.4 (Rev J.) - slau132j.pdf" Section 5.11.8, we should be able to suppress this error with:

#pragma diag_suppress=1358

However, even with this #pragma in place, compilation fails with the same error.

Given these results, I believe this is either a bug in the compiler's handling of this #pragma directive, or a bug in the intrinsics implementation of _bic_SR_register_on_exit (which should emit a warning, not an error).

  • At first; Calling a –normal- function ends always with a RET (return). Calling a ISR function ends always with a RETI (return from interrupt).

    RET takes only one cycle: pop and jump to address.
    RETI takes two cycles; 1th: Pop, and when necessary (the ‘_on_exit’) alter, the Status-register contents and save. 2nd: Pop and jump to address.

    The Compiler knows the function isn’t an interrupt call and it ends only with a single pop and can’t also change the status-register. Therefore an Error (incomplete code) and not a Warning while it will not work.
  • Simply put: this error is no diagnostic warning but a real error. So ‘diag suppress’ can’t suppress it. The on_exit intrinsics only work inside the very ISR, as they deal with the stack frame of this ISR and the stored status register data on stack.
    In a normal function, even if called form interrupt context, the required information for this operation is not available at compile-time (and could only provided with huge organizational overhead at runtime, if at all, and still leaving space for devastating failure).
    Instead, provide a return value from your function that tells the ISR to exit LPM or not. Maybe set a global (volatile) variable.

**Attention** This is a public forum