ISF  2.2 rev 5
Intelligent Sensing Framework for Kinetis with Processor Expert
ci_protocol_mbox.c
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2015, Freescale Semiconductor, Inc.
4  *
5 */
6 
7 /*!
8  * @file ci_protocol_mbox.c
9  *
10  * @brief Command interpreter source file that implements the legacy mailbox
11  * protocol functionality.
12  *
13  */
14 
15 
16 #include "isf.h"
17 #include "isf_ci.h"
18 #include "isf_ci_protocol.h"
19 #include "task_ci.h"
20 #include "ci_protocol_mbox.h"
21 #include "crc.h"
22 
23 
24 
25 extern ci_funcp_t ci_callback[];
26 
27 #define MBOX_APP_DATA "MBOX App"
28 
29 /*!
30  * @struct rli_app_info_t
31  * @This structure holds the RLI Application version and build
32  * information.
33  *
34 */
35 typedef struct
36 {
37  //! ISF Embedded Application type
39  //! ISF Embedded Application version information
41  //! ISF Embedded Application registered additional information/data size
43  //! ISF Embedded Application registered additional information/data
44  uint8 appData[sizeof(MBOX_APP_DATA)];
46 
47 
48 static inline uint8 ci_get_first_data_mb(uint8);
49 static inline uint8 ci_get_num_data_mb(void);
50 
51 // This semaphore is used for mailbox data access.
52 static semaphore_t sema_ci_mb_access;
53 // Contains the number of ci application callbacks. This value is calculated
54 // at initialization time by examining the ci_callback[] array.
55 static int32 ci_num_apps;
56 
57 // Contains the first mb number that is free for data pay load. This mb may
58 // be different than MB4 because the host may have configured them to be
59 // quick read.
60 static uint8 ci_first_data_mb;
61 
62 // Contains the number of *contiguous* mb available for data pay load.
63 static uint8 ci_num_data_mb;
64 
65 // Bit mask for quick read mailboxes. Each bit corresponds to each of the
66 // 32 mailboxes.
67 static uint32 ci_qr_mb_bit_mask;
68 
69 // HDLC protocol id for the CI protocol. The ID is passed into the init
70 // function which then stores it in this variable for later use.
71 static uint8 ci_protocol_id;
72 
73 
74 // Mailbox "registers". The buffer consists of the following data in order that
75 // they appear in the array:
76 // 1) protocol ID (1 byte)
77 // 2) Number of mailboxes
78 // 3) CRC16 value (2 byte, optional)
79 // Note that the protocol ID is required to be the first element in the array. The
80 // optional CRC value is placed last in the array. When working with the mailbox data,
81 // use the pciMailboxes pointer since it offsets 1 into the array to skip pass the
82 // protocol ID. When sending mbox data to the host, use the ciMailboxes[] array which
83 // contains the protocol ID at the beginning of the array.
84 static uint8 ciMailboxes[MAX_NUM_OUT_BUFFER];
85 static uint8 *pciMailboxes = (uint8 *)&ciMailboxes[CI_PROTOCOL_DATA_OFFSET];
86 
87 static ci_regs_t ciRegisters;
88 static uint32 ci_sp_writes;
89 
90 /* App Info Structure returned by the CI_CMD_READ_APP_VERSION command */
91 static const ci_mbox_app_info_t gsMBOX_AppInfo = {
93  .version_info = 0x0100,
94  .numBytes = sizeof(MBOX_APP_DATA),
95  .appData = MBOX_APP_DATA
96 };
97 
98 
99 // See isf_ci.h for documentation
100 ci_status_t isf_ci_qr_update(uint8 aAppId, int8 anumBytes, uint8 *apSrc)
101 {
102 
103  uint32_t ret = !ISF_SUCCESS;
104  ci_status_t ci_ret;
105 
106 
107  // If streaming mode is not enabled, quit.
109  return ret;
110 
111  ret = OSA_SemaWait(&sema_ci_mb_access, OSA_WAIT_FOREVER);
112 
113  if (ret == ISF_SUCCESS)
114  {
115 
116  uint8 *pTemp_src;
117  int8 i = 0;
118  int8 j = 0;
119  int8 qr_bytes_written = 0;
120 
121  int8 prevIndex = 0;
122  int8 qr_cont_cnt = 0; // Contiguous QR mb count
124  uint8 *pQRBuf = (uint8*)&qr_send_buf[CI_PROTOCOL_DATA_OFFSET]; // First byte reserved for protocol id.
125 
126  // Assign protocol id.
127  qr_send_buf[0] = ci_protocol_id;
128 
129 
130  // We are only writing a few bytes to the mailboxes and would like this to
131  // be done as one set and not get preempted in the middle of the process.
132  // We want this set of data to be coherent when the host is reading it.
133  // Stopping preemption is also essentially raising the priority to highest
134  // level and let this task complete to prevent priority inversion.
135  OSA_EnterCritical(kCriticalLockSched);
136  while( (i < NUM_QR_MAILBOXES) && (qr_bytes_written < anumBytes) )
137  {
138  // We examine each mailbox configuration separately because its possible
139  // for the app to have its quick read info spread out among the mailboxes.
140  if (ciRegisters.qr_config[i].appId == aAppId)
141  {
142 
143  if (prevIndex == 0)
144  // This will be set once to the first QR mailbox found.
145  prevIndex = i-1;
146 
147 
148  // Only update mailboxes that are from the first set of contiguous
149  // mailboxes found. All other fragments of QR mailboxes from the
150  // same application are discarded.
151  if (prevIndex == (i-1))
152  {
153  // Start at the offset into the app's data.
154  pTemp_src = (uint8*)((uint32)apSrc + (uint32)ciRegisters.qr_config[i].byte_id);
155 
156  // Get mailbox address
157  //pDst = (uint8*)&pciMailboxes[FIRST_QR_MAILBOX_NUM+i];
158  //*pDst = *pTemp_src;
159 
160  pQRBuf[FIRST_QR_MAILBOX_NUM+j] = *pTemp_src;
161 
162  // Keep track of contiguous bytes.
163  ++qr_cont_cnt;
164  ++j;
165  }
166 
167  prevIndex = i;
168 
169  // Note that this counter could be counting QR mailboxes that are
170  // not contiguous.
171  ++qr_bytes_written;
172  }
173 
174  ++i;
175  }
176 
177  if (qr_cont_cnt > 0)
178  {
179  // Send back response only if the host has config QR mb for the app.
180  uint8 size = qr_cont_cnt + MB_APP_RESP_SIZE;
181 
182  // Create the response header.
183  pQRBuf[MB_RESP_INDEX_APP_ID] = aAppId;
185  pQRBuf[MB_RESP_INDEX_BYTES_XFER] = qr_cont_cnt;
186  pQRBuf[MB_RESP_INDEX_COUNT] = anumBytes;
187 
188 #ifdef MBOX_ENABLE_CRC
189  {
190  uint16 crc16;
191 
192  // CRC for qr data packet.
193  crc16 = ccitt_crc16_cal((uint32)size, pQRBuf);
194 
195  // Insert the CRC value into the packet going back to host. The CRC is placed at the end
196  // of the buffer.
197  ci_insert_crc(size, crc16, pQRBuf);
198 
199  }
200 #endif
201 
202  // Finally, send the packet.
204  }
205  else
206  {
207  // The host did not config any QR mb for this app.
208  ret = !ISF_SUCCESS;
209  }
210  OSA_ExitCritical(kCriticalLockSched);
211  }
212 
213  if (ret == ISF_SUCCESS)
214  ci_ret = (ci_status_t)ISF_SUCCESS;
215  else
216  ci_ret = (ci_status_t)ISF_CI_FAILURE;
217  OSA_SemaPost(&sema_ci_mb_access);
218 
219  return ci_ret;
220 }
221 
222 
223 
224 
225 // See isf_ci.h for documentation
226 uint32 isf_ci_app_read(uint8 aAppId, uint32 anumBytes, uint8 *apDst)
227 {
228 
229 
230  int32 bytes_read;
231  uint32_t ret;
232 
233  ret = OSA_SemaWait(&sema_ci_mb_access, OSA_WAIT_FOREVER);
234  if (ret == ISF_SUCCESS)
235  {
236 
237  uint8 *pSrc;
238  uint8 *pTemp_dst;
239  int32 max_bytes;
240  uint32 mb_write_bits = 0;
241  uint32 mb_num;
242 
243 
244  // We are only writing a few bytes to the mailboxes and would like this to
245  // be done as one set and not get preempted in the middle of the process.
246  // We want this set of data to be coherent when the host is reading it.
247  // Stopping preemption is also essentially raising the priority to highest
248  // level and let this task complete to prevent priority inversion.
249  OSA_EnterCritical(kCriticalLockSched);
250  bytes_read = 0;
251  max_bytes = ci_get_num_data_mb();
252 
253  // Read data from first mailbox that is available for data.
254  mb_num = ci_get_first_data_mb(aAppId);
255 
256  pSrc = (uint8*)((uint32)mb_num + (uint32)&pciMailboxes[0]);
257 
258  pTemp_dst = apDst;
259  while( (bytes_read < max_bytes) && (bytes_read < (int32)anumBytes) )
260  {
261  *pTemp_dst++ = *pSrc++;
262  ++bytes_read;
263 
264  // Set the bit corresponding to the mailbox number.
265  mb_write_bits |= (uint32)(1 << mb_num++);
266  }
267  OSA_ExitCritical(kCriticalLockSched);
268  }
269  else
270  bytes_read = 0;
271  OSA_SemaPost(&sema_ci_mb_access);
272  return (uint32)bytes_read;
273 }
274 
275 
276 // See isf_ci.h for documentation
277 uint32 isf_ci_app_write(uint8 aAppId, uint32 anumBytes, uint8 *apSrc)
278 {
279 
280  int32 bytes_written;
281  uint32_t ret;
282 
283  ret = OSA_SemaWait(&sema_ci_mb_access, OSA_WAIT_FOREVER);
284  if (ret == ISF_SUCCESS)
285  {
286  uint8 *pDst;
287  int32 max_bytes;
288 
289  // We are only writing a few bytes to the mailboxes and would like this to
290  // be done as one set and not get preempted in the middle of the process.
291  // We want this set of data to be coherent when the host is reading it.
292  // Stopping preemption is also essentially raising the priority to highest
293  // level and let this task complete to prevent priority inversion.
294  OSA_EnterCritical(kCriticalLockSched);
295  bytes_written = 0;
296  max_bytes = MAX_NUM_OUT_BUFFER;
297 
298 
299  // Write data to the first mailbox that is available for data.
300  pDst = (uint8*)((uint32)ci_get_first_data_mb(aAppId) + (uint32)&pciMailboxes[0]);
301 
302  while( (bytes_written < max_bytes) && (bytes_written < (int32)anumBytes) )
303  {
304  pDst[bytes_written] = apSrc[bytes_written];
305  ++bytes_written;
306  }
307 
308  OSA_ExitCritical(kCriticalLockSched);
309  }
310  else
311  bytes_written = 0;
312  OSA_SemaPost(&sema_ci_mb_access);
313  return (uint32)bytes_written;
314 }
315 
316 
317 
318 /*!
319  * @brief Finds the first mailbox available for data pay load, how many \n
320  * mailboxes are available for data pay load, and updates a bit mask \n
321  * that tracks which of the 32 mailboxes are used for quick read.
322  *
323  * @return None
324  *
325  * @errors None
326  *
327  * @constraints None
328  *
329  * @reentrant No.
330  *
331  * @libs \n
332  *
333  * @see \n
334  *
335 */
337 {
338  uint8 mb_num;
339  uint8 end_found;
340 
341  OSA_SemaWait(&sema_ci_mb_access, OSA_WAIT_FOREVER);
342  OSA_EnterCritical(kCriticalLockSched);
343 
344  end_found = 0;
345  mb_num = 0;
346  ci_first_data_mb = 0; // Must init to zero
347  ci_num_data_mb = 0; // Must init to zero
348  ci_qr_mb_bit_mask = 0; // Must init to zero
349 
350 
351  do
352  {
353 
354  // The first mailbox not configured for quick read is the
355  // first mb available for data. We are not handling cases
356  // of fragmented quick read mailboxes.
357  if (ciRegisters.qr_config[mb_num].appId == APP_ID_NULL)
358  {
359 
360  if (ci_first_data_mb == 0)
361  {
362  // Found first non-quick read mailbox.
363  ci_first_data_mb = mb_num + FIRST_DATA_MAILBOX_NUM;
364  ++ci_num_data_mb;
365  }
366  else if (end_found == 0)
367  // Track number of contiguous free mailboxes after the first
368  // one is found.
369  ++ci_num_data_mb;
370  }
371  else
372  {
373 
374 #if (FIRST_QR_MAILBOX_NUM > FIRST_DATA_MAILBOX_NUM)
375  if ( (ci_first_data_mb) || (mb_num == 0) )
376  {
377  // Mark end of contiguous free mailboxes.
378  end_found = 1;
379  ci_first_data_mb = FIRST_DATA_MAILBOX_NUM;
380  }
381 #else
382  if (ci_first_data_mb)
383  {
384  // Mark end of contiguous free mailboxes.
385  end_found = 1;
386  }
387 #endif
388 
389  // Keep a bit mask of quick read mailboxes. Each bit corresponds to
390  // each of the 32 mailboxes.
391  ci_qr_mb_bit_mask |= (uint32)(1 << (mb_num+FIRST_QR_MAILBOX_NUM));
392  }
393  } while(++mb_num < NUM_QR_MAILBOXES);
394 
395 
396 #if (FIRST_QR_MAILBOX_NUM > FIRST_DATA_MAILBOX_NUM)
397  ci_num_data_mb += (FIRST_QR_MAILBOX_NUM - FIRST_DATA_MAILBOX_NUM);
398 #endif
399 
400 
401  OSA_SemaPost(&sema_ci_mb_access);
402  OSA_ExitCritical(kCriticalLockSched);
403 
404 }
405 
406 
407 /*!
408  * @brief Based upon mailbox bit mask, invoke the application's \n
409  * command interpreter callback to to update quick read mailboxes.
410  *
411  * @param (in) mb_read_bits - Bit setting that indicates if a mailbox \n
412  * has been read. The corresponding mailbox quick read \n
413  * configuration is examined and its callback is invoked \n
414  * with command to update quick read registers. Each bit \n
415  * corresponds with each of the 32 mailboxes.
416  *
417  * A bit that is set indicates that the corresponding \n
418  * mailbox has been read.
419  *
420  *
421  * @return See ci_response_enum type for possible return values
422  *
423  * @errors None \n
424  *
425  * @constraints If another application is using the mailboxes, then the \n
426  * current calling application must wait until the other \n
427  * application has completed its operation on the mailboxes.
428  *
429  * @reentrant No. \n
430  *
431  * @libs \n
432  *
433  * @see \n
434  *
435 */
437 {
438  // Host read some quick read mailboxes.
439 
440  uint32 bit_pos = FIRST_QR_MAILBOX_NUM;
441  uint8 previous_app_id = APP_ID_NULL;
442 
443  ci_host_cmd_packet_t host_packet;
444  ci_app_resp_packet_t app_packet;
445  ci_response_enum callback_ret = CI_ERROR_NONE;
446 
447 
448  host_packet.offset = 0;
449  host_packet.cmd = CI_CMD_UPDATE_QUICKREAD;
450  host_packet.byte_cnt = 0;
451 
452  // For mailboxes configured as quick read and marked as read,
453  // find the application id and execute the callback if available.
454  // NOTE: The search implemented below assumes that each application's
455  // quick read configuration are contiguous. If it is fragmented,
456  // the application's callback may be invoked more than once.
457 
458 
459  do
460  {
461  if (mb_read_bits & (1 << bit_pos))
462  {
463  host_packet.appId = ciRegisters.qr_config[bit_pos-FIRST_QR_MAILBOX_NUM].appId;
464 
465  if ( (host_packet.appId != ISF_APP_ID_NULL) && (host_packet.appId != previous_app_id) && (host_packet.appId < ci_num_apps) )
466  {
467  previous_app_id = host_packet.appId;
468 
469  if (ci_callback[host_packet.appId] != NULL)
470  callback_ret = ((*((ci_funcp_t)(ci_callback[host_packet.appId])))(&host_packet, &app_packet)); // Call trap function
471  }
472  }
473  } while(++bit_pos < 32);
474 
475 
476  return callback_ret;
477 }
478 
479 
480 /*!
481  * @brief Get the first mailbox available for data.
482  *
483  * @return Mailbox number (0-31)
484  *
485  * @errors None \n
486  *
487  * @constraints None \n
488  *
489  * @reentrant No. \n
490  *
491  * @libs \n
492  *
493  * @see \n
494  *
495 */
496 static inline uint8 ci_get_first_data_mb(uint8 aAppId)
497 {
498  if (aAppId == 0)
499  return 2;
500  else
501  return ci_first_data_mb;
502 }
503 
504 /*!
505  * @brief Get the number of mailboxes available for data.
506  *
507  * @return Number of mailboxes (0-31)
508  *
509  * @errors None \n
510  *
511  * @constraints None \n
512  *
513  * @reentrant No. \n
514  *
515  * @libs \n
516  *
517  * @see \n
518  *
519 */
520 static inline uint8 ci_get_num_data_mb(void)
521 {
522 // return ci_num_data_mb;
523  return NUM_DATA_MAILBOXES;
524 }
525 
526 
527 
528 isf_status_t ci_mbox_init(uint8 aprotocolID, void *apInitData)
529 {
530 
532 
533 
534  ci_sp_writes = 0;
535 
536  // Set the id for this protocol.
537  ciMailboxes[CI_PROTOCOL_ID_INDEX] = ci_protocol_id = aprotocolID;
538 
539 
540  // Initialize the number of apps. Count number of pointers in
541  // array until we reach NULL or max num of allowable apps.
542  ci_num_apps = 0;
543  do
544  {
545  if (ci_callback[ci_num_apps] == NULL)
546  break;
547 
548  } while (++ci_num_apps < MAX_ISF_APPLICATIONS);
549 
550  if (OSA_SemaCreate(&sema_ci_mb_access, 1) != ISF_SUCCESS)
551  ret = ISF_ERR_LIB_INIT;
552 
553 
554  // Initialize quick read configuration and mailbox array.
555  {
556  int i = MAX_NUM_MAILBOXES-1;
557  do
558  {
559  ciRegisters.qr_config[i].appId = 0;
560  ciRegisters.qr_config[i].byte_id = 0;
561  pciMailboxes[i] = 0;
562  } while(--i >= 0);
563  }
564 
565 
566  // Initial Ctrl Register
567  ciRegisters.ciCtrlReg.reg = 0;
568 
569  // Update first mb free for data and # of contiguous
570  // free mailboxes after that.
572 
573  // At reset put the device Id into the mailboxes
574  {
575  device_info_t devInfo;
576 
577  // ENGR00312443: Zero out the structure. The device info structure was carried over from FXLC95000
578  // which contains some fields that were populated by the FXLC95K's ROM code. We no longer have the
579  // ROM code and these fields are unused. So we must zero them out. For KL25Z R1p1 release, this bug
580  // manifiest itself in such a way that the first call to this function will return all zeros in the
581  // unused field. But all subsequent calls returns garbage data in those fields. The only fields
582  // that are correct are the ones we populate explicitly below (build code, fw versiont, etc).
583  //_mem_zero(&devInfo, sizeof(device_info_t));
584  memset(&devInfo, 0, sizeof(devInfo));
585  _fw_device_info_get(&devInfo);
586  //isf_ci_app_write(0, sizeof(device_info_t), (unsigned char *)&devInfo);
587  isf_ci_app_write(0, sizeof(devInfo), (unsigned char *)&devInfo);
588  }
589 
590 
591 
592  return ret;
593 }
594 
595 
596 /*!
597  *
598  * @brief Callback function for mailbox application ID, ISF_APP_ID_MBOX.
599  *
600  * @param packet_ptr - host command packet
601  *
602  * @param mb_data_ptr - pointer to first mailbox address containing \n
603  * data.
604  *
605  * @return See ci_response_enum type for possible return values
606  *
607  * @errors None \n
608  *
609  * @constraints If another application is using the mailboxes, then the \n
610  * current calling application must wait until the other \n
611  * application has completed its operation on the mailboxes.
612  *
613  * @reentrant Yes. \n
614  *
615  * @libs \n
616  *
617  * @see \n
618  *
619 */
621 {
622 
623  ci_response_enum callback_ret = CI_ERROR_NONE;
624 
625 
626  switch(apHostPacket->cmd)
627  {
628 
629  case CI_CMD_READ_CONFIG:
630  case CI_CMD_WRITE_CONFIG:
631  {
632  // Host is reading or writing.
633  int32 cnt = (int32)apHostPacket->byte_cnt;
634  int32 offset = (int32)apHostPacket->offset;
635  apAppPacket->rw = CI_RW_NULL;
636  apAppPacket->bytes_xfer = 0;
637 
638  if ( (cnt == 0) || (cnt > (sizeof(ciRegisters))) )
639  {
640  callback_ret = CI_INVALID_COUNT;
641  }
642  else if ( (offset >= (sizeof(ciRegisters))) || ((cnt+offset) > (sizeof(ciRegisters))) )
643  {
644  callback_ret = CI_ERROR_INVALID_LENGTH;
645  }
646  else
647  {
648  // No errors so far, perform read or write operation.
649 
650  uint8 *pSrc_ptr;
651  uint8 *pDst_ptr;
652 
653  if (apHostPacket->cmd == CI_CMD_READ_CONFIG)
654  {
655  // Host reading current configuration.
656 
657  // Host read: src ptr points to QR config.
658  pSrc_ptr = (uint8*)((uint32)ciRegisters.qr_config + (uint32)offset);
659 
660  // Write the data to host.
661  apAppPacket->rw = CI_RW_WRITE;
662  apAppPacket->bytes_xfer = (uint8)isf_ci_app_write(apHostPacket->appId, (uint32)cnt, pSrc_ptr);
663 
664  }
665  else
666  {
667  // Host writing new configuration.
668 
669  // Host write: dst ptr points to application data
670  pDst_ptr = (uint8*)((uint32)ciRegisters.qr_config + (uint32)offset);
671 
672  // Read data from the host.
673  apAppPacket->rw = CI_RW_READ;
674  apAppPacket->bytes_xfer = (uint8)isf_ci_app_read(apHostPacket->appId, (uint32)apHostPacket->byte_cnt, pDst_ptr);
675 
676  if(offset < sizeof(ciRegisters.qr_config))
677  {
678 
679  // Host had updated the quick read configuration. Update.
681 
682 
683  // NOTE: For uart comm, do not try to do QR update. The app will
684  // need to update QR which will send the data immediately to host.
685  // Doing the QR update here may complicate things with the host because
686  // it will get back a QR packet and command-reponse packet back to back.
687 #if 0
688  // Do quick read update for any new applications that got added.
689  new_qr_bits = old_qr_bit_mask | ci_qr_mb_bit_mask;
690  new_qr_bits ^= old_qr_bit_mask;
691 
692 
693  // Return value is discarded. This quick read update is not
694  // in response to a host read. Rather, this is the first time the
695  // host has registered for the application's quick read and the
696  // app needs to update the mailboxes for the first time.
697  ci_qr_update(new_qr_bits);
698 #endif
699  }
700 
701  }
702  }
703  }
704 
705  break;
706 
707  case CI_CMD_RESET_APP:
708 
709  // Host is requesting to clear all QR config.
710  qr_config_clear();
711 
712  // Host had updated the quick read configuration. Update.
714 
715  // Turn off everything.
716  ciRegisters.ciCtrlReg.reg = 0;
717 
718  break;
719 
720  // Read ISF Embedded Application Version Info.
721  case CI_CMD_READ_VERSION:
722  // Write the ISF Application information to the host interface.
723  apAppPacket->bytes_xfer = isf_ci_app_write(apHostPacket->appId, sizeof(gsMBOX_AppInfo), (uint8*)&gsMBOX_AppInfo);
724  break;
725 
727  break;
729  default:
730  callback_ret = CI_ERROR_COMMAND;
731  break;
732 
733  }
734 
735  // Note: The return packet is for future use. The information could be used
736  // to implement multipacket transfer without handshake for every packet. The
737  // exact method to do this is TBD.
738  apAppPacket->bytes_left = 0;
739 
740  return callback_ret;
741 }
742 
743 
744 /*!
745  *
746  * @brief Callback function for the device info command, ISF_APP_ID_DEV_INFO.
747  *
748  * @param packet_ptr - host command packet
749  *
750  * @param mb_data_ptr - pointer to first mailbox address containing \n
751  * data.
752  *
753  * @return See ci_response_enum type for possible return values
754  *
755  * @errors None \n
756  *
757  * @constraints If another application is using the mailboxes, then the \n
758  * current calling application must wait until the other \n
759  * application has completed its operation on the mailboxes.
760  *
761  * @reentrant Yes. \n
762  *
763  * @libs \n
764  *
765  * @see \n
766  *
767 */
769 {
770 
771  device_info_t devInfo;
772 
773  // ENGR00312443: Zero out the structure. The device info structure was carried over from FXLC95000
774  // which contains some fields that were populated by the FXLC95K's ROM code. We no longer have the
775  // ROM code and these fields are unused. So we must zero them out. For KL25Z R1p1 release, this bug
776  // manifiest itself in such a way that the first call to this function will return all zeros in the
777  // unused field. But all subsequent calls returns garbage data in those fields. The only fields
778  // that are correct are the ones we populate explicitly below (build code, fw versiont, etc).
779  memset(&devInfo, 0, sizeof(devInfo));
780  _fw_device_info_get(&devInfo);
781  apAppPacket->bytes_xfer = (uint8)isf_ci_app_write(apHostPacket->appId, sizeof(devInfo), (unsigned char *)&devInfo) - 4;
782 
783  apAppPacket->rw = CI_RW_WRITE;
784  apAppPacket->bytes_left = 0;
785 
786 
787  return CI_ERROR_NONE;
788 }
789 
790 
791 
792 
793 
794 
795 isf_status_t ci_protocol_CB_mbox(uint32 anumBytes, uint8 *apSrc, uint32 *apnumDestBytes, uint8 *apDest)
796 {
797 
798  uint8 coco_status;
799  ci_app_resp_packet_t app_packet;
801  ci_response_t ci_status = CI_ERROR_NONE;
802  uint32 rx_count = 0;
803  byte command = 0;
804 
805  app_packet.bytes_left = 0;
806  app_packet.bytes_xfer = 0;
807  app_packet.rw = CI_RW_NULL;
808  coco_status = COCO_BIT_MASK;
809  ci_sp_writes = 0;
810 
811 
812 #ifdef MBOX_ENABLE_CRC
813  // Do CRC check first.
814  {
815  uint16 crc16;
816 
817  // CRC check for entire mbox packet. Note that this packet does not
818  // include the protocol id.
819  crc16 = ccitt_crc16_cal(anumBytes, apSrc);
820 
821  if (crc16)
822  return CI_ERROR_CRC;
823  }
824 #endif
825 
826 
827  // Move data over to mbox buffer. Don't include CRC. Note that packet does
828  // not include the protocol id.
829  while(rx_count < (anumBytes - MBOX_CRC_BYTE_SIZE))
830  {
831  // Store data to mailbox.
832  pciMailboxes[rx_count] = apSrc[rx_count];
833 
834  // Mark the particular mailbox as written to.
835  ci_sp_writes |= (uint32)(1 << rx_count);
836 
837  ++rx_count;
838  }
839  command = ci_get_wr_cmd();
840 
841  // Host sent a command packet. Process it.
842 
843  if ( (anumBytes > (MAX_NUM_MAILBOXES + MBOX_CRC_BYTE_SIZE)) || (anumBytes < ((MB_HOST_CMD_SIZE (command)) + MBOX_CRC_BYTE_SIZE)) )
844  {
845  return CI_INVALID_COUNT;
846  }
847 
848  if ( ci_sp_writes & ci_qr_mb_bit_mask )
849  {
850 
851  // ENGR00233533 bug fix. We have to return error status if the host
852  // has written over any data mailboxes that was designated as quick
853  // read register. If the host did over write any one of the quick
854  // read registers, then we return an invalid count error.
855  ci_status = CI_ERROR_INVALID_LENGTH;
856 
857  }
858  else if (
859  ((ci_sp_writes & CMD_PACKET_BITS) == CMD_PACKET_BITS) || // Regular 4 byte command header
860  ((ci_sp_writes == 0x03) && (MB_HOST_CMD == CI_CMD_READ_VERSION)) // Read device info command
861  )
862  {
863 
864  // Command was written, MB0-3.
865 
866  // If the command was a host writing to the app, then make sure all
867  // the data payload is there.
869  {
870 
871  // If the command is a write (host writing data), then we need to make sure
872  // that all the data has been written to the mailboxes (MB4...MB31).
873  // The mailbox index, mbIndex, started at zero and goes up contiguously.
874  // mbindex minus 4 for the command packet will give us the data bytes we
875  // received. Compare that with the command count field and it should equal.
876  // If it does not equal, then the packet is bad.
877  if ( (rx_count - (MB_HOST_CMD_SIZE (command))) != (ci_get_wr_cnt(command))){
878  ci_status = CI_ERROR_INVALID_LENGTH;
879  }else{
880  ci_first_data_mb = ci_get_first_mailbox(command);
881  }
882 
883  }else{
884  ci_first_data_mb = FIRST_DATA_MAILBOX_NUM;
885  }
886 
887  }
888 
889  // Packet has been processed, clear and start over.
890  ci_sp_writes = 0;
891 
892 
893  // If an error occurred with packet, send back error.
894  if (ci_status != CI_ERROR_NONE)
895  {
897  MB_RESP_STATUS_CC = coco_status | ci_status;
898  MB_RESP_BYTES_XFER = 0;
899  MB_RESP_COUNT = 0;
900 
901 
903  {
904  uint16 crc16;
905 
906  // CRC only for the response packet.
908 
909  ciMailboxes[size + 0] = (uint8)((uint16)(crc16 & 0xff00) >> 8);
910  ciMailboxes[size + 1] = (uint8)(crc16 & 0xff);
911  }
912 
913  // Send only response header.
914  ci_send_packet(size + MBOX_CRC_BYTE_SIZE, (uint8*)ciMailboxes); // +1 for protocol id
915  }
916  else
917  {
918 
919  // Process mbox command packet internal data.
920 
921  ci_host_cmd_packet_t host_packet;
922 
923  // Immediately clear COCO bit.
925 
926  host_packet.appId = ci_get_wr_appid();
927  host_packet.cmd = ci_get_wr_cmd();
928  host_packet.offset = ci_get_wr_offset(command);
929  host_packet.byte_cnt = ci_get_wr_cnt(command);
930 
931  if (host_packet.cmd <= CI_CMD_LAST)
932  {
933 
934  if (host_packet.appId < ci_num_apps)
935  {
936  // If callback exists, then invoke it.
937  if (ci_callback[host_packet.appId] != NULL)
938  {
939  ci_status = ((*((ci_funcp_t)(ci_callback[host_packet.appId])))(&host_packet, &app_packet)); // Call trap function
940 
941 #ifdef DEBUG_TRACE_ENABLE
942 debug_trace_set(4, ci_debug_rx_packet_cnt);
943 #endif
944 
945  }
946  else
947  {
948  ci_status = CI_ERROR_CB_NOT_REGISTERED;
949  }
950  }
951  else
952  ci_status = CI_ERROR_PARAM;
953  }
954 #ifdef CI_DEBUG_ENABLE_LOOPBACK_CMD
955  else if (host_packet.cmd == CI_CMD_DEBUG_LOOPBACK)
956  {
957  ci_status = CI_ERROR_NONE;
958  app_packet.bytes_xfer = host_packet.byte_cnt;
959  app_packet.bytes_left = 0;
960  }
961 #endif
962  else
963  {
964  ci_status = CI_ERROR_COMMAND;
965  }
966 
967  // Return status to host.
968  MB_RESP_APP_ID = host_packet.appId;
969 
970  // Except for appId=0 (device info command), send back actual byte count and bytes requested.
971  if (host_packet.appId != 0)
972  {
973  MB_RESP_BYTES_XFER = app_packet.bytes_xfer; // Bytes actually xfered, updated by callback.
974  MB_RESP_COUNT = host_packet.byte_cnt; // Bytes requested by host
975  }
976 
977  // Tell host we are done processing command.
978  MB_RESP_STATUS_CC = coco_status | ci_status;
979 
980 
981  switch(host_packet.cmd)
982  {
983  // These commands only have the response header going back to host.
984  case CI_CMD_WRITE_CONFIG:
986  case CI_CMD_RESET_APP:
988  {
990 
991 #ifdef MBOX_ENABLE_CRC
992  {
993  uint16 crc16;
994 
995  // CRC only for the reponse packet.
997 
998  // Insert the CRC value into the packet going back to host. The CRC is placed at the end
999  // of the buffer.
1000  ci_insert_crc(size, crc16, ciMailboxes);
1001  }
1002 #endif
1003 
1004  ci_send_packet(size + MBOX_CRC_BYTE_SIZE, (uint8*)ciMailboxes);
1005 
1006  }
1007  break;
1008 
1009  default:
1010  {
1011  // All other commands require at least the response header plus
1012  // any data the host requested.
1013  uint8 size = MB_APP_RESP_SIZE + CI_PROTOCOL_ID_SIZE + app_packet.bytes_xfer;
1014 
1015 #ifdef MBOX_ENABLE_CRC
1016  {
1017  uint16 crc16;
1018 
1019  // CRC for reponse packet plus data size.
1020  crc16 = ccitt_crc16_cal(MB_APP_RESP_SIZE + app_packet.bytes_xfer, &ciMailboxes[CI_PROTOCOL_DATA_OFFSET]);
1021 
1022  // Insert the CRC value into the packet going back to host. The CRC is placed at the end
1023  // of the buffer.
1024  ci_insert_crc(size, crc16, ciMailboxes);
1025 
1026  }
1027 #endif
1028 
1029  // NOTE: This code assumes that we are sending back the 4 byte header in
1030  // MB0-3 and data payload starting at MB4. The number of bytes in the
1031  // payload depends on how many the callback processed and reported back.
1032  ci_send_packet(size + MBOX_CRC_BYTE_SIZE, (uint8*)ciMailboxes);
1033 
1034  }
1035 
1036  break;
1037  }
1038 
1039  }
1040 
1041 
1042 
1043  if (ci_status != CI_ERROR_NONE)
1044  ret = !ISF_SUCCESS;
1045 
1046  return ret;
1047 }
1048 
#define CI_PROTOCOL_DATA_OFFSET
Define offset to where protocol data begins of the send/receive buffer that skips pass the protocol i...
unsigned char uint8
Definition: isf_types.h:76
#define MB_RESP_BYTES_XFER
uint16 version_info
ISF Embedded Application version information.
void _fw_device_info_get(device_info_t *info_ptr)
Definition: isf.c:77
Command Interpreter Registers Structure. Contains all CI registers. .
ci_ctrl_reg_t ciCtrlReg
#define MB_RESP_INDEX_STATUS_CC
#define NUM_QR_MAILBOXES
Maximum number of mailboxes available on this system for quick read. Note that not all mailboxes de...
This structure holds the ROM device information such as device id and number of EmbApps present...
Definition: isf.h:187
ci_funcp_t ci_callback[]
Command interpreter callbacks. The array index is the application ID.
Definition: ISFCore1.c:94
isf_status_t ci_mbox_init(uint8 aprotocolID, void *apInitData)
#define ci_get_wr_cmdId()
#define MB_HOST_CMD
#define MB_APP_RESP_SIZE
#define MBOX_CRC_BYTE_SIZE
Define to enable CRC check. When enabled, CRC calculation is performed and CRC bytes are included in ...
#define MAX_NUM_MAILBOXES
Number of mailboxes available on this system.
ci_status_enum ci_status_t
Type definition for the CI status values.
Definition: isf_ci.h:187
Command Interpreter (CI) Protocol header file.
#define ISF_APP_ID_NULL
ci_response_t isf_app_callback_mbox(ci_host_cmd_packet_t *apHostPacket, ci_app_resp_packet_t *apAppPacket)
Callback function for mailbox application ID, ISF_APP_ID_MBOX.
#define MAX_ISF_APPLICATIONS
Maximum number of applications.
Definition: isf.h:95
#define qr_config_clear()
qr_config_t qr_config[NUM_QR_MAILBOXES]
#define MBOX_APP_DATA
#define ci_insert_crc(insert_offset, crc16_value, pBuf)
CRC header file.
ci_rw_enum rw
Definition: isf_ci.h:228
uint8 appType
ISF Embedded Application type.
#define CI_CMD_DEBUG_LOOPBACK
Debug commands.
ci_response_t isf_app_callback_dev_info(ci_host_cmd_packet_t *apHostPacket, ci_app_resp_packet_t *apAppPacket)
Callback function for the device info command, ISF_APP_ID_DEV_INFO.
Command interpreter task header file. This file is internal ISF code.
isf_status_t ci_protocol_CB_mbox(uint32 anumBytes, uint8 *apSrc, uint32 *apnumDestBytes, uint8 *apDest)
#define CI_PROTOCOL_ID_INDEX
Define the index of the send/receive buffer of where the protocol ID resides. Do not modify...
#define MB_RESP_INDEX_BYTES_XFER
#define CMD_PACKET_BITS
Mailboxes write bit. Bit setting for the 4 byte command packet from host. Bit position has same mea...
#define MB_RESP_COUNT
#define ci_get_wr_cnt(x)
#define CI_STREAMING_MODE
#define ci_get_wr_offset(x)
#define MB_RESP_INDEX_COUNT
#define CI_PROTOCOL_ID_SIZE
Define the number of bytes for the protocol ID. Do not modify.
uint8 numBytes
ISF Embedded Application registered additional information/data size.
uint32 isf_ci_app_read(uint8 aAppId, uint32 anumBytes, uint8 *apDst)
This API reads data from the host via the mailboxes.
uint32 isf_ci_app_write(uint8 aAppId, uint32 anumBytes, uint8 *apSrc)
This API writes data to the host via the mailboxes.
ISF Application Type for MailBox Application.
Definition: isf.h:49
isf_status_t ci_send_packet(uint32 anumBytes, uint8 *apSrc)
CI send packet - main function to send data to host.
Definition: task_ci.c:338
#define MB_RESP_STATUS_CC
uint16 ccitt_crc16_cal(uint32 anumBytes, uint8 *apBuf)
This crc function contains the standard CCITT CRC 16-bit implementation.
Definition: crc.c:18
Main ISF header file. Contains code common to all ISF components.
signed long int int32
Definition: isf_types.h:74
unsigned short int uint16
Definition: isf_types.h:77
#define ci_get_first_mailbox(x)
API definitions, types, and macros for the Intelligent Sensing Framework (ISF) Command Interpreter (C...
General library initialization failure status.
Definition: isf.h:34
ci_status_enum
ISF CI return status type.
Definition: isf_ci.h:31
ci_status_t isf_ci_qr_update(uint8 aAppId, int8 anumBytes, uint8 *apSrc)
This API updates the Quick-Read mailboxes.
#define APP_ID_NULL
Null application ID.
Definition: isf.h:103
ci_response_enum ci_qr_update(uint32 mb_read_bits)
Based upon mailbox bit mask, invoke the application's command interpreter callback to to update qui...
This structure enables an application to read from or write to the host.
Definition: isf_ci.h:221
int32 isf_status_t
ISF return status type.
Definition: isf.h:76
#define NUM_DATA_MAILBOXES
Maximum number of mailboxes available on this system for data from/to host. Note that not all mailb...
#define MB_HOST_CMD_SIZE(x)
unsigned char byte
Definition: isf_types.h:66
#define ci_get_wr_cmd()
#define FIRST_DATA_MAILBOX_NUM
First mailbox number for data transfer at powerup. Note that the actual first mailbox available for d...
This structure contains host command information.
Definition: isf_ci.h:197
struct ci_ctrl_reg_t::@3 Bits
unsigned long int uint32
Definition: isf_types.h:78
#define FIRST_QR_MAILBOX_NUM
First mailbox number that can be configured for quick read data. Quick read data can be written to t...
#define MB_RESP_APP_ID
ci_response_enum
These are the CI errors provided to the host.
Definition: isf_ci.h:119
#define COCO_BIT_MASK
#define CI_CMD_LAST
The maximum enumeration value implemented as a valid CI command.
Definition: isf_ci.h:179
void ci_update_first_data_mb(void)
Finds the first mailbox available for data pay load, how many mailboxes are available for data pay ...
ci_response_t(* ci_funcp_t)(ci_host_cmd_packet_t *, ci_app_resp_packet_t *)
This is a CI callback function pointer.
Definition: isf_ci.h:253
Command interpreter header file for the legacy mailbox protocol.
#define MB_RESP_INDEX_APP_ID
#define ci_get_wr_appid()
signed char int8
Definition: isf_types.h:72
#define MAX_NUM_OUT_BUFFER
Number of output buffer available on this system.