📄 freemaster_serial.c
字号:
/******************************************************************************
*
* Freescale Semiconductor Inc.
* (c) Copyright 2004-2005 Freescale Semiconductor, Inc.
* (c) Copyright 2001-2004 Motorola, Inc.
* ALL RIGHTS RESERVED.
*
****************************************************************************//*!
*
* @file freemaster_serial.c
*
* @brief FreeMaster SCI communication routines
*
* @version 1.0.1.0
*
* @date Oct-12-2006
*
*******************************************************************************/
#include "freemaster.h"
#include "freemaster_private.h"
#include "freemaster_protocol.h"
#if FMSTR_USE_SCI || FMSTR_USE_JTAG
/***********************************
* local variables
***********************************/
/// PC Master communication buffer (in/out) plus the STS and LEN bytes
static FMSTR_BCHR pcm_pCommBuffer[FMSTR_COMM_BUFFER_SIZE+2];
/// PC Master runtime flags
static volatile union
{
FMSTR_FLAGS all;
struct
{
unsigned bTxActive : 1; ///< response is being transmitted
unsigned bTxLastCharSOB : 1; ///< last transmitted char was equal to SOB
unsigned bRxLastCharSOB : 1; ///< last received character was SOB
unsigned bRxMsgLengthNext : 1; ///< expect the length byte next time
} flg;
} pcm_wFlags;
// receive and transmit buffers and counters
static FMSTR_SIZE8 pcm_nTxTodo; ///< transmission to-do counter (0 when tx is idle)
static FMSTR_SIZE8 pcm_nRxTodo; ///< reception to-do counter (0 when rx is idle)
static FMSTR_BPTR pcm_pTxBuff; ///< pointer to next byte to transmit
static FMSTR_BPTR pcm_pRxBuff; ///< pointer to next free place in RX buffer
static FMSTR_BCHR pcm_nRxCheckSum; ///< checksum of data being received
#if FMSTR_SHORT_INTR
static FMSTR_BCHR pcm_pRQueueBuffer[FMSTR_COMM_RQUEUE_SIZE]; // SHORT_INTR receive queue (circular)
static FMSTR_BPTR pcm_pRQueueRP; ///< SHORT_INTR queue, Read-Pointer
static FMSTR_BPTR pcm_pRQueueWP; ///< SHORT_INTR queue, Write-Pointer
#endif
#if FMSTR_USE_JTAG
static FMSTR_U32 pcm_wJtagTxData; ///< four bytes buffer to be sent over JTAG (LSB first)
static FMSTR_SIZE8 pcm_wJtagTxCtr; ///< counter of bytes in pcm_wJtagTxData
#endif
/***********************************
* local function prototypes
***********************************/
static void FMSTR_Listen(void);
static void FMSTR_SendError(FMSTR_BCHR nErrCode);
static void FMSTR_Tx(void);
static void FMSTR_Rx(FMSTR_BCHR nRxChar);
static void FMSTR_RxQueue(FMSTR_BCHR nRxChar);
static void FMSTR_RxDequeue(void);
/**************************************************************************//*!
*
* @brief Serial communication initialization
*
******************************************************************************/
void FMSTR_InitSerial(void)
{
// initialize all state variables
pcm_wFlags.all = 0;
pcm_nTxTodo = 0;
pcm_nRxTodo = 0;
#if FMSTR_SHORT_INTR
pcm_pRQueueRP = pcm_pRQueueBuffer;
pcm_pRQueueWP = pcm_pRQueueBuffer;
#endif
// start listening for commands
FMSTR_Listen();
}
/**************************************************************************//*!
*
* @brief Start listening on a serial line
*
* Reset the receiver machine and start listening on a serial line
*
******************************************************************************/
static void FMSTR_Listen(void)
{
pcm_nRxTodo = 0;
// disable transmitter, enable receiver (enables single-wire connection)
#if FMSTR_USE_SCI
FMSTR_SCI_TD();
FMSTR_SCI_RE();
#endif
// disable transmit, enable receive interrupts
#if FMSTR_SHORT_INTR || FMSTR_LONG_INTR
#if FMSTR_USE_SCI
FMSTR_SCI_DTXI(); // disable SCI transmit interrupt
FMSTR_SCI_ERXI(); // enable SCI recieve interrupt
#elif FMSTR_USE_JTAG
FMSTR_JTAG_DTXI(); // disable JTAG transmit interrupt
FMSTR_JTAG_ERXI(); // enable JTAG recieve interrupt
#endif
#endif
}
/**************************************************************************//*!
*
* @brief Send response of given error code (no data)
*
* @param nErrCode - error code to be sent
*
******************************************************************************/
static void FMSTR_SendError(FMSTR_BCHR nErrCode)
{
// fill & send single-byte response
*pcm_pCommBuffer = nErrCode;
FMSTR_SendResponse(pcm_pCommBuffer, 1);
}
/**************************************************************************//*!
*
* @brief Finalize transmit buffer before transmitting
*
* @param nLength - response length (1 for status + data length)
*
*
* This Function takes the data already prepared in the transmit buffer
* (inlcuding the status byte). It computes the check sum and kicks on tx.
*
******************************************************************************/
void FMSTR_SendResponse(FMSTR_BPTR pResponse, FMSTR_SIZE8 nLength)
{
volatile FMSTR_U16 wDummy;
FMSTR_U8 i, chSum = 0;
// remeber the buffer to be sent
pcm_pTxBuff = pResponse;
// status byte and data are already there, compute checksum only
for (i=0; i<nLength; i++)
chSum += *pResponse++;
// store checksum after the message
*pResponse++ = (~chSum) + 1;
// send the message and the checksum and the SOB
pcm_nTxTodo = nLength+1;
// now transmitting the response
pcm_wFlags.flg.bTxActive = 1;
// do not replicate the initial SOB
pcm_wFlags.flg.bTxLastCharSOB = 0;
#if FMSTR_USE_SCI
// disable receiver, enable transmitter (single-wire communication)
FMSTR_SCI_RD();
FMSTR_SCI_TE();
// kick on the SCI transmission (also clear TX Empty flag)
wDummy = FMSTR_SCI_GETSR();
FMSTR_SCI_PUTCHAR(FMSTR_SOB);
#elif FMSTR_USE_JTAG
// kick on the JTAG transmission
pcm_wJtagTxData = FMSTR_SOB;
pcm_wJtagTxCtr = 1;
// send the next two bytes immediatelly (we can be sure there are two bytes)
FMSTR_Tx();
FMSTR_Tx();
// send the third byte (if any) or flush the 32bit JTAG word
FMSTR_Tx();
#endif
// TX interrupt enable, RX interrupt disable
#if FMSTR_LONG_INTR || FMSTR_SHORT_INTR
#if FMSTR_USE_SCI
FMSTR_SCI_DRXI();
FMSTR_SCI_ETXI();
#elif FMSTR_USE_JTAG
#if FMSTR_USE_JTAG_TXFIX
// in TX-bugfix mode, keep the RX interrupt enabled as it
// is used as "able-to-TX" notification from the PC
FMSTR_JTAG_ERXI();
#else
// otherwise, JTAG is very same as the SCI
FMSTR_JTAG_DRXI();
FMSTR_JTAG_ETXI();
#endif
#endif
#endif
}
/**************************************************************************//*!
*
* @brief Output buffer transmission
*
* This function sends one character of the transmit buffer. It handles
* replicating of the SOB characted inside the message body.
*
******************************************************************************/
static void FMSTR_Tx(void)
{
FMSTR_U8 ch;
if (pcm_nTxTodo)
{
// fetch & send character ready to transmit
ch = (*pcm_pTxBuff) & 0xff;
#if FMSTR_USE_SCI
// just put the byte into the SCI transmit buffer
FMSTR_SCI_PUTCHAR((FMSTR_U8) ch);
#elif FMSTR_USE_JTAG
// put byte to 32bit JTAG buffer
pcm_wJtagTxData = (pcm_wJtagTxData << 8) | ch;
// another byte
pcm_wJtagTxCtr++;
// all four bytes ready?
if(pcm_wJtagTxCtr & 0x4)
{
FMSTR_JTAG_PUTDWORD(pcm_wJtagTxData);
pcm_wJtagTxCtr = 0;
}
#endif
// SOB replication?
if (ch != FMSTR_SOB || pcm_wFlags.flg.bTxLastCharSOB)
{
// no, advance tx buffer pointer
pcm_nTxTodo--;
pcm_pTxBuff++;
pcm_wFlags.flg.bTxLastCharSOB = 0;
}
else
{
// yes, repeat the SOB next time
pcm_wFlags.flg.bTxLastCharSOB = 1;
}
}
#if FMSTR_USE_JTAG
// on JTAG, the some bytes may still be pending in a 32bit buffer
else if(pcm_wJtagTxCtr > 0)
{
// add padding bytes
while(!(pcm_wJtagTxCtr & 4))
{
pcm_wJtagTxData = (pcm_wJtagTxData << 8) | 0xff;
pcm_wJtagTxCtr++;
}
// send the word just completed
FMSTR_JTAG_PUTDWORD(pcm_wJtagTxData);
// done, bTxActive will be deactivated next time
pcm_wJtagTxCtr = 0;
}
#endif
// transmission finished, start listening again
else
{
// turn off the transmitter machine
pcm_wFlags.flg.bTxActive = 0;
// start listening again
FMSTR_Listen();
}
}
/**************************************************************************//*!
*
* @brief Handle received character
*
* @param nRxChar The character to be processed
*
* Handle the character received and -if the message is complete- call the
* protocol decode routine.
*
******************************************************************************/
static void FMSTR_Rx(FMSTR_BCHR nRxChar)
{
// first, handle the replicated SOB characters
if(nRxChar == FMSTR_SOB)
{
// this is the 2nd byte of replicated SOB char
if(pcm_wFlags.flg.bRxLastCharSOB)
{
// join the two SOBs into one 0x2b character and continue processing
pcm_wFlags.flg.bRxLastCharSOB = 0;
}
// this is either the first byte of replicated SOB or a
// real Start-of-Block mark - we will decide next time in FMSTR_Rx
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -