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

📄 uarthw_mcbsp.c

📁 DSP串口的UART程序
💻 C
字号:
/*
 *  Copyright 2003 by Texas Instruments Incorporated.
 *  All rights reserved. Property of Texas Instruments Incorporated.
 *  Restricted rights to use, duplicate or disclose this code are
 *  granted through contract.
 *  
 */
/* "@(#) DDK 1.11.00.00 11-04-03 (ddk-b13)" */
/*
 *  ======== uarthw_mcbsp.c ========
 */
 
#include <std.h>

#include <iom.h>

#include <uarthw.h>
#include <uarthw_mcbsp.h>

#define LSRREG                  (portObj.LSRVAL)
#define THRREG                  (portObj.THRVAL)
#define LSRCLEARRXFULLMASK      0xFE
#define LSRCLEARTXEMPTYMASK     0xDF
#define LSRCLEARRXFEMASK        0xF7

#define LSRSETTXEMPTYMASK       0x20
#define LSRSETRXFULLMASK        0x01
#define LSRSETRXFEMASK          0x08

#define CURRENTTXOFFSET         portObj.txOffset
#define CURRENTRXOFFSET         portObj.rxOffset

static void processTx(MdUns *buffer);
static void processRx(MdUns *buffer);

typedef struct UARTHW_Obj {
    Byte        THRVAL;
    Byte        LSRVAL;
    MdUns *     txBuffer;
    MdUns *     rxBuffer;
    Uns         txOffset;
    Uns         rxOffset;
    Bool        breakOn;
    Ptr         cbArg;
    UARTHW_Tcallback *cbFxns;
} UARTHW_Obj;

/*
 *  This driver only supports a single UART.
 */
static UARTHW_Obj  portObj;

#if defined(_54_) || defined(_55_)
/* rxBuffer and txBuffer must be aligned for the DMA to work correctly */
#pragma DATA_ALIGN(rxBuffer, 32)
#pragma DATA_ALIGN(txBuffer, 32)
#endif

/*
 * CACHE issue on c6x1x!  For 6x1x these buffers need to be in on-chip
 * memory (cache needs to be split) or cache needs to be disabled. You can
 * do this by setting 3-way cache, defining a new on-chip memory section
 * and placing .bss in on-chip memory.  This probably needs to be a 
 * parameter so that 6x version can do correct cache management.
 */
static MdUns rxBuffer[UARTHW_MCBSP_MAXBITS * 2];
static MdUns txBuffer[UARTHW_MCBSP_MAXBITS * 2];

/*
 *  ======== UARTHW_open ========
 *  This function is used to attach to the software UART.
 *  Typically this function plugs the UART interrupt vector with
 *  the internal driver supplied isr routine.
 */
UARTHW_Handle UARTHW_open(Int uartId, Ptr attrs, Ptr cbArg, UARTHW_Tcallback 
        *cbFxns)
{
    Uns  i;
 
    if (uartId != 0) {
        return (NULL);
    }

    /* save the callback functions and argument */
    portObj.cbFxns = cbFxns;
    portObj.cbArg = cbArg;
    
    /* Initialize the uart parameters given by the app */
    portObj.txBuffer  = txBuffer;
    portObj.rxBuffer  = rxBuffer;
    portObj.breakOn   = FALSE;

    /* Initialize the Rx and Tx buffers to all 0xFFFF */ 
    for (i = 0; i < UARTHW_MCBSP_MAXBITS * 2; i++) {
        portObj.txBuffer[i] = portObj.rxBuffer[i] = 0xFFFF;
    }

    /* set the initial offsets */
    CURRENTRXOFFSET = 0;
    CURRENTTXOFFSET = 0;
    
    /* Enable the device */
    LSRREG = 0x20;      
    THRREG = 0x00;
        
    /* start the MCBSP/DMA ping-pong buffering and ISRs ... */
    UARTHW_MCBSP_start(portObj.rxBuffer, portObj.txBuffer, attrs);

    return (&portObj);
}

/*
 *  ======== UARTHW_disableRx ========
 *  This is an empty function for the McBSP implementation since this 
 *  implementation does not support flow control.
 */
void UARTHW_disableRx(UARTHW_Handle hUart)
{
}

/*
 *  ======== UARTHW_enableRx ========
 *  This is an empty function for the McBSP implementation since this 
 *  implementation does not support flow control.
 */
void UARTHW_enableRx(UARTHW_Handle hUart)
{
}

/*
 *  ======== UARTHW_getModemStatus ========
 *  This function is not implemented by the simulated McBSP UART driver.
 */
Int UARTHW_getModemStatus(UARTHW_Handle hUart, Char *pmodemStatus)
{
    *pmodemStatus = 0;
   
    return (IOM_ENOTIMPL);
}

/*
 *  ======== UARTHW_resetDevice ========
 *  This function is used to reset the UART.
 *  Currently this is a dummy function.
 */
void UARTHW_resetDevice(UARTHW_Handle hUart)
{
}

/*
 *  ======== UARTHW_setBreak ========
 *  This function is used to set the break on/off for the simulated UART  
 */
Int UARTHW_setBreak(UARTHW_Handle hUart, Int bBreak)
{
    portObj.breakOn = (Bool)bBreak; 
   
    if (!bBreak) {
        (*(portObj.cbFxns)[UARTHW_TXEMPTY_STATUSHANDLER])(portObj.cbArg, 0);
    }

    return (IOM_COMPLETED);
}

/*
 *  ======== UARTHW_setDTR ========
 *  This function is not implemented by the simulated McBSP UART driver.
 */
Int UARTHW_setDTR(UARTHW_Handle hUart, Int dtrval)
{
    return (IOM_ENOTIMPL);
}

/*
 *  ======== UARTHW_setRTS ========
 *  This function is not implemented by the simulated McBSP UART driver.
 */
Int UARTHW_setRTS(UARTHW_Handle hUart, Int rtsval)
{
    return (IOM_ENOTIMPL);
}

/*
 *  ======== UARTHW_writeChar ========
 *
 *  This function is used to write a character to the transmit register 
 */
void UARTHW_writeChar(UARTHW_Handle hUart, Char c)
{
    THRREG = c;
    LSRREG = LSRREG & LSRCLEARTXEMPTYMASK; 
}

/*
 *  ======== UARTHW_txEmpty ========
 *
 *  This function is used to get the transmit buffer empty condition 
 */
Int UARTHW_txEmpty(UARTHW_Handle hUart)
{
    return (LSRREG & 0x20);
}

/*
 *  -------- support functions --------
 */

/*
 *  ======== decodeBit ========
 *
 *  This function decoded the received character by testing the     
 *  center 4 bits of the baud. A majority rule is used for the      
 *  decoding
 */
static Bool decodeBit(Uns value)
{
    /* Test middle 4 bits in received raw data */
    value = ((value >> 6) & 0x0F );

    if ((value == 7) || (value > 10)) {
        return (1);
    }
    else {
        return (0);
    }
}

/* 
 *  ======== UARTHW_MCBSP_dmaRxIsr ========
 *
 *  This is the interrupt service handler used by the DSK 5402
 *  McBSP driver for the receive channel.
 */
Void UARTHW_MCBSP_dmaRxIsr(void)
{
     MdUns *bufp;

     bufp = &(portObj.rxBuffer[CURRENTRXOFFSET]);

     CURRENTRXOFFSET = CURRENTRXOFFSET ^ UARTHW_MCBSP_RxPKTBITS;

     processRx(bufp);
}

/* 
 *  ======== UARTHW_MCBSP_dmaTxIsr ========
 *
 *  This is the interrupt service handler used by the DSK 5402
 *  McBSP driver for the transmit channel
 */
Void UARTHW_MCBSP_dmaTxIsr(Void)
{
     MdUns *bufp;

     bufp = &(portObj.txBuffer[CURRENTTXOFFSET]);

     CURRENTTXOFFSET = CURRENTTXOFFSET ^ UARTHW_MCBSP_TxPKTBITS;

     processTx(bufp);
}

/*
 *  ======== processRx ========
 *  Process Reception function : Reception of a buffer from the 
 *  McBSP and reformat it to get the associated character value 
 */
static void processRx(MdUns *buffer)
{
    Uns rawData = 0;
    Bool bitValue;
    Uns bitCnt;
    Int rxchar = 0;

    /*
     *  Point to start of data in dma buffer 
     *  skip the start bit
     */
    rawData = *buffer++;

    /* get the value of the majority of the bits */
    bitValue = decodeBit(rawData);
        
    /*The start bit should be zero */
    if (bitValue != 0) {
        LSRREG = LSRREG | LSRSETRXFEMASK;
        (*(portObj.cbFxns)[UARTHW_LINE_STATUSHANDLER])(portObj.cbArg, LSRREG);
        LSRREG = LSRREG & LSRCLEARRXFEMASK;
    }
        
    /* Walk through each data bit */
    for (bitCnt = 0; bitCnt < UARTHW_MCBSP_DATABITS; bitCnt++) {
        /* read raw bit (word) from dma buffer */
        rawData = *buffer++;

        /* get the value of the majority of the bits */
        bitValue = decodeBit(rawData);
                        
        /* put received bit into proper place */
        rxchar += bitValue << bitCnt;
    }
                 
    (*(portObj.cbFxns)[UARTHW_RXFULL_STATUSHANDLER])(portObj.cbArg, rxchar);
}

/*
 *  ======== processTx ========
 *
 *  Process transmission function : this function is filling the
 *  xmitbuffer with appropriate data or 0xFFFF if idle mode.
 */
static void processTx(MdUns *buffer)
{
    Uns bitCnt;
                        
    /* Check if break is on . Note that this code can be further optimized */
    if (portObj.breakOn) {
        for (bitCnt = 0; bitCnt < UARTHW_MCBSP_TxPKTBITS; bitCnt++) {
            *buffer++ = 0x0000;
        }
        return;                                 
    }                                   

    /*
     * If new char waiting to be sent
     */
    if (!UARTHW_txEmpty(&portObj)) {
        /* Mark output Fifo as empty */
        LSRREG = LSRREG | LSRSETTXEMPTYMASK; 

        /* Set start bit in buffer */
        *buffer++ = 0x0000;

        /* Walk through each data bit */
        for (bitCnt = 0; bitCnt < UARTHW_MCBSP_DATABITS; bitCnt++) {

            /* determine state of bit and set dma buffer value */
            if ((THRREG >> bitCnt & 0x1) == 1 ) {
                *buffer++ = 0xFFFF;
            }
            else {
                *buffer++ = 0x0000;
            }
        }
                    
        (*(portObj.cbFxns)[UARTHW_TXEMPTY_STATUSHANDLER])(portObj.cbArg, 0);
    } 
    else {
        /* 
         * Walk through each data bit and start bit 
         * and fill with idle.
         */
        for (bitCnt = 0; bitCnt < UARTHW_MCBSP_TxPKTBITS; bitCnt++) {
            *buffer++ = 0xFFFF;
        }
    } 
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -