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

📄 uarthw_evmdm642.c

📁 DM642支持4个串口的驱动代码
💻 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.10.00.23 07-02-03 (ddk-b12)" */
/*
 *  ======== uarthw_evmdm642.c ========
 */
 
#include <std.h>

#define CHIP_DM642      1

#include <hwi.h>
#include <iom.h>

#include <csl.h>
#include <csl_irq.h>

#include <evmdm642.h>
#include <evmdm642_osd.h>

#include <uarthw.h>
#include <uarthw_evmdm642.h>
#include <uarthw_evmdm642hal.h>

#define DM642_CPLD_UART_BASE	0xa0000000

#define RBRREG(regset)  (regset->uart[0])
#define THRREG(regset)  (regset->uart[0])
#define DLLREG(regset)  (regset->uart[0])
#define DLHREG(regset)  (regset->uart[1])
#define IERREG(regset)  (regset->uart[1])
#define FCRREG(regset)  (regset->uart[2])
#define EFRREG(regset)  (regset->uart[2])
#define IIRREG(regset)  (regset->uart[2])
#define LCRREG(regset)  (regset->uart[3])
#define MCRREG(regset)  (regset->uart[4])
#define XON1REG(regset) (regset->uart[4])
#define LSRREG(regset)  (regset->uart[5])
#define XON2REG(regset) (regset->uart[5])
#define MSRREG(regset)  (regset->uart[6])
#define XOF1REG(regset) (regset->uart[6])
#define TCRREG(regset)  (regset->uart[6])
#define SPRREG(regset)  (regset->uart[7])
#define XOF2REG(regset) (regset->uart[7])
#define TLRREG(regset)  (regset->uart[7])
#define FRDYREG(regset) (regset->uart[7])

#define getLineStatus(regset)           ((Byte)LSRREG(regset))
#define getModemControlReg(regset)      ((Byte)MCRREG(regset))
#define setModemControlReg(regset, c)   MCRREG(regset) = (c)
#define getLineControlReg(regset)       ((Byte)LCRREG(regset))
#define setLineControlReg(regset, c)    LCRREG(regset) = (c)
#define disableRx(regset)               (IERREG(regset) &= ~UART_IER_RXDATAEN)
#define disableTx(regset)               (IERREG(regset) &= ~UART_IER_THREMPEN)
#define enableRx(regset)                (IERREG(regset) |= UART_IER_RXDATAEN)
#define enableTx(regset)                (IERREG(regset) |= UART_IER_THREMPEN)
#ifdef _DEBUG
#define getInt(regset)                  ((Byte)IIRREG(regset) & 0x3f)
#else
#define getInt(regset)                  ((Byte)IIRREG(regset) & 0x0f)
#endif /* _DEBUG */

#define NUMPORTS                        4
#define NOINTPENDING                    0x01
#define IDENTIFYINT(id)                 ((id >> 1) & 0x03)

#define MCRDTRMASK                      0xFE
#define MCRRTSMASK                      0xFD
#define LCRBRKMASK                      0xBF

#define AFERTSCTSMASK                   0xDD
#define AFERTSCTSFLW                    0x22
#define AFECTSFLW                       0x20
#define AFEDISFLW                       0x00

#define LCRBREAKPOS                     6
#define MCRRTSPOS                       1

typedef struct UartRegs {
    volatile unsigned short uart[8];
} UartRegs;

static void setupFlowParams(UARTHW_Handle hUart, Uns flowParam);
static void uartIsr(Ptr cbArg);
static Int uartRxFull(UartRegs * regs);

static UARTHW_EVMDM642_Params defaultParams = { \
    UARTHW_EVMDM642_FLOW_NONE,                  \
    UARTHW_EVMDM642_DISABLE_PARITY,             \
    UARTHW_EVMDM642_WORD8,                      \
    UARTHW_EVMDM642_STOP1,                      \
    UARTHW_EVMDM642_BAUD_115200                 \
};

typedef struct UARTHW_Obj {
    Int uartId;                         /* UART port ID */
    Int rxDisabled;                     /* disabled flag */
    UartRegs * regs;                    /* base pointer to reg set */
    UARTHW_EVMDM642_Params *params;
    UARTHW_Tcallback * cbFxns;
    Ptr cbArg;
} UARTHW_Obj;

UARTHW_Obj portObj[NUMPORTS];

#ifdef _DEBUG
struct {
        Int errInts;
        Int mdmInts;
        Int rhrInts;
        Int thrInts;
        Int rtoInts;
        Int rxCnt;
        Int rxXoff;
        Int rtsCts;
} intStats[NUMPORTS] =
{
        {0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0}
};
#endif /* _DEBUG */


/*
 *  ======== UARTHW_open ========
 *
 *  This function is used to attach to the UART.
 *  Typically this function plugs the UART interrupt vector with
 *  the internal driver supplied isr routine.
 *  Initializes the UART, UART flow parameters and UART communication parameters
 *
 */
UARTHW_Handle UARTHW_open(Int uartId, Ptr params, Ptr cbArg, UARTHW_Tcallback *cbFxns)
{
    volatile Char c;
        UartRegs *regs;
    UARTHW_EVMDM642_Params *uartParams = (UARTHW_EVMDM642_Params *)params;
    UARTHW_Handle  port;

    if (uartId >= NUMPORTS) {
        return (NULL);                  // invalid UART id
    }

    port = &portObj[uartId];
    
    port->uartId = uartId;
    regs = port->regs = (UartRegs *) (DM642_CPLD_UART_BASE + (uartId * sizeof(UartRegs)));

    /* 
     * Initialize the isrhandler to the one given by
     * generic uart.
     */
    port->cbFxns = cbFxns;
    port->cbArg = cbArg;
       
    EVMDM642_OSD_init();

/*    if (uartId == 0) {
        EVMDM642_OSD_intHook(UARTA_IRQ, uartIsr, port);
    } 
    else {
        EVMDM642_OSD_intHook(UARTB_IRQ, uartIsr, port);
    }
*/
	switch(uartId)
	{
	case 0:
        EVMDM642_OSD_intHook(UARTA_IRQ, uartIsr, port);
        break;
	case 1:
        EVMDM642_OSD_intHook(UARTB_IRQ, uartIsr, port);
        break;
   	case 2:
        EVMDM642_OSD_intHook(UARTC_IRQ, uartIsr, port);
        break;
	case 3:
        EVMDM642_OSD_intHook(UARTD_IRQ, uartIsr, port);
        break;
	}
	
    /* 
     * Use the default attributes if one is not given
     */
    if (uartParams == NULL) {
        uartParams = &defaultParams;
    }

    /*
     * Set EFR registers
     */
    LCRREG(regs) = 0xBF;                /* address secondary register set */
    EFRREG(regs) =  0;   //UART_EFR_AUTOCTS | UART_EFR_AUTORTS | UART_EFR_ENHFUNCEN; /* enable enhanced functions */
					
    LCRREG(regs) = 0x00;                /* back to primary register set */
    MCRREG(regs) = 0x00;
    MCRREG(regs) = UART_MCR_IRQENOP | UART_MCR_FIFORDYEN; /* enable IRQ and FIF rdy register */
    IERREG(regs) = 0x00;                /* set interrupt enable register */
    FCRREG(regs) = 0x00;                /* set FIFO control */

    /*
     * Set up baud rate and other comm parameters
     */
    LCRREG(regs) = UART_LCR_DLTCHEN; /* enable divisor */
    DLLREG(regs) = uartParams->baud;
    DLHREG(regs) = uartParams->baud >> 8;
    LCRREG(regs) = uartParams->wordSize | (uartParams->stopBits << 2) |
                (uartParams->parity << 3);

    FCRREG(regs) =                              /* FIFO control register */
                UART_FCR_RXTRG16 | UART_FCR_TXTRG32 | UART_FCR_DMAMODE |
                UART_FCR_RSTTXFIFO | UART_FCR_RSTRXFIFO | UART_FCR_FIFOEN;
    IERREG(regs) =                              /* enable normal interrupts */
                UART_IER_MDMSTATEN | UART_IER_RXLSTATEN | UART_IER_THREMPEN |
                UART_IER_RXDATAEN;
    LSRREG(regs);                               /* clear previous line status */
    MSRREG(regs);                               /* modem status register */
    MCRREG(regs);                               /* modem control register */

    while (uartRxFull(regs)) { /* remove active characters */
        c = (Byte)RBRREG(regs);
    }

    port->params = uartParams;
      
    setupFlowParams(port, (uartParams->flowControl) & UARTHW_EVMDM642_HW_FLOW_MASK);

    port->rxDisabled = 0;               /* indicate we're enabled now */
    enableRx(regs);
    enableTx(regs);
  
    return (port);
}

/*
 *  ======== UARTHW_getModemStatus ========
 *
 *  This function is used to get the modem status for the UART. 
 */
 
Int UARTHW_getModemStatus(UARTHW_Handle hUart, char *pmodemStatus)
{
    *pmodemStatus = (Byte)MSRREG(hUart->regs);

    return (IOM_COMPLETED);
}

/*
 *  ======== UARTHW_resetDevice ========
 *
 *  This function is used to reset the UART 16c75x.
 *  Ideally this function should clear the transmit and 
 *  receive fifos if the fifos are being used.
 */
void UARTHW_resetDevice(UARTHW_Handle hUart)
{
    FCRREG(hUart->regs) =
                UART_FCR_RXTRG16 | UART_FCR_TXTRG32 | UART_FCR_DMAMODE |
                UART_FCR_RSTTXFIFO | UART_FCR_RSTRXFIFO | UART_FCR_FIFOEN;
}

/*
 *  ======== UARTHW_setBreak ========
 *
 *  This function is used to set the break on/off for the UART 16c75x 
 */
Int UARTHW_setBreak(UARTHW_Handle hUart, Int bBreak)
{
    char lcrVal;

    lcrVal = getLineControlReg(hUart->regs);
    lcrVal = (lcrVal & LCRBRKMASK) | (bBreak << LCRBREAKPOS);
    setLineControlReg(hUart->regs, lcrVal);
   
    return (IOM_COMPLETED);
}

/*
 *  ======== UARTHW_setDTR ========
 *
 *  This function is used to set the DTR signal for the UART 16c75x 
 */
Int UARTHW_setDTR(UARTHW_Handle hUart, int dtrval)
{
    char mcrVal;

    mcrVal = getModemControlReg(hUart->regs);
    mcrVal = (mcrVal & MCRDTRMASK) | dtrval;
    setModemControlReg(hUart->regs, mcrVal);

    return (IOM_COMPLETED);
}

/*
 *  ======== UARTHW_setRTS ========
 *
 *  This function is used to set the RTS signal for the UART 16c75x 
 */
Int UARTHW_setRTS(UARTHW_Handle hUart, int rtsval)
{
    char mcrVal;

    mcrVal = getModemControlReg(hUart->regs);
    mcrVal = (mcrVal & MCRRTSMASK) | (rtsval << MCRRTSPOS);
    setModemControlReg(hUart->regs, mcrVal);
    
    return (IOM_COMPLETED);
}

/*
 *  ======== UARTHW_txEmpty ========
 *
 *  This function is used to get the transmit buffer empty condition 
 */
Int UARTHW_txEmpty(UARTHW_Handle hUart)
{
    return ((Byte)LSRREG(hUart->regs) & UART_LSR_THREMPTY);
}

/*
 *  ======== UARTHW_writeChar ========
 *
 *  This function is used to write a character to the transmit register 
 */
void UARTHW_writeChar(UARTHW_Handle hUart, char c)
{
    THRREG(hUart->regs) = c;
}

/*
 *  ======== UARTHW_enableRx ========
 *  Enable the Rx Interrupt of the UART.
 *
 */
void UARTHW_enableRx(UARTHW_Handle hUart)
{
    if (ATM_seti(&hUart->rxDisabled, 0)) {
        enableRx(hUart->regs);
    }
}

/*
 *  ======== UARTHW_disableRx ========
 *  Disable the Rx Interrupt of the UART.
 *
 */
void UARTHW_disableRx(UARTHW_Handle hUart)
{
    int gie;

    gie = IRQ_globalDisable();
    disableRx(hUart->regs);
    hUart->rxDisabled = 1;
    IRQ_globalRestore(gie);
}

/*
 *  ======== setupFlowParams ========
 *
 *  This function is used to setup the UART 16c75x flow paramaters
 */
static void setupFlowParams(UARTHW_Handle hUart, Uns flowParam)
{
    char mcrVal;
 
    mcrVal = getModemControlReg(hUart->regs);
        mcrVal &= AFERTSCTSMASK;
 
    if (flowParam & UARTHW_EVMDM642_FLOW_AFE_RTSCTS) {
        mcrVal |= AFERTSCTSFLW;
    }
    else if (flowParam & UARTHW_EVMDM642_FLOW_AFE_CTS) {
        mcrVal |= AFECTSFLW;
    }
    else {
        mcrVal |= AFEDISFLW;  
    }

    setModemControlReg(hUart->regs, mcrVal);                
}

/* 
 *  ======== uartIsr ========
 *
 *  This is the interrupt service handler used by the EVMDM642
 *  UART driver.
 */
static void uartIsr(Ptr portArg)
{
    Int                 id;
    Int                 argval;
    Int                 temp;
    UARTHW_Handle       port = (UARTHW_Handle) portArg;
    UARTHW_Tcallback    *callbacks = port->cbFxns;
    Ptr                 cbArg = port->cbArg;

    /*
     * While loop here since 16C752/4 holds interrupt line high until
     * all interrupt conditions are handled (2 or more may be pending
     * at same time).  DM642 uses edge-triggered interrupts and would
     * miss interrupts otherwise.
     */
    while (!((id = getInt(port->regs)) & NOINTPENDING)) {
        switch (id) {
            case UART_INT_MSR: /* Modem status interrupt -- read and dispatch */
#ifdef _DEBUG
                intStats[port->uartId].mdmInts++;
#endif /* _DEBUG */
                argval = (Byte)MSRREG(port->regs);
                (*callbacks[UARTHW_MODEM_STATUSHANDLER])(cbArg, argval);
                break;

            case UART_INT_THR:          /* Transmit handler */
#ifdef _DEBUG
                intStats[port->uartId].thrInts++;
#endif /* _DEBUG */
                /* NOTE:
                 * This shouldn't be necessary, but sometimes the interrupt
                 * comes in before the transmitter is really empty.  Still
                 * working on this one
                 */
                while (!(temp = UARTHW_txEmpty(port))) {
                    asm(" NOP");
                }

                (*callbacks[UARTHW_TXEMPTY_STATUSHANDLER])(cbArg, temp);
                break;

            case UART_INT_RHR:          /* Receive Handler */
            case UART_INT_RXTO:         /* Receive time-out error */
#ifdef _DEBUG
                if (id == UART_INT_RHR)
                    intStats[port->uartId].rhrInts++;
                else
                    intStats[port->uartId].rtoInts++;
#endif /* _DEBUG */
                while ((!port->rxDisabled) && uartRxFull(port->regs)) {
#ifdef _DEBUG
                    intStats[port->uartId].rxCnt++;
#endif /* _DEBUG */
                    argval = (Byte)RBRREG(port->regs);
                    (*callbacks[UARTHW_RXFULL_STATUSHANDLER])(cbArg, argval); 
                }
                break;

                case UART_INT_RLSERR:   /* Receiver line status error */
#ifdef _DEBUG
                    intStats[port->uartId].errInts++;
#endif /* _DEBUG */
                    argval = (Byte)LSRREG(port->regs);
                    /*
                     * Isolate parity/framing/overrun and data ready
                     * Discard characters by reading the receiver buffer
                     * ready register, and get the line status again
                     */
                    while ((argval & UART_LSR_ERRMASK) && (argval & UART_LSR_DATAIN)) {
                        (Byte)RBRREG(port->regs);
                        argval = (Byte)LSRREG(port->regs);
                    }
                    (*callbacks[UARTHW_LINE_STATUSHANDLER])(cbArg, argval);
                    break;
#ifdef _DEBUG
                case UART_INT_XOFF:     /* Xoff interrupt */
                    intStats[port->uartId].rxXoff++;
                    break;

                case UART_INT_CTSRTS:  /* RTS or CTS pin change to inactive */
                    intStats[port->uartId].rtsCts++;
                    break;
                default:
                    while (1) {
                        /* should never get here ... */
                        asm(" NOP");
                    }
#endif /* _DEBUG */
        }
    }
}

/*
 * ======== uartRxFull ========
* * 
 * This function is used to get the Receive Buffer Full condition 
 */
static Int uartRxFull(UartRegs *regs)
{
    return ((Byte)LSRREG(regs) & UART_LSR_DATAIN);
}

⌨️ 快捷键说明

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