As of February 2, 2026, the NXP MEMS Sensor products have been transferred to STMicroelectronics. For details on the transferred products, see this page. Please reach out to STMicroelectronics for further information.
All,
We are busily working to integrate Version 7.00 of the sensor fusion library into the Kinetis Expert (KEX) ecosystem. ETA is early August. I have attached here a preview copy of the user manual for that release. This is subject to the usual disclaimers: content subject to change, no liability, yada yada yada. There are a LOT of changes. These are documented ad nauseum in the user guide. I've also added a lot of our old blog content into the user guide, as I keep getting requests for them. Please take a look and give me your feedback.
FYI, Here is a sample main() for the new fusion, running on FreeRTOS:
/* FreeRTOS kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "timers.h"
#include "event_groups.h"
// KSDK and ISSDK Headers
#include "fsl_debug_console.h" // KSDK header file for the debug interface
#include "board.h" // KSDK header file to define board configuration
#include "pin_mux.h" // KSDK header file for pin mux initialization functions
#include "clock_config.h" // KSDK header file for clock configuration
#include "fsl_port.h" // KSDK header file for Port I/O control
#include "fsl_i2c.h" // KSDK header file for I2C interfaces
#include "Driver_I2C_SDK2.h" // ISSDK header file for CMSIS I2C Driver
#include "fxas21002.h" // register address and bit field definitions
#include "mpl3115.h" // register address and bit field definitions
#include "fxos8700.h" // register address and bit field definitions
// Sensor Fusion Headers
#include "sensor_fusion.h" // top level magCal and sensor fusion interfaces
#include "control.h" // Command/Streaming interface - application specific
#include "status.h" // Sta:tus indicator interface - application specific
#include "drivers.h" // NXP sensor drivers OR customer-supplied drivers
// Global data structures
SensorFusionGlobals sfg; ///< This is the primary sensor fusion data structure
ControlSubsystem controlSubsystem; ///< used for serial communications
StatusSubsystem statusSubsystem; ///< provides visual (usually LED) status indicator
PhysicalSensor sensors[3]; ///< This implementation uses three physical sensors
EventGroupHandle_t event_group = NULL;
static void read_task(void *pvParameters); // FreeRTOS Task definition
static void fusion_task(void *pvParameters); // FreeRTOS Task definition
/// This is a FreeRTOS (dual task) implementation of the NXP sensor fusion demo build.
int main(void)
{
ARM_DRIVER_I2C* I2Cdrv = &I2C_S_DRIVER_BLOCKING; // defined in the <shield>.h file
BOARD_InitPins(); // defined in pin_mux.c, initializes pkg pins
BOARD_BootClockRUN(); // defined in clock_config.c, initializes clocks
BOARD_InitDebugConsole(); // defined in board.c, initializes the OpenSDA port
I2Cdrv->Initialize(NULL); // Initialize the KSDK driver for the I2C port
I2Cdrv->Control(ARM_I2C_BUS_SPEED, ARM_I2C_BUS_SPEED_FAST); // Configure the I2C bus speed
initializeControlPort(&controlSubsystem); // configure pins and ports for the control sub-system
initializeStatusSubsystem(&statusSubsystem); // configure pins and ports for the status sub-system
initSensorFusionGlobals(&sfg, &statusSubsystem, &controlSubsystem); // Initialize sensor fusion structures
// "install" the sensors we will be using
sfg.installSensor(&sfg, &sensors[0], FXOS8700_I2C_ADDR, 1, (void*) I2Cdrv, FXOS8700_Init, FXOS8700_Read);
sfg.installSensor(&sfg, &sensors[1], FXAS21002_I2C_ADDR, 1, (void*) I2Cdrv, FXAS21002_Init, FXAS21002_Read);
sfg.installSensor(&sfg, &sensors[2], MPL3115_I2C_ADDR, 2, (void*) I2Cdrv, MPL3115_Init, MPL3115_Read);
sfg.initializeFusionEngine(&sfg); // This will initialize sensors and magnetic calibration
event_group = xEventGroupCreate();
xTaskCreate(read_task, "READ", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL);
xTaskCreate(fusion_task, "FUSION", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);
sfg.setStatus(&sfg, NORMAL); // If we got this far, let's set status state to NORMAL
vTaskStartScheduler(); // Start the RTOS scheduler
sfg.setStatus(&sfg, HARD_FAULT); // If we got this far, FreeRTOS does not have enough memory allocated
for (;;) ;
}
static void read_task(void *pvParameters)
{
uint16_t i=0; // general counter variable
portTickType lastWakeTime;
const portTickType frequency = 1; // tick counter runs at the read rate
lastWakeTime = xTaskGetTickCount();
while (1)
{
for (i=1; i<=OVERSAMPLE_RATE; i++) {
vTaskDelayUntil(&lastWakeTime, frequency);
sfg.readSensors(&sfg, i); // Reads sensors, applies HAL and does averaging (if applicable)
}
xEventGroupSetBits(event_group, B0);
}
}
static void fusion_task(void *pvParameters)
{
uint16_t i=0; // general counter variable
while (1)
{
xEventGroupWaitBits(event_group, /* The event group handle. */
B0, /* The bit pattern the event group is waiting for. */
pdTRUE, /* BIT_0 and BIT_4 will be cleared automatically. */
pdFALSE, /* Don't wait for both bits, either bit unblock task. */
portMAX_DELAY); /* Block indefinitely to wait for the condition to be met. */
sfg.conditionSensorReadings(&sfg); // magCal is run as part of this
sfg.runFusion(&sfg); // Run the actual fusion algorithms
sfg.applyPerturbation(&sfg); // apply debug perturbation (testing only)
sfg.loopcounter++; // The loop counter is used to "serialize" mag cal operations
i=i+1;
if (i>=4) { // Some status codes include a "blink" feature. This loop
i=0; // should cycle at least four times for that to operate correctly.
sfg.updateStatus(&sfg); // This is where pending status updates are made visible
}
sfg.queueStatus(&sfg, NORMAL); // assume NORMAL status for next pass through the loop
sfg.pControlSubsystem->stream(&sfg, sUARTOutputBuffer); // Send stream data to the Sensor Fusion Toolbox
}
}
/// \endcode