2 * Copyright 1994-2012 The MathWorks, Inc.
7 * External mode server interface (TCPIP example). Provides functions
8 * that get called by main routine (model-name.c):
9 * o ExtParseArgsAndInitUD: parse args and create UserData
10 * o ExtWaitForStartPkt: return true if waiting for host to start
11 * o rt_ExtModeInit: external mode initialization
12 * o rt_ExtModeSleep: pause the process
13 * o rt_PktServerWork: server for setting/getting packets from host
14 * o rt_PktServer: server dispatcher - for multi-tasking targets
15 * o rt_UploadServerWork: server for setting data upload packets on host
16 * o rt_UploadServer: server dispatcher - for multi-tasking targets
17 * o rt_ExtModeShutdown: external mode termination
19 * Parameter downloading and data uploading supported for single and
20 * multi-tasking targets.
28 #ifndef EXTMODE_DISABLEPRINTF
37 # include <selectLib.h>
44 /*Real Time Workshop headers*/
46 #include "rtw_extmode.h"
48 #include "ext_types.h"
49 #include "ext_share.h"
51 #include "ext_svr_transport.h"
53 #include "updown_util.h"
56 /*Uncomment to test 4 byte reals*/
57 /*#define real_T float*/
59 /**********************
60 * External Variables *
61 **********************/
62 extern int_T volatile startModel;
63 extern TargetSimStatus volatile modelStatus;
65 extern SEM_ID uploadSem;
68 extern boolean_T host_upstatus_is_uploading;
77 PRIVATE boolean_T connected = FALSE;
78 PRIVATE boolean_T commInitialized = FALSE;
81 * Pointer to opaque user data (defined by ext_svr_transport.c).
83 PRIVATE ExtUserData *extUD = NULL;
86 * Buffer used to receive packets.
88 PRIVATE int_T pktBufSize = 0;
89 PRIVATE char *pktBuf = NULL;
92 #ifndef EXTMODE_DISABLESIGNALMONITORING
93 #ifndef EXTMODE_DISABLEPRINTF
94 PRIVATE char ERRMSG_PROCESSSELECTSIGNAL[] =
95 "\nError in UploadLogInfoInit(). Most likely a memory\n"
96 "allocation error or an attempt to re-initialize the\n"
97 "signal selection during the data logging process\n"
98 "(i.e., multiple EXT_SELECT_SIGNAL packets were received\n"
99 "before the logging session terminated or an\n"
100 "EXT_CANCEL_LOGGING packet was received)\n";
102 PRIVATE char ERRMSG_PROCESSSELECTTRIGGER[] =
103 "\nError in UploadInitTrigger(). Most likely a memory\n"
104 "allocation error or an attempt to re-initialize the\n"
105 "trigger selection during the data logging process\n"
106 "(i.e., multiple EXT_SELECT_TRIGGER packets were received\n"
107 "before the logging session terminated or an\n"
108 "EXT_CANCEL_LOGGING packet was received)\n";
110 PRIVATE char ERRMSG_PROCESSSELECTSIGNAL[] = "";
111 PRIVATE char ERRMSG_PROCESSSELECTTRIGGER[] = "";
119 /* Function: GrowRecvBufIfNeeded ===============================================
121 * Allocate or increase the size of buffer for receiving packets from target.
123 PRIVATE boolean_T GrowRecvBufIfNeeded(const int pktSize)
125 if (pktSize > pktBufSize) {
126 if (pktBuf != NULL) {
131 pktBuf = (char *)malloc(pktSize);
132 if (pktBuf == NULL) return(EXT_ERROR);
134 pktBufSize = pktSize;
136 return(EXT_NO_ERROR);
137 } /* end GrowRecvBufIfNeeded */
140 /* Function: GetPktHdr =========================================================
142 * Attempts to retrieve a packet header from the host. If a header is in
143 * fact retrieved, the reference arg, 'hdrAvail' will be returned as true.
145 * EXT_NO_ERROR is returned on success, EXT_ERROR is returned on failure.
148 * o It is not necessarily an error for 'hdrAvail' to be returned as false.
149 * It typically means that we were polling for packets and none were
152 PRIVATE boolean_T GetPktHdr(PktHeader *pktHdr, boolean_T *hdrAvail)
154 int_T nGot = 0; /* assume */
156 int_T pktSize = sizeof(PktHeader);
157 boolean_T error = EXT_NO_ERROR;
159 /* Get the header. */
160 while(nGotTotal < pktSize) {
161 error = ExtGetHostPkt(extUD,
162 pktSize - nGotTotal, &nGot, (char_T *)((char_T *)pktHdr + nGotTotal));
163 if (error) goto EXIT_POINT;
167 if (nGotTotal == 0) break;
169 assert((nGot == 0) || (nGotTotal == pktSize));
172 *hdrAvail = (boolean_T)(nGot > 0);
174 } /* end GetPktHdr */
177 /* Function: ClearPkt ==========================================================
179 * Remove the data from the communication line one byte at a time. This
180 * function is called when there was not enough memory to receive an entire
181 * packet. Since the data was never received, it must be discarded so that
182 * other packets can be sent.
184 PRIVATE void ClearPkt(const int pktSize)
187 boolean_T error = EXT_NO_ERROR;
191 /* Get and discard the data one char at a time. */
192 while(nGotTotal < pktSize) {
193 error = ExtGetHostPkt(extUD, 1, &nGot, (char_T *)&buffer);
195 #ifndef EXTMODE_DISABLEPRINTF
196 fprintf(stderr,"ExtGetHostPkt() failed.\n");
210 /* Function: GetPkt ============================================================
212 * Receive nBytes from the host. Return a buffer containing the bytes or
213 * NULL if an error occurs. Note that the pointer returned is that of the
214 * global pktBuf. If the buf needs to be grown to accommodate the package,
215 * it is realloc'd. This function will try to get the requested number
216 * of bytes indefinitely - it is assumed that the data is either already there,
217 * or will show up in a "reasonable" amount of time.
219 PRIVATE const char *GetPkt(const int pktSize)
222 boolean_T error = EXT_NO_ERROR;
225 error = GrowRecvBufIfNeeded(pktSize);
226 if (error != EXT_NO_ERROR) {
227 #ifndef EXTMODE_DISABLEPRINTF
228 fprintf(stderr,"Previous pkt from host thrown away due to lack of memory.\n");
235 while(nGotTotal < pktSize) {
236 error = ExtGetHostPkt(extUD,
237 pktSize - nGotTotal, &nGot, (char_T *)(pktBuf + nGotTotal));
239 #ifndef EXTMODE_DISABLEPRINTF
240 fprintf(stderr,"ExtGetHostPkt() failed.\n");
249 return((error == EXT_NO_ERROR) ? pktBuf : NULL);
253 #ifndef EXTMODE_DISABLESIGNALMONITORING
254 /* Forward declaration */
255 void UploadServerWork(int32_T, int_T numSampTimes);
258 /* Function: DisconnectFromHost ================================================
260 * Disconnect from the host.
262 PRIVATE void DisconnectFromHost(int_T numSampTimes)
266 for (i=0; i<NUM_UPINFOS; i++) {
267 UploadPrepareForFinalFlush(i);
271 * UploadPrepareForFinalFlush() has already called semGive(uploadSem)
272 * two times. Now the server thread will wait until the upload thread
273 * has processed all of the data in the buffers for the final upload
274 * and exhausted the uploadSem semaphores. If the server thread
275 * attempts to call UploadServerWork() while the upload thread is in
276 * the middle of processing the buffers, the target code may crash
277 * with a NULL pointer exception (the buffers are destroyed after
278 * calling UploadLogInfoTerm).
280 while(semTake(uploadSem, NO_WAIT) != ERROR) {
285 #ifndef EXTMODE_DISABLESIGNALMONITORING
286 if (host_upstatus_is_uploading) {
287 UploadServerWork(i, numSampTimes);
292 UploadLogInfoTerm(i, numSampTimes);
296 commInitialized = FALSE;
298 ExtCloseConnection(extUD);
299 } /* end DisconnectFromHost */
302 /* Function: ForceDisconnectFromHost ===========================================
304 * Force a disconnect from the host. This is not a graceful shutdown and
305 * should only be used when the integrity of the external mode connection
306 * is in question. To shutdown the connection gracefully, use
307 * DisconnectFromHost().
309 PRIVATE void ForceDisconnectFromHost(int_T numSampTimes)
313 commInitialized = FALSE;
315 for (i=0; i<NUM_UPINFOS; i++) {
316 UploadEndLoggingSession(i, numSampTimes);
319 ExtForceDisconnect(extUD);
320 } /* end ForceDisconnectFromHost */
323 /* Function: ProcessConnectPkt =================================================
325 * Process the EXT_CONNECT packet and send response to host.
327 PRIVATE boolean_T ProcessConnectPkt(RTWExtModeInfo *ei)
332 uint32_T *tmpBuf = NULL;
333 boolean_T error = EXT_NO_ERROR;
335 const DataTypeTransInfo *dtInfo = rteiGetModelMappingInfo(ei);
336 uint_T *dtSizes = dtGetDataTypeSizes(dtInfo);
337 int_T nDataTypes = dtGetNumDataTypes(dtInfo);
340 assert(!comminitialized);
343 * Send the 1st of two EXT_CONNECT_RESPONSE packets to the host.
344 * The packet consists purely of the pktHeader. In this special
345 * case the pktSize actually contains the number of bits per byte
346 * (not always 8 - see TI compiler for C30 and C40).
348 pktHdr.type = (uint32_T)EXT_CONNECT_RESPONSE;
349 pktHdr.size = (uint32_T)8; /* 8 bits per byte */
351 error = ExtSetHostPkt(extUD,sizeof(pktHdr),(char_T *)&pktHdr,&nSet);
352 if (error || (nSet != sizeof(pktHdr))) {
353 #ifndef EXTMODE_DISABLEPRINTF
355 "ExtSetHostPkt() failed for 1st EXT_CONNECT_RESPONSE.\n");
360 /* Send 2nd EXT_CONNECT_RESPONSE packet containing the following
363 * CS1 - checksum 1 (uint32_T)
364 * CS2 - checksum 2 (uint32_T)
365 * CS3 - checksum 3 (uint32_T)
366 * CS4 - checksum 4 (uint32_T)
368 * intCodeOnly - flag indicating if target is integer only (uint32_T)
370 * MWChunkSize - multiword data type chunk size on target (uint32_T)
372 * targetStatus - the status of the target (uint32_T)
374 * nDataTypes - # of data types (uint32_T)
375 * dataTypeSizes - 1 per nDataTypes (uint32_T[])
379 int nPktEls = 4 + /* checkSums */
380 1 + /* intCodeOnly */
381 1 + /* MW chunk size */
382 1 + /* targetStatus */
384 dtGetNumDataTypes(dtInfo); /* data type sizes */
386 tmpBufSize = nPktEls * sizeof(uint32_T);
387 tmpBuf = (uint32_T *)malloc(tmpBufSize);
388 if (tmpBuf == NULL) {
389 error = EXT_ERROR; goto EXIT_POINT;
393 /* Send packet header. */
394 pktHdr.type = EXT_CONNECT_RESPONSE;
395 pktHdr.size = tmpBufSize;
397 error = ExtSetHostPkt(extUD,sizeof(pktHdr),(char_T *)&pktHdr,&nSet);
398 if (error || (nSet != sizeof(pktHdr))) {
399 #ifndef EXTMODE_DISABLEPRINTF
401 "ExtSetHostPkt() failed for 2nd EXT_CONNECT_RESPONSE.\n");
406 /* Checksums, target status & SL_DOUBLESize. */
407 tmpBuf[0] = rteiGetChecksum0(ei);
408 tmpBuf[1] = rteiGetChecksum1(ei);
409 tmpBuf[2] = rteiGetChecksum2(ei);
410 tmpBuf[3] = rteiGetChecksum3(ei);
412 #if INTEGER_CODE == 0
413 tmpBuf[4] = (uint32_T)0;
415 tmpBuf[4] = (uint32_T)1;
418 tmpBuf[5] = (uint32_T)sizeof(uchunk_T);
420 tmpBuf[6] = (uint32_T)modelStatus;
422 /* nDataTypes and dataTypeSizes */
425 tmpBuf[7] = (uint32_T)nDataTypes;
426 for (i=0; i<nDataTypes; i++) {
427 tmpBuf[8+i] = (uint32_T)dtSizes[i];
431 /* Send the packet. */
432 error = ExtSetHostPkt(extUD,tmpBufSize,(char_T *)tmpBuf,&nSet);
433 if (error || (nSet != tmpBufSize)) {
434 #ifndef EXTMODE_DISABLEPRINTF
436 "ExtSetHostPkt() failed.\n");
441 commInitialized = TRUE;
446 } /* end ProcessConnectPkt */
449 /* Function: SendPktHdrToHost ==================================================
451 * Send a packet header to the host.
453 PRIVATE boolean_T SendPktHdrToHost(
454 const ExtModeAction action,
455 const int size) /* # of bytes to follow pkt header */
459 boolean_T error = EXT_NO_ERROR;
461 pktHdr.type = (uint32_T)action;
464 error = ExtSetHostPkt(extUD,sizeof(pktHdr),(char_T *)&pktHdr,&nSet);
465 if (error || (nSet != sizeof(pktHdr))) {
467 #ifndef EXTMODE_DISABLEPRINTF
468 fprintf(stderr,"ExtSetHostPkt() failed.\n");
475 } /* end SendPktHdrToHost */
478 /* Function: SendPktDataToHost =================================================
480 * Send packet data to host. You are responsible for sending a header
481 * prior to sending the header.
483 PRIVATE boolean_T SendPktDataToHost(const char *data, const int size)
486 boolean_T error = EXT_NO_ERROR;
488 error = ExtSetHostPkt(extUD,size,data,&nSet);
489 if (error || (nSet != size)) {
491 #ifndef EXTMODE_DISABLEPRINTF
492 fprintf(stderr,"ExtSetHostPkt() failed.\n");
499 } /* end SendPktDataToHost */
502 /* Function: SendPktToHost =====================================================
504 * Send a packet to the host. Packets can be of two forms:
505 * o packet header only
506 * the type is used as a flag to notify Simulink of an event
507 * that has taken place on the target (event == action == type)
508 * o pkt header, followed by data
510 PUBLIC boolean_T SendPktToHost(
511 const ExtModeAction action,
512 const int size, /* # of bytes to follow pkt header */
515 boolean_T error = EXT_NO_ERROR;
518 semTake(pktSem, WAIT_FOREVER);
521 error = SendPktHdrToHost(action,size);
522 if (error != EXT_NO_ERROR) goto EXIT_POINT;
525 error = SendPktDataToHost(data, size);
526 if (error != EXT_NO_ERROR) goto EXIT_POINT;
536 } /* end SendPktToHost */
539 /* Function: SendResponseStatus ===============================================
542 PRIVATE boolean_T SendResponseStatus(const ExtModeAction response,
543 const ResponseStatus status,
547 boolean_T error = EXT_NO_ERROR;
549 msg[0] = (int32_T)status;
552 error = SendPktToHost(response,2*sizeof(int32_T),(char_T *)&msg);
555 } /* end SendResponseStatus */
558 #ifndef EXTMODE_DISABLEPARAMETERTUNING
559 /* Function: ProcessSetParamPkt ================================================
560 * Receive and process the EXT_SETPARAM packet.
562 PRIVATE boolean_T ProcessSetParamPkt(RTWExtModeInfo *ei,
567 boolean_T error = EXT_NO_ERROR;
570 * Receive packet and set parameters.
572 pkt = GetPkt(pktSize);
574 msg = (int32_T)NOT_ENOUGH_MEMORY;
575 SendPktToHost(EXT_SETPARAM_RESPONSE,sizeof(int32_T),(char_T *)&msg);
581 msg = (int32_T)STATUS_OK;
582 error = SendPktToHost(EXT_SETPARAM_RESPONSE,sizeof(int32_T),(char_T *)&msg);
583 if (error != EXT_NO_ERROR) goto EXIT_POINT;
587 } /* end ProcessSetParamPkt */
588 #endif /* ifndef EXTMODE_DISABLEPARAMETERTUNING */
590 #ifndef EXTMODE_DISABLEPARAMETERTUNING
591 /* Function: ProcessGetParamsPkt ===============================================
592 * Respond to the hosts request for the parameters by gathering up all the
593 * params and sending them to the host.
595 PRIVATE boolean_T ProcessGetParamsPkt(RTWExtModeInfo *ei)
599 boolean_T error = EXT_NO_ERROR;
600 const DataTypeTransInfo *dtInfo = rteiGetModelMappingInfo(ei);
601 const DataTypeTransitionTable *dtTable = dtGetParamDataTypeTrans(dtInfo);
603 if (dtTable != NULL) {
605 * We've got some params in the model. Send their values to the
608 int_T nTrans = dtGetNumTransitions(dtTable);
609 const uint_T *dtSizes = dtGetDataTypeSizes(dtInfo);
612 #ifndef EXTMODE_DISABLEPRINTF
613 printf("\nUploading initial parameters....\n");
618 * Take pass 1 through the transitions to figure out how many
619 * bytes we're going to send.
622 for (i=0; i<nTrans; i++) {
623 int_T dt = dtTransGetDataType(dtTable, i);
624 int_T dtSize = dtSizes[dt];
625 int_T nEls = dtTransNEls(dtTable, i); /* complexity accounted for in trans tbl num of els */
626 int_T nBytes = dtSize * nEls;
628 nBytesTotal += nBytes;
632 * Send the packet header.
634 error = SendPktHdrToHost(EXT_GETPARAMS_RESPONSE,nBytesTotal);
635 if (error != EXT_NO_ERROR) goto EXIT_POINT;
638 * Take pass 2 through the transitions and send the parameters.
640 for (i=0; i<nTrans; i++) {
641 char_T *tranAddress = dtTransGetAddress(dtTable, i);
642 int_T dt = dtTransGetDataType(dtTable, i);
643 int_T dtSize = dtSizes[dt];
644 int_T nEls = dtTransNEls(dtTable, i); /* complexity accounted for in trans tbl num of els */
645 int_T nBytes = dtSize * nEls;
647 error = SendPktDataToHost(tranAddress, nBytes);
648 if (error != EXT_NO_ERROR) goto EXIT_POINT;
652 * We've got no params in the model.
654 error = SendPktHdrToHost(EXT_GETPARAMS_RESPONSE,0);
655 if (error != EXT_NO_ERROR) goto EXIT_POINT;
660 } /* end ProcessGetParamsPkt */
661 #endif /* ifndef EXTMODE_DISABLEPARAMETERTUNING */
664 #ifndef EXTMODE_DISABLESIGNALMONITORING
665 /* Function: ProcessSelectTriggerSignalPkt ===========================================
666 * Receive and process the EXT_SELECT_TRIGGER or EXT_SELECT_SIGNALS packet.
668 PRIVATE boolean_T ProcessSelectTriggerSignalPkt(const ExtModeAction ACTION_ID,
676 boolean_T error = EXT_NO_ERROR;
678 pkt = GetPkt(pktSize);
680 SendResponseStatus(ACTION_ID, NOT_ENOUGH_MEMORY, -1);
684 (void)memcpy(&upInfoIdx, pkt, sizeof(int32_T)); /* Extract upInfoIdx */
686 case EXT_SELECT_TRIGGER_RESPONSE:
687 #ifndef EXTMODE_DISABLEPRINTF
689 ("got EXT_SELECT_TRIGGER packet for upInfoIdx : %d\n", upInfoIdx));
691 error = UploadInitTrigger(ei, pkt+sizeof(int32_T), upInfoIdx);
693 case EXT_SELECT_SIGNALS_RESPONSE:
694 #ifndef EXTMODE_DISABLEPRINTF
696 ("got EXT_SELECT_SIGNALS packet for upInfoIdx : %d\n", upInfoIdx));
698 error = UploadLogInfoInit(ei, numSampTimes, pkt+sizeof(int32_T), upInfoIdx);
704 if (error != EXT_NO_ERROR) {
705 SendResponseStatus(ACTION_ID, NOT_ENOUGH_MEMORY, upInfoIdx);
706 #ifndef EXTMODE_DISABLEPRINTF
707 printf("%s\n", errMsg);
712 error = SendResponseStatus(ACTION_ID, STATUS_OK, upInfoIdx);
713 return(error); /* Can be EXT_NO_ERROR */
714 } /* end ProcessSelectTriggerSignalPkt */
715 #endif /* ifndef EXTMODE_DISABLESIGNALMONITORING */
718 #ifndef EXTMODE_DISABLESIGNALMONITORING
719 /* Function: ProcessCancelLoggingArmTriggerPkt ===========================================
720 * Receive and process the EXT_CANCEL_LOGGING or EXT_ARM_TRIGGER packet.
722 PRIVATE boolean_T ProcessCancelLoggingArmTriggerPkt(const ExtModeAction ACTION_ID,
728 boolean_T error = EXT_NO_ERROR;
730 pkt = GetPkt(pktSize);
732 SendResponseStatus(ACTION_ID, NOT_ENOUGH_MEMORY, -1);
736 (void)memcpy(&upInfoIdx, pkt, sizeof(int32_T)); /* Extract upInfoIdx */
739 case EXT_CANCEL_LOGGING_RESPONSE:
740 #ifndef EXTMODE_DISABLEPRINTF
742 ("got EXT_CANCEL_LOGGING packet for upInfoIdx : %d\n", upInfoIdx));
744 UploadCancelLogging(upInfoIdx);
746 case EXT_ARM_TRIGGER_RESPONSE:
747 #ifndef EXTMODE_DISABLEPRINTF
749 ("got EXT_ARM_TRIGGER packet for upInfoIdx : %d\n", upInfoIdx));
751 UploadArmTrigger(upInfoIdx, numSampTimes);
757 error = SendResponseStatus(ACTION_ID, STATUS_OK, upInfoIdx);
758 return(error); /* Can be EXT_NO_ERROR */
759 } /* end ProcessCancelLoggingArmTriggerPkt */
760 #endif /* ifndef EXTMODE_DISABLESIGNALMONITORING */
763 #ifdef EXTMODE_DISABLEPARAMETERTUNING
764 PRIVATE boolean_T AcknowledgeSetParamPkt(const int pktSize)
768 boolean_T error = EXT_NO_ERROR;
770 pkt = GetPkt(pktSize);
771 msg = (int32_T)STATUS_OK;
772 error = SendPktToHost(EXT_SETPARAM_RESPONSE, sizeof(int32_T), (char_T *)&msg);
775 #endif /* ifdef EXTMODE_DISABLEPARAMETERTUNING */
777 #ifdef EXTMODE_DISABLESIGNALMONITORING
778 PRIVATE boolean_T AcknowledgeSignalActionPkt(const int pktSize, const ExtModeAction ACTION_ID)
782 boolean_T error = EXT_NO_ERROR;
784 pkt = GetPkt(pktSize);
785 (void)memcpy(&upInfoIdx, pkt, sizeof(int32_T));
786 error = SendResponseStatus(ACTION_ID, STATUS_OK, upInfoIdx);
789 #endif /* ifdef EXTMODE_DISABLESIGNALMONITORING */
791 /*********************
792 * Visible Functions *
793 *********************/
796 /* Function: ExtParseArgsAndInitUD =============================================
798 * Pass remaining arguments (main program should have NULL'ed out any args
799 * that it processed) to external mode.
801 * The actual, transport-specific parsing routine (implemented in
802 * ext_svr_transport.c) MUST NULL out all entries of argv that it processes.
803 * The main program depends on this in order to determine if any unhandled
804 * command line options were specified (i.e., if the main program detects
805 * any non-null fields after the parse, it throws an error).
807 * Returns an error string on failure, NULL on success.
810 * The external mode UserData is created here so that the specified command-
811 * line options can be stored.
813 PUBLIC const char_T *ExtParseArgsAndInitUD(const int_T argc,
814 const char_T *argv[])
816 const char_T *error = NULL;
819 * Create the user data.
821 extUD = ExtUserDataCreate();
823 error = "Could not create external mode user data. Out of memory.\n";
828 * Parse the transport-specific args.
830 error = ExtProcessArgs(extUD,argc,argv);
831 if (error != NULL) goto EXIT_POINT;
835 ExtUserDataDestroy(extUD);
839 } /* end ExtParseArgsAndInitUD */
842 /* Function: ExtWaitForStartPkt ================================================
844 * Return true if waiting for host to tell us when to start.
846 PUBLIC boolean_T ExtWaitForStartPkt(void)
848 return(ExtWaitForStartPktFromHost(extUD));
849 } /* end ExtWaitForStartPkt */
852 #ifndef EXTMODE_DISABLESIGNALMONITORING
853 /* Function: UploadServerWork =================================================
855 * Upload model signals to host for a single upInfo.
857 void UploadServerWork(int32_T upInfoIdx, int_T numSampTimes)
860 ExtBufMemList upList;
861 boolean_T error = EXT_NO_ERROR;
865 * Don't spin the CPU unless we've got data to upload.
866 * The upload.c/UploadBufAddTimePoint function gives the sem
867 * each time that data is added.
870 semTake(uploadSem, WAIT_FOREVER);
874 if (!connected) goto EXIT_POINT;
876 UploadBufGetData(&upList, upInfoIdx, numSampTimes);
877 while(upList.nActiveBufs > 0) {
878 for (i=0; i<upList.nActiveBufs; i++) {
879 const BufMem *bufMem = &upList.bufs[i];
882 * We call SendPktDataToHost() instead of SendPktToHost() because
883 * the packet header is combined with packet payload. We do this
884 * to avoid the overhead of making two calls for each upload
885 * packet - one for the head and one for the payload.
887 error = SendPktDataToHost(
890 if (error != EXT_NO_ERROR) {
891 #ifndef EXTMODE_DISABLEPRINTF
892 fprintf(stderr,"SendPktDataToHost() failed on data upload.\n");
897 if (bufMem->nBytes2 > 0) {
899 error = SendPktDataToHost(
902 if (error != EXT_NO_ERROR) {
903 #ifndef EXTMODE_DISABLEPRINTF
904 fprintf(stderr,"SendPktDataToHost() failed on data upload.\n");
909 /* confirm that the data was sent */
910 UploadBufDataSent(upList.tids[i], upInfoIdx);
912 UploadBufGetData(&upList, upInfoIdx, numSampTimes);
916 if (error != EXT_NO_ERROR) {
917 /* An error in this function is caused by a physical failure in the
918 * external mode connection. We assume this failure caused the host
919 * to disconnect. The target must be disconnected and returned to a
920 * state where it is running and can be re-connected to by the host.
922 ForceDisconnectFromHost(numSampTimes);
925 /* end UploadServerWork */
926 #endif /* ifndef EXTMODE_DISABLESIGNALMONITORING */
928 #ifndef EXTMODE_DISABLESIGNALMONITORING
929 /* Function: rt_UploadServerWork ===============================================
931 * Wrapper function that calls UploadServerWork once for each upInfo
933 PUBLIC void rt_UploadServerWork(int_T numSampTimes)
937 for (i=0; i<NUM_UPINFOS; i++) {
938 UploadServerWork(i, numSampTimes);
940 } /* end rt_UploadServerWork */
941 #endif /* ifndef EXTMODE_DISABLESIGNALMONITORING */
943 /* Function: rt_ExtModeInit ====================================================
945 * Called once at program startup to do any initialization related to external
948 PUBLIC boolean_T rt_ExtModeInit(void)
951 boolean_T error = EXT_NO_ERROR;
953 #ifdef TMW_EXTMODE_TESTING_REQ
954 # ifndef TMW_EXTMODE_TESTING
955 #ifndef EXTMODE_DISABLEPRINTF
956 fprintf(stderr,"Error: External mode tests should use the external mode test harness.\n");
961 if (error != EXT_NO_ERROR) goto EXIT_POINT;
963 error = ExtInit(extUD);
964 if (error != EXT_NO_ERROR) goto EXIT_POINT;
966 for (i=0; i<NUM_UPINFOS; i++) {
967 UploadLogInfoReset(i);
970 rtExtModeTestingInit();
974 } /* end rt_ExtModeInit */
977 /* Function: rt_ExtModeSleep ===================================================
979 * Called by grt_main, ert_main, and grt_malloc_main to "pause". It attempts
980 * to do this in a way that does not hog the processor.
983 PUBLIC void rt_ExtModeSleep(
984 long sec, /* number of seconds to wait */
985 long usec) /* number of micro seconds to wait */
987 ExtModeSleep(extUD,sec,usec);
988 } /* end rt_ExtModeSleep */
992 /* Function: rt_PktServerWork ==================================================
994 * If not connected, establish communication of the packet line and the
995 * data upload line. If connected, send/receive packets and parameters
996 * on the packet line.
998 PUBLIC void rt_PktServerWork(RTWExtModeInfo *ei,
1004 boolean_T error = EXT_NO_ERROR;
1005 boolean_T disconnectOnError = FALSE;
1008 * If not connected, attempt to make connection to host.
1011 rtExtModeTestingKillIfOrphaned(FALSE);
1013 error = ExtOpenConnection(extUD,&connected);
1014 if (error != EXT_NO_ERROR) goto EXIT_POINT;
1018 * If ExtOpenConnection is not blocking and there are no pending
1019 * requests to open a connection, we'll still be unconnected.
1021 if (!connected) goto EXIT_POINT; /* nothing to do */
1027 /* Wait for a packet. */
1028 error = GetPktHdr(&pktHdr, &hdrAvail);
1029 if (error != EXT_NO_ERROR) {
1030 #ifndef EXTMODE_DISABLEPRINTF
1031 fprintf(stderr, "\nError occurred getting packet header.\n");
1033 disconnectOnError = TRUE;
1036 rtExtModeTestingKillIfOrphaned(hdrAvail);
1038 if (!hdrAvail) goto EXIT_POINT; /* nothing to do */
1041 * This is the first packet. Should contain the string:
1042 * 'ext-mode'. Its contents are not important to us.
1043 * It is used as a flag to start the handshaking process.
1045 if (!commInitialized) {
1046 pktHdr.type = EXT_CONNECT;
1050 * At this point we know that we have a packet: process it.
1055 switch(pktHdr.type) {
1059 /* Skip verbosity print out - we get too many of these */
1060 PRINT_VERBOSE(("got EXT_GET_TIME packet.\n"));
1061 time_T t = rteiGetT(ei);
1063 error = SendPktToHost(
1064 EXT_GET_TIME_RESPONSE,sizeof(time_T),
1066 if (error != EXT_NO_ERROR) goto EXIT_POINT;
1070 case EXT_ARM_TRIGGER:
1072 #ifndef EXTMODE_DISABLESIGNALMONITORING
1073 error = ProcessCancelLoggingArmTriggerPkt(EXT_ARM_TRIGGER_RESPONSE, pktHdr.size, numSampTimes);
1074 if (error != EXT_NO_ERROR) goto EXIT_POINT;
1076 error = AcknowledgeSignalActionPkt(pktHdr.size, EXT_ARM_TRIGGER_RESPONSE);
1077 if (error != EXT_NO_ERROR) goto EXIT_POINT;
1082 case EXT_SELECT_SIGNALS:
1084 #ifndef EXTMODE_DISABLESIGNALMONITORING
1085 error = ProcessSelectTriggerSignalPkt(EXT_SELECT_SIGNALS_RESPONSE, ei, pktHdr.size, numSampTimes, ERRMSG_PROCESSSELECTSIGNAL);
1086 if (error != EXT_NO_ERROR) goto EXIT_POINT;
1088 error = AcknowledgeSignalActionPkt(pktHdr.size, EXT_SELECT_SIGNALS_RESPONSE);
1089 if (error != EXT_NO_ERROR) goto EXIT_POINT;
1094 case EXT_SELECT_TRIGGER:
1096 #ifndef EXTMODE_DISABLESIGNALMONITORING
1097 error = ProcessSelectTriggerSignalPkt(EXT_SELECT_TRIGGER_RESPONSE, ei, pktHdr.size, -1, ERRMSG_PROCESSSELECTTRIGGER);
1098 if (error != EXT_NO_ERROR) goto EXIT_POINT;
1100 error = AcknowledgeSignalActionPkt(pktHdr.size, EXT_SELECT_TRIGGER_RESPONSE);
1101 if (error != EXT_NO_ERROR) goto EXIT_POINT;
1108 PRINT_VERBOSE(("got EXT_CONNECT packet.\n"));
1109 error = ProcessConnectPkt(ei);
1110 if (error != EXT_NO_ERROR) goto EXIT_POINT;
1116 #ifndef EXTMODE_DISABLEPARAMETERTUNING
1117 PRINT_VERBOSE(("got EXT_SETPARAM packet.\n"));
1118 error = ProcessSetParamPkt(ei, pktHdr.size);
1119 if (error != EXT_NO_ERROR) goto EXIT_POINT;
1121 PRINT_VERBOSE(("discard EXT_SETPARAM packet.\n"));
1122 error = AcknowledgeSetParamPkt(pktHdr.size);
1123 if (error != EXT_NO_ERROR) goto EXIT_POINT;
1130 #ifndef EXTMODE_DISABLEPARAMETERTUNING
1131 PRINT_VERBOSE(("got EXT_GETPARAMS packet.\n"));
1132 error = ProcessGetParamsPkt(ei);
1133 if (error != EXT_NO_ERROR) goto EXIT_POINT;
1138 case EXT_DISCONNECT_REQUEST:
1140 PRINT_VERBOSE(("got EXT_DISCONNECT_REQUEST packet.\n"));
1143 * Note that from the target's point of view this is
1144 * more a "notify" than a "request". The host needs to
1145 * have this acknowledged before it can begin closing
1148 error = SendPktToHost(EXT_DISCONNECT_REQUEST_RESPONSE, 0, NULL);
1149 if (error != EXT_NO_ERROR) goto EXIT_POINT;
1151 DisconnectFromHost(numSampTimes);
1156 case EXT_DISCONNECT_REQUEST_NO_FINAL_UPLOAD:
1158 PRINT_VERBOSE(("got EXT_DISCONNECT_REQUEST_NO_FINAL_UPLOAD packet.\n"));
1161 * The target receives this packet when the host is
1162 * immediately terminating the extmode communication due
1163 * to some error. The target should not send back a
1164 * response or a final upload of data because the host is
1165 * expecting neither. The target must be disconnected and
1166 * returned to a state where it is running and can be
1167 * re-connected to by the host.
1169 ForceDisconnectFromHost(numSampTimes);
1174 case EXT_MODEL_START:
1175 PRINT_VERBOSE(("got EXT_MODEL_START packet.\n"));
1178 extern SEM_ID startStopSem;
1179 semGive(startStopSem);
1183 error = SendPktToHost(EXT_MODEL_START_RESPONSE, 0, NULL);
1184 if (error != EXT_NO_ERROR) goto EXIT_POINT;
1187 case EXT_MODEL_STOP:
1188 PRINT_VERBOSE(("got EXT_MODEL_STOP packet.\n"));
1191 #ifndef EXTMODE_DISABLETESTING
1192 case EXT_MODEL_PAUSE:
1193 PRINT_VERBOSE(("got EXT_MODEL_PAUSE packet.\n"));
1194 modelStatus = TARGET_STATUS_PAUSED;
1197 error = SendPktToHost(EXT_MODEL_PAUSE_RESPONSE, 0, NULL);
1198 if (error != EXT_NO_ERROR) goto EXIT_POINT;
1200 case EXT_MODEL_STEP:
1201 PRINT_VERBOSE(("got EXT_MODEL_STEP packet.\n"));
1202 if ((modelStatus == TARGET_STATUS_PAUSED) && !startModel) {
1206 error = SendPktToHost(EXT_MODEL_STEP_RESPONSE, 0, NULL);
1207 if (error != EXT_NO_ERROR) goto EXIT_POINT;
1209 case EXT_MODEL_CONTINUE:
1210 PRINT_VERBOSE(("got EXT_MODEL_CONTINUE packet.\n"));
1211 if (modelStatus == TARGET_STATUS_PAUSED) {
1212 modelStatus = TARGET_STATUS_RUNNING;
1216 error = SendPktToHost(EXT_MODEL_CONTINUE_RESPONSE, 0, NULL);
1217 if (error != EXT_NO_ERROR) goto EXIT_POINT;
1221 case EXT_CANCEL_LOGGING:
1223 #ifndef EXTMODE_DISABLESIGNALMONITORING
1224 error = ProcessCancelLoggingArmTriggerPkt(EXT_CANCEL_LOGGING_RESPONSE, pktHdr.size, numSampTimes);
1225 if (error != EXT_NO_ERROR) goto EXIT_POINT;
1227 error = AcknowledgeSignalActionPkt(pktHdr.size, EXT_CANCEL_LOGGING_RESPONSE);
1228 if (error != EXT_NO_ERROR) goto EXIT_POINT;
1234 #ifndef EXTMODE_DISABLEPRINTF
1235 fprintf(stderr,"received invalid packet.\n");
1241 if (error != EXT_NO_ERROR) {
1242 if (disconnectOnError) {
1243 #ifndef EXTMODE_DISABLEPRINTF
1245 "Error occurred in rt_PktServerWork.\n"
1246 "Disconnecting from host!\n");
1248 /* An error in this function which causes disconnectOnError to be
1249 * set to true is caused by a physical failure in the external mode
1250 * connection. We assume this failure caused the host to disconnect.
1251 * The target must be disconnected and returned to a state
1252 * where it is running and can be re-connected to by the host.
1254 ForceDisconnectFromHost(numSampTimes);
1260 } /* end rt_PktServerWork */
1263 /* Function: rt_PktServer ======================================================
1265 * Call rt_PktServerWork forever. Used only for RTOS (e.g., Tornado/VxWorks
1266 * when running as a low priority task.
1269 PUBLIC void rt_PktServer(RTWExtModeInfo *ei,
1274 rt_PktServerWork(ei,numSampTimes,stopReq);
1280 /* Function: rt_UploadServer ===================================================
1282 * Call rt_UploadServerWork forever. Used only for RTOS (e.g.,
1283 * Tornado/VxWorks when running as a low priority task.
1286 #ifndef EXTMODE_DISABLESIGNALMONITORING
1287 PUBLIC void rt_UploadServer(int_T numSampTimes)
1290 rt_UploadServerWork(numSampTimes);
1292 } /* end rt_UploadServer */
1293 #endif /* ifndef EXTMODE_DISABLESIGNALMONITORING */
1297 /* Function: rt_SetPortInExtUD =================================================
1299 * Set the port in the external mode user data structure.
1302 PUBLIC void rt_SetPortInExtUD(const int_T port)
1304 ExtUserDataSetPort(extUD, port);
1305 } /* end rt_SetPortInExtUD */
1308 /* Function: ExtModeShutdown ==================================================
1310 * Called when target program terminates to enable cleanup of external
1311 * mode for a given upInfo.
1313 PRIVATE void ExtModeShutdown(int32_T upInfoIdx, int_T numSampTimes)
1316 * Make sure buffers are flushed so that the final points get to
1317 * host (this is important for the case of the target reaching tfinal
1318 * while data uploading is in progress).
1320 UploadPrepareForFinalFlush(upInfoIdx);
1321 #ifndef EXTMODE_DISABLESIGNALMONITORING
1322 UploadServerWork(upInfoIdx, numSampTimes);
1325 UploadLogInfoTerm(upInfoIdx, numSampTimes);
1327 if (pktBuf != NULL) {
1332 } /* end ExtModeShutdown */
1334 /* Function: rt_ExtModeShutdown ================================================
1336 * Called when target program terminates to enable cleanup of external
1339 PUBLIC boolean_T rt_ExtModeShutdown(int_T numSampTimes)
1342 boolean_T error = EXT_NO_ERROR;
1344 for (i=0; i<NUM_UPINFOS; i++) {
1345 ExtModeShutdown(i, numSampTimes);
1348 if (commInitialized) {
1349 error = SendPktToHost(EXT_MODEL_SHUTDOWN, 0, NULL);
1350 if (error != EXT_NO_ERROR) {
1351 #ifndef EXTMODE_DISABLEPRINTF
1353 "\nError sending EXT_MODEL_SHUTDOWN packet to host.\n");
1356 commInitialized = FALSE;
1360 modelStatus = TARGET_STATUS_WAITING_TO_START;
1364 ExtUserDataDestroy(extUD);
1366 rtExtModeTestingRemoveBatMarker();
1369 } /* end rt_ExtModeShutdown */
1371 #ifndef EXTMODE_DISABLESIGNALMONITORING
1372 /* Function: rt_UploadCheckTrigger =============================================
1374 * Wrapper function that calls UploadCheckTrigger once for each upInfo
1376 PUBLIC void rt_UploadCheckTrigger(int_T numSampTimes)
1379 for (i=0; i<NUM_UPINFOS; i++) {
1380 UploadCheckTrigger(i, numSampTimes);
1382 } /* end rt_UploadCheckTrigger */
1384 /* Function: rt_UploadCheckEndTrigger ==========================================
1386 * Wrapper function that calls UploadCheckTrigger once for each upInfo
1388 PUBLIC void rt_UploadCheckEndTrigger(void)
1392 for (i=0; i<NUM_UPINFOS; i++) {
1393 UploadCheckEndTrigger(i);
1395 } /* end rt_UploadCheckEndTrigger */
1397 /* Function: rt_UploadBufAddTimePoint ==========================================
1399 * Wrapper function that calls UploadBufAddTimePoint once for each upInfo
1401 PUBLIC void rt_UploadBufAddTimePoint(int_T tid, real_T taskTime)
1405 for (i=0; i<NUM_UPINFOS; i++) {
1406 UploadBufAddTimePoint(tid, taskTime, i);
1408 } /* end rt_UploadBufAddTimePoint */
1409 #endif /* ifndef EXTMODE_DISABLESIGNALMONITORING */
1411 /* [EOF] ext_svr.c */