⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 freemaster_serial.c

📁 BCM 控制demo源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************
*
* 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 + -