1 /*
2 * Copyright 2019-2021 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 /**
9 * @file fxos8700_freemaster_demo.c
10 * @brief The fxos8700_freemaster.c file implements FreeMASTER demo using the ISSDK
11 * FXOS8700 sensor driver example demonstration with interrupt mode.
12 */
13
14 /* SDK Includes */
15 #include "pin_mux.h"
16 #include "clock_config.h"
17 #include "board.h"
18 #include "fsl_debug_console.h"
19 #include "math.h"
20 #include "fsl_uart.h"
21 #include "fsl_common.h"
22 #include "freemaster.h"
23 #include "freemaster_serial_uart.h"
24
25 /* CMSIS Includes */
26 #include "Driver_I2C.h"
27
28 /* ISSDK Includes */
29 #include "issdk_hal.h"
30 #include "gpio_driver.h"
31 #include "fxos8700_drv.h"
32
33 /*******************************************************************************
34 * Macro Definitions
35 ******************************************************************************/
36
37 #define FXOS8700_NUM_REGISTERS (FXOS8700_A_FFMT_THS_Z_LSB + 1)
38 #define FF_A_FFMT_THS (0x08) /* FreeFall Threshold Value. */
39 #define A_FFMT_COUNT (0x18) /* Freefall/motion debounce count value. */
40 #define PL_COUNT (0x15) /* Pulse debounce count value. */
41 #define ASLP_COUNTER (0x07) /* Auto Sleep after ~5s. */
42 #define ACCEL_2G_SENS (0.000244) /* Sensitivity factor for 2G FS */
43 #define ACCEL_4G_SENS (0.000488) /* Sensitivity factor for 4G FS */
44 #define ACCEL_8G_SENS (0.000976) /* Sensitivity factor for 8G FS */
45 #define N (500U) /* Number of samples used to measure offset/noise */
46 #define RAW_ACCELMAG_DATA_SIZE (12U) /* Accel + Mag Data Size */
47 #define MAX8BITSTORAGE (255U)
48
49 /*******************************************************************************
50 * Constants
51 ******************************************************************************/
52 /*!
53 * @brief Defines the register write list to configure FXOS8700 in Hybrid mode.
54 */
55 const registerwritelist_t fxos8700_Config_Hybrid[] = {
56 /*! Clear F_SETUP. */
57 {FXOS8700_F_SETUP, 0x00, 0x00},
58 /*! Set FS 2G Mode. */
59 {FXOS8700_XYZ_DATA_CFG, FXOS8700_XYZ_DATA_CFG_FS_2G_0P244, FXOS8700_XYZ_DATA_CFG_FS_MASK},
60 /*! Configure the FXOS8700 to 100Hz sampling rate. */
61 {FXOS8700_CTRL_REG1, FXOS8700_CTRL_REG1_DR_HYBRID_100_HZ, FXOS8700_CTRL_REG1_DR_MASK},
62 /*! Configure the FXOS8700 to Set High Resolution Mode. */
63 {FXOS8700_CTRL_REG2, FXOS8700_CTRL_REG2_MODS_HIGH_RES, FXOS8700_CTRL_REG2_MODS_MASK},
64 {FXOS8700_CTRL_REG3, FXOS8700_CTRL_REG3_IPOL_ACTIVE_HIGH | FXOS8700_CTRL_REG3_PP_OD_PUSH_PULL,
65 FXOS8700_CTRL_REG3_IPOL_MASK | FXOS8700_CTRL_REG3_PP_OD_MASK}, /*! Active High, Push-Pull */
66 {FXOS8700_CTRL_REG4, FXOS8700_CTRL_REG4_INT_EN_DRDY_EN,FXOS8700_CTRL_REG4_INT_EN_DRDY_MASK}, /*! Data Ready Event. */
67 {FXOS8700_CTRL_REG5, FXOS8700_CTRL_REG5_INT_CFG_DRDY_INT2, FXOS8700_CTRL_REG5_INT_CFG_DRDY_MASK}, /*! INT2 Pin */
68 {FXOS8700_M_CTRL_REG1, FXOS8700_M_CTRL_REG1_M_ACAL_DISABLE | FXOS8700_M_CTRL_REG1_M_HMS_HYBRID_MODE | FXOS8700_M_CTRL_REG1_M_OS_OSR0,
69 FXOS8700_M_CTRL_REG1_M_ACAL_MASK | FXOS8700_M_CTRL_REG1_M_HMS_MASK | FXOS8700_M_CTRL_REG1_M_OS_MASK}, /*! Enable the Hybrid Mode. */
70 {FXOS8700_M_CTRL_REG2, FXOS8700_M_CTRL_REG2_M_AUTOINC_HYBRID_MODE, FXOS8700_M_CTRL_REG2_M_AUTOINC_MASK}, /*! Enable the Data read with Hybrid Mode. */
71 {FXOS8700_CTRL_REG5,0x7E,0x00},
72 {FXOS8700_CTRL_REG4,255,0x00},
73
74 /*! Landscape-Portrait registers configurations */
75 {FXOS8700_PL_CFG,FXOS8700_PL_CFG_DBCNTM_CLEAR_MODE ,FXOS8700_PL_CFG_DBCNTM_MASK},
76 {FXOS8700_PL_CFG,FXOS8700_PL_CFG_PL_EN_ENABLE ,FXOS8700_PL_CFG_PL_EN_MASK },
77 /*! PL count set to (64 * 2.5ms) = 160ms */
78 {FXOS8700_PL_COUNT, 0x40, 0x00},
79 /*! Z-lock angle threshold set to ~28deg */
80 {FXOS8700_PL_BF_ZCOMP,4 ,FXOS8700_PL_BF_ZCOMP_ZLOCK_MASK},
81 /*! Back/front trip angle threshold set to ~44deg */
82 {FXOS8700_PL_BF_ZCOMP,2 ,FXOS8700_PL_BF_ZCOMP_BKFR_MASK},
83 /*! PL_THS set to 0x10=> 45deg threshold angle, HYS set to 0b100=> LtoP trip angle 59deg and PtoL trip angle 31deg*/
84 {FXOS8700_PL_THS_REG,132,0x00},
85
86 /*! Freefall detection registers configurations */
87 /*! Configure FreeFall debounce counter to 60msec */
88 {FXOS8700_A_FFMT_COUNT, A_FFMT_COUNT, 0}, /* Debounce Counter */
89 /*! Configure FreeFall detection threshold to 0.5g */
90 {FXOS8700_A_FFMT_THS, FF_A_FFMT_THS | FXOS8700_A_FFMT_THS_DBCNTM_MASK,
91 FXOS8700_A_FFMT_THS_THS_MASK | FXOS8700_A_FFMT_THS_DBCNTM_MASK}, /* Threshold */
92 /*! Configure sensor to detect freefall, raise event on X, Y, Z axes */
93 {FXOS8700_A_FFMT_CFG,
94 FXOS8700_A_FFMT_CFG_OAE_FREEFALL | FXOS8700_A_FFMT_CFG_ZEFE_RAISE_EVENT |
95 FXOS8700_A_FFMT_CFG_YEFE_RAISE_EVENT | FXOS8700_A_FFMT_CFG_XEFE_RAISE_EVENT,
96 FXOS8700_A_FFMT_CFG_OAE_MASK | FXOS8700_A_FFMT_CFG_ZEFE_MASK |
97 FXOS8700_A_FFMT_CFG_YEFE_MASK | FXOS8700_A_FFMT_CFG_XEFE_MASK},
98 {FXOS8700_CTRL_REG4, FXOS8700_CTRL_REG4_INT_EN_FFMT_EN, FXOS8700_CTRL_REG4_INT_EN_FFMT_MASK},
99
100 /*! Pulse detection registers configurations */
101 /*! Configure to raise event flag on detection of single-pulse event (spefe) on X, Y & Z axes*/
102 {FXOS8700_PULSE_CFG,21,0x00},
103 /*! Configure Pulse Time Limit to 50msec */
104 {FXOS8700_PULSE_TMLT,80,0x00},
105 /*! Configure pulse latency to 300msec */
106 {FXOS8700_PULSE_LTCY,240,0x00},
107 /*! Configure Pulse detection threshold for X, Y, Z axes */
108 {FXOS8700_PULSE_THSX,55,0x00},
109 {FXOS8700_PULSE_THSY,55,0x00},
110 {FXOS8700_PULSE_THSZ,82,0x00},
111
112 /*! VECM change detection configurations */
113 { FXOS8700_A_VECM_CNT,15,0x00},
114 /*! Configure VECM to enable VECM ELE (0x40) and VECM EN (0x08)*/
115 { FXOS8700_A_VECM_CFG,72,0x00},
116 /*! Set VECM THS to ~0.5g; THS = 0x788=>1928 (=0.47g in 2g mode) */
117 { FXOS8700_A_VECM_THS_LSB,88,0x00},
118 { FXOS8700_A_VECM_THS_MSB,1, FXOS8700_A_VECM_THS_MSB_A_VBECM_DBCNTM_MASK },
119 { FXOS8700_A_VECM_THS_MSB,27, FXOS8700_A_VECM_THS_MSB_A_VBECM_THS_MASK },
120
121 __END_WRITE_DATA__};
122
123 /*!
124 * @brief Defines the register read list to read the Data Ready Status.
125 */
126 const registerreadlist_t cFXOS8700_whoami[] = {
127 {.readFrom = FXOS8700_WHO_AM_I, .numBytes = 1}, __END_READ_DATA__};
128 /*!
129 * @brief Defines the register read list to read the Interrupt Source.
130 */
131 const registerreadlist_t cFXOS8700_int_src[] = {
132 {.readFrom = FXOS8700_INT_SOURCE, .numBytes = 1}, __END_READ_DATA__};
133 /*!
134 * @brief Defines the register read list to read the FullScale range.
135 */
136 const registerreadlist_t cFXOS8700_fs_src[] = {
137 {.readFrom = FXOS8700_XYZ_DATA_CFG, .numBytes = 1}, __END_READ_DATA__};
138
139 /*!
140 * @brief Defines the register read list to read all-registers.
141 */
142 const registerreadlist_t FXOS8700_ALL_REG_READ[] = {{.readFrom = FXOS8700_STATUS, .numBytes = FXOS8700_NUM_REGISTERS},
143 __END_READ_DATA__};
144 /*!
145 * @brief Defines the register read list to read FFMT Source.
146 */
147 const registerreadlist_t cFXOS8700_ffmt_src[] = {
148 {.readFrom = FXOS8700_A_FFMT_SRC , .numBytes = 1}, __END_READ_DATA__};
149 /*!
150 * @brief Defines the register read list to read the PL Status.
151 */
152 const registerreadlist_t cFXOS8700_pl_status[] = {
153 {.readFrom = FXOS8700_PL_STATUS, .numBytes = 1}, __END_READ_DATA__};
154
155 /*!
156 * @brief This structure defines the fxos8700 all registers metadata.
157 */
158 typedef struct
159 {
160 uint8_t offset;
161 uint8_t value;
162 uint8_t trigger;
163 uint8_t read_offset;
164 uint8_t read_value;
165 uint8_t read_trigger;
166 uint8_t readall_value[FXOS8700_NUM_REGISTERS];
167 uint8_t readall_size;
168 uint8_t readall_trigger;
169 uint8_t toggle;
170 uint8_t trigger_accel_offnoise;
171 uint8_t trigger_mag_offnoise;
172 uint8_t fs_value;
173 uint8_t mods_value;
174 uint16_t freefall_cntr;
175 uint16_t tapdetect_cntr;
176 uint16_t orient_cntr;
177 uint16_t vecmchange_cntr;
178 uint8_t reg_addr[FXOS8700_NUM_REGISTERS];
179 uint8_t dataready_cntr;
180 float accel[3];
181 float mag[3];
182 } fxos8700_allregs_t;
183
184 /*!
185 * @brief This structure defines the fxos8700 offset and noise calculation parameters.
186 */
187 typedef struct
188 {
189 float offx;
190 float offy;
191 float offz;
192 float rmsx;
193 float rmsy;
194 float rmsz;
195 float mag_off[3];
196 float mag_rms[3];
197 uint8_t complete_accel_offnoise;
198 uint8_t complete_mag_offnoise;
199 } fxos8700_offset_noise_t;
200
201 /*!
202 * @brief Defines host operation types.
203 */
204 typedef enum fxos8700_operation_type
205 {
206 FXOS8700_REG_WRITE = 1U,
207 FXOS8700_REG_READ = 2U,
208 FXOS8700_ALLREG_READ = 3U,
209 FXOS8700_ACCEL_CONFIG_END
210
211 } fxos8700_operation_type_t;
212
213
214 /*******************************************************************************
215 * Globals
216 ******************************************************************************/
217
218 fxos8700_accelmagdata_t rawData;
219 fxos8700_allregs_t registers;
220 fxos8700_offset_noise_t offnoise_data;
221 uint8_t prev_toggle = 1;
222 volatile bool bFxos8700DataReady = false;
223
224 static FMSTR_U8 recBuffer[1024*10];
225 FMSTR_REC_BUFF recBuffCfg;
226 FMSTR_REC_VAR recVar;
227 FMSTR_REC_CFG recCfg;
228
229 /*******************************************************************************
230 * Local functions
231 ******************************************************************************/
232 /*! @brief Function to initialize target communication to FreeMASTER host.
233 * @details This function initializes FreeMASTER UART communication.
234 * @param[in] void.
235 * @return void.
236 */
237 static void init_freemaster_uart(void);
238 /*! @brief ISR for FXOS8700 data ready event.
239 * @details This function implements ISR for FXOS8700 DRDY event.
240 * @param[in] void *.
241 * @return void.
242 */
243 void fxos8700_isr_callback(void *pUserData);
244 /*! @brief Function to apply FXOS8700 register write operation.
245 * @details This function apply FXOS8700 register write based on write trigger from host.
246 * @param[in] fxos8700_i2c_sensorhandle_t FXOS8700drv, FXOS8700 sensor I2C handle.
247 * @param[in] uint8_t offset, the address of the register to start writing from.
248 * @param[in] uint8_t value, value to write on register offset.
249 * @return returns the status of the operation.
250 */
251 int32_t apply_register_write(fxos8700_i2c_sensorhandle_t FXOS8700drv, uint8_t offset, uint8_t value);
252 /*! @brief Function to apply FXOS8700 register read operation.
253 * @details This function apply FXOS8700 register read based on read trigger from host.
254 * @param[in] fxos8700_i2c_sensorhandle_t FXOS8700drv, FXOS8700 sensor I2C handle.
255 * @param[in] uint8_t offset, the address of the register to read from.
256 * @param[in/out] uint8_t *value, pointer to output buffer.
257 * @return returns the status of the operation.
258 */
259 int32_t apply_register_read(fxos8700_i2c_sensorhandle_t FXOS8700drv, uint8_t offset, uint8_t *value);
260 /*! @brief Function to apply FXOS8700 register read-all operation.
261 * @details This function apply FXOS8700 all-registers read based on read-all trigger from host.
262 * @param[in] fxos8700_i2c_sensorhandle_t FXOS8700drv, FXOS8700 sensor I2C handle.
263 * @return returns the status of the operation.
264 */
265 int32_t apply_register_readall(fxos8700_i2c_sensorhandle_t FXOS8700drv);
266 /*! @brief Function to update dropdown selection.
267 * @details This function updates the dropdown selection values in real-time based on read/write/read-all triggers.
268 * @param[in/out] fxos8700_allregs_t *registers, pointer to FXOS8700 all-registers metadata.
269 * @param[in] uint8_t caller, called from which operation type.
270 * @return returns the status of the operation.
271 */
272 int32_t update_dropdown_selection( fxos8700_allregs_t *registers, uint8_t caller);
273 /*! @brief Function to initialize offset noise measurement.
274 * @details This function initializes offset noise measurement metadata.
275 * @param[in/out] fxos8700_offset_noise_t *offnoiseptr, pointer to FXOS8700 offset noise metadata.
276 * @return void.
277 */
278 void offset_noise_init(fxos8700_offset_noise_t *offnoiseptr);
279 /*! @brief Function to measure accelerometer offset noise.
280 * @details This function measures accelerometer offset noise.
281 * @param[in] fxos8700_accelmagdata_t *rawData, pointer to FXOS8700 rawdata metadata.
282 * @param[in/out] fxos8700_offset_noise_t *offnoiseptr, pointer to FXOS8700 offset noise metadata.
283 * @param[in] float sens, FXOS8700 sensitivity based on FS configuration.
284 * @return void.
285 */
286 void accel_off_noise(fxos8700_accelmagdata_t* rawData,fxos8700_offset_noise_t *offnoiseptr, float sens);
287 /*! @brief Function to measure magnetometer offset noise.
288 * @details This function measures magnetometer offset noise.
289 * @param[in] fxos8700_accelmagdata_t *rawData, pointer to FXOS8700 rawdata metadata.
290 * @param[in/out] fxos8700_offset_noise_t *offnoiseptr, pointer to FXOS8700 offset noise metadata.
291 * @return void.
292 */
293 void mag_off_noise(fxos8700_accelmagdata_t* rawData,fxos8700_offset_noise_t *offnoiseptr);
294 void FRM_Recorder_Init();
295
296 /*******************************************************************************
297 * Code
298 ******************************************************************************/
299
300 /*! This is the Sensor Data Ready ISR implementation.*/
fxos8700_isr_callback(void * pUserData)301 void fxos8700_isr_callback(void *pUserData)
302 { /*! @brief Set flag to indicate Sensor has signalled data ready. */
303 bFxos8700DataReady = true;
304 }
305
306 /* Create TSA table and add output variables. */
307 /*!
308 * @brief Target Side Addressable (TSA) table created for this application.
309 */
310 FMSTR_TSA_TABLE_BEGIN(main_table)
FMSTR_TSA_STRUCT(fxos8700_accelmagdata_t)311 FMSTR_TSA_STRUCT(fxos8700_accelmagdata_t)
312 FMSTR_TSA_MEMBER(fxos8700_accelmagdata_t, mag, FMSTR_TSA_SINT16)
313
314 FMSTR_TSA_STRUCT(fxos8700_allregs_t)
315 FMSTR_TSA_MEMBER(fxos8700_allregs_t, offset, FMSTR_TSA_UINT8)
316 FMSTR_TSA_MEMBER(fxos8700_allregs_t, value, FMSTR_TSA_UINT8)
317 FMSTR_TSA_MEMBER(fxos8700_allregs_t, trigger, FMSTR_TSA_UINT8)
318 FMSTR_TSA_MEMBER(fxos8700_allregs_t, read_offset, FMSTR_TSA_UINT8)
319 FMSTR_TSA_MEMBER(fxos8700_allregs_t, read_value, FMSTR_TSA_UINT8)
320 FMSTR_TSA_MEMBER(fxos8700_allregs_t, read_trigger, FMSTR_TSA_UINT8)
321 FMSTR_TSA_MEMBER(fxos8700_allregs_t, readall_value, FMSTR_TSA_UINT8)
322 FMSTR_TSA_MEMBER(fxos8700_allregs_t, readall_size, FMSTR_TSA_UINT8)
323 FMSTR_TSA_MEMBER(fxos8700_allregs_t, readall_trigger, FMSTR_TSA_UINT8)
324 FMSTR_TSA_MEMBER(fxos8700_allregs_t, trigger_accel_offnoise, FMSTR_TSA_UINT8)
325 FMSTR_TSA_MEMBER(fxos8700_allregs_t, trigger_mag_offnoise, FMSTR_TSA_UINT8)
326 FMSTR_TSA_MEMBER(fxos8700_allregs_t, fs_value, FMSTR_TSA_UINT8)
327 FMSTR_TSA_MEMBER(fxos8700_allregs_t, mods_value, FMSTR_TSA_UINT8)
328 FMSTR_TSA_MEMBER(fxos8700_allregs_t, toggle, FMSTR_TSA_UINT8)
329 FMSTR_TSA_MEMBER(fxos8700_allregs_t, freefall_cntr, FMSTR_TSA_UINT16)
330 FMSTR_TSA_MEMBER(fxos8700_allregs_t, tapdetect_cntr, FMSTR_TSA_UINT16)
331 FMSTR_TSA_MEMBER(fxos8700_allregs_t, orient_cntr, FMSTR_TSA_UINT16)
332 FMSTR_TSA_MEMBER(fxos8700_allregs_t, vecmchange_cntr, FMSTR_TSA_UINT16)
333 FMSTR_TSA_MEMBER(fxos8700_allregs_t, reg_addr, FMSTR_TSA_UINT8)
334 FMSTR_TSA_MEMBER(fxos8700_allregs_t, accel, FMSTR_TSA_FLOAT)
335 FMSTR_TSA_MEMBER(fxos8700_allregs_t, dataready_cntr, FMSTR_TSA_UINT8)
336
337 FMSTR_TSA_STRUCT(fxos8700_offset_noise_t)
338 FMSTR_TSA_MEMBER(fxos8700_offset_noise_t, offx, FMSTR_TSA_FLOAT)
339 FMSTR_TSA_MEMBER(fxos8700_offset_noise_t, offy, FMSTR_TSA_FLOAT)
340 FMSTR_TSA_MEMBER(fxos8700_offset_noise_t, offz, FMSTR_TSA_FLOAT)
341 FMSTR_TSA_MEMBER(fxos8700_offset_noise_t, rmsx, FMSTR_TSA_FLOAT)
342 FMSTR_TSA_MEMBER(fxos8700_offset_noise_t, rmsy, FMSTR_TSA_FLOAT)
343 FMSTR_TSA_MEMBER(fxos8700_offset_noise_t, rmsz, FMSTR_TSA_FLOAT)
344 FMSTR_TSA_MEMBER(fxos8700_offset_noise_t, mag_rms, FMSTR_TSA_FLOAT)
345 FMSTR_TSA_MEMBER(fxos8700_offset_noise_t, mag_off, FMSTR_TSA_FLOAT)
346 FMSTR_TSA_MEMBER(fxos8700_offset_noise_t, complete_accel_offnoise, FMSTR_TSA_UINT8)
347 FMSTR_TSA_MEMBER(fxos8700_offset_noise_t, complete_mag_offnoise, FMSTR_TSA_UINT8)
348
349 FMSTR_TSA_RO_VAR(rawData, FMSTR_TSA_USERTYPE(fxos8700_accelmagdata_t))
350
351 FMSTR_TSA_RW_VAR(registers, FMSTR_TSA_USERTYPE(fxos8700_allregs_t))
352
353 FMSTR_TSA_RO_VAR(offnoise_data, FMSTR_TSA_USERTYPE(fxos8700_offset_noise_t))
354
355 FMSTR_TSA_TABLE_END()
356
357 FMSTR_TSA_TABLE_LIST_BEGIN()
358 FMSTR_TSA_TABLE(main_table)
359 FMSTR_TSA_TABLE_LIST_END()
360
361 /*!
362 * @brief FreeMASTER recorder initialization
363 */
364 void FRM_Recorder_Init()
365 {
366 /* Do local configuration of additional recorder */
367
368 /* Setup the additional recorder raw buffer */
369 recBuffCfg.addr = recBuffer;
370 recBuffCfg.size = sizeof(recBuffer);
371 recBuffCfg.basePeriod_ns = 0; /* Unknown period */
372 recBuffCfg.name = "FXOS8700 3-Axis Accelerometer Data";
373
374 FMSTR_RecorderCreate(1, &recBuffCfg);
375 }
376
377 /*!
378 * @brief Main function
379 */
380
main(void)381 int main(void)
382 {
383 int32_t status;
384 uint16_t ffmt_incr = 0;
385 uint16_t pulse_incr = 0;
386 uint16_t orient_incr = 0;
387 uint16_t vecm_incr = 0;
388 uint8_t regdata;
389 float sensitivity = ACCEL_2G_SENS;
390
391 ARM_DRIVER_I2C *I2Cdrv = &I2C_S_DRIVER; // Now using the shield.h value!!!
392 GENERIC_DRIVER_GPIO *pGpioDriver = &Driver_GPIO_KSDK;
393 fxos8700_i2c_sensorhandle_t FXOS8700drv;
394
395 /*! Initialize the MCU hardware. */
396 BOARD_InitPins();
397 BOARD_BootClockRUN();
398 BOARD_InitDebugConsole();
399
400 /*! Initialize FXOS8700_INT2 pin used by FRDM board */
401 pGpioDriver->pin_init(&FXOS8700_INT2, GPIO_DIRECTION_IN, NULL, &fxos8700_isr_callback, NULL);
402
403 /*! Initialize RGB LED pin used by FRDM board */
404 pGpioDriver->pin_init(&GREEN_LED, GPIO_DIRECTION_OUT, NULL, NULL, NULL);
405
406 /*! FreeMASTER communication layer initialization */
407 init_freemaster_uart();
408
409 /*! Initialize the I2C driver. */
410 status = I2Cdrv->Initialize(I2C_S_SIGNAL_EVENT);
411 if (ARM_DRIVER_OK != status)
412 {
413 return status;
414 }
415
416 /*! Set the I2C Power mode. */
417 status = I2Cdrv->PowerControl(ARM_POWER_FULL);
418 if (ARM_DRIVER_OK != status)
419 {
420 return status;
421 }
422
423 /*! Set the I2C bus speed. */
424 status = I2Cdrv->Control(ARM_I2C_BUS_SPEED, ARM_I2C_BUS_SPEED_FAST);
425 if (ARM_DRIVER_OK != status)
426 {
427 return status;
428 }
429
430 /*! Initialize the FXOS8700 sensor driver. */
431 status = FXOS8700_I2C_Initialize(&FXOS8700drv, &I2C_S_DRIVER, I2C_S_DEVICE_INDEX, FXOS8700_I2C_ADDR,
432 FXOS8700_WHO_AM_I_PROD_VALUE);
433 if (SENSOR_ERROR_NONE != status)
434 {
435 return status;
436 }
437
438 /*! Set the task to be executed while waiting for I2C transactions to complete. */
439 FXOS8700_I2C_SetIdleTask(&FXOS8700drv, (registeridlefunction_t)SMC_SetPowerModeVlpr, SMC);
440
441 /*! Configure the fxos8700 sensor driver. */
442 status = FXOS8700_I2C_Configure(&FXOS8700drv, fxos8700_Config_Hybrid);
443 if (SENSOR_ERROR_NONE != status)
444 {
445 return status;
446 }
447
448 /*! FreeMASTER Driver Initialization */
449 FMSTR_Init();
450
451 /*! FreeMASTER Recorder Initialization */
452 FRM_Recorder_Init();
453
454 /*! Initialize trigger flags */
455 registers.toggle = 1;
456 registers.trigger = 0;
457 registers.read_trigger = 0;
458 registers.read_value = 0;
459 registers.readall_trigger = 0;
460 registers.trigger_accel_offnoise=0;
461 registers.trigger_mag_offnoise=0;
462 registers.dataready_cntr = 0;
463
464 /*! Initialize read all values */
465 for(int i = 0; i < FXOS8700_NUM_REGISTERS; i++)
466 {
467 registers.readall_value[i] = 0;
468 }
469
470 for (;;) /* Forever loop */
471 {
472
473 /*! Call Recorder#0 in execution loop for generic high-speed variables sampling. */
474 FMSTR_Recorder(0);
475
476 /*! Call FreeMASTER host in polling mode */
477 FMSTR_Poll();
478
479 /*! Check for any write register trigger from Host */
480 if (registers.trigger == 1)
481 {
482 /*! Apply Register Write */
483 status = apply_register_write(FXOS8700drv, registers.offset, registers.value);
484 if (SENSOR_ERROR_NONE != status)
485 {
486 return status;
487 }
488 registers.trigger = 0;
489 /*! Update drop down menu selection based on updated register write */
490 update_dropdown_selection(®isters, FXOS8700_REG_WRITE);
491 }
492
493 /*! Check for any read register trigger from Host */
494 if (registers.read_trigger == 1)
495 {
496 /*! Apply Register Write */
497 status = apply_register_read(FXOS8700drv, registers.read_offset, &(registers.read_value));
498 if (SENSOR_ERROR_NONE != status)
499 {
500 return status;
501 }
502 registers.read_trigger = 0;
503 /*! Update drop down menu selection based on updated register read */
504 update_dropdown_selection(®isters, FXOS8700_REG_READ);
505 }
506
507 /*! Check for any read all register trigger from Host */
508 if (registers.readall_trigger == 1)
509 {
510 /*! Apply Register Write */
511 status = apply_register_readall(FXOS8700drv);
512 if (SENSOR_ERROR_NONE != status)
513 {
514 return status;
515 }
516 registers.readall_trigger = 0;
517 registers.readall_size = FXOS8700_NUM_REGISTERS;
518 /*! Update drop down menu selection based on updated all-register read */
519 update_dropdown_selection(®isters, FXOS8700_ALLREG_READ);
520 }
521
522 /*! Wait for data ready interrupt from the FXOS8700. */
523 if (false == bFxos8700DataReady)
524 {
525 SMC_SetPowerModeWait(SMC); /* Power save, wait if nothing to do. */
526 continue;
527 }
528 else
529 { /*! Clear the data ready flag, it will be set again by the ISR. */
530 bFxos8700DataReady = false;
531 //pGpioDriver->toggle_pin(&GREEN_LED);
532 }
533
534 /*! Calling Recorder#1 for sampling sensor data when we get sensor data ready interrupt based on ODR. */
535 FMSTR_Recorder(1);
536
537 /*! Read all FXOS8700 registers */
538 status = FXOS8700_I2C_ReadData(&FXOS8700drv, FXOS8700_ALL_REG_READ, registers.reg_addr);
539 if (0 == (registers.reg_addr[0] & FXOS8700_DR_STATUS_ZYXDR_MASK))
540 { /* Loop, if new sample is not available. */
541 continue;
542 }
543
544 /*! Convert the raw sensor data to signed 16-bit container for display to the debug port. */
545 rawData.accel[0] = ((int16_t)registers.reg_addr[1] << 8) | registers.reg_addr[2];
546 rawData.accel[0] /= 4;
547 rawData.accel[1] = ((int16_t)registers.reg_addr[3] << 8) | registers.reg_addr[4];
548 rawData.accel[1] /= 4;
549 rawData.accel[2] = ((int16_t)registers.reg_addr[5] << 8) | registers.reg_addr[6];
550 rawData.accel[2] /= 4;
551 rawData.mag[0] = ((int16_t)registers.reg_addr[7] << 8) | registers.reg_addr[8];
552 rawData.mag[1] = ((int16_t)registers.reg_addr[9] << 8) | registers.reg_addr[10];
553 rawData.mag[2] = ((int16_t)registers.reg_addr[11] << 8) | registers.reg_addr[12];
554
555 status = FXOS8700_I2C_ReadData(&FXOS8700drv, cFXOS8700_whoami, (uint8_t *)®isters.reg_addr[13]);
556
557 /*! Check the FS and apply sensitivity */
558 status = FXOS8700_I2C_ReadData(&FXOS8700drv, cFXOS8700_fs_src, ®data);
559 if (regdata == 1)
560 {
561 sensitivity = ACCEL_4G_SENS;
562 }
563 else if (regdata == 2)
564 {
565 sensitivity = ACCEL_8G_SENS;
566 }
567 else
568 {
569 sensitivity = ACCEL_2G_SENS;
570 }
571
572 /*! Convert raw values to Gs */
573 registers.accel[0] = (float) (rawData.accel[0] * sensitivity);
574 registers.accel[1] = (float) (rawData.accel[1] * sensitivity);
575 registers.accel[2] = (float) (rawData.accel[2] * sensitivity);
576
577 /*! Increment data ready counter and check for rollover */
578 registers.dataready_cntr++;
579 if(MAX8BITSTORAGE == registers.dataready_cntr)
580 {
581 registers.dataready_cntr = 0;
582 }
583
584 if (prev_toggle != registers.toggle)
585 {
586 pGpioDriver->toggle_pin(&GREEN_LED);
587 prev_toggle = registers.toggle;
588 }
589
590 /*! Call offset and noise calculation function for FXOS8700 accelerometer */
591 if (registers.trigger_accel_offnoise == 1)
592 {
593 accel_off_noise(&(rawData), &(offnoise_data), sensitivity);
594 if (offnoise_data.complete_accel_offnoise == 1)
595 {
596 registers.trigger_accel_offnoise = 0;
597 //offnoise_data.complete_accel_offnoise = 0;
598 }
599 }
600
601 /*! Call offset and noise calculation function for FXOS8700 magnetometer */
602 if (registers.trigger_mag_offnoise == 1)
603 {
604 mag_off_noise(&(rawData), &(offnoise_data));
605 if (offnoise_data.complete_mag_offnoise == 1)
606 {
607 registers.trigger_mag_offnoise = 0;
608 PRINTF("\r\n Mag offset X = %f Y = %f Z = %f\r\n", offnoise_data.mag_off[0], offnoise_data.mag_off[1], offnoise_data.mag_off[2]);
609 }
610 }
611
612 status = FXOS8700_I2C_ReadData(&FXOS8700drv, cFXOS8700_int_src, ®data);
613
614 /*! The following condition checks for multiple interrupts occurring at the same time */
615 if((regdata & FXOS8700_INT_SOURCE_SRC_FFMT_MASK) == 0x04)
616 {
617 ffmt_incr++;
618 if (ffmt_incr == 1)
619 {
620 registers.freefall_cntr++;
621 }
622 }
623 /*! Check for single-tap detection interrupt */
624 else if((regdata & FXOS8700_INT_SOURCE_SRC_PULSE_MASK) == 0x08)
625 {
626 pulse_incr++;
627 if (pulse_incr == 1)
628 {
629 registers.tapdetect_cntr++;
630 }
631 }
632 /*! Check for Vector Magnitude change interrupt */
633 else if((regdata & FXOS8700_INT_SOURCE_SRC_A_VECM_MASK) == 0x02)
634 {
635 vecm_incr++;
636 if (vecm_incr == 1)
637 {
638 registers.vecmchange_cntr++;
639 }
640 }
641 /*! Check for Vector Magnitude change interrupt */
642 else if((regdata & FXOS8700_INT_SOURCE_SRC_LNDPRT_MASK) == 0x10)
643 {
644 orient_incr++;
645 if (orient_incr == 1)
646 {
647 registers.orient_cntr++;
648 }
649 }
650 /* Else send other interrupts, clear counters */
651 else
652 {
653 /* Reset all event counters */
654 ffmt_incr = 0;
655 pulse_incr = 0;
656 orient_incr = 0;
657 vecm_incr = 0;
658 }
659
660 /*! Read FFMT interrupt source register to clear flags */
661 status = FXOS8700_I2C_ReadData(&FXOS8700drv, cFXOS8700_int_src, ®data);
662 status = FXOS8700_I2C_ReadData(&FXOS8700drv, cFXOS8700_ffmt_src, ®data);
663 status = FXOS8700_I2C_ReadData(&FXOS8700drv, cFXOS8700_pl_status, ®data);
664
665 }
666 }
667
668
669 /*!
670 * @brief Service register write trigger from Host
671 */
apply_register_write(fxos8700_i2c_sensorhandle_t FXOS8700drv,uint8_t offset,uint8_t value)672 int32_t apply_register_write(fxos8700_i2c_sensorhandle_t FXOS8700drv, uint8_t offset, uint8_t value)
673 {
674 int32_t status;
675
676 if (offset > FXOS8700_NUM_REGISTERS)
677 {
678 return SENSOR_ERROR_INVALID_PARAM;
679 }
680
681 registerwritelist_t register_write[] = {
682 /*! Set register offset with provided value */
683 {offset, value, 0},
684 __END_WRITE_DATA__};
685
686 status = FXOS8700_I2C_Configure(&FXOS8700drv, register_write);
687 if (SENSOR_ERROR_NONE != status)
688 {
689 return SENSOR_ERROR_WRITE;
690 }
691
692 return SENSOR_ERROR_NONE;
693 }
694
695 /*!
696 * @brief Service register read trigger from Host
697 */
apply_register_read(fxos8700_i2c_sensorhandle_t FXOS8700drv,uint8_t read_offset,uint8_t * read_value)698 int32_t apply_register_read(fxos8700_i2c_sensorhandle_t FXOS8700drv, uint8_t read_offset, uint8_t *read_value)
699 {
700 int32_t status;
701
702 if (read_offset > FXOS8700_NUM_REGISTERS)
703 {
704 return SENSOR_ERROR_INVALID_PARAM;
705 }
706
707 registerreadlist_t register_read[] = {
708 /*! Set register offset with provided value */
709 {.readFrom = read_offset, .numBytes = 1}, __END_READ_DATA__};
710
711 status = FXOS8700_I2C_ReadData(&FXOS8700drv, register_read, read_value);
712 if (SENSOR_ERROR_NONE != status)
713 {
714 return SENSOR_ERROR_WRITE;
715 }
716
717 return SENSOR_ERROR_NONE;
718 }
719
720 /*!
721 * @brief Service register read all trigger from Host
722 */
apply_register_readall(fxos8700_i2c_sensorhandle_t FXOS8700drv)723 int32_t apply_register_readall(fxos8700_i2c_sensorhandle_t FXOS8700drv)
724 {
725 int32_t status;
726
727 for (int reg_offset = FXOS8700_STATUS; reg_offset <= FXOS8700_A_FFMT_THS_Z_LSB; reg_offset++)
728 {
729 registerreadlist_t register_readall[] = {
730 /*! Set register offset with provided value */
731 {.readFrom = reg_offset, .numBytes = 1}, __END_READ_DATA__};
732
733 status = FXOS8700_I2C_ReadData(&FXOS8700drv, register_readall, &(registers.readall_value[reg_offset]));
734 if (SENSOR_ERROR_NONE != status)
735 {
736 return SENSOR_ERROR_READ;
737 }
738 }
739
740 return SENSOR_ERROR_NONE;
741 }
742
743 /*!
744 * @brief Update drop down selection values based on register write, read or readall.
745 */
update_dropdown_selection(fxos8700_allregs_t * registers,uint8_t caller)746 int32_t update_dropdown_selection( fxos8700_allregs_t *registers, uint8_t caller)
747 {
748
749 int32_t status = SENSOR_ERROR_NONE;
750
751 switch (caller)
752 {
753 case FXOS8700_REG_WRITE:
754
755 /*! Update drop down option based on updated read value */
756 if(FXOS8700_XYZ_DATA_CFG == registers->offset) //FS Selection
757 {
758 registers->fs_value = registers->value;
759 }
760 else if (FXOS8700_CTRL_REG2 == registers->offset)
761 {
762 registers->mods_value = registers->value;
763 }
764 break;
765 case FXOS8700_REG_READ: //Called from Register Read
766
767 /*! Update drop down option based on updated read value */
768 if(FXOS8700_XYZ_DATA_CFG == registers->read_offset) //FS Selection
769 {
770 registers->fs_value = registers->read_value;
771 }
772 else if (FXOS8700_CTRL_REG2 == registers->offset)
773 {
774 registers->mods_value = registers->read_value;
775 }
776 break;
777 case FXOS8700_ALLREG_READ: //Called from Register ReadAll
778
779 /*! Update drop down option based on updated read values */
780 registers->fs_value = registers->reg_addr[FXOS8700_XYZ_DATA_CFG];
781 registers->mods_value = registers->reg_addr[FXOS8700_CTRL_REG2];
782 break;
783 default:
784 status = SENSOR_ERROR_INVALID_PARAM;
785 break;
786 }
787
788 return status;
789
790 }
791
792 /*******************************************************************************
793 * OFFSET NOISE CALCULATION
794 ******************************************************************************/
795
796 /*!
797 * @brief Initialize Offset-Noise Variables
798 */
offset_noise_init(fxos8700_offset_noise_t * offnoiseptr)799 void offset_noise_init(fxos8700_offset_noise_t *offnoiseptr)
800 {
801 offnoiseptr->offx = 0.0;
802 offnoiseptr->offy = 0.0;
803 offnoiseptr->offz = 0.0;
804 offnoiseptr->rmsx = 0.0;
805 offnoiseptr->rmsy = 0.0;
806 offnoiseptr->rmsz = 0.0;
807 offnoiseptr->mag_off[0] = 0.0;
808 offnoiseptr->mag_off[1] = 0.0;
809 offnoiseptr->mag_off[2] = 0.0;
810 offnoiseptr->mag_rms[0] = 0.0;
811 offnoiseptr->mag_rms[1] = 0.0;
812 offnoiseptr->mag_rms[2] = 0.0;
813 offnoiseptr->complete_accel_offnoise = 0;
814 offnoiseptr->complete_mag_offnoise = 0;
815 }
816
817
818 /* Calculate Offset & Noise for ACCELEROMETER */
accel_off_noise(fxos8700_accelmagdata_t * rawData,fxos8700_offset_noise_t * offnoiseptr,float sens)819 void accel_off_noise(fxos8700_accelmagdata_t* rawData,fxos8700_offset_noise_t *offnoiseptr, float sens)
820 {
821 uint16_t j;
822 static uint16_t k=0;
823 static uint16_t cntr=0;
824 static float stdx=0;
825 static float stdy=0;
826 static float stdz=0;
827 static float xx[N], yy[N], zz[N];
828 static float xm[N], ym[N], zm[N];
829 static float xsq[N], ysq[N], zsq[N];
830 float am[3];
831 static float sumx=0.0;
832 static float sumy=0.0;
833 static float sumz=0.0;
834
835 /* Init offset noise variables */
836 offset_noise_init(offnoiseptr);
837
838 cntr++;
839
840 /* Store Accel samples and calculate sum for configured N */
841 if(cntr < N)
842 {
843 am[0]=rawData->accel[0]*sens;
844 am[1]=rawData->accel[1]*sens;
845 am[2]=rawData->accel[2]*sens;
846 xx[k]=am[0];
847 yy[k]=am[1];
848 zz[k]=am[2];
849 sumx+=am[0];
850 sumy+=am[1];
851 sumz+=am[2];
852 k+=1;
853 offnoiseptr->complete_accel_offnoise = 0;
854 }
855
856 /* Measure offset and RMS */
857 if(cntr == N)
858 {
859 /* Measure average */
860 sumx=sumx/(N-1);
861 sumy=sumy/(N-1);
862 sumz=sumz/(N-1);
863
864 /* Measure offset */
865 offnoiseptr->offx=0-sumx;
866 offnoiseptr->offy=0-sumy;
867 offnoiseptr->offz=1-sumz;
868
869 /* Measure standard deviation */
870 for(j=0; j<N-1; j++)
871 {
872 xm[j]=xx[j]-sumx;
873 ym[j]=yy[j]-sumy;
874 zm[j]=zz[j]-sumz;
875
876 xsq[j]=pow(xm[j],2);
877 ysq[j]=pow(ym[j],2);
878 zsq[j]=pow(zm[j],2);
879 stdx+=xsq[j];
880 stdy+=ysq[j];
881 stdz+=zsq[j];
882 }
883 stdx=stdx/(N-2);
884 stdy=stdy/(N-2);
885 stdz=stdz/(N-2);
886
887 /* Measure RMS */
888 offnoiseptr->rmsx=pow(stdx,0.5);
889 offnoiseptr->rmsy=pow(stdy,0.5);
890 offnoiseptr->rmsz=pow(stdz,0.5);
891
892 /* Set the completion flag */
893 offnoiseptr->complete_accel_offnoise = 1;
894
895 /* Reset local storage */
896 cntr = k = 0;
897 sumx = sumy = sumz = 0;
898 stdx = stdy = stdz = 0;
899 }
900 }
901
902 /* Calculate Offset & Noise for MAGNETOMETER */
mag_off_noise(fxos8700_accelmagdata_t * rawData,fxos8700_offset_noise_t * offnoiseptr)903 void mag_off_noise(fxos8700_accelmagdata_t* rawData,fxos8700_offset_noise_t *offnoiseptr)
904 {
905 //local variables
906
907 uint16_t j;
908 static uint16_t k;
909 static uint16_t cntr=0;
910 static float stdx=0;
911 static float stdy=0;
912 static float stdz=0;
913 static float xx[N], yy[N], zz[N];
914 static float xm[N], ym[N], zm[N];
915 static float xsq[N], ysq[N], zsq[N];
916 float mm[3];
917 float Bx[2] = {0,0};
918 float By[2] = {0,0};
919 float Bz[2] = {0,0};
920 float sens=0.1; //uT
921 static float sumx=0.0;
922 static float sumy=0.0;
923 static float sumz=0.0;
924 //float refx, refy, refz;
925
926 /* Init offset noise variables */
927 offset_noise_init(offnoiseptr);
928
929 cntr++;
930 if(cntr < N)
931 {
932 /* if (cntr == 1)
933 {
934 refx = rawData->mag[0]*sens;
935 refy = rawData->mag[1]*sens;
936 refz = rawData->mag[2]*sens;
937 }*/
938 mm[0]=rawData->mag[0]*sens;
939 mm[1]=rawData->mag[1]*sens;
940 mm[2]=rawData->mag[2]*sens;
941 xx[k]=mm[0];
942 yy[k]=mm[1];
943 zz[k]=mm[2];
944 Bx[0]=xx[0];
945 Bx[1]=xx[0];
946 By[0]=yy[0];
947 By[1]=yy[0];
948 Bz[0]=zz[0];
949 Bz[1]=zz[0];
950 sumx+=mm[0];
951 sumy+=mm[1];
952 sumz+=mm[2];
953 //Bx[0]=
954 k+=1;
955 offnoiseptr->complete_mag_offnoise = 0;
956 }
957 if(cntr == N)
958 {
959 sumx=sumx/(N-1);
960 sumy=sumy/(N-1);
961 sumz=sumz/(N-1);
962 for (j=0; j<N; j++)
963 {
964 /*if (!(xx[i]>=Bx[0]))
965 {
966 Bx[0]=xx[i];
967 }
968 if(!(xx[i] <= Bx[1]))
969 {
970 Bx[1]=xx[i];
971 } */
972 if(Bx[0] > xx[j]) Bx[0]=xx[j]; //minimum value
973 if(Bx[1] < xx[j]) Bx[1]=xx[j]; //maximum value
974 if(By[0] > yy[j]) By[0]=yy[j];
975 if(By[1] < yy[j]) By[1]=yy[j];
976 if(Bz[0] > zz[j]) Bz[0]=zz[j];
977 if(Bz[1] < zz[j]) Bz[1]=zz[j];
978
979 }
980 offnoiseptr->mag_off[0]=0.5*(Bx[0]+Bx[1]);
981 offnoiseptr->mag_off[1]=0.5*(By[0]+By[1]);
982 offnoiseptr->mag_off[2]=0.5*(Bz[0]+Bz[1]);
983 for(j=0; j<N-1; j++)
984 {
985 xm[j]=xx[j]-sumx;
986 ym[j]=yy[j]-sumy;
987 zm[j]=zz[j]-sumz;
988 //PRINTF("\r\n Before X = %f Y = %f Z = %f\r\n", xx[j], yy[j], zz[j]);
989 xsq[j]=pow(xm[j],2);
990 ysq[j]=pow(ym[j],2);
991 zsq[j]=pow(zm[j],2);
992 stdx+=xsq[j];
993 stdy+=ysq[j];
994 stdz+=zsq[j];
995 }
996 stdx=stdx/(N-2);
997 stdy=stdy/(N-2);
998 stdz=stdz/(N-2);
999 //PRINTF("\r\n Accel StdX = %f StdY = %f StdZ = %f\r\n", stdx, stdy, stdz);
1000 offnoiseptr->mag_rms[0]=pow(stdx,0.5);
1001 offnoiseptr->mag_rms[1]=pow(stdy,0.5);
1002 offnoiseptr->mag_rms[2]=pow(stdz,0.5);
1003
1004 offnoiseptr->complete_mag_offnoise = 1;
1005 cntr = k = 0;
1006 sumx = sumy = sumz = 0;
1007 stdx = stdy = stdz = 0;
1008 //refx = refy = refz = 0;
1009 }
1010
1011 }
1012
1013
1014 /*!
1015 * @brief UART Module initialization (UART is a the standard block included e.g. in K22F)
1016 */
init_freemaster_uart(void)1017 static void init_freemaster_uart(void)
1018 {
1019 uart_config_t config;
1020
1021 /*
1022 * config.baudRate_Bps = 115200U;
1023 * config.parityMode = kUART_ParityDisabled;
1024 * config.stopBitCount = kUART_OneStopBit;
1025 * config.txFifoWatermark = 0;
1026 * config.rxFifoWatermark = 1;
1027 * config.enableTx = false;
1028 * config.enableRx = false;
1029 */
1030 UART_GetDefaultConfig(&config);
1031 config.baudRate_Bps = 115200U;
1032 config.enableTx = false;
1033 config.enableRx = false;
1034
1035 UART_Init((UART_Type*)BOARD_DEBUG_UART_BASEADDR, &config, BOARD_DEBUG_UART_CLK_FREQ);
1036
1037 /* Register communication module used by FreeMASTER driver. */
1038 FMSTR_SerialSetBaseAddress((UART_Type*)BOARD_DEBUG_UART_BASEADDR);
1039
1040 #if FMSTR_SHORT_INTR || FMSTR_LONG_INTR
1041 /* Enable UART interrupts. */
1042 EnableIRQ(BOARD_UART_IRQ);
1043 EnableGlobalIRQ(0);
1044 #endif
1045 }
1046
1047 #if FMSTR_SHORT_INTR || FMSTR_LONG_INTR
1048 /*
1049 * Application interrupt handler of communication peripheral used in interrupt modes
1050 * of FreeMASTER communication.
1051 *
1052 * NXP MCUXpresso SDK framework defines interrupt vector table as a part of "startup_XXXXXX.x"
1053 * assembler/C file. The table points to weakly defined symbols, which may be overwritten by the
1054 * application specific implementation. FreeMASTER overrides the original weak definition and
1055 * redirects the call to its own handler.
1056 *
1057 */
1058
BOARD_UART_IRQ_HANDLER(void)1059 void BOARD_UART_IRQ_HANDLER(void)
1060 {
1061 /* Call FreeMASTER Interrupt routine handler */
1062 FMSTR_SerialIsr();
1063 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
1064 exception return operation might vector to incorrect interrupt */
1065 #if defined __CORTEX_M && (__CORTEX_M == 4U)
1066 __DSB();
1067 #endif
1068 }
1069 #endif
1070
1071