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