Intrinsics Module

Note

The Intrinsics Module contains wrappers and abstractions for compiler intrinsics. Special functions that are built into the compiler itself and
are platform dependent.
Doxygen:

Features

Preventing variables from begin optimized away

In many debug scenarios, the developer wants to inspect variables, e.g the returned value from a function or a variable used inside a function, to figure out what went wrong. The compiler often optimizes these variables away though if it notices that they are not needed. This happens especially often when a value just gets stored in a variable for debug inspection but is not used anywhere else in the program.

To avoid this, the LEGUAN_DO_NOT_OPTIMIZE makro may be used. It can confuse the compiler about whether the variable actually hasn’t been used anywhere to prevent it from optimizing it away. This of course makes the compiled machine code less efficient but makes debugging a lot easier.

result_t result = function_that_may_fail();

LEGUAN_DO_NOT_OPTIMIZE(result);

// result isn't being used anywhere else in the code
LEGUAN_DO_NOT_OPTIMIZE(x)

Confuses the compiler to prevent it from optimizing away a variable.

Parameters
  • variable – to prevent optimization of

Unused parameters

Some libraries, e.g FreeRTOS, require the developer to implement callback functions with a fixed signature. Often the developer won’t need all parameters that need to be added for the function to have to correct signature. However, not using them will lead to a warning about unused variables.

To explicitly turn this warning off, the LEGUAN_UNUSED makro can be used.

void vTaskMain(void *pvUserData) {
    // User data is NULL and never used in the task
    LEGUAN_UNUSED(pvUserData);

    // ...
}
LEGUAN_UNUSED(x)

Marks a variable as used, even if it wasn’t.

Endian switching

Sensors and other external peripherals that are connected to e.g the SPI or I2C interface often require or report values that are represented in Big Endian. However, the ARM MCU on the Leguan Board uses Little Endian to store all variables.

To overcome this, byte swapping the values is required. The LEGUAN_BYTE_SWAP makro can swap any signed, unsigned and floating point value.

uint16_t pressure = get_big_endian_pressure_value(); // Pressure currently is 1050 hPa, sensor reports 0x1A04 (6660 in little endian)

uint16_t correct_pressure = LEGUAN_BYTE_SWAP(pressure); // Byte swap pressure to get 0x041A (1050 in little endian)
LEGUAN_BYTE_SWAP(x)

Changes endianess of a integer or floating point.

Declare unreachability

To avoid warnings and help the compiler optimize your code better, it’s sometimes useful to explicitly tell it that a certain condition will never occur.

uint16_t coin_value = get_inserted_coin_value(); // Can only ever return 0, 10, 20, 50, 100, 200 and 500 rp.

switch (coin_value) {
    case 0:
        handle_error();
        break;
    case 10:
    case 20:
    case 50:
        handle_small_coin();
        break;
    case 100:
    case 200:
    case 500:
        handle_big_coin();
        break;
    default:
        // There aren't any other coins that could be inserted
        LEGUAN_Unreachable();
}