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, &reg);
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, &reg);
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, &reg);
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, &reg);
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