📄 uarthw_mcbsp.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 + -