420 lines
12 KiB
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;
|
|
}
|