1 /*
2 * Copyright 2020-2021 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 /**
9 * @file fxls8962_freemaster_demo.c
10 * @brief The fxls8962_freemaster_demo.c file implements FreeMASTER demo using the ISSDK
11 * FXLS896x sensor driver example demonstration with interrupt mode.
12 */
13
14 //-----------------------------------------------------------------------
15 // SDK Includes
16 //-----------------------------------------------------------------------
17 #include "pin_mux.h"
18 #include "clock_config.h"
19 #include "board.h"
20 #include "fsl_debug_console.h"
21 #include "math.h"
22 #include "fsl_uart.h"
23 #include "fsl_common.h"
24 #include "freemaster.h"
25 #include "freemaster_serial_uart.h"
26 //-----------------------------------------------------------------------
27 // CMSIS Includes
28 //-----------------------------------------------------------------------
29 #include "Driver_I2C.h"
30
31 //-----------------------------------------------------------------------
32 // ISSDK Includes
33 //-----------------------------------------------------------------------
34 #include "issdk_hal.h"
35 #include "gpio_driver.h"
36 #include "fxls8962_drv.h"
37 #include "systick_utils.h"
38
39 //-----------------------------------------------------------------------
40 // Macros
41 //-----------------------------------------------------------------------
42 #define FXLS896x_NUM_REGISTERS (FXLS8962_SELF_TEST_CONFIG2 + 1)
43 #define FF_A_FFMT_THS (0x08) /* FreeFall Threshold Value. */
44 #define A_FFMT_COUNT (0x18) /* Freefall/motion debounce count value. */
45 #define PL_COUNT (0x15) /* Pulse debounce count value. */
46 #define ASLP_COUNTER (0x07) /* Auto Sleep after ~5s. */
47 #define ACCEL_2G_SENS (0.000976) /* Sensitivity factor for 2G FS */
48 #define ACCEL_4G_SENS (0.001953) /* Sensitivity factor for 4G FS */
49 #define ACCEL_8G_SENS (0.003906) /* Sensitivity factor for 8G FS */
50 #define ACCEL_16G_SENS (0.007813) /* Sensitivity factor for 16G FS */
51 #define N (100U) /* Number of samples used to measure offset/noise */
52 #define RAW_ACCEL_DATA_SIZE (6U) /* Accel Data Size */
53 #define MAX8BITSTORAGE (255U)
54 #define FXLS8962_DATA_SIZE 6
55 //-----------------------------------------------------------------------
56 // Constants
57 //-----------------------------------------------------------------------
58 /*! @brief Defines the register write list to configure FXLS896x in Interrupt mode. */
59 const registerwritelist_t cFxls8962ConfigNormal[] = {
60 /*! Set Full-scale range as 4G. */
61 {FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_FSR_4G, FXLS8962_SENS_CONFIG1_FSR_MASK},
62 /*! Clear SENS_CONFIG2 */
63 {FXLS8962_SENS_CONFIG2, 0x00, 0x00},
64 /*! Disable Self-Test. */
65 {FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_ST_AXIS_SEL_DISABLED, FXLS8962_SENS_CONFIG1_ST_AXIS_SEL_MASK},
66 /*! Set Wake Mode ODR Rate as 12.5Hz. */
67 {FXLS8962_SENS_CONFIG3, FXLS8962_SENS_CONFIG3_WAKE_ODR_12_5HZ, FXLS8962_SENS_CONFIG3_WAKE_ODR_MASK},
68 /*! Enable Interrupts for Data Ready Events. */
69 {FXLS8962_INT_EN, FXLS8962_INT_EN_DRDY_EN_EN, FXLS8962_INT_EN_DRDY_EN_MASK},
70 /*! Enable Temperature sensor. */
71 {FXLS8962_SENS_CONFIG2,FXLS8962_SENS_CONFIG2_ANIC_TEMP_EN,FXLS8962_SENS_CONFIG2_ANIC_TEMP_MASK},
72 /*! Set Self-Test ODR to 100 Hz. */
73 {0x38,0x05,0x00},
74 {0x2F,0x38,0x00},
75 {0x30,0xD8,0x00},
76 {0x33,0xC0,0x00},
77 {0x34,0xFF,0x00},
78 {0x35,0x40,0x00},
79 __END_WRITE_DATA__};
80
81 /*! @brief Register settings for Self-Test in X Axis (Positive polarity). */
82 const registerwritelist_t cFxls8962STXP[] = {
83 /* Set Self Test Axis. */
84 {FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_FSR_16G, FXLS8962_SENS_CONFIG1_FSR_MASK},
85 {FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_ST_AXIS_SEL_EN_X, FXLS8962_SENS_CONFIG1_ST_AXIS_SEL_MASK},
86 {FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_ST_POL_POSITIVE, FXLS8962_SENS_CONFIG1_ST_POL_MASK},
87 __END_WRITE_DATA__};
88
89 /*! @brief Register settings for Self-Test in X Axis (Negative polarity). */
90 const registerwritelist_t cFxls8962STXN[] = {
91 /* Set Self Test Axis. */
92 {FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_FSR_16G, FXLS8962_SENS_CONFIG1_FSR_MASK},
93 {FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_ST_AXIS_SEL_EN_X, FXLS8962_SENS_CONFIG1_ST_AXIS_SEL_MASK},
94 {FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_ST_POL_NEGATIVE, FXLS8962_SENS_CONFIG1_ST_POL_MASK},
95 __END_WRITE_DATA__};
96
97 /*! @brief Register settings for Self-Test in Y Axis (Positive polarity). */
98 const registerwritelist_t cFxls8962STYP[] = {
99 /* Set Self Test Axis. */
100 {FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_FSR_16G, FXLS8962_SENS_CONFIG1_FSR_MASK},
101 {FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_ST_AXIS_SEL_EN_Y, FXLS8962_SENS_CONFIG1_ST_AXIS_SEL_MASK},
102 {FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_ST_POL_POSITIVE,FXLS8962_SENS_CONFIG1_ST_POL_MASK},
103 __END_WRITE_DATA__};
104
105 /*! @brief Register settings for Self-Test in Y Axis (Negative polarity). */
106 const registerwritelist_t cFxls8962STYN[] = {
107 /* Set Self Test Axis. */
108 {FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_FSR_16G, FXLS8962_SENS_CONFIG1_FSR_MASK},
109 {FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_ST_AXIS_SEL_EN_Y, FXLS8962_SENS_CONFIG1_ST_AXIS_SEL_MASK},
110 {FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_ST_POL_NEGATIVE, FXLS8962_SENS_CONFIG1_ST_POL_MASK},
111 __END_WRITE_DATA__};
112
113 /*! @brief Register settings for Self-Test in Z Axis (Positive polarity). */
114 const registerwritelist_t cFxls8962STZP[] = {
115 /* Set Self Test Axis. */
116 {FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_FSR_16G, FXLS8962_SENS_CONFIG1_FSR_MASK},
117 {FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_ST_AXIS_SEL_EN_Z, FXLS8962_SENS_CONFIG1_ST_AXIS_SEL_MASK},
118 {FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_ST_POL_POSITIVE, FXLS8962_SENS_CONFIG1_ST_POL_MASK},
119 __END_WRITE_DATA__};
120
121 /*! @brief Register settings for Self-Test in Z Axis (Negative polarity). */
122 const registerwritelist_t cFxls8962STZN[] = {
123 /* Set Self Test Axis. */
124 {FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_FSR_16G, FXLS8962_SENS_CONFIG1_FSR_MASK},
125 {FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_ST_AXIS_SEL_EN_Z, FXLS8962_SENS_CONFIG1_ST_AXIS_SEL_MASK},
126 {FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_ST_POL_NEGATIVE, FXLS8962_SENS_CONFIG1_ST_POL_MASK},
127 __END_WRITE_DATA__};
128
129 /*! @brief Address of Raw Accel Data in Normal Mode. */
130 const registerreadlist_t cFxls8962OutputNormal[] = {{.readFrom = FXLS8962_OUT_X_LSB, .numBytes = FXLS8962_DATA_SIZE},
131 __END_READ_DATA__};
132
133 const registerreadlist_t cFXLS896x_whoami[] = {
134 {.readFrom = FXLS8962_WHO_AM_I, .numBytes = 1}, __END_READ_DATA__};
135
136 /*! @brief Prepare the register read for INT Status Register. */
137 const registerreadlist_t cFXLS896x_int_src[] = {
138 {.readFrom = FXLS8962_INT_STATUS, .numBytes = 1}, __END_READ_DATA__};
139
140 /*! @brief Prepare the register read for FullScale range Register. */
141 const registerreadlist_t cFXLS896x_fs_src[] = {
142 {.readFrom = FXLS8962_SENS_CONFIG1, .numBytes = 1}, __END_READ_DATA__};
143
144 /*! @brief FXLS896x register list to read all registers */
145 const registerreadlist_t FXLS896x_ALL_REG_READ[] = {{.readFrom = FXLS8962_INT_STATUS, .numBytes = FXLS896x_NUM_REGISTERS},
146 __END_READ_DATA__};
147
148 //-----------------------------------------------------------------------
149 // Global Variables
150 //-----------------------------------------------------------------------
151 /*! @brief This structure defines the fxls896x all registers metadata.*/
152 typedef struct
153 {
154 uint8_t offset;
155 uint8_t value;
156 uint8_t trigger;
157 uint8_t read_offset;
158 uint8_t read_value;
159 uint8_t read_trigger;
160 uint8_t readall_value[FXLS896x_NUM_REGISTERS];
161 uint8_t readall_size;
162 uint8_t readall_trigger;
163 uint8_t toggle;
164 uint8_t trigger_accel_offnoise;
165 uint8_t trigger_selftest;
166 uint8_t fs_value;
167 uint8_t mods_value;
168 uint8_t odr_value;
169 uint16_t freefall_cntr;
170 uint16_t tapdetect_cntr;
171 uint16_t orient_cntr;
172 uint16_t vecmchange_cntr;
173 uint8_t reg_addr[FXLS896x_NUM_REGISTERS];
174 uint8_t dataready_cntr;
175 float accel[3];
176 uint8_t sdcd;
177 int8_t temp;
178 int16_t selftest[3];
179 } fxls896x_allregs_t;
180 //-----------------------------------------------------------------------
181 /*! @brief This structure defines the fxls896x offset and noise calculation parameters. */
182 typedef struct
183 {
184 float offx;
185 float offy;
186 float offz;
187 float rmsx;
188 float rmsy;
189 float rmsz;
190 uint8_t complete_accel_offnoise;
191 } fxls896x_offset_noise_t;
192
193 /*! @brief This structure defines variables to compute self-test output change (STOC) and self-test offset (STOF). */
194 typedef struct
195 {
196 int16_t x_stoc;
197 int16_t y_stoc;
198 int16_t z_stoc;
199 int16_t x_stof;
200 int16_t y_stof;
201 int16_t z_stof;
202 uint8_t complete_selftest;
203 } fxls896x_selftest_t;
204
205 /*! @brief This structure defines the fxls8962 raw data buffer.*/
206 typedef struct
207 {
208 int16_t xdata; /*!< The x accel data */
209 int16_t ydata; /*!< The y accel data */
210 int16_t zdata; /*!< The z accel data */
211 } sensor_data;
212
213
214 typedef union rawdata
215 {
216 uint8_t byte_data[sizeof(sensor_data)];
217 sensor_data dat;
218 }RAW_DATA;
219
220 /*! @brief This structure defines the fxls8962 host operation type.*/
221 typedef enum fxls896x_operation_type
222 {
223 FXLS896x_REG_WRITE = 1U,
224 FXLS896x_REG_READ = 2U,
225 FXLS896x_ALLREG_READ = 3U,
226 FXLS896x_ACCEL_CONFIG_END
227
228 } fxls896x_operation_type_t;
229
230 /*******************************************************************************
231 * Globals
232 ******************************************************************************/
233
234 fxls8962_acceldata_t rawData;
235 fxls896x_allregs_t registers;
236 fxls896x_offset_noise_t offnoise_data;
237 fxls896x_selftest_t selftest;
238 uint8_t prev_toggle = 1;
239 volatile bool bFxls896xIntFlag = false;
240
241 static FMSTR_U8 recBuffer[1024*10];
242 FMSTR_REC_BUFF recBuffCfg;
243 FMSTR_REC_VAR recVar;
244 FMSTR_REC_CFG recCfg;
245
246 uint8_t axis=0;
247 /* variables to store self-test values (Positive(P) + / Negative(N) -) */
248 int16_t XSTP[2]={0,0},YSTP[2]={0,0},ZSTP[2]={0,0},XSTN[2]={0,0},YSTN[2]={0,0},ZSTN[2]={0,0};
249
250
251 /*******************************************************************************
252 * Local functions
253 ******************************************************************************/
254 /*! @brief Function to initialize target communication to FreeMASTER host.
255 * @details This function initializes FreeMASTER UART communication.
256 * @param[in] void.
257 * @return void.
258 */
259 static void init_freemaster_uart(void);
260 /*! @brief ISR for FXLS896x interrupt source event.
261 * @details This function implements ISR for FXLS896x INT source.
262 * @param[in] void *.
263 * @return void.
264 */
265 void fxls896x_isr_callback(void *pUserData);
266 /*! @brief Function to apply FXLS896x register write operation.
267 * @details This function apply FXLS896x register write based on write trigger from host.
268 * @param[in] fxls8962_i2c_sensorhandle_t fxls8962Driver, FXLS896x sensor I2C handle.
269 * @param[in] uint8_t offset, the address of the register to start writing from.
270 * @param[in] uint8_t value, value to write on register offset.
271 * @return returns the status of the operation.
272 */
273 int32_t apply_register_write(fxls8962_i2c_sensorhandle_t fxls8962Driver, uint8_t offset, uint8_t value);
274 /*! @brief Function to apply FXLS896x register read operation.
275 * @details This function apply FXLS896x register read based on read trigger from host.
276 * @param[in] fxls8962_i2c_sensorhandle_t fxls8962Driver, FXLS896x sensor I2C handle.
277 * @param[in] uint8_t offset, the address of the register to read from.
278 * @param[in/out] uint8_t *value, pointer to output buffer.
279 * @return returns the status of the operation.
280 */
281 int32_t apply_register_read(fxls8962_i2c_sensorhandle_t fxls8962Driver, uint8_t offset, uint8_t *value);
282 /*! @brief Function to apply FXLS896x register read-all operation.
283 * @details This function apply FXLS896x all-registers read based on read-all trigger from host.
284 * @param[in] fxls8962_i2c_sensorhandle_t fxls8962Driver, FXLS896x sensor I2C handle.
285 * @return returns the status of the operation.
286 */
287 int32_t apply_register_readall(fxls8962_i2c_sensorhandle_t fxls8962Driver);
288 /*! @brief Function to update dropdown selection.
289 * @details This function updates the dropdown selection values in real-time based on read/write/read-all triggers.
290 * @param[in/out] fxls896x_allregs_t *registers, pointer to FXLS896x all-registers metadata.
291 * @param[in] uint8_t caller, called from which operation type.
292 * @return returns the status of the operation.
293 */
294 int32_t update_dropdown_selection(fxls896x_allregs_t *registers, uint8_t caller);
295 /*! @brief Function to initialize offset noise measurement.
296 * @details This function initializes offset noise measurement metadata.
297 * @param[in/out] fxls896x_offset_noise_t *offnoiseptr, pointer to FXLS896x offset noise metadata.
298 * @return void.
299 */
300 void offset_noise_init(fxls896x_offset_noise_t *offnoiseptr);
301 /*! @brief Function to measure accelerometer offset noise.
302 * @details This function measures accelerometer offset noise.
303 * @param[in] fxls8962_acceldata_t *rawData, pointer to FXLS896x rawdata metadata.
304 * @param[in/out] fxls896x_offset_noise_t *offnoiseptr, pointer to FXLS896x offset noise metadata.
305 * @param[in] float sens, FXLS896x sensitivity based on FS configuration.
306 * @return void.
307 */
308 void accel_off_noise(fxls8962_acceldata_t* rawData, fxls896x_offset_noise_t *offnoiseptr, float sens);
309 /*! @brief Function to initialize FXLS896x self test metadata.
310 * @details This function initializes FXLS896x self test metadata.
311 * @param[in/out] fxls896x_selftest_t *selftest, pointer to FXLS896x selftest metadata.
312 * @return void.
313 */
314 void selftest_init(fxls896x_selftest_t *selftest);
315 /*! @brief Function to perform FXLS896x self test.
316 * @details This function performs FXLS896x self test.
317 * @param[in] fxls8962_i2c_sensorhandle_t fxls8962Driver, FXLS896x sensor I2C handle.
318 * @param[in/out] fxls896x_selftest_t *selftest, pointer to FXLS896x selftest metadata.
319 * @return returns the status of the operation..
320 */
321 int32_t perform_selftest(fxls8962_i2c_sensorhandle_t fxls8962Driver, fxls896x_selftest_t *selftest);
322 void FRM_Recorder_Init();
323
324 /*******************************************************************************
325 * Code
326 ******************************************************************************/
fxls896x_isr_callback(void * pUserData)327 void fxls896x_isr_callback(void *pUserData)
328 { /*! @brief Set flag to indicate Sensor has signalled data ready. */
329 bFxls896xIntFlag = true;
330 }
331
332 /* Create TSA table and add output variables. */
333 /*!
334 * @brief Target Side Addressable (TSA) table created for this application.
335 */
336 FMSTR_TSA_TABLE_BEGIN(main_table)
FMSTR_TSA_STRUCT(fxls8962_acceldata_t)337 FMSTR_TSA_STRUCT(fxls8962_acceldata_t)
338
339 FMSTR_TSA_STRUCT(fxls896x_allregs_t)
340 FMSTR_TSA_MEMBER(fxls896x_allregs_t, offset, FMSTR_TSA_UINT8)
341 FMSTR_TSA_MEMBER(fxls896x_allregs_t, value, FMSTR_TSA_UINT8)
342 FMSTR_TSA_MEMBER(fxls896x_allregs_t, trigger, FMSTR_TSA_UINT8)
343 FMSTR_TSA_MEMBER(fxls896x_allregs_t, read_offset, FMSTR_TSA_UINT8)
344 FMSTR_TSA_MEMBER(fxls896x_allregs_t, read_value, FMSTR_TSA_UINT8)
345 FMSTR_TSA_MEMBER(fxls896x_allregs_t, read_trigger, FMSTR_TSA_UINT8)
346 FMSTR_TSA_MEMBER(fxls896x_allregs_t, readall_value, FMSTR_TSA_UINT8)
347 FMSTR_TSA_MEMBER(fxls896x_allregs_t, readall_size, FMSTR_TSA_UINT8)
348 FMSTR_TSA_MEMBER(fxls896x_allregs_t, readall_trigger, FMSTR_TSA_UINT8)
349 FMSTR_TSA_MEMBER(fxls896x_allregs_t, trigger_accel_offnoise, FMSTR_TSA_UINT8)
350 FMSTR_TSA_MEMBER(fxls896x_allregs_t, trigger_selftest, FMSTR_TSA_UINT8)
351 FMSTR_TSA_MEMBER(fxls896x_allregs_t, fs_value, FMSTR_TSA_UINT8)
352 FMSTR_TSA_MEMBER(fxls896x_allregs_t, mods_value, FMSTR_TSA_UINT8)
353 FMSTR_TSA_MEMBER(fxls896x_allregs_t, odr_value, FMSTR_TSA_UINT8)
354 FMSTR_TSA_MEMBER(fxls896x_allregs_t, toggle, FMSTR_TSA_UINT8)
355 FMSTR_TSA_MEMBER(fxls896x_allregs_t, freefall_cntr, FMSTR_TSA_UINT16)
356 FMSTR_TSA_MEMBER(fxls896x_allregs_t, tapdetect_cntr, FMSTR_TSA_UINT16)
357 FMSTR_TSA_MEMBER(fxls896x_allregs_t, orient_cntr, FMSTR_TSA_UINT16)
358 FMSTR_TSA_MEMBER(fxls896x_allregs_t, vecmchange_cntr, FMSTR_TSA_UINT16)
359 FMSTR_TSA_MEMBER(fxls896x_allregs_t, reg_addr, FMSTR_TSA_UINT8)
360 FMSTR_TSA_MEMBER(fxls896x_allregs_t, accel, FMSTR_TSA_FLOAT)
361 FMSTR_TSA_MEMBER(fxls896x_allregs_t, sdcd, FMSTR_TSA_UINT8)
362 FMSTR_TSA_MEMBER(fxls896x_allregs_t, temp, FMSTR_TSA_SINT8)
363 FMSTR_TSA_MEMBER(fxls896x_allregs_t, selftest, FMSTR_TSA_SINT16)
364 FMSTR_TSA_MEMBER(fxls896x_allregs_t, dataready_cntr, FMSTR_TSA_UINT8)
365
366 FMSTR_TSA_STRUCT(fxls896x_offset_noise_t)
367 FMSTR_TSA_MEMBER(fxls896x_offset_noise_t, offx, FMSTR_TSA_FLOAT)
368 FMSTR_TSA_MEMBER(fxls896x_offset_noise_t, offy, FMSTR_TSA_FLOAT)
369 FMSTR_TSA_MEMBER(fxls896x_offset_noise_t, offz, FMSTR_TSA_FLOAT)
370 FMSTR_TSA_MEMBER(fxls896x_offset_noise_t, rmsx, FMSTR_TSA_FLOAT)
371 FMSTR_TSA_MEMBER(fxls896x_offset_noise_t, rmsy, FMSTR_TSA_FLOAT)
372 FMSTR_TSA_MEMBER(fxls896x_offset_noise_t, rmsz, FMSTR_TSA_FLOAT)
373 FMSTR_TSA_MEMBER(fxls896x_offset_noise_t, complete_accel_offnoise, FMSTR_TSA_UINT8)
374
375
376 FMSTR_TSA_STRUCT(fxls896x_selftest_t)
377 FMSTR_TSA_MEMBER(fxls896x_selftest_t, x_stoc, FMSTR_TSA_SINT16)
378 FMSTR_TSA_MEMBER(fxls896x_selftest_t, y_stoc, FMSTR_TSA_SINT16)
379 FMSTR_TSA_MEMBER(fxls896x_selftest_t, z_stoc, FMSTR_TSA_SINT16)
380 FMSTR_TSA_MEMBER(fxls896x_selftest_t, x_stof, FMSTR_TSA_SINT16)
381 FMSTR_TSA_MEMBER(fxls896x_selftest_t, y_stof, FMSTR_TSA_SINT16)
382 FMSTR_TSA_MEMBER(fxls896x_selftest_t, z_stof, FMSTR_TSA_SINT16)
383 FMSTR_TSA_MEMBER(fxls896x_selftest_t, complete_selftest, FMSTR_TSA_UINT8)
384
385 FMSTR_TSA_RO_VAR(rawData, FMSTR_TSA_USERTYPE(fxls8962_acceldata_t))
386
387 FMSTR_TSA_RW_VAR(registers, FMSTR_TSA_USERTYPE(fxls896x_allregs_t))
388
389 FMSTR_TSA_RO_VAR(offnoise_data, FMSTR_TSA_USERTYPE(fxls896x_offset_noise_t))
390
391 FMSTR_TSA_RO_VAR(selftest, FMSTR_TSA_USERTYPE(fxls896x_selftest_t))
392
393 FMSTR_TSA_TABLE_END()
394
395 FMSTR_TSA_TABLE_LIST_BEGIN()
396 FMSTR_TSA_TABLE(main_table)
397 FMSTR_TSA_TABLE_LIST_END()
398
399 /*!
400 * @brief FreeMASTER recorder initialization
401 */
402 void FRM_Recorder_Init()
403 {
404 /* Do local configuration of additional recorder */
405
406 /* Setup the additional recorder raw buffer */
407 recBuffCfg.addr = recBuffer;
408 recBuffCfg.size = sizeof(recBuffer);
409 recBuffCfg.basePeriod_ns = 0; /* Unknown period */
410 recBuffCfg.name = "FXLS896x 3-Axis Accelerometer Data";
411
412 FMSTR_RecorderCreate(1, &recBuffCfg);
413 }
414
415 /*!
416 * @brief Main function
417 */
418
main(void)419 int main(void)
420 {
421 int32_t status;
422 uint8_t whoami = 0;
423 uint8_t regdata;
424 float sensitivity = ACCEL_4G_SENS;
425
426 ARM_DRIVER_I2C *I2Cdrv = &I2C_S_DRIVER; // Now using the shield.h value!!!
427 GENERIC_DRIVER_GPIO *pGpioDriver = &Driver_GPIO_KSDK;
428 fxls8962_i2c_sensorhandle_t fxls8962Driver;
429
430 /*! Initialize the MCU hardware. */
431 BOARD_InitPins();
432 BOARD_BootClockRUN();
433 BOARD_SystickEnable();
434 BOARD_InitDebugConsole();
435
436 /*! Initialize FXLS8962_INT1 pin used by FRDM board */
437 pGpioDriver->pin_init(&FXLS8962_INT1, GPIO_DIRECTION_IN, NULL, &fxls896x_isr_callback, NULL);
438
439 /*! Initialize RGB LED pin used by FRDM board */
440 pGpioDriver->pin_init(&GREEN_LED, GPIO_DIRECTION_OUT, NULL, NULL, NULL);
441
442 /*! FreeMASTER communication layer initialization */
443 init_freemaster_uart();
444
445 /*! Initialize the I2C driver. */
446 status = I2Cdrv->Initialize(I2C_S_SIGNAL_EVENT);
447 if (ARM_DRIVER_OK != status)
448 {
449 return -1;
450 }
451
452 /*! Set the I2C Power mode. */
453 status = I2Cdrv->PowerControl(ARM_POWER_FULL);
454 if (ARM_DRIVER_OK != status)
455 {
456 return -1;
457 }
458
459 /*! Set the I2C bus speed. */
460 status = I2Cdrv->Control(ARM_I2C_BUS_SPEED, ARM_I2C_BUS_SPEED_FAST);
461 if (ARM_DRIVER_OK != status)
462 {
463 return -1;
464 }
465
466 /*! Initialize FXLS8962 sensor driver. */
467 status = FXLS8962_I2C_Initialize(&fxls8962Driver, &I2C_S_DRIVER, I2C_S_DEVICE_INDEX, FXLS8962_I2C_ADDR,
468 &whoami);
469 if (SENSOR_ERROR_NONE != status)
470 {
471 return status;
472 }
473
474 /*! Set the task to be executed while waiting for I2C transactions to complete. */
475 FXLS8962_I2C_SetIdleTask(&fxls8962Driver, (registeridlefunction_t)SMC_SetPowerModeVlpr, SMC);
476
477 /*! Configure the FXLS8962 sensor. */
478 status = FXLS8962_I2C_Configure(&fxls8962Driver, cFxls8962ConfigNormal);
479 if (SENSOR_ERROR_NONE != status)
480 {
481 return status;
482 }
483
484 /*! FreeMASTER Driver Initialization */
485 FMSTR_Init();
486
487 /*! FreeMASTER Recorder Initialization */
488 FRM_Recorder_Init();
489
490 /*! Initialize trigger flags */
491 registers.toggle = 1;
492 registers.trigger = 0;
493 registers.read_trigger = 0;
494 registers.read_value = 0;
495 registers.readall_trigger = 0;
496 registers.trigger_accel_offnoise=0;
497 registers.trigger_selftest=0;
498 registers.dataready_cntr = 0;
499 registers.selftest[0]=0;
500 registers.selftest[1]=0;
501 registers.selftest[2]=0;
502
503 for(int i = 0; i < FXLS896x_NUM_REGISTERS; i++)
504 {
505 registers.readall_value[i] = 0;
506 }
507
508 for (;;) /* Forever loop */
509 {
510
511 /*! Calling Recorder#0 in execution loop for generic high-speed variables sampling. */
512 FMSTR_Recorder(0);
513
514 /*! FreeMASTER host communication polling mode */
515 FMSTR_Poll();
516
517 /*! Check for any write register trigger from Host */
518 if (registers.trigger == 1)
519 {
520 /*! Apply Register Write */
521 status = apply_register_write(fxls8962Driver, registers.offset, registers.value);
522 if (SENSOR_ERROR_NONE != status)
523 {
524 return status;
525 }
526 registers.trigger = 0;
527 /*! Update drop down menu selection based on updated register write */
528 update_dropdown_selection(®isters, FXLS896x_REG_WRITE);
529 }
530
531 /*! Check for any read register trigger from Host */
532 if (registers.read_trigger == 1)
533 {
534 /*! Apply Register Write */
535 status = apply_register_read(fxls8962Driver, registers.read_offset, &(registers.read_value));
536 if (SENSOR_ERROR_NONE != status)
537 {
538 return status;
539 }
540 registers.read_trigger = 0;
541 /*! Update drop down menu selection based on updated register read */
542 update_dropdown_selection(®isters, FXLS896x_REG_READ);
543 }
544
545 /*! Check for any read all register trigger from Host */
546 if (registers.readall_trigger == 1)
547 {
548 /*! Apply Register Write */
549 status = apply_register_readall(fxls8962Driver);
550 if (SENSOR_ERROR_NONE != status)
551 {
552 return status;
553 }
554 registers.readall_trigger = 0;
555 registers.readall_size = FXLS896x_NUM_REGISTERS;
556 /*! Update drop down menu selection based on updated all register read */
557 update_dropdown_selection(®isters, FXLS896x_ALLREG_READ);
558 }
559
560 /*! Wait for data ready interrupt from the FXLS8962. */
561 if (false == bFxls896xIntFlag)
562 { /* Loop, if new sample is not available. */
563 SMC_SetPowerModeWait(SMC);
564 continue;
565 }
566 else
567 { /*! Clear the data ready flag, it will be set again by the ISR. */
568 bFxls896xIntFlag = false;
569 pGpioDriver->toggle_pin(&GREEN_LED);
570 }
571
572 /*! Calling Recorder#1 for sampling sensor data when we get sensor data ready interrupt based on ODR. */
573 FMSTR_Recorder(1);
574
575
576 /*! Read new raw sensor data from the FXLS8962. */
577 status = FXLS8962_I2C_ReadData(&fxls8962Driver, FXLS896x_ALL_REG_READ, registers.reg_addr);
578 if (ARM_DRIVER_OK != status)
579 {
580 return -1;
581 }
582
583 registers.temp = registers.reg_addr[1]+25;
584 registers.sdcd = (registers.reg_addr[0] & 0x10)>>4;
585
586 /*! Convert the raw sensor data to signed 16-bit container for display to the debug port. */
587 rawData.accel[0] = (int16_t)(((int16_t)(((int16_t)registers.reg_addr[3] << 8) | registers.reg_addr[2])));
588 rawData.accel[1] = (int16_t)(((int16_t)(((int16_t)registers.reg_addr[5] << 8) | registers.reg_addr[4])));
589 rawData.accel[2] = (int16_t)(((int16_t)(((int16_t)registers.reg_addr[7] << 8) | registers.reg_addr[6])));
590
591 status = FXLS8962_I2C_ReadData(&fxls8962Driver, cFXLS896x_whoami, (uint8_t *)®isters.reg_addr[13]);
592
593 /*! Check the FS and apply sensitivity */
594 status = FXLS8962_I2C_ReadData(&fxls8962Driver, cFXLS896x_fs_src, ®data);
595 if ((regdata & FXLS8962_SENS_CONFIG1_FSR_MASK) == 2)
596 {
597 sensitivity = ACCEL_4G_SENS;
598 }
599 else if ((regdata & FXLS8962_SENS_CONFIG1_FSR_MASK) == 4)
600 {
601 sensitivity = ACCEL_8G_SENS;
602 }
603 else if ((regdata & FXLS8962_SENS_CONFIG1_FSR_MASK) == 6)
604 {
605 sensitivity = ACCEL_16G_SENS;
606 }
607 else
608 {
609 sensitivity = ACCEL_2G_SENS;
610 }
611
612 /*! Convert raw values to Gs */
613 registers.accel[0] = (float) (rawData.accel[0] * sensitivity);
614 registers.accel[1] = (float) (rawData.accel[1] * sensitivity);
615 registers.accel[2] = (float) (rawData.accel[2] * sensitivity);
616
617 /*! Increment data ready counter and check for rollover */
618 registers.dataready_cntr++;
619 if(MAX8BITSTORAGE == registers.dataready_cntr)
620 {
621 registers.dataready_cntr = 0;
622 }
623
624 if (prev_toggle != registers.toggle)
625 {
626 pGpioDriver->toggle_pin(&GREEN_LED);
627 prev_toggle = registers.toggle;
628 }
629
630 /*! Call offset and noise calculation function for FXLS896x */
631 if (registers.trigger_accel_offnoise == 1)
632 {
633 accel_off_noise(&(rawData), &(offnoise_data), sensitivity);
634 if (offnoise_data.complete_accel_offnoise == 1)
635 {
636 registers.trigger_accel_offnoise = 0;
637 }
638 }
639
640 /*! Call self-test function */
641 if (registers.trigger_selftest == 1)
642 {
643 perform_selftest(fxls8962Driver, &selftest);
644 if (selftest.complete_selftest == 1)
645 {
646 registers.trigger_selftest = 0;
647
648 /*! Re-Configure the FXLS8962 sensor to default configuration */
649 status = FXLS8962_I2C_Configure(&fxls8962Driver, cFxls8962ConfigNormal);
650 if (SENSOR_ERROR_NONE != status)
651 {
652 return status;
653 }
654 }
655 }
656
657 }
658 }
659
660
661 /*!
662 * @brief Service register write trigger from Host
663 */
apply_register_write(fxls8962_i2c_sensorhandle_t fxls8962Driver,uint8_t offset,uint8_t value)664 int32_t apply_register_write(fxls8962_i2c_sensorhandle_t fxls8962Driver, uint8_t offset, uint8_t value)
665 {
666 int32_t status;
667
668 if (offset > FXLS896x_NUM_REGISTERS)
669 {
670 return SENSOR_ERROR_INVALID_PARAM;
671 }
672
673 registerwritelist_t fxls896x_register_write[] = {
674 /*! Set register offset with provided value */
675 {offset, value, 0},
676 __END_WRITE_DATA__};
677
678 status = FXLS8962_I2C_Configure(&fxls8962Driver, fxls896x_register_write);
679 if (SENSOR_ERROR_NONE != status)
680 {
681 return SENSOR_ERROR_WRITE;
682 }
683
684 return SENSOR_ERROR_NONE;
685 }
686
687 /*!
688 * @brief Service register read trigger from Host
689 */
apply_register_read(fxls8962_i2c_sensorhandle_t fxls8962Driver,uint8_t read_offset,uint8_t * read_value)690 int32_t apply_register_read(fxls8962_i2c_sensorhandle_t fxls8962Driver, uint8_t read_offset, uint8_t *read_value)
691 {
692 int32_t status;
693
694 if (read_offset > FXLS896x_NUM_REGISTERS)
695 {
696 return SENSOR_ERROR_INVALID_PARAM;
697 }
698
699 registerreadlist_t fxls896x_register_read[] = {
700 /*! Set register offset with provided value */
701 {.readFrom = read_offset, .numBytes = 1}, __END_READ_DATA__};
702
703 status = FXLS8962_I2C_ReadData(&fxls8962Driver, fxls896x_register_read, read_value);
704 if (SENSOR_ERROR_NONE != status)
705 {
706 return SENSOR_ERROR_WRITE;
707 }
708
709 return SENSOR_ERROR_NONE;
710 }
711
712 /*!
713 * @brief Service register read all trigger from Host
714 */
apply_register_readall(fxls8962_i2c_sensorhandle_t fxls8962Driver)715 int32_t apply_register_readall(fxls8962_i2c_sensorhandle_t fxls8962Driver)
716 {
717 int32_t status;
718
719 for (int reg_offset = FXLS8962_INT_STATUS; reg_offset <= FXLS8962_SELF_TEST_CONFIG2; reg_offset++)
720 {
721 registerreadlist_t fxls896x_register_readall[] = {
722 /*! Set register offset with provided value */
723 {.readFrom = reg_offset, .numBytes = 1}, __END_READ_DATA__};
724
725 status = FXLS8962_I2C_ReadData(&fxls8962Driver, fxls896x_register_readall, &(registers.readall_value[reg_offset]));
726 if (SENSOR_ERROR_NONE != status)
727 {
728 return SENSOR_ERROR_READ;
729 }
730 }
731
732 return SENSOR_ERROR_NONE;
733 }
734
735 /*!
736 * @brief Update drop down selection values based on register write, read or readall.
737 */
update_dropdown_selection(fxls896x_allregs_t * registers,uint8_t caller)738 int32_t update_dropdown_selection(fxls896x_allregs_t *registers, uint8_t caller)
739 {
740
741 int32_t status = SENSOR_ERROR_NONE;
742
743 switch (caller)
744 {
745 case FXLS896x_REG_WRITE:
746
747 /*! Update drop down option based on updated read value */
748 if(FXLS8962_SENS_CONFIG1 == registers->offset) //FS Selection
749 {
750 registers->fs_value = registers->value;
751 }
752 else if (FXLS8962_SENS_CONFIG2 == registers->offset)
753 {
754 registers->mods_value = registers->value;
755 }
756 else if (FXLS8962_SENS_CONFIG3 == registers->offset)
757 {
758 registers->odr_value = registers->value;
759 }
760 break;
761 case FXLS896x_REG_READ: //Called from Register Read
762
763 /*! Update drop down option based on updated read value */
764 if(FXLS8962_SENS_CONFIG1 == registers->read_offset) //FS Selection
765 {
766 registers->fs_value = registers->read_value;
767 }
768 else if (FXLS8962_SENS_CONFIG2 == registers->read_offset)
769 {
770 registers->mods_value = registers->read_value;
771 }
772 else if (FXLS8962_SENS_CONFIG3 == registers->read_offset)
773 {
774 registers->odr_value = registers->read_value;
775 }
776 break;
777 case FXLS896x_ALLREG_READ: //Called from Register ReadAll
778
779 /*! Update drop down option based on updated read values */
780 registers->fs_value = registers->reg_addr[FXLS8962_SENS_CONFIG1];
781 registers->mods_value = registers->reg_addr[FXLS8962_SENS_CONFIG2];
782 registers->odr_value = registers->reg_addr[FXLS8962_SENS_CONFIG3];
783 break;
784 default:
785 status = SENSOR_ERROR_INVALID_PARAM;
786 break;
787 }
788
789 return status;
790
791 }
792
793 /*******************************************************************************
794 * OFFSET NOISE CALCULATION
795 ******************************************************************************/
796
797 /*!
798 * @brief Initialize Offset-Noise Variables
799 */
offset_noise_init(fxls896x_offset_noise_t * offnoiseptr)800 void offset_noise_init(fxls896x_offset_noise_t *offnoiseptr)
801 {
802 offnoiseptr->offx = 0.0;
803 offnoiseptr->offy = 0.0;
804 offnoiseptr->offz = 0.0;
805 offnoiseptr->rmsx = 0.0;
806 offnoiseptr->rmsy = 0.0;
807 offnoiseptr->rmsz = 0.0;
808 offnoiseptr->complete_accel_offnoise = 0;
809 }
810
811
812 /* Calculate Offset & Noise for FXLS896x */
accel_off_noise(fxls8962_acceldata_t * rawData,fxls896x_offset_noise_t * offnoiseptr,float sens)813 void accel_off_noise(fxls8962_acceldata_t* rawData, fxls896x_offset_noise_t *offnoiseptr, float sens)
814 {
815 uint16_t j;
816 static uint16_t k=0;
817 static uint16_t cntr=0;
818 static float stdx=0;
819 static float stdy=0;
820 static float stdz=0;
821 static float xx[N], yy[N], zz[N];
822 static float xm[N], ym[N], zm[N];
823 static float xsq[N], ysq[N], zsq[N];
824 float am[3];
825 static float sumx=0.0;
826 static float sumy=0.0;
827 static float sumz=0.0;
828
829 /* Init offset noise variables */
830 offset_noise_init(offnoiseptr);
831
832 cntr++;
833
834 /* Store Accel samples and calculate sum for configured N */
835 if(cntr < N)
836 {
837 am[0]=rawData->accel[0]*sens;
838 am[1]=rawData->accel[1]*sens;
839 am[2]=rawData->accel[2]*sens;
840 xx[k]=am[0];
841 yy[k]=am[1];
842 zz[k]=am[2];
843 sumx+=am[0];
844 sumy+=am[1];
845 sumz+=am[2];
846 k+=1;
847 offnoiseptr->complete_accel_offnoise = 0;
848 }
849
850 /* Measure offset and RMS */
851 if(cntr == N)
852 {
853 /* Measure average */
854 sumx=sumx/(N-1);
855 sumy=sumy/(N-1);
856 sumz=sumz/(N-1);
857
858 /* Measure offset */
859 offnoiseptr->offx=0-sumx;
860 offnoiseptr->offy=0-sumy;
861 offnoiseptr->offz=1-sumz;
862
863 /* Measure standard deviation */
864 for(j=0; j<N-1; j++)
865 {
866 xm[j]=xx[j]-sumx;
867 ym[j]=yy[j]-sumy;
868 zm[j]=zz[j]-sumz;
869
870 xsq[j]=pow(xm[j],2);
871 ysq[j]=pow(ym[j],2);
872 zsq[j]=pow(zm[j],2);
873 stdx+=xsq[j];
874 stdy+=ysq[j];
875 stdz+=zsq[j];
876 }
877 stdx=stdx/(N-2);
878 stdy=stdy/(N-2);
879 stdz=stdz/(N-2);
880
881 /* Measure RMS */
882 offnoiseptr->rmsx=pow(stdx,0.5);
883 offnoiseptr->rmsy=pow(stdy,0.5);
884 offnoiseptr->rmsz=pow(stdz,0.5);
885
886 /* Set the completion flag */
887 offnoiseptr->complete_accel_offnoise = 1;
888
889 /* Reset local storage */
890 cntr = k = 0;
891 sumx = sumy = sumz = 0;
892 stdx = stdy = stdz = 0;
893 }
894 }
895
896 /*!
897 * @brief Initialize Offset-Noise Variables
898 */
selftest_init(fxls896x_selftest_t * selftest)899 void selftest_init(fxls896x_selftest_t *selftest)
900 {
901 selftest->x_stoc = 0;
902 selftest->y_stoc = 0;
903 selftest->z_stoc = 0;
904 selftest->x_stof = 0;
905 selftest->y_stof = 0;
906 selftest->z_stof = 0;
907 selftest->complete_selftest = 0;
908 }
909
910
perform_selftest(fxls8962_i2c_sensorhandle_t fxls8962Driver,fxls896x_selftest_t * selftest)911 int32_t perform_selftest(fxls8962_i2c_sensorhandle_t fxls8962Driver, fxls896x_selftest_t *selftest)
912 {
913 int32_t status;
914
915 axis=0;
916
917 /* Initialize self-test parameters */
918 selftest_init(selftest);
919
920 while (axis<6)
921 {
922
923 switch(axis)
924 {
925 case 0:status = FXLS8962_I2C_Configure(&fxls8962Driver, cFxls8962STXP);break;
926 case 1:status = FXLS8962_I2C_Configure(&fxls8962Driver, cFxls8962STXN);break;
927 case 2:status = FXLS8962_I2C_Configure(&fxls8962Driver, cFxls8962STYP);break;
928 case 3:status = FXLS8962_I2C_Configure(&fxls8962Driver, cFxls8962STYN);break;
929 case 4:status = FXLS8962_I2C_Configure(&fxls8962Driver, cFxls8962STZP);break;
930 case 5:status = FXLS8962_I2C_Configure(&fxls8962Driver, cFxls8962STZN);break;
931 default:break;
932 }
933
934 if (ARM_DRIVER_OK != status)
935 {
936 return status;
937 }
938
939 int counter =0;
940 for(counter=0;counter<1;counter++)
941 {
942
943 // In ISR Mode we do not need to check Data Ready Register.
944 // The receipt of interrupt will indicate data is ready.
945 RAW_DATA data_ = {0x00};
946 while(false == bFxls896xIntFlag)
947 {
948
949 }
950
951 /*! Set device to Standby mode. */
952 Register_I2C_Write(&I2C_S_DRIVER,&(fxls8962Driver.deviceInfo),FXLS8962_I2C_ADDR, FXLS8962_SENS_CONFIG1,0x00,0x00,0x00);
953 if (ARM_DRIVER_OK != status)
954 {
955 return SENSOR_ERROR_WRITE;
956 }
957
958
959 bFxls896xIntFlag = false;
960 //pGpioDriver->toggle_pin(&RED_LED);
961
962 /*! Read new raw sensor data from the FXLS8962. */
963 status = FXLS8962_I2C_ReadData(&fxls8962Driver, cFxls8962OutputNormal, &data_.byte_data[0]);
964 if (ARM_DRIVER_OK != status)
965 { /* Read did not work, so loop. */
966 continue;
967 }
968
969 /* store the self-test values for each axis & for each polarity*/
970 switch(axis)
971 {
972 case 0: XSTP[counter]= data_.dat.xdata;break;
973 case 1: XSTN[counter]= data_.dat.xdata;break;
974 case 2: YSTP[counter]= data_.dat.ydata;break;
975 case 3: YSTN[counter]= data_.dat.ydata;break;
976 case 4: ZSTP[counter]= data_.dat.zdata;break;
977 case 5: ZSTN[counter]= data_.dat.zdata;break;
978 default:break;
979 }
980
981 }
982
983 BOARD_DELAY_ms(1000);
984 axis++;
985 }
986
987 /* compute self-test output change*/
988 selftest->x_stoc=(XSTP[0]-XSTN[0])/2;
989 selftest->y_stoc=(YSTP[0]-YSTN[0])/2;
990 selftest->z_stoc=(ZSTP[0]-ZSTN[0])/2;
991
992 /* compute self-test offset*/
993 selftest->x_stof=(XSTP[0]+XSTN[0])/2;
994 selftest->y_stof=(YSTP[0]+YSTN[0])/2;
995 selftest->z_stof=(ZSTP[0]+ZSTN[0])/2;
996
997 selftest->complete_selftest = 1;
998 return SENSOR_ERROR_NONE;
999 }
1000
1001 /*!
1002 * @brief UART Module initialization (UART is a the standard block included e.g. in K22F)
1003 */
init_freemaster_uart(void)1004 static void init_freemaster_uart(void)
1005 {
1006 uart_config_t config;
1007
1008 /*
1009 * config.baudRate_Bps = 115200U;
1010 * config.parityMode = kUART_ParityDisabled;
1011 * config.stopBitCount = kUART_OneStopBit;
1012 * config.txFifoWatermark = 0;
1013 * config.rxFifoWatermark = 1;
1014 * config.enableTx = false;
1015 * config.enableRx = false;
1016 */
1017 UART_GetDefaultConfig(&config);
1018 config.baudRate_Bps = 115200U;
1019 config.enableTx = false;
1020 config.enableRx = false;
1021
1022 UART_Init((UART_Type*)BOARD_DEBUG_UART_BASEADDR, &config, BOARD_DEBUG_UART_CLK_FREQ);
1023
1024 /* Register communication module used by FreeMASTER driver. */
1025 FMSTR_SerialSetBaseAddress((UART_Type*)BOARD_DEBUG_UART_BASEADDR);
1026
1027 #if FMSTR_SHORT_INTR || FMSTR_LONG_INTR
1028 /* Enable UART interrupts. */
1029 EnableIRQ(BOARD_UART_IRQ);
1030 EnableGlobalIRQ(0);
1031 #endif
1032 }
1033
1034 #if FMSTR_SHORT_INTR || FMSTR_LONG_INTR
1035 /*
1036 * Application interrupt handler of communication peripheral used in interrupt modes
1037 * of FreeMASTER communication.
1038 *
1039 * NXP MCUXpresso SDK framework defines interrupt vector table as a part of "startup_XXXXXX.x"
1040 * assembler/C file. The table points to weakly defined symbols, which may be overwritten by the
1041 * application specific implementation. FreeMASTER overrides the original weak definition and
1042 * redirects the call to its own handler.
1043 *
1044 */
1045
BOARD_UART_IRQ_HANDLER(void)1046 void BOARD_UART_IRQ_HANDLER(void)
1047 {
1048 /* Call FreeMASTER Interrupt routine handler */
1049 FMSTR_SerialIsr();
1050 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
1051 exception return operation might vector to incorrect interrupt */
1052 #if defined __CORTEX_M && (__CORTEX_M == 4U)
1053 __DSB();
1054 #endif
1055 }
1056 #endif
1057
1058