📄 freemaster_serial.c
字号:
else
{
pcm_wFlags.flg.bRxLastCharSOB = 1;
return;
}
}
// we have got a common character preceeded by the SOB -
// this is the command code!
if(pcm_wFlags.flg.bRxLastCharSOB)
{
// reset reciving process
pcm_pRxBuff = pcm_pCommBuffer;
*pcm_pRxBuff++ = nRxChar;
// start computing the checksum
pcm_nRxCheckSum = nRxChar;
pcm_nRxTodo = 0;
// fast command?
if((nRxChar & FMSTR_FASTCMD) == FMSTR_FASTCMD)
{
// there will be no length information
pcm_wFlags.flg.bRxMsgLengthNext = 0;
// as it is encoded in the command byte directly
pcm_nRxTodo = ((nRxChar & FMSTR_FASTCMD_DATALEN_MASK) >> FMSTR_FASTCMD_DATALEN_SHIFT) + 1;
}
// standard command
else
{
// the message length will come in next byte
pcm_wFlags.flg.bRxMsgLengthNext = 1;
}
// command code stored & processed
pcm_wFlags.flg.bRxLastCharSOB = 0;
return;
}
// we are waiting for the length byte
if(pcm_wFlags.flg.bRxMsgLengthNext)
{
// this byte, total data length and the checksum
pcm_nRxTodo = 1 + nRxChar + 1;
// now read the data bytes
pcm_wFlags.flg.bRxMsgLengthNext = 0;
}
// waiting for a data byte?
if(pcm_nRxTodo)
{
// add this byte to checksum
pcm_nRxCheckSum += nRxChar;
// was it the last byte of the message (checksum)?
if(!--pcm_nRxTodo)
{
// receive buffer overflow?
if(pcm_pRxBuff == NULL)
{
FMSTR_SendError(FMSTR_STC_CMDTOOLONG);
}
// checksum error?
else if((pcm_nRxCheckSum & 0xff) != 0)
{
FMSTR_SendError(FMSTR_STC_CMDCSERR);
}
// message is okay
else
{
// do decode now!
FMSTR_ProtocolDecoder(pcm_pCommBuffer);
}
}
// not the last character, is there a space in buffer?
else if(pcm_pRxBuff)
{
if(pcm_pRxBuff < (pcm_pCommBuffer + FMSTR_COMM_BUFFER_SIZE))
{
// store byte
*pcm_pRxBuff++ = nRxChar;
}
// buffer is full!
else
{
// NULL rx pointer means buffer overflow - but we still need
// to receive all message characters (for the single-wire mode)
// so keep "receiving" - but throw away all characters from now
pcm_pRxBuff = NULL;
}
}
}
}
/*******************************************************************************
*
* @brief Routine to quick-receive a character (put to a queue only)
*
* This function puts received character into a queue and exits as soon as possible.
*
*******************************************************************************/
#if FMSTR_SHORT_INTR
static void FMSTR_RxQueue(FMSTR_BCHR nRxChar)
{
// future value of write pointer
FMSTR_BPTR wpnext = pcm_pRQueueWP + 1;
if(wpnext >= (pcm_pRQueueBuffer + FMSTR_COMM_RQUEUE_SIZE))
wpnext = pcm_pRQueueBuffer;
// any space in queue?
if(wpnext != pcm_pRQueueRP)
{
*pcm_pRQueueWP = (FMSTR_U8) nRxChar;
pcm_pRQueueWP = wpnext;
}
}
#endif // FMSTR_SHORT_INTR
/*******************************************************************************
*
* @brief Late processing of queued characters
*
* This function takes the queued characters and calls FMSTR_Rx() for each of them,
* just like as the characters would be received from SCI one by one.
*
*******************************************************************************/
#if FMSTR_SHORT_INTR
static void FMSTR_RxDequeue(void)
{
FMSTR_BCHR nChar = 0;
// get all queued characters
while(pcm_pRQueueRP != pcm_pRQueueWP)
{
nChar = *pcm_pRQueueRP++;
if(pcm_pRQueueRP >= (pcm_pRQueueBuffer + FMSTR_COMM_RQUEUE_SIZE))
pcm_pRQueueRP = pcm_pRQueueBuffer;
// emulate the SCI receive event
if(!pcm_wFlags.flg.bTxActive)
FMSTR_Rx(nChar);
}
}
#endif // FMSTR_SHORT_INTR
/**************************************************************************//*!
*
* @brief Handle SCI communication (both TX and RX)
*
* This function checks the SCI flags and calls the Rx and/or Tx functions
*
* @note This function can be called either from SCI ISR or from the polling routine
*
******************************************************************************/
#if FMSTR_USE_SCI
void FMSTR_ProcessSCI(void)
{
// read & clear status
register FMSTR_U16 wSciSR = FMSTR_SCI_RDCLRSR();
// transmitter active and empty?
if (pcm_wFlags.flg.bTxActive)
{
// able to send another character?
if(wSciSR & FMSTR_SCISR_TDRE)
FMSTR_Tx();
// ignore (read-out) received character (loopback?)
if(wSciSR & FMSTR_SCISR_RDRF)
{
volatile FMSTR_U16 nRxChar;
nRxChar = FMSTR_SCI_GETCHAR();
}
}
// transmitter not active, able to receive
else
{
// data byte received?
if (wSciSR & FMSTR_SCISR_RDRF)
{
register FMSTR_BCHR nRxChar = 0;
nRxChar = FMSTR_SCI_GETCHAR();
#if FMSTR_SHORT_INTR
FMSTR_RxQueue(nRxChar);
#else
FMSTR_Rx(nRxChar);
#endif
}
}
}
#endif
/**************************************************************************//*!
*
* @brief Handle JTAG communication (both TX and RX)
*
* This function checks the JTAG flags and calls the Rx and/or Tx functions
*
* @note This function can be called either from JTAG ISR or from the polling routine
*
******************************************************************************/
#if FMSTR_USE_JTAG
void FMSTR_ProcessJTAG(void)
{
// read & clear status
register FMSTR_U16 wJtagSR = FMSTR_JTAG_GETSR();
// transmitter active?
if (pcm_wFlags.flg.bTxActive)
{
// able to transmit a new character? (TX must be empty = read-out by PC)
if(!(wJtagSR & FMSTR_JTAG_OTXRXSR_TDF))
{
#if FMSTR_USE_JTAG_TXFIX
// if TDF bit is useless due to silicon bug, use the RX flag
// instead (PC sends us a dummy word to kick the RX flag on)
if(wJtagSR & FMSTR_JTAG_OTXRXSR_RDF)
#endif
{
// send one byte always
FMSTR_Tx();
// try to fill-up the full 32bit JTAG word
while(pcm_wFlags.flg.bTxActive && pcm_wJtagTxCtr)
FMSTR_Tx();
}
}
// ignore (read-out) the JTAG-received word
if(wJtagSR & FMSTR_JTAG_OTXRXSR_RDF)
{
volatile FMSTR_U16 nRxWord;
nRxWord = FMSTR_JTAG_GETWORD();
}
}
// transmitter not active
else
{
// JTAG 32bit word (four bytes) received?
if(wJtagSR & FMSTR_JTAG_OTXRXSR_RDF)
{
register FMSTR_U32 nRxDWord;
FMSTR_INDEX i;
nRxDWord = FMSTR_JTAG_GETDWORD();
// process all bytes, MSB first
for(i=0; i<4; i++)
{
#if FMSTR_SHORT_INTR
FMSTR_RxQueue((FMSTR_BCHR)((nRxDWord >> 24) & 0xff));
#else
FMSTR_Rx((FMSTR_BCHR)((nRxDWord >> 24) & 0xff));
// ignore the rest if previous bytes triggered a transmission
// (i.e. the packet was complete and only filled-up to 32bit word)
if(pcm_wFlags.flg.bTxActive)
break;
#endif
// next byte of 32bit word
nRxDWord = nRxDWord << 8;
}
}
}
}
#endif
/*******************************************************************************
*
* @brief API: Main "Polling" call from the application main loop
*
* This function either handles all the SCI communictaion (polling-only mode =
* FMSTR_POLL_DRIVEN) or decodes messages received on the background by SCI interrupt
* (short-interrupt mode = FMSTR_SHORT_INTR).
*
* In fully interrupt-driven mode (FMSTR_LONG_INTR) this function does nothing.
*
*******************************************************************************/
void FMSTR_Poll(void)
{
#if FMSTR_POLL_DRIVEN
#if FMSTR_USE_SCI
FMSTR_ProcessSCI();
#elif FMSTR_USE_JTAG
FMSTR_ProcessJTAG();
#endif
#elif FMSTR_SHORT_INTR
// process queued SCI characters
FMSTR_RxDequeue();
#endif
}
#else // FMSTR_USE_SCI || FMSTR_USE_JTAG
// Empty implementation of communication functions.
// Without a SCI and JTAG the FreeMaster driver still passes the compilation,
// but no communication is supported. The user may imlement his own communication
// protocol and use FreeMaster by calling FMSTR_ProtocolDecoder and
// overriding the FMSTR_SendResponse calls
void FMSTR_SendResponse(FMSTR_BPTR pResponse, FMSTR_SIZE8 nLength) {}
void FMSTR_Poll(void) {}
#endif // FMSTR_USE_SCI || FMSTR_USE_JTAG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -