1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016-2017 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 /**
10 * @file auto_detection_service.c
11 * @brief The auto detection service file implements auto detection sequence
12 * for discovery of LPC Board and Sensor Shield Board.
13 */
14
15 #include <stdio.h>
16 #include <stdint.h>
17
18 #include "diff_p.h"
19 #include "mma9553.h"
20 #include "mpl3115.h"
21 #include "mag3110.h"
22 #include "mma865x.h"
23 #include "fxls8962.h"
24 #include "fxpq3115.h"
25 #include "fxos8700.h"
26 #include "fxas21002.h"
27 #include "fxlc95000.h"
28 #include "fxls8471q.h"
29
30 #include "issdk_hal.h"
31 #include "gpio_driver.h"
32 #include "systick_utils.h"
33 #include "register_io_spi.h"
34 #include "register_io_i2c.h"
35 #include "auto_detection_shield.h"
36 #include "auto_detection_service.h"
37
38 #include "fsl_flashiap.h"
39
40 /*******************************************************************************
41 * Definitions
42 ******************************************************************************/
43 /*!
44 * @brief These variables are specific to SPI access to the FXLS8471 for ADS.
45 */
46 #define FXLS8471Q_SPI_CMD_LEN (2)
47 #define FXLS8471Q_SS_ACTIVE_VALUE SPI_SS_ACTIVE_LOW
48
49 /*!
50 * @brief These variables are specific to SPI access to the FXLS8962 for ADS.
51 */
52 #define FXLS8962_SPI_CMD_LEN (2)
53 #define FXLS8962_SS_ACTIVE_VALUE SPI_SS_ACTIVE_LOW
54
55 /*!
56 * @brief These variables are specific to SPI access to the DIFF_P for ADS.
57 */
58 #define DIFF_P_SPI_CMD_LEN (1)
59 #define DIFF_P_SS_ACTIVE_VALUE SPI_SS_ACTIVE_LOW
60 #define ADS_NVM_SECTOR_NUM (ADS_NVM_ADDR / FSL_FEATURE_SYSCON_FLASH_SECTOR_SIZE_BYTES)
61
62 #define ADS_QUERY_NUM (sizeof(ADS_SensorQueryList) / sizeof(sensorAccess_t))
63 #define ADS_NUM_BOARDS (sizeof(gADS_QueryMap) / ADS_QUERY_NUM)
64 #define SPI_MAX_MSG_SIZE (64)
65
66 /*******************************************************************************
67 * Constants
68 ******************************************************************************/
69 /*! @brief The Read Version Info Command for FXLC95000. */
70 const uint8_t ReadVersionInfo_MMA9553[4] = {0x00, 0x00, 0x00, 0x0C};
71
72 /*!
73 * @brief This constant data structure contains the expected valid MCU Device ID combinations.
74 * Refer : LPC5411x User manual - UM10914, Section: 33.5.12
75 */
76 const mcuDEVID_t ADS_ValidDEVIDValues[] = {
77 {0x06254113, ADS_LPC_54113J128}, // LPC-54113J128
78 {0x36454113, ADS_LPC_54113J256}, // LPC-54113J256
79 {0x36454114, ADS_LPC_54114J256}, // LPC-54114J256
80 };
81
82 /*!
83 * @brief This constant data structure contains the expected valid comm/sensor/who_am_i combinations.
84 */
85 const sensorAccess_t ADS_SensorQueryList[] = {
86 {ADS_SPI_DEV, FXLS8471, FXLS8471Q_WHO_AM_I, FXLS8471Q_WHO_AM_I_WHOAMI_VALUE, 0xFF},
87 {ADS_SPI_DEV, FXLS8962, FXLS8962_WHO_AM_I, FXLS8962_WHOAMI_VALUE, 0xFF},
88 {ADS_SPI_DEV, DIFF_P, DIFF_P_WHO_AM_I, DIFF_P_NPS3000VV_WHOAMI_VALUE, 0xFC},
89 {ADS_I2C_EXT, FXLS8962_I2C_ADDR, FXLS8962_WHO_AM_I, FXLS8962_WHOAMI_VALUE, 0xFF},
90 {ADS_I2C_EXT, FXAS21002_I2C_ADDR, FXAS21002_WHO_AM_I, FXAS21002_WHO_AM_I_WHOAMI_PROD_VALUE, 0xFF},
91 {ADS_I2C_EXT, FXLC95000, ADS_NO_WHO_AM_I, ADS_NO_WHO_AM_I, 0xFF},
92 {ADS_I2C_EXT, FXOS8700_I2C_ADDR, FXOS8700_WHO_AM_I, FXOS8700_WHO_AM_I_PROD_VALUE, 0xFF},
93 {ADS_I2C_EXT, FXPQ3115_I2C_ADDR, FXPQ3115_WHO_AM_I, FXPQ3115_WHOAMI_VALUE, 0xFF},
94 {ADS_I2C_EXT, MAG3110_I2C_ADDR, MAG3110_WHO_AM_I, MAG3110_WHOAMI_VALUE, 0xFF},
95 {ADS_I2C_EXT, MMA8652_I2C_ADDR, MMA865x_WHO_AM_I, MMA8652_WHOAMI_VALUE, 0xFF},
96 {ADS_I2C_EXT, MMA9553, ADS_NO_WHO_AM_I, ADS_NO_WHO_AM_I, 0xFF},
97 {ADS_I2C_EXT, DIFF_P_I2C_ADDR, DIFF_P_WHO_AM_I, DIFF_P_NPS3000VV_WHOAMI_VALUE, 0xFC},
98 {ADS_I2C_EXT, MPL3115_I2C_ADDR, MPL3115_WHO_AM_I, MPL3115_WHOAMI_VALUE, 0xFF},
99 };
100
101 /*!
102 * @brief These are the expected query signatures for the shield boards.
103 */
104 const ADS_Status_t gADS_QueryMap[][ADS_QUERY_NUM] = {
105 {
106 // FRDM-STBC-AGM01
107 ADS_FAIL, // FXLS8471
108 ADS_FAIL, // FXLS8962
109 ADS_FAIL, // DIFF-P
110 ADS_FAIL, // FXLS8962
111 ADS_OK, // FXAS21002
112 ADS_FAIL, // FXLC95000
113 ADS_OK, // FXOS8700
114 ADS_FAIL, // FXPQ3115
115 ADS_FAIL, // MAG3110
116 ADS_FAIL, // MMA865x
117 ADS_FAIL, // MMA9553
118 ADS_FAIL, // DIFF-P
119 ADS_FAIL, // MPL3115
120 },
121 {
122 // FRDM-STBC-SA9500
123 ADS_FAIL, // FXLS8471
124 ADS_FAIL, // FXLS8962
125 ADS_FAIL, // DIFF-P
126 ADS_FAIL, // FXLS8962
127 ADS_FAIL, // FXAS21002
128 ADS_OK, // FXLC95000
129 ADS_FAIL, // FXOS8700
130 ADS_FAIL, // FXPQ3115
131 ADS_FAIL, // MAG3110
132 ADS_FAIL, // MMA865x
133 ADS_FAIL, // MMA9553
134 ADS_FAIL, // DIFF-P
135 ADS_FAIL, // MPL3115
136 },
137 {
138 // FRDMSTBC-A8471
139 ADS_OK, // FXLS8471
140 ADS_FAIL, // FXLS8962
141 ADS_FAIL, // DIFF-P
142 ADS_FAIL, // FXLS8962
143 ADS_FAIL, // FXAS21002
144 ADS_FAIL, // FXLC95000
145 ADS_FAIL, // FXOS8700
146 ADS_FAIL, // FXPQ3115
147 ADS_FAIL, // MAG3110
148 ADS_FAIL, // MMA865x
149 ADS_FAIL, // MMA9553
150 ADS_FAIL, // DIFF-P
151 ADS_FAIL, // MPL3115
152 },
153 {
154 // FRDMSTBC-P3115
155 ADS_FAIL, // FXLS8471
156 ADS_FAIL, // FXLS8962
157 ADS_FAIL, // DIFF-P
158 ADS_FAIL, // FXLS8962
159 ADS_FAIL, // FXAS21002
160 ADS_FAIL, // FXLC95000
161 ADS_FAIL, // FXOS8700
162 ADS_FAIL, // FXPQ3115
163 ADS_FAIL, // MAG3110
164 ADS_FAIL, // MMA865x
165 ADS_FAIL, // MMA9553
166 ADS_FAIL, // DIFF-P
167 ADS_OK, // MPL3115
168 },
169 {
170 // FRDMSTBC-DIFF-P SPI
171 ADS_FAIL, // FXLS8471
172 ADS_FAIL, // FXLS8962
173 ADS_OK, // DIFF-P
174 ADS_FAIL, // FXLS8962
175 ADS_FAIL, // FXAS21002
176 ADS_FAIL, // FXLC95000
177 ADS_FAIL, // FXOS8700
178 ADS_FAIL, // FXPQ3115
179 ADS_FAIL, // MAG3110
180 ADS_FAIL, // MMA865x
181 ADS_FAIL, // MMA9553
182 ADS_OK, // DIFF-P
183 ADS_FAIL, // MPL3115
184 },
185 {
186 // FRDMSTBC-DIFF-P I2C
187 ADS_FAIL, // FXLS8471
188 ADS_FAIL, // FXLS8962
189 ADS_FAIL, // DIFF-P
190 ADS_FAIL, // FXLS8962
191 ADS_FAIL, // FXAS21002
192 ADS_FAIL, // FXLC95000
193 ADS_FAIL, // FXOS8700
194 ADS_FAIL, // FXPQ3115
195 ADS_FAIL, // MAG3110
196 ADS_FAIL, // MMA865x
197 ADS_FAIL, // MMA9553
198 ADS_OK, // DIFF-P
199 ADS_FAIL, // MPL3115
200 },
201 {
202 // FRDMSTBC-B3115
203 ADS_FAIL, // FXLS8471
204 ADS_FAIL, // FXLS8962
205 ADS_FAIL, // DIFF-P
206 ADS_FAIL, // FXLS8962
207 ADS_FAIL, // FXAS21002
208 ADS_FAIL, // FXLC95000
209 ADS_FAIL, // FXOS8700
210 ADS_OK, // FXPQ3115
211 ADS_FAIL, // MAG3110
212 ADS_FAIL, // MMA865x
213 ADS_FAIL, // MMA9553
214 ADS_FAIL, // DIFF-P
215 ADS_FAIL, // MPL3115
216 },
217 {
218 // FRDM-FXS-MULT2-B
219 ADS_OK, // FXLS8471
220 ADS_FAIL, // FXLS8962
221 ADS_FAIL, // DIFF-P
222 ADS_FAIL, // FXLS8962
223 ADS_OK, // FXAS21002
224 ADS_FAIL, // FXLC95000
225 ADS_OK, // FXOS8700
226 ADS_FAIL, // FXPQ3115
227 ADS_OK, // MAG3110
228 ADS_OK, // MMA865x
229 ADS_OK, // MMA9553
230 ADS_FAIL, // DIFF-P
231 ADS_OK, // MPL3115
232 },
233 {
234 // FRDM-STBC-AGMP03 over SPI
235 ADS_FAIL, // FXLS8471
236 ADS_OK, // FXLS8962
237 ADS_FAIL, // DIFF-P
238 ADS_FAIL, // FXLS8962
239 ADS_FAIL, // FXAS21002
240 ADS_FAIL, // FXLC95000
241 ADS_FAIL, // FXOS8700
242 ADS_FAIL, // FXPQ3115
243 ADS_OK, // MAG3110
244 ADS_FAIL, // MMA865x
245 ADS_FAIL, // MMA9553
246 ADS_FAIL, // DIFF-P
247 ADS_OK, // MPL3115
248 },
249 {
250 // FRDM-STBC-AGMP03 over I2C
251 ADS_FAIL, // FXLS8471
252 ADS_FAIL, // FXLS8962
253 ADS_FAIL, // DIFF-P
254 ADS_OK, // FXLS8962
255 ADS_OK, // FXAS21002
256 ADS_FAIL, // FXLC95000
257 ADS_FAIL, // FXOS8700
258 ADS_FAIL, // FXPQ3115
259 ADS_OK, // MAG3110
260 ADS_FAIL, // MMA865x
261 ADS_FAIL, // MMA9553
262 ADS_FAIL, // DIFF-P
263 ADS_OK, // MPL3115
264 },
265 {
266 // FRDM-STBC-AGM04
267 ADS_FAIL, // FXLS8471
268 ADS_FAIL, // FXLS8962
269 ADS_FAIL, // DIFF-P
270 ADS_FAIL, // FXLS8962
271 ADS_OK, // FXAS21002
272 ADS_FAIL, // FXLC95000
273 ADS_FAIL, // FXOS8700
274 ADS_FAIL, // FXPQ3115
275 ADS_OK, // MAG3110
276 ADS_OK, // MMA865x
277 ADS_FAIL, // MMA9553
278 ADS_FAIL, // DIFF-P
279 ADS_FAIL, // MPL3115
280 },
281 };
282
283 /*******************************************************************************
284 * Global Variables
285 ******************************************************************************/
286 /*!
287 * @brief This global contains the results from the sensor query.
288 */
289 ADS_Status_t gADS_QueryResults[ADS_QUERY_NUM];
290
291 char ADS_ShieldList[][ADS_MAX_STRING_LENGTH] = {
292 "FRDM-STBC-AGM01", "FRDM-STBC-SA9500", "FRDMSTBC-A8471",
293 "FRDMSTBC-P3115", "FRDMSTBI-DP300x", "FRDMSTBI-DP300x", "FRDMSTBC-B3115",
294 "FRDM-FXS-MULT2-B", "FRDM-STBC-AGMP03", "FRDM-STBC-AGMP03", "FRDM-STBC-AGM04",
295 };
296
297 /*!
298 * @brief These values hold the ARM CMSIS Driver interface pointers.
299 */
300 ARM_DRIVER_SPI *SPIdrv = &SPI_S_DRIVER;
301 ARM_DRIVER_I2C *I2CextDrv = &I2C_S1_DRIVER;
302 GENERIC_DRIVER_GPIO *pGPIODriver = &Driver_GPIO_KSDK;
303
304 spiSlaveSpecificParams_t spiParams_8471;
305 spiSlaveSpecificParams_t spiParams_8962;
306 spiSlaveSpecificParams_t spiParams_diff_p;
307 uint8_t spiRead_CmdBuffer[SPI_MAX_MSG_SIZE] = {0};
308 uint8_t spiRead_DataBuffer[SPI_MAX_MSG_SIZE] = {0};
309 uint8_t spiWrite_CmdDataBuffer[SPI_MAX_MSG_SIZE] = {0};
310
311 /*******************************************************************************
312 * FXLS8471 SPI Specific Functions
313 *****************************************************************************/
ADS_FXLS8471Q_SPI_ReadPreprocess(void * pCmdOut,uint32_t offset,uint32_t size)314 void ADS_FXLS8471Q_SPI_ReadPreprocess(void *pCmdOut, uint32_t offset, uint32_t size)
315 {
316 spiCmdParams_t *pSlaveCmd = pCmdOut;
317
318 uint8_t *pWBuff = spiRead_CmdBuffer;
319 uint8_t *pRBuff = spiRead_DataBuffer;
320
321 /* Formatting for Read command of FXLS8471Q SENSOR. */
322 *(pWBuff) = offset & 0x7F; /* offset is the internal register address of the sensor at which write is performed. */
323 *(pWBuff + 1) = offset & 0x80;
324
325 // Create the slave read command.
326 pSlaveCmd->size = size + FXLS8471Q_SPI_CMD_LEN;
327 pSlaveCmd->pWriteBuffer = pWBuff;
328 pSlaveCmd->pReadBuffer = pRBuff;
329 }
330
ADS_FXLS8471Q_SPI_WritePreprocess(void * pCmdOut,uint32_t offset,uint32_t size,void * pWritebuffer)331 void ADS_FXLS8471Q_SPI_WritePreprocess(void *pCmdOut, uint32_t offset, uint32_t size, void *pWritebuffer)
332 {
333 spiCmdParams_t *pSlaveCmd = pCmdOut;
334
335 uint8_t *pWBuff = spiWrite_CmdDataBuffer;
336 uint8_t *pRBuff = spiWrite_CmdDataBuffer + size + FXLS8471Q_SPI_CMD_LEN;
337
338 /* Formatting for Write command of FXLS8471Q SENSOR. */
339 *(pWBuff) = offset | 0x80; /* offset is the internal register address of the sensor at which write is performed. */
340 *(pWBuff + 1) = offset & 0x80;
341
342 /* Copy the slave write command */
343 memcpy(pWBuff + FXLS8471Q_SPI_CMD_LEN, pWritebuffer, size);
344
345 /* Create the slave command. */
346 pSlaveCmd->size = size + FXLS8471Q_SPI_CMD_LEN;
347 pSlaveCmd->pWriteBuffer = pWBuff;
348 pSlaveCmd->pReadBuffer = pRBuff;
349 }
350
ADS_InitSPI_FXLS8471()351 void ADS_InitSPI_FXLS8471()
352 {
353 spiParams_8471.pReadPreprocessFN = ADS_FXLS8471Q_SPI_ReadPreprocess;
354 spiParams_8471.pWritePreprocessFN = ADS_FXLS8471Q_SPI_WritePreprocess;
355 spiParams_8471.pTargetSlavePinID = &FXLS8471_SPI_CS;
356 spiParams_8471.spiCmdLen = FXLS8471Q_SPI_CMD_LEN;
357 spiParams_8471.ssActiveValue = FXLS8471Q_SS_ACTIVE_VALUE;
358
359 /* Initialize the Slave Select Pin. */
360 pGPIODriver->pin_init(&FXLS8471_SPI_CS, GPIO_DIRECTION_OUT, NULL, NULL, NULL);
361 if (spiParams_8471.ssActiveValue == SPI_SS_ACTIVE_LOW)
362 {
363 pGPIODriver->set_pin(&FXLS8471_SPI_CS);
364 }
365 else
366 {
367 pGPIODriver->clr_pin(&FXLS8471_SPI_CS);
368 }
369 };
370
ADS_FXLS8471Query(uint8_t whoAmiAddr,uint8_t whoAmi)371 ADS_Status_t ADS_FXLS8471Query(uint8_t whoAmiAddr, uint8_t whoAmi)
372 {
373 int32_t status;
374 uint8_t reg;
375 registerDeviceInfo_t deviceInfo = {
376 .deviceInstance = SPI_S_DEVICE_INDEX, .functionParam = NULL, .idleFunction = NULL};
377
378 /*! Read and store the device's WHO_AM_I.*/
379 status = Register_SPI_Read(SPIdrv, &deviceInfo, &spiParams_8471, whoAmiAddr, 1, ®);
380 if ((ARM_DRIVER_OK != status) || (whoAmi != reg))
381 {
382 return ADS_FAIL;
383 }
384
385 return ADS_OK;
386 }
387
388 /*******************************************************************************
389 * FXLS8962 SPI Specific Functions
390 *****************************************************************************/
ADS_FXLS8962_SPI_ReadPreprocess(void * pCmdOut,uint32_t offset,uint32_t size)391 void ADS_FXLS8962_SPI_ReadPreprocess(void *pCmdOut, uint32_t offset, uint32_t size)
392 {
393 spiCmdParams_t *pSlaveCmd = pCmdOut;
394
395 uint8_t *pWBuff = spiRead_CmdBuffer;
396 uint8_t *pRBuff = spiRead_DataBuffer;
397
398 /* Formatting for Read command of FXLS8962 SENSOR. */
399 *(pWBuff) = offset | 0x80; /* offset is the internal register address of the sensor at which write is performed. */
400 *(pWBuff + 1) = 0x00;
401
402 /* Create the slave read command. */
403 pSlaveCmd->size = size + FXLS8962_SPI_CMD_LEN;
404 pSlaveCmd->pWriteBuffer = pWBuff;
405 pSlaveCmd->pReadBuffer = pRBuff;
406 }
407
ADS_FXLS8962_SPI_WritePreprocess(void * pCmdOut,uint32_t offset,uint32_t size,void * pWritebuffer)408 void ADS_FXLS8962_SPI_WritePreprocess(void *pCmdOut, uint32_t offset, uint32_t size, void *pWritebuffer)
409 {
410 spiCmdParams_t *pSlaveCmd = pCmdOut;
411
412 uint8_t *pWBuff = spiWrite_CmdDataBuffer;
413 uint8_t *pRBuff = spiWrite_CmdDataBuffer + size + FXLS8962_SPI_CMD_LEN;
414
415 /* Formatting for Write command of FXLS8962 SENSOR. */
416 *(pWBuff) = offset & 0x7F; /* offset is the internal register address of the sensor at which write is performed. */
417 *(pWBuff + 1) = 0x00;
418
419 /* Copy the slave write command */
420 memcpy(pWBuff + FXLS8962_SPI_CMD_LEN, pWritebuffer, size);
421
422 /* Create the slave command. */
423 pSlaveCmd->size = size + FXLS8962_SPI_CMD_LEN;
424 pSlaveCmd->pWriteBuffer = pWBuff;
425 pSlaveCmd->pReadBuffer = pRBuff;
426 }
427
ADS_InitSPI_FXLS8962()428 void ADS_InitSPI_FXLS8962()
429 { /*! Initialize the sensor handle. */
430 spiParams_8962.pReadPreprocessFN = ADS_FXLS8962_SPI_ReadPreprocess;
431 spiParams_8962.pWritePreprocessFN = ADS_FXLS8962_SPI_WritePreprocess;
432 spiParams_8962.pTargetSlavePinID = &FXLS8962_CS;
433 spiParams_8962.spiCmdLen = FXLS8962_SPI_CMD_LEN;
434 spiParams_8962.ssActiveValue = FXLS8962_SS_ACTIVE_VALUE;
435
436 /* Initialize the Slave Select Pin. */
437 pGPIODriver->pin_init(&FXLS8962_CS, GPIO_DIRECTION_OUT, NULL, NULL, NULL);
438 if (spiParams_8962.ssActiveValue == SPI_SS_ACTIVE_LOW)
439 {
440 pGPIODriver->set_pin(&FXLS8962_CS);
441 }
442 else
443 {
444 pGPIODriver->clr_pin(&FXLS8962_CS);
445 }
446 };
447
ADS_FXLS8962Query(uint8_t whoAmiAddr,uint8_t whoAmi)448 ADS_Status_t ADS_FXLS8962Query(uint8_t whoAmiAddr, uint8_t whoAmi)
449 {
450 int32_t status;
451 uint8_t reg;
452 registerDeviceInfo_t deviceInfo = {
453 .deviceInstance = SPI_S_DEVICE_INDEX, .functionParam = NULL, .idleFunction = NULL};
454
455 /*! Read and store the device's WHO_AM_I.*/
456 status = Register_SPI_Read(SPIdrv, &deviceInfo, &spiParams_8962, whoAmiAddr, 1, ®);
457 if ((ARM_DRIVER_OK != status) || (whoAmi != reg))
458 {
459 return ADS_FAIL;
460 }
461
462 return ADS_OK;
463 }
464
465 /*******************************************************************************
466 * DIFF-P SPI Specific Functions
467 *****************************************************************************/
ADS_DIFF_P_SPI_ReadPreprocess(void * pCmdOut,uint32_t offset,uint32_t size)468 void ADS_DIFF_P_SPI_ReadPreprocess(void *pCmdOut, uint32_t offset, uint32_t size)
469 {
470 spiCmdParams_t *pSlaveCmd = pCmdOut;
471
472 uint8_t *pWBuff = spiRead_CmdBuffer;
473 uint8_t *pRBuff = spiRead_DataBuffer;
474
475 /* Formatting for Read command of DIFF-P SENSOR. */
476 *(pWBuff) = offset & 0x7F; /* offset is the internal register address of the sensor at which write is performed. */
477
478 // Create the slave read command.
479 pSlaveCmd->size = size + DIFF_P_SPI_CMD_LEN;
480 pSlaveCmd->pWriteBuffer = pWBuff;
481 pSlaveCmd->pReadBuffer = pRBuff;
482 }
483
ADS_DIFF_P_SPI_WritePreprocess(void * pCmdOut,uint32_t offset,uint32_t size,void * pWritebuffer)484 void ADS_DIFF_P_SPI_WritePreprocess(void *pCmdOut, uint32_t offset, uint32_t size, void *pWritebuffer)
485 {
486 spiCmdParams_t *pSlaveCmd = pCmdOut;
487
488 uint8_t *pWBuff = spiWrite_CmdDataBuffer;
489 uint8_t *pRBuff = spiWrite_CmdDataBuffer + size + DIFF_P_SPI_CMD_LEN;
490
491 /* Formatting for Write command of DIFF-P SENSOR. */
492 *(pWBuff) = offset | 0x80; /* offset is the internal register address of the sensor at which write is performed. */
493
494 /* Copy the slave write command */
495 memcpy(pWBuff + DIFF_P_SPI_CMD_LEN, pWritebuffer, size);
496
497 /* Create the slave command. */
498 pSlaveCmd->size = size + DIFF_P_SPI_CMD_LEN;
499 pSlaveCmd->pWriteBuffer = pWBuff;
500 pSlaveCmd->pReadBuffer = pRBuff;
501 }
502
ADS_InitSPI_DIFF_P()503 void ADS_InitSPI_DIFF_P()
504 {
505 spiParams_diff_p.pReadPreprocessFN = ADS_DIFF_P_SPI_ReadPreprocess;
506 spiParams_diff_p.pWritePreprocessFN = ADS_DIFF_P_SPI_WritePreprocess;
507 spiParams_diff_p.pTargetSlavePinID = &DIFF_P_SPI_CS;
508 spiParams_diff_p.spiCmdLen = DIFF_P_SPI_CMD_LEN;
509 spiParams_diff_p.ssActiveValue = DIFF_P_SS_ACTIVE_VALUE;
510
511 /* Initialize the Slave Select Pin. */
512 pGPIODriver->pin_init(&DIFF_P_SPI_CS, GPIO_DIRECTION_OUT, NULL, NULL, NULL);
513 if (spiParams_diff_p.ssActiveValue == SPI_SS_ACTIVE_LOW)
514 {
515 pGPIODriver->set_pin(&DIFF_P_SPI_CS);
516 }
517 else
518 {
519 pGPIODriver->clr_pin(&DIFF_P_SPI_CS);
520 }
521 };
522
ADS_DIFF_PQuery(uint8_t whoAmiAddr,uint8_t whoAmi)523 ADS_Status_t ADS_DIFF_PQuery(uint8_t whoAmiAddr, uint8_t whoAmi)
524 {
525 int32_t status;
526 uint8_t reg;
527 registerDeviceInfo_t deviceInfo = {
528 .deviceInstance = SPI_S_DEVICE_INDEX, .functionParam = NULL, .idleFunction = NULL};
529
530 /*! Read and store the device's WHO_AM_I.*/
531 status = Register_SPI_Read(SPIdrv, &deviceInfo, &spiParams_diff_p, whoAmiAddr, 1, ®);
532 if ((ARM_DRIVER_OK != status) || (whoAmi != reg))
533 {
534 return ADS_FAIL;
535 }
536
537 return ADS_OK;
538 }
539
540 /*******************************************************************************
541 * FXLC95000 Specific Functions
542 *****************************************************************************/
ADS_FXLC95000Query()543 ADS_Status_t ADS_FXLC95000Query()
544 {
545 int32_t status;
546 uint16_t partNumber;
547
548 registerDeviceInfo_t deviceInfo = {
549 .deviceInstance = I2C_S1_DEVICE_INDEX, .functionParam = NULL, .idleFunction = NULL};
550
551 /* ADS is required to confirm only the presence of FXLC95000 and not the contents of its FLASH.
552 * As such we will not send command to Boot FXLC95000 to Flash.
553 * We send the Get Device Info ROM CI command and validate response. */
554 Register_I2C_BlockWrite(I2CextDrv, &deviceInfo, FXLC95000_I2C_ADDR, 0, GetDeviceInfoCmd, sizeof(GetDeviceInfoCmd));
555 BOARD_DELAY_ms(1);
556
557 /* Read the Device Info Result.
558 * A valid response COCO indicates command acceptance and by nature Sensor Identity. */
559 status = Register_I2C_Read(I2CextDrv, &deviceInfo, FXLC95000_I2C_ADDR, FXLC95000_PART_NUMBER_OFFSET,
560 FXLC95000_PART_NUMBER_SIZE, (uint8_t *)&partNumber);
561 partNumber = (partNumber >> 8) | (partNumber << 8);
562 if (ARM_DRIVER_OK != status || partNumber != FXLC95000_PART_NUMBER)
563 {
564 return ADS_FAIL;
565 }
566 return ADS_OK;
567 };
568
569 /*******************************************************************************
570 * MMA9553 Specific Functions
571 *****************************************************************************/
ADS_MMA9553Query()572 ADS_Status_t ADS_MMA9553Query()
573 {
574 int32_t status;
575 uint8_t cmdRespHdr[MMA9553_HDR_SIZE] = {0};
576
577 registerDeviceInfo_t deviceInfo = {
578 .deviceInstance = I2C_S1_DEVICE_INDEX, .functionParam = NULL, .idleFunction = NULL};
579
580 /* We send the Read Version Info command and validate response. */
581 Register_I2C_BlockWrite(I2CextDrv, &deviceInfo, MMA9553_I2C_ADDR, 0, ReadVersionInfo_MMA9553,
582 sizeof(ReadVersionInfo_MMA9553));
583 BOARD_DELAY_ms(1);
584
585 /* Read the Device Info Result.
586 * A valid response COCO and length fields indicate command acceptance and by nature Sensor Identity. */
587 status = Register_I2C_Read(I2CextDrv, &deviceInfo, MMA9553_I2C_ADDR, 0, sizeof(cmdRespHdr), cmdRespHdr);
588 if (ARM_DRIVER_OK != status || (cmdRespHdr[1] & 0x80) != 0x80 || cmdRespHdr[2] != ReadVersionInfo_MMA9553[3] ||
589 cmdRespHdr[3] != ReadVersionInfo_MMA9553[3])
590 {
591 return ADS_FAIL;
592 }
593 return ADS_OK;
594 };
595
596 /*******************************************************************************
597 * Functions
598 *****************************************************************************/
ADS_InitI2CBuses()599 int ADS_InitI2CBuses()
600 {
601 int32_t status;
602
603 /*! Initialize the External I2C driver. */
604 status = I2CextDrv->Initialize(I2C_S1_SIGNAL_EVENT);
605 if (ARM_DRIVER_OK != status)
606 {
607 return ARM_DRIVER_ERROR;
608 }
609
610 /*! Set the External I2C Power mode. */
611 status = I2CextDrv->PowerControl(ARM_POWER_FULL);
612 if (ARM_DRIVER_OK != status)
613 {
614 return ARM_DRIVER_ERROR;
615 }
616
617 /*! Set the External I2C bus speed. */
618 status = I2CextDrv->Control(ARM_I2C_BUS_SPEED, ARM_I2C_BUS_SPEED_FAST);
619 if (ARM_DRIVER_OK != status)
620 {
621 return ARM_DRIVER_ERROR;
622 }
623
624 return status;
625 }
626
ADS_InitSPIBus()627 int ADS_InitSPIBus()
628 {
629 int32_t status;
630
631 /*! Initialize the SPI driver. */
632 status = SPIdrv->Initialize(SPI_S_SIGNAL_EVENT);
633 if (ARM_DRIVER_OK != status)
634 {
635 return ARM_DRIVER_ERROR;
636 }
637
638 /*! Set the SPI Power mode. */
639 status = SPIdrv->PowerControl(ARM_POWER_FULL);
640 if (ARM_DRIVER_OK != status)
641 {
642 return ARM_DRIVER_ERROR;
643 }
644
645 /*! Set the SPI Slave speed. */
646 status = SPIdrv->Control(ARM_SPI_MODE_MASTER | ARM_SPI_CPOL1_CPHA0, SPI_S_BAUDRATE);
647 if (ARM_DRIVER_OK != status)
648 {
649 return ARM_DRIVER_ERROR;
650 }
651
652 return status;
653 }
654
ADS_DeInitI2CBuses()655 int ADS_DeInitI2CBuses()
656 {
657 int32_t status;
658
659 /*! De-Initialize the External I2C driver. */
660 status = I2CextDrv->Uninitialize();
661 if (ARM_DRIVER_OK != status)
662 {
663 return ARM_DRIVER_ERROR;
664 }
665
666 return status;
667 }
668
ADS_DeInitSPIBus()669 int ADS_DeInitSPIBus()
670 {
671 int32_t status;
672
673 /*! De-Initialize the SPI0 driver. */
674 status = SPIdrv->Uninitialize();
675 if (ARM_DRIVER_OK != status)
676 {
677 return ARM_DRIVER_ERROR;
678 }
679
680 return status;
681 }
682
683 // Private function to detect Shield.
ADS_DetectShield(char * pShieldString,size_t bufferLength)684 int ADS_DetectShield(char *pShieldString, size_t bufferLength)
685 {
686 int32_t status;
687 uint8_t reg;
688 bool match;
689 uint32_t boardFound = ADS_NO_SHIELD_DETECTED;
690 registerDeviceInfo_t deviceInfo = {0};
691
692 /* We init SPI bus to test for SPI Sensors. */
693 ADS_InitSPIBus();
694
695 // Execute the SPI queries based on the ADS_SensorQueryList.
696 for (uint32_t i = 0; i < ADS_QUERY_NUM; i++)
697 {
698 if (ADS_SPI_DEV == ADS_SensorQueryList[i].channel)
699 {
700 gADS_QueryResults[i] = ADS_FAIL;
701 if (FXLS8962 == ADS_SensorQueryList[i].slaveAddr)
702 {
703 ADS_InitSPI_FXLS8962();
704 gADS_QueryResults[i] =
705 ADS_FXLS8962Query(ADS_SensorQueryList[i].whoAmIAddr, ADS_SensorQueryList[i].whoAmIValue);
706 continue;
707 }
708 if (FXLS8471 == ADS_SensorQueryList[i].slaveAddr)
709 {
710 ADS_InitSPI_FXLS8471();
711 gADS_QueryResults[i] =
712 ADS_FXLS8471Query(ADS_SensorQueryList[i].whoAmIAddr, ADS_SensorQueryList[i].whoAmIValue);
713 continue;
714 }
715 if (DIFF_P == ADS_SensorQueryList[i].slaveAddr)
716 {
717 ADS_InitSPI_DIFF_P();
718 gADS_QueryResults[i] =
719 ADS_DIFF_PQuery(ADS_SensorQueryList[i].whoAmIAddr, ADS_SensorQueryList[i].whoAmIValue);
720 continue;
721 }
722 }
723 }
724
725 /* We now disable SPI bus and init I2C buses to test for I2C sensors. */
726 ADS_DeInitSPIBus();
727 ADS_InitI2CBuses();
728
729 // Execute the Ext I2C queries based on the ADS_SensorQueryList.
730 for (uint32_t i = 0; i < ADS_QUERY_NUM; i++)
731 {
732 if (ADS_I2C_EXT == ADS_SensorQueryList[i].channel)
733 {
734 gADS_QueryResults[i] = ADS_FAIL;
735 deviceInfo.deviceInstance = I2C_S1_DEVICE_INDEX;
736 if (FXLC95000 == ADS_SensorQueryList[i].slaveAddr)
737 {
738 gADS_QueryResults[i] = ADS_FXLC95000Query();
739 continue;
740 }
741 if (MMA9553 == ADS_SensorQueryList[i].slaveAddr)
742 {
743 gADS_QueryResults[i] = ADS_MMA9553Query();
744 continue;
745 }
746 status = Register_I2C_Read(I2CextDrv, &deviceInfo, ADS_SensorQueryList[i].slaveAddr,
747 ADS_SensorQueryList[i].whoAmIAddr, 1, ®);
748 if ((ARM_DRIVER_OK != status) ||
749 ((ADS_SensorQueryList[i].whoAmIValue & ADS_SensorQueryList[i].whoAmIMask) !=
750 (reg & ADS_SensorQueryList[i].whoAmIMask)))
751 {
752 gADS_QueryResults[i] = ADS_FAIL;
753 }
754 else
755 {
756 gADS_QueryResults[i] = ADS_OK;
757 }
758 }
759 }
760
761 /* I2C Sensor verified, disable I2C buses. */
762 ADS_DeInitI2CBuses();
763
764 // Analyze the responses and return the Sensor Shield or Reference name.
765 for (uint32_t board = 0; board < ADS_NUM_BOARDS; board++)
766 {
767 match = true;
768 for (uint32_t sensor = 0; sensor < ADS_QUERY_NUM; sensor++)
769 {
770 if (gADS_QueryMap[board][sensor] == ADS_NULL)
771 {
772 continue;
773 }
774 if (gADS_QueryMap[board][sensor] != gADS_QueryResults[sensor])
775 {
776 match = false;
777 break;
778 }
779 }
780 if (match)
781 {
782 boardFound = board;
783 break;
784 }
785 }
786
787 // If a board was found, then put the proper string into the response.
788 if (boardFound != ADS_NO_SHIELD_DETECTED)
789 {
790 strncpy(pShieldString, ADS_ShieldList[boardFound], bufferLength);
791 status = ARM_DRIVER_OK;
792 }
793 else
794 {
795 status = ARM_DRIVER_ERROR;
796 }
797
798 return status;
799 }
800
801 // Private function to detect the MCU.
ADS_DetectLPC(char * pBoardString,size_t bufferLength)802 int ADS_DetectLPC(char *pBoardString, size_t bufferLength)
803 {
804 int32_t status;
805
806 // Declare the DEVID Query structure
807 mcuDEVID_t MCUInfo = {.mcuDeviceId = 0, .board = ADS_NO_BOARD_DETECTED};
808
809 if (pBoardString == NULL)
810 {
811 return ARM_DRIVER_ERROR_PARAMETER;
812 }
813
814 uint32_t command[5] = {0}, result[4] = {0};
815
816 command[0] = kIapCmd_FLASHIAP_ReadPartId;
817 iap_entry(command, result);
818
819 MCUInfo.mcuDeviceId = result[1];
820 // Compare the values extracted to the static table and return detected board.
821 for (uint8_t i = 0; i < (sizeof(ADS_ValidDEVIDValues) / sizeof(mcuDEVID_t)); i++)
822 {
823 if (MCUInfo.mcuDeviceId == ADS_ValidDEVIDValues[i].mcuDeviceId)
824 {
825 MCUInfo.board = ADS_ValidDEVIDValues[i].board;
826 break;
827 }
828 }
829
830 status = ARM_DRIVER_OK;
831 // Translate the result into the string.
832 switch (MCUInfo.board)
833 {
834 case ADS_LPC_54113J128:
835 strncpy(pBoardString, "LPCXPRESSO54113J128", bufferLength);
836 break;
837 case ADS_LPC_54113J256:
838 strncpy(pBoardString, "LPCXPRESSO54113J256", bufferLength);
839 break;
840 case ADS_LPC_54114J256:
841 strncpy(pBoardString, "LPCXPRESSO54114J256", bufferLength);
842 break;
843 default:
844 status = ARM_DRIVER_ERROR;
845 break;
846 }
847
848 return status;
849 }
850
851 // Private function to compare flash contents.
ADS_FlashCompare(char * pResultString)852 ADS_FlashStatus_t ADS_FlashCompare(char *pResultString)
853 {
854 ADSFlashRecord_t flashRecord = {0};
855 uint32_t status;
856
857 flashRecord.cookie = ADS_COOKIE_VALUE;
858 status = FLASHIAP_Compare(ADS_NVM_ADDR, (uint32_t *)&flashRecord.cookie, sizeof(flashRecord.cookie));
859 // Check that the ADS_COOKIE is as expected.
860 if (kStatus_FLASHIAP_Success != status)
861 {
862 return ADS_NO_FLASH_RECORD; // Flash record is not valid.
863 }
864 else
865 { // Compare the result string with the ADS stored results in Flash.
866 flashRecord.length = strlen(pResultString);
867 strcpy(flashRecord.ADSString, pResultString);
868 status = FLASHIAP_Compare(ADS_NVM_ADDR, (uint32_t *)&flashRecord, sizeof(flashRecord));
869 if (kStatus_FLASHIAP_Success != status)
870 {
871 return ADS_FLASH_RECORD_CHANGE;
872 }
873 else
874 {
875 return ADS_FLASH_RECORD_NO_CHANGE;
876 }
877 }
878 }
879
880 // Private function to update flash contents.
ADS_FlashUpdate(char * pResultString)881 ADS_Status_t ADS_FlashUpdate(char *pResultString)
882 {
883 status_t result;
884 ADS_Status_t retVal = ADS_FAIL;
885 ADSFlashRecord_t flashRecord = {0};
886
887 // Create the ADS Flash Record.
888 flashRecord.cookie = ADS_COOKIE_VALUE;
889 flashRecord.length = strlen(pResultString);
890 strcpy(flashRecord.ADSString, pResultString);
891
892 // Setup flash for write.
893 result = FLASHIAP_PrepareSectorForWrite(ADS_NVM_SECTOR_NUM, ADS_NVM_SECTOR_NUM);
894 if (kStatus_FLASHIAP_Success == result)
895 { // Erase the target sector.
896 result = FLASHIAP_EraseSector(ADS_NVM_SECTOR_NUM, ADS_NVM_SECTOR_NUM, SystemCoreClock);
897 if (kStatus_FLASHIAP_Success == result)
898 { // Setup flash for write.
899 result = FLASHIAP_PrepareSectorForWrite(ADS_NVM_SECTOR_NUM, ADS_NVM_SECTOR_NUM);
900 if (kStatus_FLASHIAP_Success == result)
901 { /* Write the ADS Record to the Flash.
902 * Note: Flash write needs to be 32-bit word aligned in length and in multiples of page size. */
903 result = FLASHIAP_CopyRamToFlash(ADS_NVM_ADDR, (uint32_t *)&flashRecord,
904 FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES, SystemCoreClock);
905 if (kStatus_FLASHIAP_Success == result)
906 {
907 retVal = ADS_OK;
908 }
909 }
910 }
911 }
912
913 return retVal;
914 }
915
916 // API to register Application Name and trigger Board Shield detection.
BOARD_RunADS(const char * appName,char * boardString,char * shieldString,size_t bufferLength)917 void BOARD_RunADS(const char *appName, char *boardString, char *shieldString, size_t bufferLength)
918 {
919 int32_t position, status = ADS_OK;
920 char finalString[ADS_FLASH_STRING_LENGTH] = {0};
921
922 status = ADS_DetectLPC(boardString, bufferLength);
923 if (ARM_DRIVER_ERROR == status)
924 {
925 strncpy(boardString, "NotDetected", bufferLength);
926 status = ADS_FAIL;
927 }
928
929 status = ADS_DetectShield(shieldString, bufferLength);
930 if (ARM_DRIVER_ERROR == status)
931 {
932 strncpy(shieldString, "NotDetected", bufferLength);
933 status = ADS_FAIL;
934 }
935
936 // Build the string with App Name and Shield Name to write to flash.
937 strncpy(finalString, appName, ADS_FLASH_STRING_LENGTH);
938 position = strlen(appName);
939
940 finalString[position++] = ':';
941
942 strncpy(&finalString[position], shieldString, ADS_FLASH_STRING_LENGTH - position);
943 position += strlen(shieldString);
944
945 /* Fill the remaining string with 0. */
946 memset(&finalString[position], 0, ADS_FLASH_STRING_LENGTH - position);
947
948 status = ADS_FlashCompare(finalString);
949 if (ADS_FLASH_RECORD_NO_CHANGE != status)
950 {
951 ADS_FlashUpdate(finalString);
952 strcpy(finalString, shieldString);
953 snprintf(shieldString, bufferLength, "Changed:%s", finalString);
954 }
955 }
956