| ISF 2.1 Intelligent Sensing Framework for Kinetis with Processor Expert

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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.
70 static uint8 ciMailboxes[CI_PROTOCOL_ID_SIZE + MAX_NUM_MAILBOXES + MBOX_CRC_BYTE_SIZE];
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.
88 if(ciRegisters.ciCtrlReg.Bits.blockTransferMode != CI_STREAMING_MODE)
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
105 uint8 qr_send_buf[MAX_NUM_MAILBOXES + CI_PROTOCOL_ID_SIZE + MBOX_CRC_BYTE_SIZE];
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;
167 pQRBuf[MB_RESP_INDEX_STATUS_CC] = 0x80 | CI_RESP_QUICKREAD;
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.
186 ci_send_packet(CI_PROTOCOL_ID_SIZE + size + MBOX_CRC_BYTE_SIZE, (uint8*)qr_send_buf);
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 */
335 void ci_update_first_data_mb(void)
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 */
439 ci_response_enum ci_qr_update(uint32 mb_read_bits)
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
534 isf_status_t ret = ISF_SUCCESS;
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.
576 ci_update_first_data_mb();
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 */
626 ci_response_t isf_app_callback_mbox(ci_host_cmd_packet_t *apHostPacket, ci_app_resp_packet_t *apAppPacket)
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.
686 ci_update_first_data_mb();
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.
719 ci_update_first_data_mb();
720
721 // Turn off everything.
722 ciRegisters.ciCtrlReg.reg = 0;
723
724 break;
725 case CI_CMD_UPDATE_QUICKREAD:
726 break;
727 case CI_CMD_READ_APP_DATA:
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 */
767 ci_response_t isf_app_callback_dev_info(ci_host_cmd_packet_t *apHostPacket, ci_app_resp_packet_t *apAppPacket)
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;
800 isf_status_t ret = ISF_SUCCESS;
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.
868 if (ci_get_wr_cmdId() == CI_CMD_WRITE_CONFIG)
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 {
896 MB_RESP_APP_ID = ci_get_wr_appid();
897 MB_RESP_STATUS_CC = coco_status | ci_status;
898 MB_RESP_BYTES_XFER = 0;
899 MB_RESP_COUNT = 0;
900
901
902 uint8 size = MB_APP_RESP_SIZE + CI_PROTOCOL_ID_SIZE;
903 {
904 uint16 crc16;
905
906 // CRC only for the response packet.
907 crc16 = ccitt_crc16_cal((uint32)MB_APP_RESP_SIZE, &ciMailboxes[CI_PROTOCOL_DATA_OFFSET]);
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.
924 MB_RESP_STATUS_CC &= ~((uint8)COCO_BIT_MASK);
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:
985 case CI_CMD_UPDATE_QUICKREAD:
986 case CI_CMD_RESET_APP:
987 {
988 uint8 size = MB_APP_RESP_SIZE + CI_PROTOCOL_ID_SIZE;
989
990 #ifdef MBOX_ENABLE_CRC
991 {
992 uint16 crc16;
993
994 // CRC only for the reponse packet.
995 crc16 = ccitt_crc16_cal((uint32)MB_APP_RESP_SIZE, &ciMailboxes[CI_PROTOCOL_DATA_OFFSET]);
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 }
CI_PROTOCOL_DATA_OFFSET
#define CI_PROTOCOL_DATA_OFFSET
Define offset to where protocol data begins of the send/receive buffer that skips pass the protocol i...
Definition: isf_ci_protocol.h:53
isf_target.h
ISF board support header files.
uint8
unsigned char uint8
This defines uint8 as unsigned char.
Definition: isf_types.h:18
CI_RW_WRITE
Definition: isf_ci.h:55
MB_RESP_BYTES_XFER
#define MB_RESP_BYTES_XFER
Definition: ci_protocol_mbox.h:66
ci_ctrl_reg_t::reg
uint8 reg
Definition: ci_protocol_mbox.h:202
_fw_device_info_get
void _fw_device_info_get(device_info_t *info_ptr)
Definition: isf.c:68
ci_regs_t
Command Interpreter Registers Structure. Contains all CI registers. .
Definition: ci_protocol_mbox.h:217
ci_regs_t::ciCtrlReg
ci_ctrl_reg_t ciCtrlReg
Definition: ci_protocol_mbox.h:220
MB_RESP_INDEX_STATUS_CC
#define MB_RESP_INDEX_STATUS_CC
Definition: ci_protocol_mbox.h:69
CI_CMD_READ_CONFIG
Definition: isf_ci.h:74
NUM_QR_MAILBOXES
#define NUM_QR_MAILBOXES
Maximum number of mailboxes available on this system for quick read. Note that not all mailboxes de...
Definition: ci_protocol_mbox.h:160
device_info_t
This structure holds the ROM device information such as version and part number and is returned by th...
Definition: isf.h:115
ci_host_cmd_packet_t::byte_cnt
uint8 byte_cnt
Definition: isf_ci.h:198
ci_host_cmd_packet_t::offset
uint16 offset
Definition: isf_ci.h:195
ci_callback
ci_funcp_t ci_callback[]
Command interpreter callbacks. The array index is the application ID.
Definition: ISFCore1.c:49
ISF_CI_FAILURE
Definition: isf_ci.h:34
ci_mbox_init
isf_status_t ci_mbox_init(uint8 aprotocolID, void *apInitData)
Definition: ci_protocol_mbox.c:531
ISF_SUCCESS
Definition: isf.h:33
MB_HOST_CMD
#define MB_HOST_CMD
Definition: ci_protocol_mbox.h:55
MB_APP_RESP_SIZE
#define MB_APP_RESP_SIZE
Definition: ci_protocol_mbox.h:73
MBOX_CRC_BYTE_SIZE
#define MBOX_CRC_BYTE_SIZE
Define to enable CRC check. When enabled, CRC calculation is performed and CRC bytes are included in ...
Definition: ci_protocol_mbox.h:35
MAX_NUM_MAILBOXES
#define MAX_NUM_MAILBOXES
Number of mailboxes available on this sytem.
Definition: ci_protocol_mbox.h:119
ci_status_t
ci_status_enum ci_status_t
Type definition for the CI status values.
Definition: isf_ci.h:176
qr_config_t::byte_id
uint8 byte_id
Definition: ci_protocol_mbox.h:185
isf_ci_protocol.h
Command Interpreter (CI) Protocol header file.
CI_ERROR_INVALID_LENGTH
Definition: isf_ci.h:128
ISF_APP_ID_NULL
#define ISF_APP_ID_NULL
Definition: ci_protocol_mbox.h:44
isf_app_callback_mbox
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.
Definition: ci_protocol_mbox.c:626
qr_config_clear
#define qr_config_clear()
Definition: ci_protocol_mbox.h:243
ci_get_wr_cmdId
#define ci_get_wr_cmdId()
Definition: ci_protocol_mbox.h:235
CI_ERROR_COMMAND
Definition: isf_ci.h:125
MAX_ISF_APPLICATIONS
#define MAX_ISF_APPLICATIONS
Maximum number of applications.
Definition: isf.h:70
ci_regs_t::qr_config
qr_config_t qr_config[NUM_QR_MAILBOXES]
Definition: ci_protocol_mbox.h:219
CI_CMD_UPDATE_QUICKREAD
Definition: isf_ci.h:83
int8
signed char int8
Definition: basic_types.h:12
ci_insert_crc
#define ci_insert_crc(insert_offset, crc16_value, pBuf)
Definition: ci_protocol_mbox.h:254
crc.h
CRC header file.
uint32
unsigned long uint32
This defines uint32 as unsigned long.
Definition: isf_types.h:36
ci_host_cmd_packet_t::cmd
uint8 cmd
Definition: isf_ci.h:192
CI_RESP_QUICKREAD
Definition: isf_ci.h:150
ci_app_resp_packet_t::rw
ci_rw_enum rw
Definition: isf_ci.h:217
ci_app_resp_packet_t::bytes_xfer
uint8 bytes_xfer
Definition: isf_ci.h:222
CI_RW_NULL
Definition: isf_ci.h:49
CI_CMD_DEBUG_LOOPBACK
#define CI_CMD_DEBUG_LOOPBACK
Debug commands.
Definition: ci_protocol_mbox.h:225
isf_app_callback_dev_info
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.
Definition: ci_protocol_mbox.c:767
task_ci.h
Command interpreter task header file. This file is internal ISF code.
ci_protocol_CB_mbox
isf_status_t ci_protocol_CB_mbox(uint32 anumBytes, uint8 *apSrc, uint32 *apnumDestBytes, uint8 *apDest)
Definition: ci_protocol_mbox.c:795
CI_RW_READ
Definition: isf_ci.h:52
CI_ERROR_CB_NOT_REGISTERED
Definition: isf_ci.h:146
CI_PROTOCOL_ID_INDEX
#define CI_PROTOCOL_ID_INDEX
Define the index of the send/receive buffer of where the protocol ID resides. Do not modify...
Definition: isf_ci_protocol.h:59
qr_config_t::appId
uint8 appId
Definition: ci_protocol_mbox.h:184
MB_RESP_INDEX_BYTES_XFER
#define MB_RESP_INDEX_BYTES_XFER
Definition: ci_protocol_mbox.h:70
ci_get_wr_cnt
#define ci_get_wr_cnt(x)
Definition: ci_protocol_mbox.h:237
CMD_PACKET_BITS
#define CMD_PACKET_BITS
Mailboxes write bit. Bit setting for the 4 byte command packet from host. Bit position has same mea...
Definition: ci_protocol_mbox.h:88
MB_RESP_COUNT
#define MB_RESP_COUNT
Definition: ci_protocol_mbox.h:67
CI_STREAMING_MODE
#define CI_STREAMING_MODE
Definition: ci_protocol_mbox.h:76
ci_get_wr_offset
#define ci_get_wr_offset(x)
Definition: ci_protocol_mbox.h:236
MB_RESP_INDEX_COUNT
#define MB_RESP_INDEX_COUNT
Definition: ci_protocol_mbox.h:71
CI_PROTOCOL_ID_SIZE
#define CI_PROTOCOL_ID_SIZE
Define the number of bytes for the protocol ID. Do not modify.
Definition: isf_ci_protocol.h:47
CI_CMD_READ_APP_DATA
Definition: isf_ci.h:80
CI_INVALID_COUNT
Definition: isf_ci.h:122
isf_ci_app_read
uint32 isf_ci_app_read(uint8 aAppId, uint32 anumBytes, uint8 *apDst)
This API reads data from the host via the mailboxes.
Definition: ci_protocol_mbox.c:211
isf_ci_app_write
uint32 isf_ci_app_write(uint8 aAppId, uint32 anumBytes, uint8 *apSrc)
This API writes data to the host via the mailboxes.
Definition: ci_protocol_mbox.c:268
ci_get_wr_appid
#define ci_get_wr_appid()
Definition: ci_protocol_mbox.h:233
ci_send_packet
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
MB_RESP_STATUS_CC
#define MB_RESP_STATUS_CC
Definition: ci_protocol_mbox.h:65
ccitt_crc16_cal
uint16 ccitt_crc16_cal(uint32 anumBytes, uint8 *apBuf)
This crc function contains the standard CCITT CRC 16-bit implementation.
Definition: crc.c:18
int32
long int32
This defines int32 as long.
Definition: isf_types.h:32
ci_app_resp_packet_t::bytes_left
uint8 bytes_left
Definition: isf_ci.h:227
isf.h
Main ISF header file. Contains code common to all ISF components.
CI_ERROR_PARAM
Definition: isf_ci.h:117
ci_get_first_mailbox
#define ci_get_first_mailbox(x)
Definition: ci_protocol_mbox.h:238
isf_ci.h
API definitions, types, and macros for the Intelligent Sensing Framework (ISF) Command Interpreter (C...
ISF_ERR_LIB_INIT
General library initialization failure status.
Definition: isf.h:36
ci_status_enum
ci_status_enum
ISF CI return status type.
Definition: isf_ci.h:31
isf_ci_qr_update
ci_status_t isf_ci_qr_update(uint8 aAppId, int8 anumBytes, uint8 *apSrc)
This API updates the Quick-Read mailboxes.
Definition: ci_protocol_mbox.c:80
APP_ID_NULL
#define APP_ID_NULL
Null application ID.
Definition: isf.h:78
ci_funcp_t
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_CMD_READ_VERSION
Definition: isf_ci.h:71
ci_qr_update
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...
Definition: ci_protocol_mbox.c:439
uint16
unsigned short uint16
This defines uint16 as unsigned short.
Definition: isf_types.h:27
ci_app_resp_packet_t
This structure enables an application to read from or write to the host.
Definition: isf_ci.h:210
isf_status_t
int32 isf_status_t
ISF return status type.
Definition: isf.h:51
NUM_DATA_MAILBOXES
#define NUM_DATA_MAILBOXES
Maximum number of mailboxes available on this system for data from/to host. Note that not all mailb...
Definition: ci_protocol_mbox.h:136
MB_HOST_CMD_SIZE
#define MB_HOST_CMD_SIZE(x)
Definition: ci_protocol_mbox.h:58
ci_get_wr_cmd
#define ci_get_wr_cmd()
Definition: ci_protocol_mbox.h:234
FIRST_DATA_MAILBOX_NUM
#define FIRST_DATA_MAILBOX_NUM
First mailbox number for data transfer at powerup. Note that the actual first mailbox available for d...
Definition: ci_protocol_mbox.h:128
ci_host_cmd_packet_t
This structure contains host command information.
Definition: isf_ci.h:186
FIRST_QR_MAILBOX_NUM
#define FIRST_QR_MAILBOX_NUM
First mailbox number that can be configured for quick read data. Quick read data can be written to t...
Definition: ci_protocol_mbox.h:144
CI_ERROR_NONE
Definition: isf_ci.h:111
ci_host_cmd_packet_t::appId
uint8 appId
Definition: isf_ci.h:189
MB_RESP_APP_ID
#define MB_RESP_APP_ID
Definition: ci_protocol_mbox.h:64
ci_response_enum
ci_response_enum
These are the CI errors provided to the host.
Definition: isf_ci.h:107
COCO_BIT_MASK
#define COCO_BIT_MASK
Definition: ci_protocol_mbox.h:96
CI_CMD_RESET_APP
Definition: isf_ci.h:89
CI_CMD_WRITE_CONFIG
Definition: isf_ci.h:77
CI_CMD_LAST
#define CI_CMD_LAST
The maximum enumeration value implemented as a valid CI command.
Definition: isf_ci.h:167
ci_update_first_data_mb
void ci_update_first_data_mb(void)
Finds the first mailbox available for data pay load, how many mailboxes are available for data pay ...
Definition: ci_protocol_mbox.c:335
ci_protocol_mbox.h
Command interpreter header file for the legacy mailbox protocol.
ci_ctrl_reg_t::Bits
struct ci_ctrl_reg_t::@4 Bits
MB_RESP_INDEX_APP_ID
#define MB_RESP_INDEX_APP_ID
Definition: ci_protocol_mbox.h:68
ci_ctrl_reg_t::blockTransferMode
uint8 blockTransferMode
Definition: ci_protocol_mbox.h:206
- © Freescale Semiconductor, Inc. 2015. All Rights Reserved.