1/*
2 * Copyright (c) 2007-2015 Freescale Semiconductor, Inc.
3 * Copyright 2018-2021 NXP
4 *
5 * License: NXP LA_OPT_NXP_Software_License
6 *
7 * NXP Confidential. This software is owned or controlled by NXP and may
8 * only be used strictly in accordance with the applicable license terms.
9 * By expressly accepting such terms or by downloading, installing,
10 * activating and/or otherwise using the software, you are agreeing that
11 * you have read, and that you agree to comply with and are bound by,
12 * such license terms. If you do not agree to be bound by the applicable
13 * license terms, then you may not retain, install, activate or otherwise
14 * use the software. This code may only be used in a microprocessor,
15 * microcontroller, sensor or digital signal processor ("NXP Product")
16 * supplied directly or indirectly from NXP. See the full NXP Software
17 * License Agreement in license/LA_OPT_NXP_Software_License.pdf
18 *
19 * FreeMASTER Communication Driver - Serial communication
20 */
21
22#include "freemaster.h"
23#include "freemaster_private.h"
24
25/* Numeric identifier to help pre-processor to identify whether our transport is used or not. */
26#define FMSTR_SERIAL_ID 1
27
28#if (FMSTR_MK_IDSTR(FMSTR_TRANSPORT) == FMSTR_SERIAL_ID) && FMSTR_DISABLE == 0
29
30#if FMSTR_SESSION_COUNT != 1
31/* Serial transport only supports a single session */
32#warning Please set FMSTR_SESSION_COUNT to 1.
33#endif
34
35#include "freemaster_protocol.h"
36#include "freemaster_serial.h"
37#include "freemaster_utils.h"
38
39/***********************************
40 * local variables
41 ***********************************/
42
43/* FreeMASTER communication buffer (in/out) plus the STS, LEN(LEB) and CRC bytes */
44static FMSTR_BCHR fmstr_pCommBuffer[FMSTR_COMM_BUFFER_SIZE + 1 + 4 + 2];
45
46/* FreeMASTER runtime flags */
47/*lint -e{960} using union */
48typedef volatile union
49{
50 FMSTR_FLAGS all;
51
52 struct
53 {
54 unsigned bTxActive : 1; /* response is being transmitted */
55 unsigned bTxWaitTC : 1; /* response sent, wait for transmission complete */
56 unsigned bTxLastCharSOB : 1; /* last transmitted char was equal to SOB */
57 unsigned bRxLastCharSOB : 1; /* last received character was SOB */
58 unsigned bRxMsgLengthNext : 1; /* expect the length byte next time */
59 } flg;
60
61} FMSTR_SERIAL_FLAGS;
62
63static FMSTR_SERIAL_FLAGS _fmstr_wFlags;
64
65/* receive and transmit buffers and counters */
66static FMSTR_SIZE8 fmstr_nTxTodo; /* transmission to-do counter (0 when tx is idle) */
67static FMSTR_SIZE8 fmstr_nRxTodo; /* reception to-do counter (0 when rx is idle) */
68static FMSTR_BPTR fmstr_pTxBuff; /* pointer to next byte to transmit */
69static FMSTR_BPTR fmstr_pRxBuff; /* pointer to next free place in RX buffer */
70static FMSTR_BCHR fmstr_nRxCrc8; /* checksum of data being received for short messages */
71
72/* Maximal length of message to use 8 bit CRC8. */
73#define FMSTR_SHORT_MSG_LEN 128
74
75#if FMSTR_DEBUG_TX > 0
76/* The poll counter is used to roughly measure duration of test frame transmission.
77 * The test frame will be sent once per N.times this measured period. */
78static FMSTR_S32 fmstr_nDebugTxPollCount;
79/* the N factor for multiplying the transmission time to get the wait time */
80#define FMSTR_DEBUG_TX_POLLCNT_XFACTOR 32
81#define FMSTR_DEBUG_TX_POLLCNT_MIN (-1 * 0x4000000L)
82#endif
83
84/***********************************
85 * local function prototypes
86 ***********************************/
87
88static void _FMSTR_Listen(void);
89static void _FMSTR_SendError(FMSTR_BCHR nErrCode);
90static FMSTR_BOOL _FMSTR_Tx(FMSTR_BCHR *getTxChar);
91static FMSTR_BOOL _FMSTR_Rx(FMSTR_BCHR rxChar);
92
93/***********************************
94 * local variables
95 ***********************************/
96
97/* SHORT_INTR receive queue (circular buffer) */
98#if FMSTR_SHORT_INTR > 0
99static FMSTR_BCHR fmstr_rxBuff[FMSTR_COMM_RQUEUE_SIZE];
100static FMSTR_RING_BUFFER fmstr_rxQueue;
101#endif
102
103/***********************************
104 * local function prototypes
105 ***********************************/
106
107#if FMSTR_SHORT_INTR > 0
108static void _FMSTR_RxDequeue(void);
109#endif
110
111/* Interface function - Initialization of serial transport */
112static FMSTR_BOOL _FMSTR_SerialInit(void);
113/* Interface function - Poll function of serial transport */
114static void _FMSTR_SerialPoll(void);
115/* Interface function - Send Response function of serial transport */
116static void _FMSTR_SerialSendResponse(FMSTR_BPTR pResponse,
117 FMSTR_SIZE nLength,
118 FMSTR_U8 statusCode,
119 void *identification);
120
121/***********************************
122 * global variables
123 ***********************************/
124
125/* Interface of this serial driver */
126const FMSTR_TRANSPORT_INTF FMSTR_SERIAL = {
127 FMSTR_C99_INIT(Init) _FMSTR_SerialInit,
128 FMSTR_C99_INIT(Poll) _FMSTR_SerialPoll,
129 FMSTR_C99_INIT(SendResponse) _FMSTR_SerialSendResponse,
130};
131
132/*lint -esym(752,_FMSTR_RxQueue) this may be unreferenced in some cases */
133/*lint -esym(752,_FMSTR_RxDequeue) this may be unreferenced in some cases */
134
135/*******************************************************************************
136 *
137 * @brief Routine to quick-receive a character (put to a queue only)
138 *
139 * This function puts received character into a queue and exits as soon as possible.
140 *
141 *******************************************************************************/
142
143#if FMSTR_SHORT_INTR > 0
144
145/*******************************************************************************
146 *
147 * @brief Late processing of queued characters
148 *
149 * This function takes the queued characters and calls FMSTR_Rx() for each of them,
150 * just like as the characters would be received from SCI one by one.
151 *
152 *******************************************************************************/
153
154static void _FMSTR_RxDequeue(void)
155{
156 FMSTR_BCHR nChar = 0U;
157
158 /* get all queued characters */
159 while (_FMSTR_RingBuffHasData(&fmstr_rxQueue) != FMSTR_FALSE)
160 {
161 nChar = _FMSTR_RingBuffGet(&fmstr_rxQueue);
162
163 /* emulate the SCI receive event */
164 if (_fmstr_wFlags.flg.bTxActive == 0U)
165 {
166 (void)_FMSTR_Rx(nChar);
167 }
168 }
169}
170
171#endif /* FMSTR_SHORT_INTR */
172
173/******************************************************************************
174 *
175 * @brief Handle SCI communication (both TX and RX)
176 *
177 * This function checks the SCI flags and calls the Rx and/or Tx functions
178 *
179 * @note This function can be called either from SCI ISR or from the polling routine
180 *
181 ******************************************************************************/
182
183void FMSTR_ProcessSerial(void)
184{
185 FMSTR_BOOL endOfPacket = FMSTR_FALSE;
186
187 /* transmitter active and empty? */
188 if (_fmstr_wFlags.flg.bTxActive != 0U)
189 {
190 /* able to accept another character? */
191 while (FMSTR_SERIAL_DRV.IsTransmitRegEmpty() != FMSTR_FALSE)
192 {
193 FMSTR_BCHR ch;
194 /* just put the byte into the SCI transmit buffer */
195 endOfPacket = _FMSTR_Tx(&ch);
196 if (endOfPacket == FMSTR_FALSE)
197 {
198#if FMSTR_DEBUG_LEVEL >= 3
199 FMSTR_DEBUG_PRINTF("FMSTR Tx: %02x\n", (FMSTR_U8)ch);
200#endif
201 FMSTR_SERIAL_DRV.PutChar((FMSTR_U8)ch);
202 }
203 else
204 {
205 break;
206 }
207 }
208
209 /* Flush data */
210 if (endOfPacket != FMSTR_FALSE)
211 {
212#if FMSTR_DEBUG_LEVEL >= 3
213 FMSTR_DEBUG_PRINTF("FMSTR Tx Flush\n");
214#endif
215 FMSTR_SERIAL_DRV.Flush();
216 _fmstr_wFlags.flg.bTxWaitTC = 1U;
217
218#if FMSTR_SHORT_INTR || FMSTR_LONG_INTR
219 /* Enable UART Transfer Complete interrupt in case of interrupt mode of communication. */
220 if (FMSTR_SERIAL_DRV.IsTransmitterActive() != FMSTR_FALSE)
221 {
222 /* Enable Trasmit complete interrupt */
223 FMSTR_SERIAL_DRV.EnableTransmitCompleteInterrupt(FMSTR_TRUE);
224 }
225#endif
226 }
227
228 /* when SCI TX buffering is enabled, we must first wait until all
229 characters are physically transmitted (before disabling transmitter) */
230 if (_fmstr_wFlags.flg.bTxWaitTC != 0U && FMSTR_SERIAL_DRV.IsTransmitterActive() == FMSTR_FALSE)
231 {
232 /* after TC, we can switch to listen mode safely */
233 _FMSTR_Listen();
234 }
235 }
236 /* transmitter not active, able to receive */
237 else
238 {
239 /* data byte received? */
240 while (FMSTR_SERIAL_DRV.IsReceiveRegFull() != FMSTR_FALSE)
241 {
242 FMSTR_BCHR rxChar = 0U;
243 rxChar = FMSTR_SERIAL_DRV.GetChar();
244
245#if FMSTR_DEBUG_LEVEL >= 3
246 FMSTR_DEBUG_PRINTF("FMSTR Rx: %02x\n", (FMSTR_U8)rxChar);
247#endif
248
249#if FMSTR_SHORT_INTR > 0
250 _FMSTR_RingBuffPut(&fmstr_rxQueue, rxChar); // TODO: if queue is lower than received data
251#else
252 (void)_FMSTR_Rx(rxChar);
253#endif
254 }
255#if FMSTR_DEBUG_TX > 0
256 /* time to send another test frame? */
257 if (fmstr_doDebugTx != 0U && fmstr_nDebugTxPollCount == 0)
258 {
259 /* yes, start sending it now */
260 if (FMSTR_SendTestFrame(&fmstr_pCommBuffer[2], NULL) != FMSTR_FALSE)
261 {
262 /* measure how long it takes to transmit it */
263 fmstr_nDebugTxPollCount = -1;
264 }
265 }
266#endif
267 }
268}
269
270/******************************************************************************
271 *
272 * @brief Start listening on a serial line
273 *
274 * Reset the receiver machine and start listening on a serial line
275 *
276 ******************************************************************************/
277
278static void _FMSTR_Listen(void)
279{
280 fmstr_nRxTodo = 0U;
281
282 /* disable transmitter state machine */
283 _fmstr_wFlags.flg.bTxActive = 0U;
284 _fmstr_wFlags.flg.bTxWaitTC = 0U;
285
286 /* disable transmitter, enable receiver (enables single-wire connection) */
287 FMSTR_SERIAL_DRV.EnableTransmit(FMSTR_FALSE);
288 FMSTR_SERIAL_DRV.EnableReceive(FMSTR_TRUE);
289
290 /* disable transmit, enable receive interrupts */
291#if FMSTR_SHORT_INTR || FMSTR_LONG_INTR
292 FMSTR_SERIAL_DRV.EnableTransmitInterrupt(FMSTR_FALSE); /* disable Serial transmit interrupt */
293 FMSTR_SERIAL_DRV.EnableTransmitCompleteInterrupt(FMSTR_FALSE); /* disable Serial transmit complete interrupt */
294 FMSTR_SERIAL_DRV.EnableReceiveInterrupt(FMSTR_TRUE); /* enable Serial receive interrupt */
295#endif /* FMSTR_SHORT_INTR || FMSTR_LONG_INTR */
296
297#if FMSTR_DEBUG_TX > 0
298 /* we have just finished the transmission of the test frame, now wait the 32x times the sendtime
299 to receive any command from PC (count<0 is measurement, count>0 is waiting, count=0 is send trigger) */
300 if (fmstr_nDebugTxPollCount < 0)
301 {
302 fmstr_nDebugTxPollCount *= -(FMSTR_DEBUG_TX_POLLCNT_XFACTOR);
303 }
304#endif
305
306#if FMSTR_DEBUG_LEVEL >= 2
307 FMSTR_DEBUG_PRINTF("FMSTR Listening...\n");
308#endif
309}
310
311/******************************************************************************
312 *
313 * @brief Send response of given error code (no data)
314 *
315 * @param nErrCode - error code to be sent
316 *
317 ******************************************************************************/
318
319static void _FMSTR_SendError(FMSTR_BCHR nErrCode)
320{
321#if FMSTR_DEBUG_LEVEL >= 1
322 FMSTR_DEBUG_PRINTF("FMSTR SendError code: 0x%x\n", (FMSTR_U8)nErrCode);
323#endif
324
325 /* fill & send single-byte response */
326 _FMSTR_SerialSendResponse(&fmstr_pCommBuffer[2], 0U, nErrCode, NULL);
327}
328
329/******************************************************************************
330 *
331 * @brief Finalize transmit buffer before transmitting
332 *
333 * @param nLength - response length (1 for status + data length)
334 *
335 *
336 * This Function takes the data already prepared in the transmit buffer
337 * (inlcuding the status byte). It computes the check sum and kicks on tx.
338 *
339 ******************************************************************************/
340
341static void _FMSTR_SerialSendResponse(FMSTR_BPTR pResponse,
342 FMSTR_SIZE nLength,
343 FMSTR_U8 statusCode,
344 void *identification)
345{
346 FMSTR_SIZE8 i;
347 FMSTR_U8 c;
348
349 FMSTR_UNUSED(identification);
350
351 if (nLength > 254U || pResponse != &fmstr_pCommBuffer[2])
352 {
353 /* The Serial driver doesn't support bigger responses than 254 bytes, change the response to status error */
354 statusCode = FMSTR_STC_RSPBUFFOVF;
355 nLength = 0U;
356 }
357
358 /* remember the buffer to be sent */
359 fmstr_pTxBuff = fmstr_pCommBuffer;
360 /* Send the message with status, length and checksum. SOB is not counted as it is sent right here. */
361 fmstr_nTxTodo = (FMSTR_SIZE8)(nLength + 3U);
362
363 if ((statusCode & FMSTR_STSF_VARLEN) != 0U)
364 {
365 fmstr_pCommBuffer[0] = (FMSTR_BCHR)statusCode;
366 fmstr_pCommBuffer[1] = (FMSTR_BCHR)nLength;
367 }
368 else
369 {
370 fmstr_pCommBuffer[1] = (FMSTR_BCHR)statusCode;
371 fmstr_pTxBuff++;
372 fmstr_nTxTodo--;
373 }
374
375 /* Initialize CRC algorithms */
376 FMSTR_Crc8Init(&fmstr_nRxCrc8);
377
378 /* status byte and data are already there, compute checksum only */
379 pResponse = fmstr_pTxBuff;
380 for (i = 1U; i < fmstr_nTxTodo; i++)
381 {
382 pResponse = FMSTR_ValueFromBuffer8(&c, pResponse);
383 /* add character to checksum */
384 FMSTR_Crc8AddByte(&fmstr_nRxCrc8, c);
385 }
386
387 /* store checksum after the message */
388 pResponse = FMSTR_ValueToBuffer8(pResponse, fmstr_nRxCrc8);
389
390 /* now transmitting the response */
391 _fmstr_wFlags.flg.bTxActive = 1U;
392 _fmstr_wFlags.flg.bTxWaitTC = 0U;
393
394 /* do not replicate the initial SOB */
395 _fmstr_wFlags.flg.bTxLastCharSOB = 0U;
396
397 /* disable receiver, enable transmitter (single-wire communication) */
398 FMSTR_SERIAL_DRV.EnableReceive(FMSTR_FALSE);
399 FMSTR_SERIAL_DRV.EnableTransmit(FMSTR_TRUE);
400
401#if FMSTR_DEBUG_LEVEL >= 3
402 FMSTR_DEBUG_PRINTF("FMSTR Tx: %02x\n", (FMSTR_U8)FMSTR_SOB);
403#endif
404
405 /* kick on the SCI transmission (also clears TX Empty flag on some platforms) */
406 (void)FMSTR_SERIAL_DRV.IsTransmitRegEmpty();
407 FMSTR_SERIAL_DRV.PutChar(FMSTR_SOB);
408
409 /* TX interrupt enable, RX interrupt disable */
410#if FMSTR_LONG_INTR > 0 || FMSTR_SHORT_INTR > 0
411 FMSTR_SERIAL_DRV.EnableReceiveInterrupt(FMSTR_FALSE); /* disable SCI receive interrupt */
412 FMSTR_SERIAL_DRV.EnableTransmitInterrupt(FMSTR_TRUE); /* enable SCI transmit interrupt */
413#endif /* FMSTR_LONG_INTR || FMSTR_SHORT_INTR */
414}
415
416/******************************************************************************
417 *
418 * @brief Output buffer transmission
419 *
420 * @param getTxChar Return character to be transmitted
421 *
422 * @return Non-zero when transmission is complete
423 *
424 * get ready buffer(prepare data to send)
425 *
426 ******************************************************************************/
427
428static FMSTR_BOOL _FMSTR_Tx(FMSTR_BCHR *getTxChar)
429{
430 if (fmstr_nTxTodo > 0U)
431 {
432 /* fetch & send character ready to transmit */
433 /*lint -e{534} ignoring return value */
434 (void)FMSTR_ValueFromBuffer8(getTxChar, fmstr_pTxBuff);
435
436 /* first, handle the replicated SOB characters */
437 if (*getTxChar == FMSTR_SOB)
438 {
439 _fmstr_wFlags.flg.bTxLastCharSOB = _fmstr_wFlags.flg.bTxLastCharSOB != 0U ? 0U : 1U;
440
441 if (_fmstr_wFlags.flg.bTxLastCharSOB != 0U)
442 {
443 /* yes, repeat the SOB next time */
444 return FMSTR_FALSE;
445 }
446 }
447
448 /* no, advance tx buffer pointer */
449 fmstr_nTxTodo--;
450 fmstr_pTxBuff = FMSTR_SkipInBuffer(fmstr_pTxBuff, 1U);
451 return FMSTR_FALSE;
452 }
453
454 return FMSTR_TRUE;
455}
456
457/******************************************************************************
458 *
459 * @brief Handle received character
460 *
461 * @param rxChar The character to be processed
462 *
463 * Handle the character received and -if the message is complete- call the
464 * protocol decode routine.
465 *
466 ******************************************************************************/
467
468static FMSTR_BOOL _FMSTR_Rx(FMSTR_BCHR rxChar)
469{
470 FMSTR_SERIAL_FLAGS *pflg = &_fmstr_wFlags;
471 /* first, handle the replicated SOB characters */
472 if (rxChar == FMSTR_SOB)
473 {
474 pflg->flg.bRxLastCharSOB = pflg->flg.bRxLastCharSOB != 0U ? 0U : 1U;
475 if (pflg->flg.bRxLastCharSOB != 0U)
476 {
477 /* this is either the first byte of replicated SOB or a */
478 /* real Start-of-Block mark - we will decide next time in FMSTR_Rx */
479 return FMSTR_FALSE;
480 }
481 }
482
483 /* we have got a common character preceded by the SOB - */
484 /* this is the command code! */
485 if (pflg->flg.bRxLastCharSOB != 0U)
486 {
487#if FMSTR_DEBUG_LEVEL >= 3
488 FMSTR_DEBUG_PRINTF("FMSTR Rx Frame start. Cmd: 0x%x\n", rxChar);
489#endif
490
491 /* reset receiving process */
492 fmstr_pRxBuff = fmstr_pCommBuffer;
493
494 FMSTR_Crc8Init(&fmstr_nRxCrc8);
495 FMSTR_Crc8AddByte(&fmstr_nRxCrc8, rxChar);
496
497 *(fmstr_pRxBuff++) = rxChar;
498 fmstr_nRxTodo = 0;
499
500 /* if the standard command was received, the message length will come in next byte */
501 pflg->flg.bRxMsgLengthNext = 1U;
502
503 /* command code stored & processed */
504 pflg->flg.bRxLastCharSOB = 0U;
505 return FMSTR_FALSE;
506 }
507
508 /* we are waiting for the length byte */
509 if (pflg->flg.bRxMsgLengthNext != 0U)
510 {
511#if FMSTR_DEBUG_LEVEL >= 3
512 FMSTR_DEBUG_PRINTF("FMSTR Rx Frame length: 0x%x\n", rxChar);
513#endif
514 /* total data length and the checksum */
515 fmstr_nRxTodo = (FMSTR_SIZE8)(rxChar + 1U);
516 FMSTR_Crc8AddByte(&fmstr_nRxCrc8, rxChar);
517
518 *(fmstr_pRxBuff++) = rxChar;
519
520 /* now read the data bytes */
521 pflg->flg.bRxMsgLengthNext = 0U;
522
523 return FMSTR_FALSE;
524 }
525
526 /* waiting for a data byte? */
527 if (fmstr_nRxTodo > 0U)
528 {
529 /* decrease number of expected bytes */
530 fmstr_nRxTodo--;
531 /* was it the last byte of the message (checksum)? */
532 if (fmstr_nRxTodo == 0U)
533 {
534#if FMSTR_DEBUG_LEVEL >= 3
535 FMSTR_DEBUG_PRINTF("FMSTR Rx Checksum: 0x%x, expected: 0x%x\n", rxChar, fmstr_nRxCrc8);
536#endif
537
538 /* receive buffer overflow? */
539 if (fmstr_pRxBuff == NULL)
540 {
541 _FMSTR_SendError(FMSTR_STC_CMDTOOLONG);
542 }
543 /* checksum error? */
544 else if (fmstr_nRxCrc8 != rxChar)
545 {
546 _FMSTR_SendError(FMSTR_STC_CMDCSERR);
547 }
548 /* message is okay */
549 else
550 {
551 FMSTR_BPTR pMessageIO = fmstr_pCommBuffer;
552 FMSTR_BOOL processed;
553 FMSTR_U8 cmd, size;
554
555 /* command code comes first in the message */
556 /*lint -e{534} return value is not used */
557 pMessageIO = FMSTR_ValueFromBuffer8(&cmd, pMessageIO);
558 /* length of command follows */
559 /*lint -e{534} return value is not used */
560 pMessageIO = FMSTR_ValueFromBuffer8(&size, pMessageIO);
561
562 /* do decode now! use "serial" as a globally unique pointer value as our identifier */
563 processed = FMSTR_ProtocolDecoder(pMessageIO, size, cmd, (void *)"serial");
564 FMSTR_UNUSED(processed);
565 }
566
567 return FMSTR_TRUE;
568 }
569 /* not the last character yet */
570 else
571 {
572 /* add this byte to checksum */
573 FMSTR_Crc8AddByte(&fmstr_nRxCrc8, rxChar);
574
575 /* is there still a space in the buffer? */
576 if (fmstr_pRxBuff != NULL)
577 {
578 /*lint -e{946} pointer arithmetic is okay here (same array) */
579 if (fmstr_pRxBuff < (fmstr_pCommBuffer + FMSTR_COMM_BUFFER_SIZE))
580 {
581 /* store byte */
582 *fmstr_pRxBuff++ = rxChar;
583 }
584 /* buffer is full! */
585 else
586 {
587 /* NULL rx pointer means buffer overflow - but we still need */
588 /* to receive all message characters (for the single-wire mode) */
589 /* so keep "receiving" - but throw away all characters from now */
590 fmstr_pRxBuff = NULL;
591 }
592 }
593 }
594 }
595
596 return FMSTR_FALSE;
597}
598
599/******************************************************************************
600 *
601 * @brief Serial communication initialization
602 *
603 ******************************************************************************/
604
605static FMSTR_BOOL _FMSTR_SerialInit(void)
606{
607 /* initialize all state variables */
608 _fmstr_wFlags.all = 0U;
609 fmstr_nTxTodo = 0U;
610
611#if FMSTR_DEBUG_LEVEL >= 2
612 FMSTR_DEBUG_PRINTF("FMSTR SerialInit\n");
613#endif
614
615 /* Check the interface if it's valid */
616 FMSTR_ASSERT_RETURN(FMSTR_SERIAL_DRV.Init != NULL, FMSTR_FALSE);
617 FMSTR_ASSERT_RETURN(FMSTR_SERIAL_DRV.EnableTransmit != NULL, FMSTR_FALSE);
618 FMSTR_ASSERT_RETURN(FMSTR_SERIAL_DRV.EnableReceive != NULL, FMSTR_FALSE);
619 FMSTR_ASSERT_RETURN(FMSTR_SERIAL_DRV.IsTransmitRegEmpty != NULL, FMSTR_FALSE);
620 FMSTR_ASSERT_RETURN(FMSTR_SERIAL_DRV.IsReceiveRegFull != NULL, FMSTR_FALSE);
621 FMSTR_ASSERT_RETURN(FMSTR_SERIAL_DRV.IsTransmitterActive != NULL, FMSTR_FALSE);
622 FMSTR_ASSERT_RETURN(FMSTR_SERIAL_DRV.PutChar != NULL, FMSTR_FALSE);
623 FMSTR_ASSERT_RETURN(FMSTR_SERIAL_DRV.GetChar != NULL, FMSTR_FALSE);
624 FMSTR_ASSERT_RETURN(FMSTR_SERIAL_DRV.Flush != NULL, FMSTR_FALSE);
625
626#if FMSTR_SHORT_INTR || FMSTR_LONG_INTR
627 FMSTR_ASSERT_RETURN(FMSTR_SERIAL_DRV.EnableTransmitInterrupt != NULL, FMSTR_FALSE);
628 FMSTR_ASSERT_RETURN(FMSTR_SERIAL_DRV.EnableTransmitCompleteInterrupt != NULL, FMSTR_FALSE);
629 FMSTR_ASSERT_RETURN(FMSTR_SERIAL_DRV.EnableReceiveInterrupt != NULL, FMSTR_FALSE);
630#endif
631
632 /* Call initialization of serial driver */
633 if (FMSTR_SERIAL_DRV.Init() == FMSTR_FALSE)
634 {
635 return FMSTR_FALSE;
636 }
637
638 /* Initialize Serial interface */
639 FMSTR_SERIAL_DRV.EnableReceive(FMSTR_TRUE); /* enable SCI receive interrupt */
640 FMSTR_SERIAL_DRV.EnableTransmit(FMSTR_TRUE); /* enable SCI transmit interrupt */
641
642#if FMSTR_SHORT_INTR > 0
643 _FMSTR_RingBuffCreate(&fmstr_rxQueue, fmstr_rxBuff, FMSTR_COMM_RQUEUE_SIZE);
644#endif
645
646#if FMSTR_DEBUG_TX > 0
647 /* this zero will initiate the test frame transmission
648 * as soon as possible during Listen */
649 fmstr_nDebugTxPollCount = 0;
650#endif
651
652 /* start listening for commands */
653 _FMSTR_Listen();
654
655#if FMSTR_DEBUG_LEVEL >= 2
656 FMSTR_DEBUG_PRINTF("FMSTR SerialInit done\n");
657#endif
658
659 return FMSTR_TRUE;
660}
661
662/*******************************************************************************
663 *
664 * @brief API: Serial Transport "Polling" call from the application main loop
665 *
666 * This function either handles all the SCI communication (polling-only mode =
667 * FMSTR_POLL_DRIVEN) or decodes messages received on the background by SCI interrupt
668 * (short-interrupt mode = FMSTR_SHORT_INTR).
669 *
670 *******************************************************************************/
671
672static void _FMSTR_SerialPoll(void)
673{
674 /* invoke low-level driver's poll if needed */
675 if (FMSTR_SERIAL_DRV.Poll != NULL)
676 {
677 FMSTR_SERIAL_DRV.Poll();
678 }
679
680#if FMSTR_POLL_DRIVEN > 0
681
682 /* polled SCI mode */
683 FMSTR_ProcessSerial();
684
685#elif FMSTR_SHORT_INTR > 0
686 /* process queued SCI characters */
687 _FMSTR_RxDequeue();
688#endif
689
690#if FMSTR_DEBUG_TX > 0
691 /* down-counting the polls for heuristic time measurement */
692 if (fmstr_nDebugTxPollCount != 0 && fmstr_nDebugTxPollCount > FMSTR_DEBUG_TX_POLLCNT_MIN)
693 {
694 fmstr_nDebugTxPollCount--;
695 }
696#endif
697}
698
699#endif /* !(FMSTR_DISABLE) */
700