Hello All,
I am writing a interrupt driven, FIFO ring buffer fed SCI driver for a Matlab Embedded C2000 project.
The Matlab project has one other peripheral interrupt (for CAN RX) and a few timer interrupts.
Currently, when I enable the PIE interrupts for the SCI TX and RX (lines 212 and 232), I seem to crash my app, preventing other normal external activity such as CAN traffic.
My suspicion is that the interrupts are not clearing, and blocking.
Given that I based my interrupts on the datasheets and example code, I am struggling to find a difference that cause this issue, and also how to debug it.
Attached is the current version of my driver (note the TX and RX_INTERRUPT defines are most definitely enabled).
If anyone could recommend a path forward, I would be most appreciative,
Thank you
Neal O'Hara
/*! @file sci_drv.c
*
* $Revision: 1303 $
* $Date: 2018-02-15 09:47:58 -0500 (Thu, 15 Feb 2018) $
* $Author: abraham_mathew $
* $HeadURL: https://emsredmine/svn/p121619/Software/SW_11340_1_APP_Embedded/branches/Sandbox_1122018/C_Functions/sci_drv.c $
*
* @brief
* Driver Source Code for the Danfoss Serial Protocol
*
* @par
*
* (c) Copyright 2016-2018, LORD Corporation – LORD Confidential and Proprietary
*/
/*******************************************************************************
** Includes
******************************************************************************/
#include "sci_drv.h"
#include "utils_rb.h"
/*******************************************************************************
** Constants (exported only)
*******************************************************************************/
/*******************************************************************************
** Local Constants
*******************************************************************************/
#define SCI_FE_PE_MASK 0xC000 //Mask the FIFO Framing & Parity Error Bits
#define SCI_RXFFOVF_MASK 0x2000 //Mask the RXFFOVF bit from RB 16b data
#define SCI_RXFFOVF_SHIFT 13 //Shift RXFFOVF to 13th bit
#define SCI_RXDT_MASK 0x00FF //Mask the Received Character Bits of SCIRXBUF
#define SCI_TXDT_MASK 0x00FF //Mask the Transmit Character Bits of SCITXBUF
#define MAX_TX_FIFO_SIZE 0x4 //Max size for the DSP2803x TX FIFO
#define MAX_RX_FIFO_SIZE 0x4 //Max size for the DSP2803x RX FIFO
#define TX_RB_BUF_SIZE 64 //
#define RX_RB_BUF_SIZE 64 //
#define PUT_
/*******************************************************************************
** External Global Variables
******************************************************************************/
extern Uint16 Drv_Put_Debug_Value;
extern Uint16 Drv_Put_Status;
extern Uint16 Drv_Tx_Isr_Call_Ctr;
extern Uint16 Drv_Put_Call_Ctr;
extern Uint16 Drv_Rx_Isr_Call_Ctr;
extern Uint16 Drv_Read_Call_Ctr;
extern Uint16 Drv_Read_Status;
extern Uint16 Drv_Read_Err_Ctr;
/*******************************************************************************
** Static data declarations
******************************************************************************/
_STATIC_ bool sci_port_initialized = false;
#ifdef TX_INTERRUPT
_STATIC_ utils_rb_data_t transmit_rb;
_STATIC_ uint8_t tx_data[TX_RB_BUF_SIZE];
_STATIC_ sci_drv_err_t transmit_isr_err = SCI_DRV_ERR_NONE;
#endif
#ifdef RX_INTERRUPT
_STATIC_ utils_rb_data_t recieve_rb;
_STATIC_ uint16_t rx_data[RX_RB_BUF_SIZE];
_STATIC_ sci_drv_err_t recieve_isr_err = SCI_DRV_ERR_NONE;
#endif
/*******************************************************************************
** Function bodies
******************************************************************************/
/*******************************************************************************
* @name sci_drv_init
*
* @brief This function initializes the GPIO and serial control registers
*
* @param none
*
* @return none
******************************************************************************/
void sci_drv_init()
{
//initialize the GPIO pin registers associated with the serial bus module
//Unlock the registers to allow modifications
EALLOW;
// Enable internal pull-up for the selected pins
GpioCtrlRegs.GPAPUD.bit.GPIO28 = 0; // Serial RX (SCIRXDA)
GpioCtrlRegs.GPAPUD.bit.GPIO29 = 0; // Serial TX (SCITXDA)
// Inputs are synchronized to SYSCLKOUT by default.
// This will disable of synchronization for the selected pins
GpioCtrlRegs.GPAQSEL2.bit.GPIO28 = 3; // Asynch input GPIO28 (SCIRXDA)
// Configure pins to connect with the Serial module
GpioCtrlRegs.GPAMUX2.bit.GPIO28 = 1; // Serial RX (SCIRXDA)
GpioCtrlRegs.GPAMUX2.bit.GPIO29 = 1; // Serial TX (SCITXDA)
// enable SCI peripheral clock, in case it is not enabled elsewhere
SysCtrlRegs.PCLKCR0.bit.SCIAENCLK = 1;
//lock the registers to re-enable protection
EDIS;
//configure the Serial Bus control registers
SciaRegs.SCICCR.all =0x0007; // 1 stop bit, No loop-back
// No parity,8 char bits,
// async mode, idle-line protocol
/*
SciaRegs.SCICCR.bit.SCICHAR = 0x7; // 2:0 Character length control (8 chars)
SciaRegs.SCICCR.bit.ADDRIDLE_MODE = 0; // 3 ADDR/IDLE Mode control (Idle mode)
SciaRegs.SCICCR.bit.LOOPBKENA = 0; // 4 Loop Back enable (Disabled)
SciaRegs.SCICCR.bit.PARITYENA = 0; // 5 Parity enable (Disabled)
SciaRegs.SCICCR.bit.PARITY = 0; // 6 Even or Odd Parity (Odd)
SciaRegs.SCICCR.bit.STOPBITS = 0; // 7 Number of Stop Bits (one)
//SciaRegs.SCICCR.bit.rsvd1// // 15:8 reserved
*/
SciaRegs.SCICTL1.all =0x0003; // enable TX, RX, internal SCICLK,
// Disable RX ERR, SLEEP, TXWAKE
/*
SciaRegs.SCICTL1.bit.RXENA = 1; // 0 SCI receiver enable (Enabled)
SciaRegs.SCICTL1.bit.TXENA = 1; // 1 SCI transmitter enable (Enabled)
SciaRegs.SCICTL1.bit.SLEEP = 0; // 2 SCI sleep (Disabled)
SciaRegs.SCICTL1.bit.TXWAKE = 0; // 3 Transmitter wakeup method (Disabled)
//SciaRegs.SCICTL1.bit.rsvd// // 4 reserved
SciaRegs.SCICTL1.bit.SWRESET = 0; // 5 Software reset (Clear Flags)
SciaRegs.SCICTL1.bit.RXERRINTENA = 0; // 6 Receive interrupt enable (Disabled)
//SciaRegs.SCICTL1.bit.rsvd1// // 15:7 reserved
*/
SciaRegs.SCICTL2.bit.TXINTENA = 0; //disables serial TX
SciaRegs.SCICTL2.bit.RXBKINTENA = 0; //and RX interrupts
/*
SciaRegs.SCICTL2.bit.TXINTENA = 0; // 0 Transmit interrupt enable (Disabled)
SciaRegs.SCICTL2.bit.RXBKINTENA = 0; // 1 Receiver-buffer break enable (Disabled)
//SciaRegs.SCICTL2.bit.rsvd// // 5:2 reserved
//SciaRegs.SCICTL2.bit.TXEMPTY// // 6 Transmitter empty flag (Read Only)
//SciaRegs.SCICTL2.bit.TXRDY// // 7 Transmitter ready flag (Read Only)
//SciaRegs.SCICTL2.bit.rsvd1// // 15:8 reserved
*/
// Baud rate = LSPCLK/((BRR+1)*8)
//SciaRegs.SCIHBAUD =0x0000; // 19200 baud @LSPCLK = 15MHz (60 MHz SYSCLK).
SciaRegs.SCILBAUD =0x0006; // HDR_491: roughly 267860 baud @LSPCLK = 15MHz (60 MHz SYSCLK).
//267857 = (15*10^6)/(6+1)*8)
SciaRegs.SCIFFTX.bit.TXFIFOXRESET = 0; // 13 FIFO reset (Clear FIFO)
SciaRegs.SCIFFTX.all=0xE040; //setup TX buffer and reset TX interrupt
/*
SciaRegs.SCIFFTX.bit.TXFFIL = 0x0; // 4:0 Interrupt level (Match zero bytes)
SciaRegs.SCIFFTX.bit.TXFFIENA = 0; // 5 Interrupt enable (Disabled)
SciaRegs.SCIFFTX.bit.TXFFINTCLR = 1; // 6 Clear INT flag (Clear)
SciaRegs.SCIFFTX.bit.TXFFINT = 0; // 7 INT flag (Disabled)
//SciaRegs.SCIFFTX.bit.TXFFST = 0x0;// // 12:8 FIFO status (Read Only)
SciaRegs.SCIFFTX.bit.TXFIFOXRESET = 1; // 13 FIFO reset (Re-enable FIFO)
SciaRegs.SCIFFTX.bit.SCIFFENA = 1; // 14 Enhancement enable (Enabled)
SciaRegs.SCIFFTX.bit.SCIRST = 1; // 15 SCI reset rx/tx channels (Enable SCI FIFO)
*/
SciaRegs.SCIFFRX.bit.RXFIFORESET = 0; // 13 FIFO reset (Clear FIFO)
SciaRegs.SCIFFRX.all=0x2044; //setup RX buffer and reset RX interrupt
/*
SciaRegs.SCIFFRX.bit.RXFFIL = 0x4; // 4:0 Interrupt level (Match four bytes)
SciaRegs.SCIFFRX.bit.RXFFIENA = 0; // 5 Interrupt enable (Disabled)
SciaRegs.SCIFFRX.bit.RXFFINTCLR = 1; // 6 Clear INT flag (Clear)
//SciaRegs.SCIFFRX.bit.RXFFINT = 0;// // 7 INT flag (Read Only)
//SciaRegs.SCIFFRX.bit.RXFFST = 0x0;// // 12:8 FIFO status (Read Only)
SciaRegs.SCIFFRX.bit.RXFIFORESET = 1; // 13 FIFO reset (Re-enable FIFO)
SciaRegs.SCIFFRX.bit.RXFFOVRCLR = 0; // 14 Clear overflow (No clear)
//SciaRegs.SCIFFRX.bit.RXFFOVF = 0;// // 15 FIFO overflow (Read Only)
*/
SciaRegs.SCIFFCT.all=0x0; //no delay between bits sent
/*
SciaRegs.SCIFFCT.bit.FFTXDLY = 0x0; // 7:0 FIFO transmit delay (No Delay)
//SciaRegs.SCIFFCT.bit.rsvd = 0x0// // 12:8 reserved
SciaRegs.SCIFFCT.bit.CDC = 0; // 13 Auto baud mode enable (Disabled)
SciaRegs.SCIFFCT.bit.ABDCLR = 0; // 14 Auto baud clear (No Clear)
//SciaRegs.SCIFFCT.bit.ABD = 0;// // 15 Auto baud detect (Read Only)
*/
// SCIPRI left as default
/*
//SciaRegs.SCIPRI.bit.rsvd// // 2:0 reserved
SciaRegs.SCIPRI.bit.FREE = 0; // 3 Free emulation suspend mode
SciaRegs.SCIPRI.bit.SOFT = 0; // 4 Soft emulation suspend mode (Immediate stop on suspend)
//SciaRegs.SCIPRI.bit.rsvd1// // 15:5 reserved
*/
SciaRegs.SCICTL1.all =0x0023; // Relinquish SCI from Reset
/*
SciaRegs.SCICTL1.bit.RXENA = 1; // 0 SCI receiver enable (Enabled)
SciaRegs.SCICTL1.bit.TXENA = 1; // 1 SCI transmitter enable (Enabled)
SciaRegs.SCICTL1.bit.SLEEP = 0; // 2 SCI sleep (Disabled)
SciaRegs.SCICTL1.bit.TXWAKE = 0; // 3 Transmitter wakeup method (Disabled)
//SciaRegs.SCICTL1.bit.rsvd// // 4 reserved
SciaRegs.SCICTL1.bit.SWRESET = 1; // 5 Software reset (Re-Enable SCI) !!!
SciaRegs.SCICTL1.bit.RXERRINTENA = 0; // 6 Receive interrupt enable (Disabled)
//SciaRegs.SCICTL1.bit.rsvd1// // 15:7 reserved
*/
sci_port_initialized = true;
#ifdef TX_INTERRUPT
// Interrupts that are used in this driver are re-mapped to
// ISR functions found within this file.
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.SCITXINTA = &sciTxFifoIsr;
EDIS; // This is needed to disable write to EALLOW protected registers
PieCtrlRegs.PIEIER9.bit.INTx2 = 1; /* Enable interrupt SCITXINTA*/
IER |= M_INT9; //TODO: not sure about m_int9
// Disable the TX buffer INT, Enable the TX FIFO INT
SciaRegs.SCICTL2.bit.TXINTENA = 0; // 0 Transmit interrupt enable (Disabled)
SciaRegs.SCIFFTX.bit.TXFFIENA = 1; // 5 Interrupt enable (Enabled)
transmit_rb.data = tx_data;
transmit_rb.max_size = TX_RB_BUF_SIZE;
transmit_rb.head = 0U;
transmit_rb.tail = 0U;
transmit_rb.size = 0U;
#endif
#ifdef RX_INTERRUPT
// Interrupts that are used in this driver are re-mapped to
// ISR functions found within this file.
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.SCIRXINTA = &sciRxFifoIsr;
EDIS; // This is needed to disable write to EALLOW protected registers
PieCtrlRegs.PIEIER9.bit.INTx1 = 1; /* Enable interrupt SCIRXINTA*/
IER |= M_INT9; //TODO: not sure about m_int9
SciaRegs.SCIFFRX.bit.RXFFIENA = 1; // 5 Interrupt enable (Enabled)
SciaRegs.SCIFFRX.bit.RXFFINTCLR = 1; // 6 Clear INT flag (Clear)
// Error interrupts disable, will be checked by sci_drv_read_data()
SciaRegs.SCICTL1.bit.RXERRINTENA = 0; // 6 Receive interrupt enable (Disabled)
SciaRegs.SCICTL2.bit.RXBKINTENA = 0; // 1 Receiver-buffer break enable (Enabled)
recieve_rb.data = rx_data;
recieve_rb.max_size = RX_RB_BUF_SIZE;
recieve_rb.head = 0U;
recieve_rb.tail = 0U;
recieve_rb.size = 0U;
#endif
Drv_Put_Status = 0;
Drv_Tx_Isr_Call_Ctr = 0;
Drv_Put_Call_Ctr = 0;
Drv_Rx_Isr_Call_Ctr = 0;
Drv_Read_Call_Ctr = 0;
Drv_Read_Status = 0;
Drv_Read_Err_Ctr = 0;
return;
}
/*******************************************************************************
* @name sci_drv_put_data()
*
* @brief Write the desired number of bytes to the SCI TX bus through TX FIFO
* Note: DSP2803x has max FIFO size of 4 bytes
*
* @param p_buffer, byte buffer for write bytes
* @param num_bytes, desired number of bytes for TX
*
* @return SCI_DRV_ERR_NONE when bytes written correctly
* @return SCI_DRV_ERR_TX_INT_NONE interrupt occurred without MAX_TX_FIFO_SIZE bytes
* @return SCI_DRV_ERR_RB ring buffer error during TX interrupt
* @return SCI_DRV_ERR_TX_OVERFLOW if num_bytes greater than FIFO/Ring Buffer size
* @return SCI_DRV_ERR_TX_NOT_NUM_BYTES if num_bytes greater than Ring Buffer space
* @return SCI_DRV_ERR_RB error occurred with ring buffer
* @return SCI_DRV_ERR_INVALID_PARAMS if called with null pointers
* @return SCI_DRV_ERR_NOT_INITIALIZED if SCI not initialized
******************************************************************************/
sci_drv_err_t sci_drv_put_data(uint8_t * p_buffer, uint16_t num_bytes)
{
sci_drv_err_t err_code = SCI_DRV_ERR_NONE;
#ifndef TX_INTERRUPT
uint8_t count = 0;
#endif
Drv_Put_Status = 0;
if(sci_port_initialized)
{
if (NULL != p_buffer)
{
Drv_Put_Call_Ctr++;
#ifdef TX_INTERRUPT
if(num_bytes <= TX_RB_BUF_SIZE)
{
Drv_Put_Debug_Value = transmit_rb.size;
if(num_bytes <= utils_rb_available_bytes(&transmit_rb))
{
if (ERR_UTILS_RB_NONE == utils_rb_put_data(&transmit_rb,
p_buffer,
num_bytes))
{
//no action should be necessary. Maybe replace ifs with return code checks?
err_code = transmit_isr_err; // pass through any errors given by interrupt
transmit_isr_err = SCI_DRV_ERR_NONE;
}
else
{
err_code = SCI_DRV_ERR_RB;
}
}
else
{
err_code = SCI_DRV_ERR_TX_NOT_NUM_BYTES;
}
}
else
{
err_code = SCI_DRV_ERR_TX_OVERFLOW;
}
#else
if(num_bytes <= MAX_TX_FIFO_SIZE)
{
DINT; //Disable Interrupts while reading/writing SCI
for(count=0;count<num_bytes;count++)
{
while(!SciaRegs.SCICTL2.bit.TXRDY); //wait until buffer is available
SciaRegs.SCITXBUF = (p_buffer[count] & SCI_TXDT_MASK);
}
EINT; //Re-enable
}
else
{
err_code = SCI_DRV_ERR_TX_OVERFLOW;
}
#endif
}
else
{
err_code = SCI_DRV_ERR_INVALID_PARAMS;
}
}
else
{
err_code = SCI_DRV_ERR_NOT_INITIALIZED;
}
if(err_code != SCI_DRV_ERR_NONE)
{
Drv_Put_Status = (uint16_t) err_code;
}
return err_code;
}
/*******************************************************************************
* @name sci_drv_TX_status()
*
* @brief Determine the availability of the TX buffer and FIFO
*
* @param none
*
* @return SCI_DRV_ERR_NOT_INITIALIZED if SCI not initialized
* @return SCI_DRV_ERR_TX_NOT_EMPTY if TX FIFO or buffer not empty
* @return SCI_DRV_ERR_NONE if both FIFO and buffer are empty
******************************************************************************/
sci_drv_err_t sci_drv_TX_status()
{
sci_drv_err_t err_code = SCI_DRV_ERR_NONE;
if(sci_port_initialized)
{
DINT; //Disable Interrupts while reading/writing SCI
if((SciaRegs.SCIFFTX.bit.TXFFST != 0) || //If FIFO
(SciaRegs.SCICTL2.bit.TXEMPTY != 1)) //or buffer not empty
{
err_code = SCI_DRV_ERR_TX_NOT_EMPTY;
}
EINT; //Re-enable
}
else
{
err_code = SCI_DRV_ERR_NOT_INITIALIZED;
}
return err_code;
}
/*******************************************************************************
* @name sci_drv_get_read_size()
*
* @brief returns the number of bytes in the receive ring buffer
*
* @param none
*
* @return number of bytes
******************************************************************************/
uint16_t sci_drv_get_read_size(void)
{
return recieve_rb.size;
}
/*******************************************************************************
* @name sci_drv_read_data()
*
* @brief Read the desired number of bytes from the SCI RX bus through RX FIFO
*
* @param p_buffer, byte buffer for read bytes
* @param num_bytes, desired number of bytes from RX
* @param p_num_returned, actual number of bytes read
*
* @return SCI_DRV_ERR_NONE when bytes read correctly
* @return SCI_DRV_ERR_RB when ring buffer returns error
* @return SCI_DRV_ERR_RX_RB_OVERFLOW when interrupt occurs and no space in RB
* @return SCI_DRV_ERR_RX_NOT_NUM_BYTES when FIFO less than num_bytes
* @return SCI_DRV_ERR_RX_FIFO_OVERFLOW when FIFO overflowed from RX bytes
* @return SCI_DRV_ERR_RX_FIFO_FE_PE when FIFO bytes Frame or Parity error
* @return SCI_DRV_ERR_RX_OE when RX over wrote while reading
* @return SCI_DRV_ERR_RX_FE when RX bus had Frame error
* @return SCI_DRV_ERR_RX_BRKDT when RX bus has Break Detect error
* @return SCI_DRV_ERR_INVALID_PARAMS if called with null pointers, or too large
* @return SCI_DRV_ERR_NOT_INITIALIZED if SCI not initialized
******************************************************************************/
sci_drv_err_t sci_drv_read_data( uint16_t * p_buffer,
uint16_t num_bytes,
uint16_t * p_num_returned)
{
sci_drv_err_t err_code = SCI_DRV_ERR_NONE;
uint8_t count = 0;
#ifndef RX_INTERRUPT
uint16_t data_bytes = 0;
#endif
if(sci_port_initialized)
{
if ((NULL != p_buffer)||(NULL != p_num_returned))
{
Drv_Read_Call_Ctr++;
DINT; //Disable Interrupts while reading/writing SCI
#ifdef RX_INTERRUPT
if(num_bytes <= RX_RB_BUF_SIZE)
{
if(num_bytes <= recieve_rb.size)
{
if (ERR_UTILS_RB_NONE == utils_rb_get_data(&recieve_rb,
p_buffer,
num_bytes,
p_num_returned))
{
for(count=0;count<num_bytes;count++)
{
//check for errors, and parse out just data bytes
if((p_buffer[count] & SCI_FE_PE_MASK) != 0)
{
err_code = SCI_DRV_ERR_RX_FIFO_FE_PE;
}
else if((p_buffer[count] & SCI_RXFFOVF_MASK) != 0)
{
err_code = SCI_DRV_ERR_RX_FIFO_OVERFLOW;
}
p_buffer[count] = ((p_buffer[count] & SCI_RXDT_MASK));
}
err_code = recieve_isr_err; // pass through any errors given by interrupt
recieve_isr_err = SCI_DRV_ERR_NONE; //clear isr error code
}
else
{
err_code = SCI_DRV_ERR_RB;
}
}
else
{
err_code = SCI_DRV_ERR_RX_NOT_NUM_BYTES;
}
}
else
{ // requested bytes too large for ring buffer
err_code = SCI_DRV_ERR_INVALID_PARAMS;
}
#else
*p_num_returned = 0; //Initialize to none
if(SciaRegs.SCIFFRX.bit.RXFFST >= num_bytes)
{
//Read, if possible, num_bytes from RX FIFO
for(count=0;count<num_bytes;count++)
{
if(SciaRegs.SCIFFRX.bit.RXFFST != 0 ) // while bytes in RX FIFO keep processing
{
data_bytes = SciaRegs.SCIRXBUF.all;
if(SciaRegs.SCIFFRX.bit.RXFFOVF)
{ // FIFO Overflow, may still be able to parse bytes
err_code = SCI_DRV_ERR_RX_FIFO_OVERFLOW;
}
if((data_bytes & SCI_FE_PE_MASK) != 0)
{ // Frame or Parity errors have higher priority than Overflow,
// and corrupt bytes
//Serial_Failure_Count++; //TODO: Get protocol layer to do this !!!!!!!!
//SerialRxCtr |= 0x1000;
err_code = SCI_DRV_ERR_RX_FIFO_FE_PE;
break; //if error, stop reading bytes
}
else
{ // Desired correct action of reading bytes
p_buffer[count] = (uint8_t)(data_bytes & SCI_RXDT_MASK);
*p_num_returned = (count+1); // +1 for zero offset
}
}
else
{
//should not occur
err_code = SCI_DRV_ERR_RX_NOT_NUM_BYTES;
break;
}
}
}
else
{
err_code = SCI_DRV_ERR_RX_NOT_NUM_BYTES;
}
#endif
// These SCI Signal errors require FIFO bytes to be discarded
if(SciaRegs.SCIRXST.bit.OE)
{
err_code = SCI_DRV_ERR_RX_OE; //Needs SW Reset to clear
}
else if(SciaRegs.SCIRXST.bit.FE)
{
err_code = SCI_DRV_ERR_RX_FE; //Needs SW Reset to clear
}
else if(SciaRegs.SCIRXST.bit.BRKDT)
{
err_code = SCI_DRV_ERR_RX_BRKDT; //Needs SW Reset to clear
}
EINT; //Re-enable
}
else
{
err_code = SCI_DRV_ERR_INVALID_PARAMS;
}
}
else
{
err_code = SCI_DRV_ERR_NOT_INITIALIZED;
}
if(err_code != SCI_DRV_ERR_NONE )
{
Drv_Read_Status = (uint16_t) err_code;
Drv_Read_Err_Ctr++;
}
return err_code;
}
/*******************************************************************************
* @name sci_drv_RX_enable()
*
* @brief Enables the SCI RX read buffer, FIFO, and (if applicable) interrupts
*
* @param none
*
* @return SCI_DRV_ERR_NOT_INITIALIZED if SCI not initialized
* @return SCI_DRV_ERR_NONE after proper enable
******************************************************************************/
sci_drv_err_t sci_drv_RX_enable()
{
sci_drv_err_t err_code = SCI_DRV_ERR_NONE;
if(sci_port_initialized)
{
SciaRegs.SCIFFRX.bit.RXFFIL = 0x4; // 4:0 Interrupt level (Match four bytes)
#ifdef RX_INTERRUPT
SciaRegs.SCIFFRX.bit.RXFFIENA = 1; // 5 Interrupt enable (Enabled)
SciaRegs.SCIFFRX.bit.RXFFINTCLR = 1; // 6 Clear INT flag (Clear)
//SciaRegs.SCIFFRX.bit.RXFFINT = 0;// // 7 INT flag (Read Only)
SciaRegs.SCIFFTX.bit.SCIFFENA = 1; // 14 Enhancement enable (Enabled)
#endif
//SciaRegs.SCIFFRX.bit.RXFFST = 0x0;// // 12:8 FIFO status (Read Only)
SciaRegs.SCIFFRX.bit.RXFIFORESET = 1; // 13 FIFO reset (Enable FIFO)
SciaRegs.SCIFFRX.bit.RXFFOVRCLR = 1; // 14 Clear overflow (Clear)
//SciaRegs.SCIFFRX.bit.RXFFOVF = 0;// // 15 FIFO overflow (Read Only)
SciaRegs.SCICTL1.bit.RXENA = 1; // 0 SCI receiver enable (Enabled)
#ifdef RX_INTERRUPT
// Error interrupts disable, will be checked by sci_drv_read_data()
SciaRegs.SCICTL1.bit.RXERRINTENA = 0; // 6 Receive interrupt enable (Disabled)
SciaRegs.SCICTL2.bit.RXBKINTENA = 0; // 1 Receiver-buffer break enable (Disabled)
#endif
}
else
{
err_code = SCI_DRV_ERR_NOT_INITIALIZED;
}
return err_code;
}
/*******************************************************************************
* @name sci_drv_RX_disable()
*
* @brief Disables the SCI RX read buffer, FIFO, and (if applicable) interrupts
*
* @param none
*
* @return SCI_DRV_ERR_NOT_INITIALIZED if SCI not initialized
* @return SCI_DRV_ERR_NONE after proper disable
******************************************************************************/
sci_drv_err_t sci_drv_RX_disable()
{
sci_drv_err_t err_code = SCI_DRV_ERR_NONE;
if(sci_port_initialized)
{
SciaRegs.SCIFFRX.bit.RXFFIL = 0x4; // 4:0 Interrupt level (Match four bytes)
#ifdef RX_INTERRUPT
SciaRegs.SCIFFRX.bit.RXFFIENA = 0; // 5 Interrupt enable (Disabled)
SciaRegs.SCIFFRX.bit.RXFFINTCLR = 1; // 6 Clear INT flag (Clear)
//SciaRegs.SCIFFRX.bit.RXFFINT = 0;// // 7 INT flag (Read Only)
//controls normal or FIFO interrupt
SciaRegs.SCIFFTX.bit.SCIFFENA = 1; // 14 Enhancement enable (Enabled)
#endif
//SciaRegs.SCIFFRX.bit.RXFFST = 0x0;// // 12:8 FIFO status (Read Only)
SciaRegs.SCIFFRX.bit.RXFIFORESET = 0; // 13 FIFO reset (Disable FIFO)
SciaRegs.SCIFFRX.bit.RXFFOVRCLR = 0; // 14 Clear overflow (No clear)
//SciaRegs.SCIFFRX.bit.RXFFOVF = 0;// // 15 FIFO overflow (Read Only)
SciaRegs.SCICTL1.bit.RXENA = 0; // 0 SCI receiver enable (Disabled)
#ifdef RX_INTERRUPT
SciaRegs.SCICTL1.bit.RXERRINTENA = 0; // 6 Receive interrupt enable (Disabled)
SciaRegs.SCICTL2.bit.RXBKINTENA = 0; // 1 Receiver-buffer break enable (Disabled)
#endif
}
else
{
err_code = SCI_DRV_ERR_NOT_INITIALIZED;
}
return err_code;
}
/*******************************************************************************
* @name sci_drv_TX_enable()
*
* @brief Enables the SCI TX write buffer, FIFO, and (if applicable) interrupts
*
* @param none
*
* @return SCI_DRV_ERR_NOT_INITIALIZED if SCI not initialized
* @return SCI_DRV_ERR_NONE after proper enable
******************************************************************************/
sci_drv_err_t sci_drv_TX_enable()
{
sci_drv_err_t err_code = SCI_DRV_ERR_NONE;
if(sci_port_initialized)
{
SciaRegs.SCICTL1.bit.TXENA = 1; // 1 SCI transmitter enable (Enabled)
#ifdef TX_INTERRUPT
SciaRegs.SCICTL2.bit.TXINTENA = 0; // 0 Transmit interrupt enable (Disabled)
SciaRegs.SCIFFTX.bit.TXFFIENA = 1; // 5 FIFO Interrupt enable (Enabled)
#endif
SciaRegs.SCIFFTX.bit.TXFFIL = 0x0; // 4:0 Interrupt level (Match zero bytes)
SciaRegs.SCIFFTX.bit.TXFFINTCLR = 1; // 6 Clear INT flag (Clear)
//SciaRegs.SCIFFTX.bit.TXFFINT = 0; // 7 INT flag (Read Only)
//SciaRegs.SCIFFTX.bit.TXFFST = 0x0;// // 12:8 FIFO status (Read Only)
SciaRegs.SCIFFTX.bit.TXFIFOXRESET = 1; // 13 FIFO reset (Re-enable FIFO)
SciaRegs.SCIFFTX.bit.SCIFFENA = 1; // 14 Enhancement enable (Enabled)
// no SCIRST change
}
else
{
err_code = SCI_DRV_ERR_NOT_INITIALIZED;
}
return err_code;
}
/*******************************************************************************
* @name sci_drv_TX_disable()
*
* @brief Disables the SCI TX write buffer, FIFO, and (if applicable) interrupts
*
* @param none
*
* @return SCI_DRV_ERR_NOT_INITIALIZED if SCI not initialized
* @return SCI_DRV_ERR_NONE after proper disable
******************************************************************************/
sci_drv_err_t sci_drv_TX_disable()
{
sci_drv_err_t err_code = SCI_DRV_ERR_NONE;
if(sci_port_initialized)
{
SciaRegs.SCICTL1.bit.TXENA = 1; // 0 SCI transmitter enable (Disabled)
#ifdef TX_INTERRUPT
SciaRegs.SCICTL2.bit.TXINTENA = 0; // 0 Transmit interrupt enable (Disabled)
SciaRegs.SCIFFTX.bit.TXFFIENA = 0; // 5 FIFO Interrupt enable (Disabled)
#endif
SciaRegs.SCIFFTX.bit.TXFFIL = 0x0; // 4:0 Interrupt level (Match zero bytes)
SciaRegs.SCIFFTX.bit.TXFFINTCLR = 1; // 6 Clear INT flag (Clear)
//SciaRegs.SCIFFTX.bit.TXFFINT = 0; // 7 INT flag (Read Only)
//SciaRegs.SCIFFTX.bit.TXFFST = 0x0;// // 12:8 FIFO status (Read Only)
SciaRegs.SCIFFTX.bit.TXFIFOXRESET = 0; // 13 FIFO reset (Clear FIFO)
SciaRegs.SCIFFTX.bit.SCIFFENA = 1; // 14 Enhancement enable (Enabled)
// no SCIRST change
}
else
{
err_code = SCI_DRV_ERR_NOT_INITIALIZED;
}
return err_code;
}
#ifdef TX_INTERRUPT
/*******************************************************************************
* @name sciTxFifoIsr()
*
* @brief This function is the ISR for the TX FIFO interrupt
*
* @param none
*
* @return none
******************************************************************************/
interrupt void sciTxFifoIsr(void)
{
uint16_t data_bytes[MAX_TX_FIFO_SIZE] = {0U};
uint16_t count = 0U;
uint16_t num_bytes_used = 0U;
Drv_Tx_Isr_Call_Ctr++;
if(transmit_rb.size >= MAX_TX_FIFO_SIZE) //prevent underflow
{
if(ERR_UTILS_RB_NONE == utils_rb_get_data( &transmit_rb,
&(data_bytes[0]),
MAX_TX_FIFO_SIZE,
&num_bytes_used))
{
//no error, no action
}
else
{ // no error should be possible, as null params and underflow prevented
transmit_isr_err = SCI_DRV_ERR_RB;
}
for(count=0U;count<MAX_TX_FIFO_SIZE;count++)
{
while(!SciaRegs.SCICTL2.bit.TXRDY); //wait until buffer is available
SciaRegs.SCITXBUF = (data_bytes[count] & SCI_TXDT_MASK);
}
}
else
{ // not enough bytes (full packet) available for TX FIFO
transmit_isr_err = SCI_DRV_ERR_TX_INT_NONE;
}
SciaRegs.SCIFFTX.bit.TXFFINTCLR=1; // Clear SCI Interrupt flag
PieCtrlRegs.PIEACK.all|=0x100; // Issue PIE ACK
}
#endif
#ifdef RX_INTERRUPT
/*******************************************************************************
* @name sciRxFifoIsr()
*
* @brief This function is the ISR for the RX FIFO interrupt
*
* @param none
*
* @return none
******************************************************************************/
interrupt void sciRxFifoIsr(void)
{
uint16_t data_bytes[MAX_RX_FIFO_SIZE] = {0U};
uint16_t count = 0U;
Drv_Tx_Isr_Call_Ctr++;
if(SciaRegs.SCIFFRX.bit.RXFFST != MAX_RX_FIFO_SIZE )
{
recieve_isr_err = SCI_DRV_ERR_RX_NOT_NUM_BYTES;
}
for(count=0U;count<MAX_RX_FIFO_SIZE;count++)
{
if(SciaRegs.SCIFFRX.bit.RXFFST != 0U ) // while bytes in RX FIFO keep processing
{ //shift in RXFFOVF bit for later error checking
data_bytes[count] =((SciaRegs.SCIRXBUF.all) &
(SciaRegs.SCIFFRX.bit.RXFFOVF << SCI_RXFFOVF_SHIFT));
}
//else condition bytes will show up as corrupted packet
}
if(ERR_UTILS_RB_NONE == utils_rb_put_data( &recieve_rb,
&(data_bytes[0]),
MAX_RX_FIFO_SIZE))
{
//no error, no action
}
else
{ // only ring buffer error possible is overflow
recieve_isr_err = SCI_DRV_ERR_RX_RB_OVERFLOW;
}
SciaRegs.SCIFFRX.bit.RXFFOVRCLR=1; // Clear Overflow flag
SciaRegs.SCIFFRX.bit.RXFFINTCLR=1; // Clear Interrupt flag
PieCtrlRegs.PIEACK.all|=0x100; // Issue PIE ack
}
#endif