ISSDK  1.8
IoT Sensing Software Development Kit
main_freertos_agm02_power_cycling.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 /*! \file main_freertos_agm02_power_cycling.c
10  \brief FreeRTOS (two task) implementation of sensor fusion on FRDM-K64F/FRDM-FXS-AGM02 with smart power-cycling support.
11 
12  This file shows one recommended way to incorporate sensor fusion capabilities
13  into a FreeRTOS project AND adds intelligent power down of sensors when
14  the DUT is stationary.
15 */
16 
17 /* FreeRTOS kernel includes. */
18 #include "FreeRTOS.h"
19 #include "task.h"
20 #include "queue.h"
21 #include "timers.h"
22 #include "event_groups.h"
23 
24 // KSDK and ISSDK Headers
25 #include "fsl_debug_console.h" // KSDK header file for the debug interface
26 #include "FSL_SMC.H" // KDSK header file for the System Mode Controller Driver
27 #include "board.h" // KSDK header file to define board configuration
28 #include "pin_mux.h" // KSDK header file for pin mux initialization functions
29 #include "clock_config.h" // KSDK header file for clock configuration
30 #include "fsl_port.h" // KSDK header file for Port I/O control
31 #include "fsl_i2c.h" // KSDK header file for I2C interfaces
32 #include "register_io_i2c.h"
33 #include "fsl_i2c_cmsis.h"
34 #include "fsl_dspi_cmsis.h"
35 
36 // Sensor Fusion Headers
37 #include "sensor_fusion.h" // top level magCal and sensor fusion interfaces
38 #include "control.h" // Command/Streaming interface - application specific
39 #include "status.h" // Status indicator interface - application specific
40 #include "drivers.h" // NXP sensor drivers OR customer-supplied drivers
41 #include "fusion.h" // Need lower level function for power management
42 
45  .functionParam = NULL,
46  .idleFunction = NULL
47 };
48 
49 // Global data structures
50 SensorFusionGlobals sfg; ///< This is the primary sensor fusion data structure
51 ControlSubsystem controlSubsystem; ///< used for serial communications
52 StatusSubsystem statusSubsystem; ///< provides visual (usually LED) status indicator
53 struct PhysicalSensor sensors[3]; ///< This implementation uses three physical sensors
54 EventGroupHandle_t event_group = NULL;
56 {
57  // MCU low power modes are not debugged at this point in time
58  //volatile smc_power_state_t state;
59  //SMC_SetPowerModeStop(SMC, kSMC_PartialStop );
60  //state = SMC_GetPowerModeState(SMC);
61  //asm("wfi");
62 }
64 {
65  sfg.queueStatus(&sfg, NORMAL); // assume NORMAL status for next pass through the loop
66 }
67 
68 static void read_task(void *pvParameters);
69 static void fusion_task(void *pvParameters);
70 bool motionCheck( float sample[3],
71  float baseline[3],
72  float tolerance,
73  uint32_t winLength,
74  uint32_t *count); // defined in motionCheck.c
75 /// This is a FreeRTOS (dual task) implementation of the NXP sensor fusion demo build.
76 int main(void)
77 {
78  ARM_DRIVER_I2C* I2Cdrv = &I2C_S_DRIVER; // defined in the <shield>.h file
79  BOARD_InitPins(); // defined in pin_mux.c, initializes pkg pins
80  BOARD_BootClockRUN(); // defined in clock_config.c, initializes clocks
81  BOARD_InitDebugConsole(); // defined in board.c, initializes the OpenSDA port
82 
83  I2Cdrv->Initialize(I2C_S_SIGNAL_EVENT); // Initialize the KSDK driver for the I2C port
84  I2Cdrv->PowerControl(ARM_POWER_FULL); // Set the I2C Power mode.
85  I2Cdrv->Control(ARM_I2C_BUS_SPEED, ARM_I2C_BUS_SPEED_FAST); // Configure the I2C bus speed
86 
87  initializeControlPort(&controlSubsystem); // configure pins and ports for the control sub-system
88  initializeStatusSubsystem(&statusSubsystem); // configure pins and ports for the status sub-system
89  initSensorFusionGlobals(&sfg, &statusSubsystem, &controlSubsystem); // Initialize sensor fusion structures
90  // "install" the sensors we will be using
91  sfg.installSensor(&sfg, &sensors[0], FXLS8952C_I2C_ADDR, 1, (void*) I2Cdrv, &i2cBusInfo, FXLS8952_Init, FXLS8952_Read);
92  sfg.installSensor(&sfg, &sensors[1], FXAS21002_I2C_ADDR, 1, (void*) I2Cdrv, &i2cBusInfo, FXAS21002_Init, FXAS21002_Read);
93  sfg.installSensor(&sfg, &sensors[2], MAG3110_I2C_ADDR, 1, (void*) I2Cdrv, &i2cBusInfo, MAG3110_Init, MAG3110_Read);
94  sfg.initializeFusionEngine(&sfg); // This will initialize sensors and magnetic calibration
95 
96  event_group = xEventGroupCreate();
97  xTaskCreate(read_task, "READ", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL);
98  xTaskCreate(fusion_task, "FUSION", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);
99 
100  sfg.setStatus(&sfg, NORMAL); // If we got this far, let's set status state to NORMAL
101  vTaskStartScheduler(); // Start the RTOS scheduler
102  sfg.setStatus(&sfg, HARD_FAULT); // If we got this far, FreeRTOS does not have enough memory allocated
103  for (;;) ;
104 }
105 
106 static void read_task(void *pvParameters)
107 {
108  uint16_t i=0; // general counter variable
109  portTickType lastWakeTime;
110  const portTickType frequency = 1; // tick counter runs at the read rate
111  lastWakeTime = xTaskGetTickCount();
112  while (1)
113  {
114  for (i=1; i<=OVERSAMPLE_RATE; i++) {
115  vTaskDelayUntil(&lastWakeTime, frequency);
116  sfg.readSensors(&sfg, i); // Reads sensors, applies HAL and does averaging (if applicable)
117  }
118  xEventGroupSetBits(event_group, B0);
119  }
120 }
121 
122 static void fusion_task(void *pvParameters)
123 {
124  uint16_t i=0; // general counter variable
125  float motion_baseline[3] = {0.0, 0.0, 0.0};
126  bool stationary;
127  static bool lastStationary;
128  uint32_t stationaryCount = 0;
129  while (1)
130  {
131  xEventGroupWaitBits(event_group, /* The event group handle. */
132  B0, /* The bit pattern the event group is waiting for. */
133  pdTRUE, /* BIT_0 and BIT_4 will be cleared automatically. */
134  pdFALSE, /* Don't wait for both bits, either bit unblock task. */
135  portMAX_DELAY); /* Block indefinitely to wait for the condition to be met. */
136 
137  // sfg.runFusion(&sfg); // Run the actual fusion algorithms
138  // Rather than call runFusion directly, this example invokes the lower level
139  // calls here. This allows us to check to see if the board is stationary,
140  // and if so, transition to a lower power state.
141  sfg.conditionSensorReadings(&sfg); // magCal is run as part of this
142  stationary = motionCheck(
143  sfg.Accel.fGc, // calibrated accelerometer reading
144  motion_baseline, // baseline to check new values against
145  0.01, // changes less than this are ignored
146  120, // three seconds at 40Hz rate
147  &stationaryCount);
148  if (stationary) {
149  if (!lastStationary) { // suspend some operations
150  FXAS21002_Idle(&(sensors[1]), &sfg);
151  MAG3110_Idle(&(sensors[2]), &sfg);
152  }
153  sfg.clearFIFOs(&sfg);
154  } else {
155  if (lastStationary) { // restart operations
156  FXAS21002_Init(&(sensors[1]), &sfg);
157  MAG3110_Init(&(sensors[2]), &sfg);
158  }
159  // fuse the sensor data
160  sfg.runFusion(&sfg);
161  }
162 
163  sfg.applyPerturbation(&sfg); // apply debug perturbation (testing only)
164 
165  sfg.loopcounter++; // The loop counter is used to "serialize" mag cal operations
166  i=i+1;
167  if (i>=4) { // Some status codes include a "blink" feature. This loop
168  i=0; // should cycle at least four times for that to operate correctly.
169  sfg.updateStatus(&sfg); // This is where pending status updates are made visible
170  }
171  if (stationary) {
172  sfg.queueStatus(&sfg, LOWPOWER); // assume LOWPOWER status for next pass through the loop
173  } else {
174  sfg.queueStatus(&sfg, NORMAL); // assume NORMAL status for next pass through the loop
175  }
176  sfg.pControlSubsystem->stream(&sfg, sUARTOutputBuffer); // Send stream data to the Sensor Fusion Toolbox
177  lastStationary = stationary;
178  }
179 }
180 
181 /// \endcode
ControlSubsystem controlSubsystem
used for serial communications
#define B0
Definition: sensor_fusion.h:72
readSensors_t * readSensors
read all physical sensors
This structure defines the device specific info required by register I/O.
Definition: sensor_drv.h:102
initializeFusionEngine_t * initializeFusionEngine
set sensor fusion structures to initial values
#define OVERSAMPLE_RATE
Provides function prototypes for driver level interfaces.
#define MAG3110_I2C_ADDR
Operation is Nominal.
An instance of PhysicalSensor structure type should be allocated for each physical sensors (combo dev...
setStatus_t * queueStatus
queue status change for next regular interval
int8_t MAG3110_Read(struct PhysicalSensor *sensor, SensorFusionGlobals *sfg)
int8_t FXLS8952_Read(struct PhysicalSensor *sensor, SensorFusionGlobals *sfg)
int8_t MAG3110_Init(struct PhysicalSensor *sensor, SensorFusionGlobals *sfg)
int main(void)
This is a FreeRTOS (dual task) implementation of the NXP sensor fusion demo build.
Application-specific status subsystem.
conditionSensorReadings_t * conditionSensorReadings
preprocessing step for sensor fusion
Defines control sub-system.
The top level fusion structure.
void initSensorFusionGlobals(SensorFusionGlobals *sfg, StatusSubsystem *pStatusSubsystem, ControlSubsystem *pControlSubsystem)
utility function to insert default values in the top level structure
Definition: sensor_fusion.c:51
struct PhysicalSensor sensors[3]
This implementation uses three physical sensors.
int8_t FXAS21002_Init(struct PhysicalSensor *sensor, SensorFusionGlobals *sfg)
#define I2C_S_SIGNAL_EVENT
Definition: issdk_hal.h:34
The register_io_i2c.h file declares low-level interface functions for reading and writing sensor regi...
#define I2C_S_DRIVER
Definition: issdk_hal.h:33
he ControlSubsystem encapsulates command and data streaming functions.
Definition: control.h:42
StatusSubsystem statusSubsystem
provides visual (usually LED) status indicator
#define BOARD_BootClockRUN
Definition: clock_config.h:19
runFusion_t * runFusion
run the fusion routines
#define FXAS21002_I2C_ADDR
Non-recoverable FAULT = something went very wrong.
registerDeviceInfo_t i2cBusInfo
The sensor_fusion.h file implements the top level programming interface.
SensorFusionGlobals sfg
This is the primary sensor fusion data structure.
setStatus_t * setStatus
change status indicator immediately
int8_t FXAS21002_Idle(struct PhysicalSensor *sensor, SensorFusionGlobals *sfg)
ARM_DRIVER_I2C * I2Cdrv
uint8_t sUARTOutputBuffer[256]
main output buffer defined in control.c
Definition: control.c:37
updateStatus_t * updateStatus
status=next status
bool motionCheck(float sample[3], float baseline[3], float tolerance, uint32_t winLength, uint32_t *count)
Definition: motionCheck.c:23
installSensor_t * installSensor
function for installing a new sensor into t
struct ControlSubsystem * pControlSubsystem
int8_t FXLS8952_Init(struct PhysicalSensor *sensor, SensorFusionGlobals *sfg)
EventGroupHandle_t event_group
void vApplicationTickHook(void)
int8_t initializeControlPort(ControlSubsystem *pComm)
Initialize the control subsystem and all related hardware.
Definition: control.c:160
Running in reduced power mode.
void vApplicationIdleHook(void)
#define I2C_S_DEVICE_INDEX
Definition: issdk_hal.h:35
clearFIFOs_t * clearFIFOs
clear sensor FIFOs
int8_t FXAS21002_Read(struct PhysicalSensor *sensor, SensorFusionGlobals *sfg)
#define FXLS8952C_I2C_ADDR
void BOARD_InitDebugConsole(void)
Definition: board.c:15
void initializeStatusSubsystem(StatusSubsystem *pStatus)
Definition: status.c:165
int8_t MAG3110_Idle(struct PhysicalSensor *sensor, SensorFusionGlobals *sfg)
void BOARD_InitPins(void)
Configures pin routing and optionally pin electrical features.
Definition: pin_mux.c:47
streamData_t * stream
function to create packets for serial stream
Definition: control.h:51
Lower level sensor fusion interface.
applyPerturbation_t * applyPerturbation
apply step function for testing purposes
StatusSubsystem() provides an object-like interface for communicating status to the user...
Definition: status.h:22
int32_t loopcounter
counter incrementing each iteration of sensor fusion (typically 25Hz)