empty_project_28377D/device/driverlib/sci.c

420 lines
12 KiB
C

//###########################################################################
//
// FILE: sci.c
//
// TITLE: C28x SCI driver.
//
//###########################################################################
// $Copyright:
// Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the
// distribution.
//
// Neither the name of Texas Instruments Incorporated nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// $
//###########################################################################
#include "sci.h"
//*****************************************************************************
//
// SCI_setConfig
//
//*****************************************************************************
void
SCI_setConfig(uint32_t base, uint32_t lspclkHz, uint32_t baud, uint32_t config)
{
uint32_t divider;
//
// Check the arguments.
// Is the required baud rate greater than the maximum rate supported?
//
ASSERT(SCI_isBaseValid(base));
ASSERT(baud != 0U);
ASSERT((baud * 16U) <= lspclkHz);
//
// Stop the SCI.
//
SCI_disableModule(base);
//
// Compute the baud rate divider.
//
divider = ((lspclkHz / (baud * 8U)) - 1U);
//
// Set the baud rate.
//
HWREGH(base + SCI_O_HBAUD) = (divider & 0xFF00U) >> 8U;
HWREGH(base + SCI_O_LBAUD) = divider & 0x00FFU;
//
// Set parity, data length, and number of stop bits.
//
HWREGH(base + SCI_O_CCR) = ((HWREGH(base + SCI_O_CCR) &
~(SCI_CONFIG_PAR_MASK |
SCI_CONFIG_STOP_MASK |
SCI_CONFIG_WLEN_MASK)) | config);
//
// Start the SCI.
//
SCI_enableModule(base);
}
//*****************************************************************************
//
// SCI_writeCharArray
//
//*****************************************************************************
void
SCI_writeCharArray(uint32_t base, const uint16_t * const array,
uint16_t length)
{
//
// Check the arguments.
//
ASSERT(SCI_isBaseValid(base));
uint16_t i;
//
// Check if FIFO enhancement is enabled.
//
if(SCI_isFIFOEnabled(base))
{
//
// FIFO is enabled.
// For loop to write (Blocking) 'length' number of characters
//
for(i = 0U; i < length; i++)
{
//
// Wait until space is available in the transmit FIFO.
//
while(SCI_getTxFIFOStatus(base) == SCI_FIFO_TX15)
{
}
//
// Send a char.
//
HWREGH(base + SCI_O_TXBUF) = array[i];
}
}
else
{
//
// FIFO is not enabled.
// For loop to write (Blocking) 'length' number of characters
//
for(i = 0U; i < length; i++)
{
//
// Wait until space is available in the transmit buffer.
//
while(!SCI_isSpaceAvailableNonFIFO(base))
{
}
//
// Send a char.
//
HWREGH(base + SCI_O_TXBUF) = array[i];
}
}
}
//*****************************************************************************
//
// SCI_readCharArray
//
//*****************************************************************************
void
SCI_readCharArray(uint32_t base, uint16_t * const array, uint16_t length)
{
//
// Check the arguments.
//
ASSERT(SCI_isBaseValid(base));
uint16_t i;
//
// Check if FIFO enhancement is enabled.
//
if(SCI_isFIFOEnabled(base))
{
//
// FIFO is enabled.
// For loop to read (Blocking) 'length' number of characters
//
for(i = 0U; i < length; i++)
{
//
// Wait until a character is available in the receive FIFO.
//
while(SCI_getRxFIFOStatus(base) == SCI_FIFO_RX0)
{
}
//
// Return the character from the receive buffer.
//
array[i] = (uint16_t)
(HWREGH(base + SCI_O_RXBUF) & SCI_RXBUF_SAR_M);
}
}
else
{
//
// FIFO is not enabled.
// For loop to read (Blocking) 'length' number of characters
//
for(i = 0U; i < length; i++)
{
//
// Wait until a character is available in the receive buffer.
//
while(!SCI_isDataAvailableNonFIFO(base))
{
}
//
// Return the character from the receive buffer.
//
array[i] = (uint16_t)
(HWREGH(base + SCI_O_RXBUF) & SCI_RXBUF_SAR_M);
}
}
}
//*****************************************************************************
//
// SCI_enableInterrupt
//
//*****************************************************************************
void
SCI_enableInterrupt(uint32_t base, uint32_t intFlags)
{
//
// Check the arguments.
//
ASSERT(SCI_isBaseValid(base));
//
// Enable the specified interrupts.
//
if((intFlags & SCI_INT_RXERR) == SCI_INT_RXERR)
{
HWREGH(base + SCI_O_CTL1) |= SCI_CTL1_RXERRINTENA;
}
if((intFlags & SCI_INT_RXRDY_BRKDT) == SCI_INT_RXRDY_BRKDT)
{
HWREGH(base + SCI_O_CTL2) |= SCI_CTL2_RXBKINTENA;
}
if((intFlags & SCI_INT_TXRDY) == SCI_INT_TXRDY)
{
HWREGH(base + SCI_O_CTL2) |= SCI_CTL2_TXINTENA;
}
if((intFlags & SCI_INT_TXFF) == SCI_INT_TXFF)
{
HWREGH(base + SCI_O_FFTX) |= SCI_FFTX_TXFFIENA;
}
if((intFlags & SCI_INT_RXFF) == SCI_INT_RXFF)
{
HWREGH(base + SCI_O_FFRX) |= SCI_FFRX_RXFFIENA;
}
}
//*****************************************************************************
//
// SCI_disableInterrupt
//
//*****************************************************************************
void
SCI_disableInterrupt(uint32_t base, uint32_t intFlags)
{
//
// Check the arguments.
//
ASSERT(SCI_isBaseValid(base));
//
// Disable the specified interrupts.
//
if((intFlags & SCI_INT_RXERR) == SCI_INT_RXERR)
{
HWREGH(base + SCI_O_CTL1) &= ~SCI_CTL1_RXERRINTENA;
}
if((intFlags & SCI_INT_RXRDY_BRKDT) == SCI_INT_RXRDY_BRKDT)
{
HWREGH(base + SCI_O_CTL2) &= ~SCI_CTL2_RXBKINTENA;
}
if((intFlags & SCI_INT_TXRDY) == SCI_INT_TXRDY)
{
HWREGH(base + SCI_O_CTL2) &= ~SCI_CTL2_TXINTENA;
}
if((intFlags & SCI_INT_TXFF) == SCI_INT_TXFF)
{
HWREGH(base + SCI_O_FFTX) &= ~SCI_FFTX_TXFFIENA;
}
if((intFlags & SCI_INT_RXFF) == SCI_INT_RXFF)
{
HWREGH(base + SCI_O_FFRX) &= ~SCI_FFRX_RXFFIENA;
}
}
//*****************************************************************************
//
// SCI_getInterruptStatus
//
//*****************************************************************************
uint32_t
SCI_getInterruptStatus(uint32_t base)
{
uint32_t interruptStatus = 0;
//
// Check the arguments.
//
ASSERT(SCI_isBaseValid(base));
//
// Return the interrupt status.
//
if((HWREGH(base + SCI_O_CTL2) & SCI_CTL2_TXRDY) == SCI_CTL2_TXRDY)
{
interruptStatus |= SCI_INT_TXRDY;
}
if((HWREGH(base + SCI_O_RXST) & SCI_RXST_RXERROR) == SCI_RXST_RXERROR)
{
interruptStatus |= SCI_INT_RXERR;
}
if(((HWREGH(base + SCI_O_RXST) & SCI_RXST_RXRDY) == SCI_RXST_RXRDY) ||
((HWREGH(base + SCI_O_RXST) & SCI_RXST_BRKDT) == SCI_RXST_BRKDT))
{
interruptStatus |= SCI_INT_RXRDY_BRKDT;
}
if((HWREGH(base + SCI_O_FFTX) & SCI_FFTX_TXFFINT) == SCI_FFTX_TXFFINT)
{
interruptStatus |= SCI_INT_TXFF;
}
if((HWREGH(base + SCI_O_FFRX) & SCI_FFRX_RXFFINT) == SCI_FFRX_RXFFINT)
{
interruptStatus |= SCI_INT_RXFF;
}
if((HWREGH(base + SCI_O_RXST) & SCI_RXST_FE) == SCI_RXST_FE)
{
interruptStatus |= SCI_INT_FE;
}
if((HWREGH(base + SCI_O_RXST) & SCI_RXST_OE) == SCI_RXST_OE)
{
interruptStatus |= SCI_INT_OE;
}
if((HWREGH(base + SCI_O_RXST) & SCI_RXST_PE) == SCI_RXST_PE)
{
interruptStatus |= SCI_INT_PE;
}
return(interruptStatus);
}
//*****************************************************************************
//
// SCI_clearInterruptStatus
//
//*****************************************************************************
void
SCI_clearInterruptStatus(uint32_t base, uint32_t intFlags)
{
//
// Check the arguments.
//
ASSERT(SCI_isBaseValid(base));
//
// Clear the requested interrupt sources.
//
if(((intFlags & SCI_INT_RXERR) == SCI_INT_RXERR) ||
((intFlags & SCI_INT_RXRDY_BRKDT) == SCI_INT_RXRDY_BRKDT) ||
((intFlags & SCI_INT_FE) == SCI_INT_FE) ||
((intFlags & SCI_INT_OE) == SCI_INT_OE) ||
((intFlags & SCI_INT_PE) == SCI_INT_PE))
{
SCI_performSoftwareReset(base);
}
if((intFlags & SCI_INT_TXFF) == SCI_INT_TXFF)
{
HWREGH(base + SCI_O_FFTX) |= SCI_FFTX_TXFFINTCLR;
}
if((intFlags & SCI_INT_RXFF) == SCI_INT_RXFF)
{
HWREGH(base + SCI_O_FFRX) |= SCI_FFRX_RXFFINTCLR;
}
}
//*****************************************************************************
//
// SCI_setBaud
//
//*****************************************************************************
void SCI_setBaud(uint32_t base, uint32_t lspclkHz, uint32_t baud)
{
uint32_t divider;
//
// Compute the baud rate divider {ROUND TO NEAREST INTEGER}
//
divider = ((float)((float)lspclkHz / ((float)baud * 8.0F)) - 1.0F) + 0.5F;
//
// Set the baud rate.
//
HWREGH(base + SCI_O_HBAUD) = (divider & 0xFF00U) >> 8U;
HWREGH(base + SCI_O_LBAUD) = divider & 0x00FFU;
}
//*****************************************************************************
//
// SCI_setWakeFlag
//
//*****************************************************************************
void SCI_setWakeFlag(uint32_t base)
{
//
// Check the arguments.
//
ASSERT(SCI_isBaseValid(base));
//
// Set the TX wake flag bit to indicate
// that the next frame is an address frame.
//
HWREGH(base + SCI_O_CTL1) |= SCI_CTL1_TXWAKE;
}