ISF  2.1
Intelligent Sensing Framework for Kinetis with Processor Expert
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
ci_protocol_mbox.c
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014, 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_target.h"
17 #include "isf.h"
18 #include "lwevent.h"
19 #include "lwsem.h"
20 
21 #include "isf_ci.h"
22 #include "isf_ci_protocol.h"
23 #include "task_ci.h"
24 #include "ci_protocol_mbox.h"
25 #include "crc.h"
26 
27 #include "cortex.h"
28 
29 
30 extern ci_funcp_t ci_callback[];
31 
32 
33 static inline uint8 ci_get_first_data_mb(uint8);
34 static inline uint8 ci_get_num_data_mb(void);
35 
36 // This semaphore is used for mailbox data access.
37 static LWSEM_STRUCT sema_ci_mb_access;
38 
39 // Contains the number of ci application callbacks. This value is calculated
40 // at initialization time by examining the ci_callback[] array.
41 static int32 ci_num_apps;
42 
43 // Contains the first mb number that is free for data pay load. This mb may
44 // be different than MB4 because the host may have configured them to be
45 // quick read.
46 static uint8 ci_first_data_mb;
47 
48 // Contains the number of *contiguous* mb available for data pay load.
49 static uint8 ci_num_data_mb;
50 
51 // Bit mask for quick read mailboxes. Each bit corresponds to each of the
52 // 32 mailboxes.
53 static uint32 ci_qr_mb_bit_mask;
54 
55 // HDLC protocol id for the CI protocol. The ID is passed into the init
56 // function which then stores it in this variable for later use.
57 static uint8 ci_protocol_id;
58 
59 
60 // Mailbox "registers". The buffer consists of the following data in order that
61 // they appear in the array:
62 // 1) protocol ID (1 byte)
63 // 2) Number of mailboxes
64 // 3) CRC16 value (2 byte, optional)
65 // Note that the protocol ID is required to be the first element in the array. The
66 // optional CRC value is placed last in the array. When working with the mailbox data,
67 // use the pciMailboxes pointer since it offsets 1 into the array to skip pass the
68 // protocol ID. When sending mbox data to the host, use the ciMailboxes[] array which
69 // contains the protocol ID at the beginning of the array.
71 static uint8 *pciMailboxes = (uint8 *)&ciMailboxes[CI_PROTOCOL_DATA_OFFSET];
72 
73 static ci_regs_t ciRegisters;
74 static uint32 ci_sp_writes;
75 
76 
77 
78 
79 // See isf_ci.h for documentation
80 ci_status_t isf_ci_qr_update(uint8 aAppId, int8 anumBytes, uint8 *apSrc)
81 {
82 
83  _mqx_uint ret = !MQX_OK;
84  ci_status_t ci_ret;
85 
86 
87  // If streaming mode is not enabled, quit.
89  return ret;
90 
91 
92  ret = _lwsem_wait_ticks(&sema_ci_mb_access, 0);
93 
94 
95  if (ret == MQX_OK)
96  {
97 
98  uint8 *pTemp_src;
99  int8 i = 0;
100  int8 j = 0;
101  int8 qr_bytes_written = 0;
102 
103  int8 prevIndex = 0;
104  int8 qr_cont_cnt = 0; // Contiguous QR mb count
106  uint8 *pQRBuf = (uint8*)&qr_send_buf[CI_PROTOCOL_DATA_OFFSET]; // First byte reserved for protocol id.
107 
108  // Assign protocol id.
109  qr_send_buf[0] = ci_protocol_id;
110 
111 
112  // We are only writing a few bytes to the mailboxes and would like this to
113  // be done as one set and not get preempted in the middle of the process.
114  // We want this set of data to be coherent when the host is reading it.
115  // Stopping preemption is also essentially raising the priority to highest
116  // level and let this task complete to prevent priority inversion.
117  _task_stop_preemption();
118 
119  while( (i < NUM_QR_MAILBOXES) && (qr_bytes_written < anumBytes) )
120  {
121  // We examine each mailbox configuration separately because its possible
122  // for the app to have its quick read info spread out among the mailboxes.
123  if (ciRegisters.qr_config[i].appId == aAppId)
124  {
125 
126  if (prevIndex == 0)
127  // This will be set once to the first QR mailbox found.
128  prevIndex = i-1;
129 
130 
131  // Only update mailboxes that are from the first set of contiguous
132  // mailboxes found. All other fragments of QR mailboxes from the
133  // same application are discarded.
134  if (prevIndex == (i-1))
135  {
136  // Start at the offset into the app's data.
137  pTemp_src = (uint8*)((uint32)apSrc + (uint32)ciRegisters.qr_config[i].byte_id);
138 
139  // Get mailbox address
140  //pDst = (uint8*)&pciMailboxes[FIRST_QR_MAILBOX_NUM+i];
141  //*pDst = *pTemp_src;
142 
143  pQRBuf[FIRST_QR_MAILBOX_NUM+j] = *pTemp_src;
144 
145  // Keep track of contiguous bytes.
146  ++qr_cont_cnt;
147  ++j;
148  }
149 
150  prevIndex = i;
151 
152  // Note that this counter could be counting QR mailboxes that are
153  // not contiguous.
154  ++qr_bytes_written;
155  }
156 
157  ++i;
158  }
159 
160  if (qr_cont_cnt > 0)
161  {
162  // Send back response only if the host has config QR mb for the app.
163  uint8 size = qr_cont_cnt + MB_APP_RESP_SIZE;
164 
165  // Create the response header.
166  pQRBuf[MB_RESP_INDEX_APP_ID] = aAppId;
168  pQRBuf[MB_RESP_INDEX_BYTES_XFER] = qr_cont_cnt;
169  pQRBuf[MB_RESP_INDEX_COUNT] = anumBytes;
170 
171 #ifdef MBOX_ENABLE_CRC
172  {
173  uint16 crc16;
174 
175  // CRC for qr data packet.
176  crc16 = ccitt_crc16_cal((uint32)size, pQRBuf);
177 
178  // Insert the CRC value into the packet going back to host. The CRC is placed at the end
179  // of the buffer.
180  ci_insert_crc(size, crc16, pQRBuf);
181 
182  }
183 #endif
184 
185  // Finally, send the packet.
187  }
188  else
189  {
190  // The host did not config any QR mb for this app.
191  ret = !MQX_OK;
192  }
193 
194  _task_start_preemption();
195  }
196 
197  if (ret == MQX_OK)
198  ci_ret = (ci_status_t)ISF_SUCCESS;
199  else
200  ci_ret = (ci_status_t)ISF_CI_FAILURE;
201 
202  _lwsem_post(&sema_ci_mb_access);
203 
204  return ci_ret;
205 }
206 
207 
208 
209 
210 // See isf_ci.h for documentation
211 uint32 isf_ci_app_read(uint8 aAppId, uint32 anumBytes, uint8 *apDst)
212 {
213 
214 
215  int32 bytes_read;
216  _mqx_uint ret;
217 
218 
219  ret = _lwsem_wait_ticks(&sema_ci_mb_access, 0);
220 
221  if (ret == MQX_OK)
222  {
223 
224  uint8 *pSrc;
225  uint8 *pTemp_dst;
226  int32 max_bytes;
227  uint32 mb_write_bits = 0;
228  uint32 mb_num;
229 
230 
231  // We are only writing a few bytes to the mailboxes and would like this to
232  // be done as one set and not get preempted in the middle of the process.
233  // We want this set of data to be coherent when the host is reading it.
234  // Stopping preemption is also essentially raising the priority to highest
235  // level and let this task complete to prevent priority inversion.
236  _task_stop_preemption();
237 
238  bytes_read = 0;
239  max_bytes = ci_get_num_data_mb();
240 
241  // Read data from first mailbox that is available for data.
242  mb_num = ci_get_first_data_mb(aAppId);
243 
244  pSrc = (uint8*)((uint32)mb_num + (uint32)&pciMailboxes[0]);
245 
246  pTemp_dst = apDst;
247  while( (bytes_read < max_bytes) && (bytes_read < (int32)anumBytes) )
248  {
249  *pTemp_dst++ = *pSrc++;
250  ++bytes_read;
251 
252  // Set the bit corresponding to the mailbox number.
253  mb_write_bits |= (uint32)(1 << mb_num++);
254  }
255 
256  _task_start_preemption();
257  }
258  else
259  bytes_read = 0;
260 
261  _lwsem_post(&sema_ci_mb_access);
262 
263  return (uint32)bytes_read;
264 }
265 
266 
267 // See isf_ci.h for documentation
268 uint32 isf_ci_app_write(uint8 aAppId, uint32 anumBytes, uint8 *apSrc)
269 {
270 
271  int32 bytes_written;
272  _mqx_uint ret;
273 
274 
275  ret = _lwsem_wait_ticks(&sema_ci_mb_access, 0);
276 
277  if (ret == MQX_OK)
278  {
279  uint8 *pTemp_src;
280  uint8 *pDst;
281  int32 max_bytes;
282 
283  // We are only writing a few bytes to the mailboxes and would like this to
284  // be done as one set and not get preempted in the middle of the process.
285  // We want this set of data to be coherent when the host is reading it.
286  // Stopping preemption is also essentially raising the priority to highest
287  // level and let this task complete to prevent priority inversion.
288  _task_stop_preemption();
289 
290  bytes_written = 0;
291  max_bytes = ci_get_num_data_mb();
292 
293 
294  // Write data to the first mailbox that is available for data.
295  pDst = (uint8*)((uint32)ci_get_first_data_mb(aAppId) + (uint32)&pciMailboxes[0]);
296 
297 
298  pTemp_src = apSrc;
299  while( (bytes_written < max_bytes) && (bytes_written < (int32)anumBytes) )
300  {
301  *pDst++ = *pTemp_src++;
302  ++bytes_written;
303  }
304 
305  _task_start_preemption();
306  }
307  else
308  bytes_written = 0;
309 
310  _lwsem_post(&sema_ci_mb_access);
311 
312  return (uint32)bytes_written;
313 }
314 
315 
316 
317 /*!
318  * @brief Finds the first mailbox available for data pay load, how many \n
319  * mailboxes are available for data pay load, and updates a bit mask \n
320  * that tracks which of the 32 mailboxes are used for quick read.
321  *
322  * @return None
323  *
324  * @errors None
325  *
326  * @constraints None
327  *
328  * @reentrant No.
329  *
330  * @libs \n
331  *
332  * @see \n
333  *
334 */
336 {
337  uint8 mb_num;
338  uint8 end_found;
339 
340 
341  _lwsem_wait_ticks(&sema_ci_mb_access, 0);
342 
343  _task_stop_preemption();
344 
345 
346  end_found = 0;
347  mb_num = 0;
348  ci_first_data_mb = 0; // Must init to zero
349  ci_num_data_mb = 0; // Must init to zero
350  ci_qr_mb_bit_mask = 0; // Must init to zero
351 
352 
353  do
354  {
355 
356  // The first mailbox not configured for quick read is the
357  // first mb available for data. We are not handling cases
358  // of fragmented quick read mailboxes.
359  if (ciRegisters.qr_config[mb_num].appId == APP_ID_NULL)
360  {
361 
362  if (ci_first_data_mb == 0)
363  {
364  // Found first non-quick read mailbox.
365  ci_first_data_mb = mb_num + FIRST_DATA_MAILBOX_NUM;
366  ++ci_num_data_mb;
367  }
368  else if (end_found == 0)
369  // Track number of contiguous free mailboxes after the first
370  // one is found.
371  ++ci_num_data_mb;
372  }
373  else
374  {
375 
376 #if (FIRST_QR_MAILBOX_NUM > FIRST_DATA_MAILBOX_NUM)
377  if ( (ci_first_data_mb) || (mb_num == 0) )
378  {
379  // Mark end of contiguous free mailboxes.
380  end_found = 1;
381  ci_first_data_mb = FIRST_DATA_MAILBOX_NUM;
382  }
383 #else
384  if (ci_first_data_mb)
385  {
386  // Mark end of contiguous free mailboxes.
387  end_found = 1;
388  }
389 #endif
390 
391  // Keep a bit mask of quick read mailboxes. Each bit corresponds to
392  // each of the 32 mailboxes.
393  ci_qr_mb_bit_mask |= (uint32)(1 << (mb_num+FIRST_QR_MAILBOX_NUM));
394  }
395  } while(++mb_num < NUM_QR_MAILBOXES);
396 
397 
398 #if (FIRST_QR_MAILBOX_NUM > FIRST_DATA_MAILBOX_NUM)
399  ci_num_data_mb += (FIRST_QR_MAILBOX_NUM - FIRST_DATA_MAILBOX_NUM);
400 #endif
401 
402 
403  _task_start_preemption();
404 
405  _lwsem_post(&sema_ci_mb_access);
406 
407 }
408 
409 
410 /*!
411  * @brief Based upon mailbox bit mask, invoke the application's \n
412  * command interpreter callback to to update quick read mailboxes.
413  *
414  * @param (in) mb_read_bits - Bit setting that indicates if a mailbox \n
415  * has been read. The corresponding mailbox quick read \n
416  * configuration is examined and its callback is invoked \n
417  * with command to update quick read registers. Each bit \n
418  * corresponds with each of the 32 mailboxes.
419  *
420  * A bit that is set indicates that the corresponding \n
421  * mailbox has been read.
422  *
423  *
424  * @return See ci_response_enum type for possible return values
425  *
426  * @errors None \n
427  *
428  * @constraints If another application is using the mailboxes, then the \n
429  * current calling application must wait until the other \n
430  * application has completed its operation on the mailboxes.
431  *
432  * @reentrant No. \n
433  *
434  * @libs \n
435  *
436  * @see \n
437  *
438 */
440 {
441  // Host read some quick read mailboxes.
442 
443  uint32 bit_pos = FIRST_QR_MAILBOX_NUM;
444  uint8 previous_app_id = APP_ID_NULL;
445 
446  ci_host_cmd_packet_t host_packet;
447  ci_app_resp_packet_t app_packet;
448  ci_response_enum callback_ret = CI_ERROR_NONE;
449 
450 
451  host_packet.offset = 0;
452  host_packet.cmd = CI_CMD_UPDATE_QUICKREAD;
453  host_packet.byte_cnt = 0;
454 
455  // For mailboxes configured as quick read and marked as read,
456  // find the application id and execute the callback if available.
457  // NOTE: The search implemented below assumes that each application's
458  // quick read configuration are contiguous. If it is fragmented,
459  // the application's callback may be invoked more than once.
460 
461 
462  do
463  {
464  if (mb_read_bits & (1 << bit_pos))
465  {
466  host_packet.appId = ciRegisters.qr_config[bit_pos-FIRST_QR_MAILBOX_NUM].appId;
467 
468  if ( (host_packet.appId != ISF_APP_ID_NULL) && (host_packet.appId != previous_app_id) && (host_packet.appId < ci_num_apps) )
469  {
470  previous_app_id = host_packet.appId;
471 
472  if (ci_callback[host_packet.appId] != NULL)
473  callback_ret = ((*((ci_funcp_t)(ci_callback[host_packet.appId])))(&host_packet, &app_packet)); // Call trap function
474  }
475  }
476  } while(++bit_pos < 32);
477 
478 
479  return callback_ret;
480 }
481 
482 
483 /*!
484  * @brief Get the first mailbox available for data.
485  *
486  * @return Mailbox number (0-31)
487  *
488  * @errors None \n
489  *
490  * @constraints None \n
491  *
492  * @reentrant No. \n
493  *
494  * @libs \n
495  *
496  * @see \n
497  *
498 */
499 static inline uint8 ci_get_first_data_mb(uint8 aAppId)
500 {
501  if (aAppId == 0)
502  return 2;
503  else
504  return ci_first_data_mb;
505 }
506 
507 /*!
508  * @brief Get the number of mailboxes available for data.
509  *
510  * @return Number of mailboxes (0-31)
511  *
512  * @errors None \n
513  *
514  * @constraints None \n
515  *
516  * @reentrant No. \n
517  *
518  * @libs \n
519  *
520  * @see \n
521  *
522 */
523 static inline uint8 ci_get_num_data_mb(void)
524 {
525 // return ci_num_data_mb;
526  return NUM_DATA_MAILBOXES;
527 }
528 
529 
530 
531 isf_status_t ci_mbox_init(uint8 aprotocolID, void *apInitData)
532 {
533 
535 
536 
537  ci_sp_writes = 0;
538 
539  // Set the id for this protocol.
540  ciMailboxes[CI_PROTOCOL_ID_INDEX] = ci_protocol_id = aprotocolID;
541 
542 
543  // Initialize the number of apps. Count number of pointers in
544  // array until we reach NULL or max num of allowable apps.
545  ci_num_apps = 0;
546  do
547  {
548  if (ci_callback[ci_num_apps] == NULL)
549  break;
550 
551  } while (++ci_num_apps < MAX_ISF_APPLICATIONS);
552 
553 
554  // Create semaphore for writes to mailbox.
555  if (_lwsem_create(&sema_ci_mb_access, 1) != MQX_OK)
556  ret = ISF_ERR_LIB_INIT;
557 
558 
559  // Initialize quick read configuration and mailbox array.
560  {
561  int i = MAX_NUM_MAILBOXES-1;
562  do
563  {
564  ciRegisters.qr_config[i].appId = 0;
565  ciRegisters.qr_config[i].byte_id = 0;
566  pciMailboxes[i] = 0;
567  } while(--i >= 0);
568  }
569 
570 
571  // Initial Ctrl Register
572  ciRegisters.ciCtrlReg.reg = 0;
573 
574  // Update first mb free for data and # of contiguous
575  // free mailboxes after that.
577 
578  // At reset put the device Id into the mailboxes
579  {
580  device_info_t devInfo;
581 
582  // ENGR00312443: Zero out the structure. The device info structure was carried over from FXLC95000
583  // which contains some fields that were populated by the FXLC95K's ROM code. We no longer have the
584  // ROM code and these fields are unused. So we must zero them out. For KL25Z R1p1 release, this bug
585  // manifiest itself in such a way that the first call to this function will return all zeros in the
586  // unused field. But all subsequent calls returns garbage data in those fields. The only fields
587  // that are correct are the ones we populate explicitly below (build code, fw versiont, etc).
588  //_mem_zero(&devInfo, sizeof(device_info_t));
589  _mem_zero(&devInfo, sizeof(devInfo));
590 
591  _fw_device_info_get(&devInfo);
592  //isf_ci_app_write(0, sizeof(device_info_t), (unsigned char *)&devInfo);
593  isf_ci_app_write(0, sizeof(devInfo), (unsigned char *)&devInfo);
594  }
595 
596 
597 
598  return ret;
599 }
600 
601 
602 /*!
603  *
604  * @brief Callback function for mailbox application ID, ISF_APP_ID_MBOX.
605  *
606  * @param packet_ptr - host command packet
607  *
608  * @param mb_data_ptr - pointer to first mailbox address containing \n
609  * data.
610  *
611  * @return See ci_response_enum type for possible return values
612  *
613  * @errors None \n
614  *
615  * @constraints If another application is using the mailboxes, then the \n
616  * current calling application must wait until the other \n
617  * application has completed its operation on the mailboxes.
618  *
619  * @reentrant Yes. \n
620  *
621  * @libs \n
622  *
623  * @see \n
624  *
625 */
627 {
628 
629  ci_response_enum callback_ret = CI_ERROR_NONE;
630 
631 
632  switch(apHostPacket->cmd)
633  {
634 
635  case CI_CMD_READ_CONFIG:
636  case CI_CMD_WRITE_CONFIG:
637  {
638  // Host is reading or writing.
639  int32 cnt = (int32)apHostPacket->byte_cnt;
640  int32 offset = (int32)apHostPacket->offset;
641  apAppPacket->rw = CI_RW_NULL;
642  apAppPacket->bytes_xfer = 0;
643 
644  if ( (cnt == 0) || (cnt > (sizeof(ciRegisters))) )
645  {
646  callback_ret = CI_INVALID_COUNT;
647  }
648  else if ( (offset >= (sizeof(ciRegisters))) || ((cnt+offset) > (sizeof(ciRegisters))) )
649  {
650  callback_ret = CI_ERROR_INVALID_LENGTH;
651  }
652  else
653  {
654  // No errors so far, perform read or write operation.
655 
656  uint8 *pSrc_ptr;
657  uint8 *pDst_ptr;
658 
659  if (apHostPacket->cmd == CI_CMD_READ_CONFIG)
660  {
661  // Host reading current configuration.
662 
663  // Host read: src ptr points to QR config.
664  pSrc_ptr = (uint8*)((uint32)ciRegisters.qr_config + (uint32)offset);
665 
666  // Write the data to host.
667  apAppPacket->rw = CI_RW_WRITE;
668  apAppPacket->bytes_xfer = (uint8)isf_ci_app_write(apHostPacket->appId, (uint32)cnt, pSrc_ptr);
669 
670  }
671  else
672  {
673  // Host writing new configuration.
674 
675  // Host write: dst ptr points to application data
676  pDst_ptr = (uint8*)((uint32)ciRegisters.qr_config + (uint32)offset);
677 
678  // Read data from the host.
679  apAppPacket->rw = CI_RW_READ;
680  apAppPacket->bytes_xfer = (uint8)isf_ci_app_read(apHostPacket->appId, (uint32)apHostPacket->byte_cnt, pDst_ptr);
681 
682  if(offset < sizeof(ciRegisters.qr_config))
683  {
684 
685  // Host had updated the quick read configuration. Update.
687 
688 
689  // NOTE: For uart comm, do not try to do QR update. The app will
690  // need to update QR which will send the data immediately to host.
691  // Doing the QR update here may complicate things with the host because
692  // it will get back a QR packet and command-reponse packet back to back.
693 #if 0
694  // Do quick read update for any new applications that got added.
695  new_qr_bits = old_qr_bit_mask | ci_qr_mb_bit_mask;
696  new_qr_bits ^= old_qr_bit_mask;
697 
698 
699  // Return value is discarded. This quick read update is not
700  // in response to a host read. Rather, this is the first time the
701  // host has registered for the application's quick read and the
702  // app needs to update the mailboxes for the first time.
703  ci_qr_update(new_qr_bits);
704 #endif
705  }
706 
707  }
708  }
709  }
710 
711  break;
712 
713  case CI_CMD_RESET_APP:
714 
715  // Host is requesting to clear all QR config.
716  qr_config_clear();
717 
718  // Host had updated the quick read configuration. Update.
720 
721  // Turn off everything.
722  ciRegisters.ciCtrlReg.reg = 0;
723 
724  break;
726  break;
728  default:
729  callback_ret = CI_ERROR_COMMAND;
730  break;
731 
732  }
733 
734  // Note: The return packet is for future use. The information could be used
735  // to implement multipacket transfer without handshake for every packet. The
736  // exact method to do this is TBD.
737  apAppPacket->bytes_left = 0;
738 
739  return callback_ret;
740 }
741 
742 
743 /*!
744  *
745  * @brief Callback function for the device info command, ISF_APP_ID_DEV_INFO.
746  *
747  * @param packet_ptr - host command packet
748  *
749  * @param mb_data_ptr - pointer to first mailbox address containing \n
750  * data.
751  *
752  * @return See ci_response_enum type for possible return values
753  *
754  * @errors None \n
755  *
756  * @constraints If another application is using the mailboxes, then the \n
757  * current calling application must wait until the other \n
758  * application has completed its operation on the mailboxes.
759  *
760  * @reentrant Yes. \n
761  *
762  * @libs \n
763  *
764  * @see \n
765  *
766 */
768 {
769 
770  device_info_t devInfo;
771 
772  // ENGR00312443: Zero out the structure. The device info structure was carried over from FXLC95000
773  // which contains some fields that were populated by the FXLC95K's ROM code. We no longer have the
774  // ROM code and these fields are unused. So we must zero them out. For KL25Z R1p1 release, this bug
775  // manifiest itself in such a way that the first call to this function will return all zeros in the
776  // unused field. But all subsequent calls returns garbage data in those fields. The only fields
777  // that are correct are the ones we populate explicitly below (build code, fw versiont, etc).
778  _mem_zero(&devInfo, sizeof(devInfo));
779 
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:
987  {
989 
990 #ifdef MBOX_ENABLE_CRC
991  {
992  uint16 crc16;
993 
994  // CRC only for the reponse packet.
996 
997  // Insert the CRC value into the packet going back to host. The CRC is placed at the end
998  // of the buffer.
999  ci_insert_crc(size, crc16, ciMailboxes);
1000  }
1001 #endif
1002 
1003  ci_send_packet(size + MBOX_CRC_BYTE_SIZE, (uint8*)ciMailboxes);
1004 
1005  }
1006  break;
1007 
1008  default:
1009  {
1010  // All other commands require at least the response header plus
1011  // any data the host requested.
1012  uint8 size = MB_APP_RESP_SIZE + CI_PROTOCOL_ID_SIZE + app_packet.bytes_xfer;
1013 
1014 #ifdef MBOX_ENABLE_CRC
1015  {
1016  uint16 crc16;
1017 
1018  // CRC for reponse packet plus data size.
1019  crc16 = ccitt_crc16_cal(MB_APP_RESP_SIZE + app_packet.bytes_xfer, &ciMailboxes[CI_PROTOCOL_DATA_OFFSET]);
1020 
1021  // Insert the CRC value into the packet going back to host. The CRC is placed at the end
1022  // of the buffer.
1023  ci_insert_crc(size, crc16, ciMailboxes);
1024 
1025  }
1026 #endif
1027 
1028  // NOTE: This code assumes that we are sending back the 4 byte header in
1029  // MB0-3 and data payload starting at MB4. The number of bytes in the
1030  // payload depends on how many the callback processed and reported back.
1031  ci_send_packet(size + MBOX_CRC_BYTE_SIZE, (uint8*)ciMailboxes);
1032 
1033  }
1034 
1035  break;
1036  }
1037 
1038  }
1039 
1040 
1041 
1042  if (ci_status != CI_ERROR_NONE)
1043  ret = !ISF_SUCCESS;
1044 
1045  return ret;
1046 }
#define CI_PROTOCOL_DATA_OFFSET
Define offset to where protocol data begins of the send/receive buffer that skips pass the protocol i...
ISF board support header files.
unsigned char uint8
This defines uint8 as unsigned char.
Definition: isf_types.h:18
#define MB_RESP_BYTES_XFER
void _fw_device_info_get(device_info_t *info_ptr)
Definition: isf.c:68
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 version and part number and is returned by th...
Definition: isf.h:115
ci_funcp_t ci_callback[]
Command interpreter callbacks. The array index is the application ID.
Definition: ISFCore1.c:49
isf_status_t ci_mbox_init(uint8 aprotocolID, void *apInitData)
#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 sytem.
ci_status_enum ci_status_t
Type definition for the CI status values.
Definition: isf_ci.h:176
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 qr_config_clear()
#define ci_get_wr_cmdId()
#define MAX_ISF_APPLICATIONS
Maximum number of applications.
Definition: isf.h:70
qr_config_t qr_config[NUM_QR_MAILBOXES]
signed char int8
Definition: basic_types.h:12
#define ci_insert_crc(insert_offset, crc16_value, pBuf)
CRC header file.
unsigned long uint32
This defines uint32 as unsigned long.
Definition: isf_types.h:36
ci_rw_enum rw
Definition: isf_ci.h:217
#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 ci_get_wr_cnt(x)
#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_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.
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.
#define ci_get_wr_appid()
isf_status_t ci_send_packet(uint32 anumBytes, uint8 *apSrc)
CI send packet - main function to send data to host.
Definition: task_ci.c:342
#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
long int32
This defines int32 as long.
Definition: isf_types.h:32
Main ISF header file. Contains code common to all ISF components.
#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:36
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:78
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:242
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...
unsigned short uint16
This defines uint16 as unsigned short.
Definition: isf_types.h:27
This structure enables an application to read from or write to the host.
Definition: isf_ci.h:210
int32 isf_status_t
ISF return status type.
Definition: isf.h:51
#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)
#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:186
#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:107
#define COCO_BIT_MASK
#define CI_CMD_LAST
The maximum enumeration value implemented as a valid CI command.
Definition: isf_ci.h:167
void ci_update_first_data_mb(void)
Finds the first mailbox available for data pay load, how many mailboxes are available for data pay ...
Command interpreter header file for the legacy mailbox protocol.
struct ci_ctrl_reg_t::@4 Bits
#define MB_RESP_INDEX_APP_ID