Hi,
I'm working on TMS320F28035 Conrolcard. I'm using SCI pher. in Simple Tx/Rx mode. I have to use interrupts due to our OS structure.
I attached two codes below. One is modified example code that works as expected. The other one is my SCI device driver code.
In my code, Tx interrupts never occurs. Therefore, only first byte can be transmitted.
//************************************************************************* // Pavo Elektronik Tasarim Uretim Ticaret A.S. //************************************************************************* // Bu program Pavo A.S. tarafindan 2012 senesinde yazilmistir. // Tum Telif Haklari Pavo A.S.'ye aittir. //************************************************************************* // Program Modul Adi : SER // Dosya Adi : ddser.c // Versiyon : v1.0 //************************************************************************* // Designed by : Zeynel Abidin Kiremitci // Changes : //************************************************************************* #define _DECL_DDSER_C_ /* include hardware depended headers */ #include "DSP2803x_Cla_typedefs.h" // DSP2803x CLA Type definitions #include "DSP2803x_Device.h" // DSP2803x Headerfile Include File #include "DSP2803x_Examples.h" // DSP2803x Examples Include File /* PAVOS depended headers*/ #include "../../common.h" // Update here! #include "../../tools.h" // Update here! #include "../../os/os_hal.h" #include "string.h" #include "ddser_e.h" #include "ddser_i.h" /* Declarations */ void pDdSerIoInit( void ); void pDdSerWrite( u16 TxLength, u8 *TxBuffer ); interrupt void pDdSerGeneralTransmit(void); interrupt void pDdSerGeneralReceive(void); /* External variables / functions */ //************************************************************************* // Function : pDdSerInit // Arguments : - // Returns : - // Description : initialize High Res. PWM device driver //************************************************************************* void pDdSerInit( void ) { pDdSerIoInit(); mDisableInterrupts; mWrAccessReg; // Interrupt Services PieVectTable.SCIRXINTA = &pDdSerGeneralReceive; PieVectTable.SCITXINTA = &pDdSerGeneralTransmit; mWrLockReg; memset(&IcBuff[0], 0, sMaxIcDataBuffLen*sizeof(u8)); memset(&OgBuff[0], 0, sMaxOgDataBuffLen*sizeof(u8)); OgWrIndex = OgRdIndex = 0; IcWrIndex = IcRdIndex = 0; // SCI Communication Control Register (SCICCR) SciaRegs.SCICCR.bit.STOPBITS = 0; // One stop bits SciaRegs.SCICCR.bit.PARITY = 0; // Odd Parity if parity is enabled SciaRegs.SCICCR.bit.PARITYENA = 0; // Parity disabled! SciaRegs.SCICCR.bit.LOOPBKENA = 0; // Loopback disabled SciaRegs.SCICCR.bit.ADDRIDLE_MODE = 0; // Idle-line mode: One microproccessor SciaRegs.SCICCR.bit.SCICHAR = 7; // Char Lenght: 8 // SCI Control Register 1 (SCICTL1) SciaRegs.SCICTL1.bit.RXERRINTENA = 1; // Rx Error Interrupt disabled SciaRegs.SCICTL1.bit.SWRESET = 0; // Sw Reset SCI -> RESET SciaRegs.SCICTL1.bit.SLEEP = 0; // Sleep mode disabled SciaRegs.SCICTL1.bit.TXENA = 1; // Transmit enabled SciaRegs.SCICTL1.bit.RXENA = 1; // Reception enabled // SCI Baud-Select Registers (SCIHBAUD, SCILBAUD) SciaRegs.SCIHBAUD = ( (mBaudRate(38400) >> 8) & 0x00FF ); SciaRegs.SCILBAUD = ( mBaudRate(38400) & 0x00FF ); // SCI Control Register 2 (SCICTL2) SciaRegs.SCICTL2.bit.TXINTENA = 0; // Disable TXRDY interrupt SciaRegs.SCICTL2.bit.RXBKINTENA = 1; // Enable RXRDY/BRKDT interrupt // SCI Receiver Status Register (SCIRXST) // SciaRegs.SCIRXST.all = 0; // Clear the RX status flags -> Read-Only // SCI Priority Control Register (SCIPRI) SciaRegs.SCIPRI.bit.FREE = 1; // SCI Free Running // FIFO DISABLED! // SCI FIFO Transmit (SCIFFTX) // SciaRegs.SCIFFTX.bit.SCIRST = 1; // SCI Reset -> NOT RESET // SciaRegs.SCIFFTX.bit.TXFIFOXRESET = 0; // TX FIFO Reset -> RESET // SciaRegs.SCIFFTX.bit.TXFFINTCLR = 1; // Clear Interrupt flag // SciaRegs.SCIFFTX.bit.SCIFFENA = 1; // SCI FIFO enhancements are enabled // SciaRegs.SCIFFTX.bit.TXFFIENA = 1; // TX FIFO interrupt is enabled. // SciaRegs.SCIFFTX.bit.TXFFIL = 1; // TX FIFO Interrupt level is 1/Simple Rx-Tx // SCI FIFO Receive (SCIFFRX) // SciaRegs.SCIFFRX.bit.RXFIFORESET = 0; // RX FIFO Reset -> RESET // SciaRegs.SCIFFRX.bit.RXFFOVRCLR = 1; // Clear Overflow flag // SciaRegs.SCIFFRX.bit.RXFFINTCLR = 1; // Clear Interrupt flag // SciaRegs.SCIFFRX.bit.RXFFIENA = 1; // RX FIFO interrupt is enabled. // SciaRegs.SCIFFRX.bit.RXFFIL = 1; // RX FIFO Interrupt level is 1/Simple Rx-Tx // SCI FIFO Control (SCIFFCT) // SciaRegs.SCIFFCT.all = 0x0000; // Auto-baud detect disabled -> Read-Only // Auto-baud alignment disabled // None delay // SciaRegs.SCIFFTX.bit.SCIRST = 1; // SCI Reset: Tx and Rx can be resumed // SciaRegs.SCIFFTX.bit.TXFIFOXRESET=1; // Re-enabling TX FIFO // SciaRegs.SCIFFRX.bit.RXFIFORESET=1; // Re-enabling RX FIF SciaRegs.SCICTL1.bit.SWRESET = 1; // Re-enabling SCI // Enable interrupts required for this example // PieCtrlRegs.PIECTRL.bit.ENPIE = 1; // Enable the PIE block -> Pie block has already enabled at os_hal.c PieCtrlRegs.PIEIER9.bit.INTx1 = 1; // Connect to Tx Int to PIE PieCtrlRegs.PIEIER9.bit.INTx2 = 1; // Connect to Rx Int to PIE IFR &=(~( M_INT9 )); // Clearing INT9 Flag IER |= M_INT9; // Enabling interrupts mEnableInterrupts; } //************************************************************************* // Function : pDdSerIoInit // Arguments : - // Returns : - // Description : Configure SER pins using AIO registers //************************************************************************* void pDdSerIoInit( void ) { mWrAccessReg; // Enabling Pull-ups //GpioCtrlRegs.GPAPUD.bit.GPIO28 = 0; // Enable pull-up for GPIO28 (SCIRXDA) GpioCtrlRegs.GPAPUD.bit.GPIO29 = 0; // Enable pull-up for GPIO29 (SCITXDA) // Asynch input selection GpioCtrlRegs.GPAQSEL2.bit.GPIO28 = 3; // Asynch input GPIO28 (SCIRXDA) // Operation Selection GpioCtrlRegs.GPAMUX2.bit.GPIO28 = 1; // Configure GPIO28 for SCIRXDA operation GpioCtrlRegs.GPAMUX2.bit.GPIO29 = 1; // Configure GPIO29 for SCITXDA operation // Direction Selection GpioCtrlRegs.GPADIR.bit.GPIO28 = 0; // 1=OUTput, 0=INput GpioCtrlRegs.GPADIR.bit.GPIO29 = 1; // 1=OUTput, 0=INput mWrLockReg; } //************************************************************************* // Function : pDdSerOneByteWr // Parameters : u8 Data // Data to be transmitted // Returns : none // Description : Write a byte to a serial channel //************************************************************************* void pDdSerOneByteWr( u8 data ) { pDdSerWrite( 1, &data ); } //************************************************************************* // Function : pDdSerRead // Parameters : u16 RxLength // Length of data to be read // u8 *Data // Memory address where data will be stored // Returns : u8 // Size of data read // Description : Read data buffer of the selected channel //************************************************************************* u16 pDdSerRead(u16 RxLength, u8 *Data) { u16 datasize; u16 returnval; u16 wridx; u16 *rdidx; wridx = IcWrIndex; rdidx =&IcRdIndex; datasize = fRingBufferDataSize( (u32)(*rdidx), wridx, sMaxIcDataBuffLen); returnval = min(datasize, RxLength); if( returnval > 0 ) { if( ( sMaxIcDataBuffLen - *rdidx ) > returnval ) { memcpy( Data, &IcBuff[*rdidx], returnval ); *rdidx += returnval; } else { u8 dataleftinbuffer; dataleftinbuffer = ( sMaxIcDataBuffLen - *rdidx ); memcpy( Data, &IcBuff[*rdidx], dataleftinbuffer ); memcpy( &Data[dataleftinbuffer], &IcBuff[0], ( returnval - dataleftinbuffer ) ); *rdidx = ( returnval - dataleftinbuffer ); } } return returnval; } //************************************************************************* // Function : pDdSerWrite // Parameters : u16 TxLength // Length of data to be transmitted // u8 *TxBuffer // Data to be transmitted // Returns : none // Description : Start transmitting data through the selected channel //************************************************************************* void pDdSerWrite( u16 TxLength, u8 *TxBuffer ) { u16 *wridx; u16 rdidx; u16 AvailBuff; //mDisableInterrupts; wridx = &OgWrIndex; rdidx = OgRdIndex; AvailBuff = fRingBufferFreeSize( rdidx, \ *wridx, \ sMaxOgDataBuffLen); if( AvailBuff > TxLength ) { if( rdidx > *wridx ) { memcpy( &OgBuff[*wridx], TxBuffer, TxLength ); *wridx += TxLength; } else { if( ( sMaxOgDataBuffLen - *wridx ) > TxLength ) { memcpy( &OgBuff[ *wridx ], TxBuffer, TxLength ); *wridx += TxLength ; } else { memcpy( &OgBuff[ *wridx ], TxBuffer, sMaxOgDataBuffLen - *wridx ); memcpy( &OgBuff[0], &TxBuffer[sMaxOgDataBuffLen - *wridx], ( TxLength - ( sMaxOgDataBuffLen - *wridx ) ) ); *wridx = TxLength - ( sMaxOgDataBuffLen - *wridx ); } } // TODO : Check TX Interrupt status ->OK if( !( SciaRegs.SCICTL2.bit.TXINTENA == 1 )) // if interrupt disable ?? { // TODO : Add the transmit buffer address here. ->OK SciaRegs.SCITXBUF = OgBuff[ OgRdIndex]; OgRdIndex++; if( OgRdIndex >= sMaxOgDataBuffLen ) { OgRdIndex = 0; } SciaRegs.SCICTL2.bit.TXINTENA = 1; PieCtrlRegs.PIEIFR9.bit.INTx1 = 0; // Clear Tx Flag } } else { } //mEnableInterrupts; } /********* Serial Communication Rx/Tx Interrupt Service Routines *********/ //************************************************************************* // Function : pDdSerGeneralReceive // Parameters : none // Returns : - // Description : General receive interrupt subroutine for the channel //************************************************************************* interrupt void pDdSerGeneralTransmit( void ) { GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1; // if(SciaRegs.SCICTL2.bit.TXRDY == 1) { if ( OgWrIndex != OgRdIndex ) // There is data in buffer to transmit { SciaRegs.SCITXBUF = OgBuff[OgRdIndex]; OgRdIndex++; if( OgRdIndex >= sMaxOgDataBuffLen ) { OgRdIndex = 0; } } else // There is no data in buffer to transmit or // Buffer is full. { OgWrIndex = OgRdIndex = 0; //TODO : interrupt disable ->OK SciaRegs.SCICTL2.bit.TXINTENA = 0; } PieCtrlRegs.PIEACK.bit.ACK9 = 1; // Issue PIE ACK } } interrupt void pDdSerGeneralReceive( void ) { if( SciaRegs.SCIRXST.bit.RXRDY == 1 ) { GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1; //if ( SerParser == NULL ) { // If an external parser does not exist store it in the buffer if ( fRingBufferFreeSize( IcRdIndex, IcWrIndex, sMaxOgDataBuffLen) > 0 ) { // TODO : Add the receive buffer address here. ->OK // IcBuff[IcWrIndex] = u1rb; IcBuff[IcWrIndex] = ( SciaRegs.SCIRXBUF.all & 0x00FF ); IcWrIndex++; if( IcWrIndex >= sMaxOgDataBuffLen ) { IcWrIndex = 0; } } else { // Buffer FULL } } //else { // Call external parser // TODO : Add the receive buffer address here. // SerParser( u1rb & 0xFF ); // mask the error flags before sending } PieCtrlRegs.PIEIFR9.bit.INTx2 = 0; // Clear Rx Flag PieCtrlRegs.PIEACK.bit.ACK9 = 1; // Issue PIE ACK } } /*EOF*/
//########################################################################### // //! \addtogroup f2803x_example_list //! <h1>SCI Digital Loop Back with Interrupts(scia_loopback_interrupts)</h1> //! //! This program uses the internal loop back test mode of the peripheral. //! Other then boot mode pin configuration, no other hardware configuration //! is required. Both interrupts and the SCI FIFOs are used. //! //! A stream of data is sent and then compared to the received stream. //! The SCI-A sent data looks like this: \n //! 00 01 \n //! 01 02 \n //! 02 03 \n //! .... \n //! FE FF \n //! FF 00 \n //! etc.. \n //! The pattern is repeated forever. //! //! \b Watch \b Variables \n //! - \b sdataA , Data being sent //! - \b rdataA , Data received //! - \b rdata_pointA ,Keep track of where we are in the datastream. //! This is used to check the incoming data // //########################################################################### // $TI Release: F2803x C/C++ Header Files and Peripheral Examples V127 $ // $Release Date: March 30, 2013 $ //########################################################################### #include "DSP28x_Project.h" // Device Headerfile and Examples Include File #include "string.h" #define sCpuFreq (60000000) #define sLowSpdClk (sCpuFreq / 4) #define mBaudRate(a) (Uint32)((sLowSpdClk/(a*8))-1) // Prototype statements for functions found within this file. interrupt void sciaTxFifoIsr(void); interrupt void sciaRxFifoIsr(void); void scia_fifo_init(void); void oneByteWrite(Uint8 * data); // Global variables Uint8 rxData,txData,gTxWrIdx,gTxRdIdx; Uint32 gCounter = 0; void main(void) { // Step 1. Initialize System Control: // PLL, WatchDog, enable Peripheral Clocks // This example function is found in the DSP2803x_SysCtrl.c file. InitSysCtrl(); // Step 2. Initalize GPIO: // This example function is found in the DSP2803x_Gpio.c file and // illustrates how to set the GPIO to it's default state. // InitGpio(); // Setup only the GP I/O only for SCI-A and SCI-B functionality // This function is found in DSP2803x_Sci.c InitSciGpio(); // Step 3. Clear all interrupts and initialize PIE vector table: // Disable CPU interrupts DINT; // Initialize PIE control registers to their default state. // The default state is all PIE interrupts disabled and flags // are cleared. // This function is found in the DSP2803x_PieCtrl.c file. InitPieCtrl(); // Disable CPU interrupts and clear all CPU interrupt flags: IER = 0x0000; IFR = 0x0000; // Initialize the PIE vector table with pointers to the shell Interrupt // Service Routines (ISR). // This will populate the entire table, even if the interrupt // is not used in this example. This is useful for debug purposes. // The shell ISR routines are found in DSP2803x_DefaultIsr.c. // This function is found in DSP2803x_PieVect.c. InitPieVectTable(); // Interrupts that are used in this example are re-mapped to // ISR functions found within this file. EALLOW; // This is needed to write to EALLOW protected registers PieVectTable.SCIRXINTA = &sciaRxFifoIsr; PieVectTable.SCITXINTA = &sciaTxFifoIsr; EDIS; // This is needed to disable write to EALLOW protected registers // Step 4. Initialize all the Device Peripherals: // This function is found in DSP2803x_InitPeripherals.c // InitPeripherals(); // Not required for this example scia_fifo_init(); // Init SCI-A // Enable interrupts required for this example PieCtrlRegs.PIECTRL.bit.ENPIE = 1; // Enable the PIE block PieCtrlRegs.PIEIER9.bit.INTx1=1; // PIE Group 9, INT1 PieCtrlRegs.PIEIER9.bit.INTx2=1; // PIE Group 9, INT2 IER = 0x100; // Enable CPU INT EINT; rxData = txData = 0; gTxWrIdx = gTxRdIdx = 0; // Step 6. IDLE loop. Just sit and loop forever (optional): while(1) { if( ( rxData == 0xAA ) ) { oneByteWrite(&rxData); gCounter = 0; rxData = 0; } } } void oneByteWrite(Uint8 *data) { memcpy(&txData, &data, sizeof(Uint8)); // Send data SciaRegs.SCITXBUF = *data; SciaRegs.SCICTL2.bit.TXINTENA = 1; // Enable TXRDY interrupt // PieCtrlRegs.PIEIER9.bit.INTx1 = 1; // PIE Group 9, INT1 } interrupt void sciaTxFifoIsr(void) { if(SciaRegs.SCICTL2.bit.TXRDY == 1) { GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1; SciaRegs.SCICTL2.bit.TXINTENA = 0; // Enable TXRDY interrupt // PieCtrlRegs.PIEIER9.bit.INTx1 = 0; // PIE Group 9, INT1 PieCtrlRegs.PIEACK.bit.ACK9 = 1; // Issue PIE ACK } } interrupt void sciaRxFifoIsr(void) { if( SciaRegs.SCIRXST.bit.RXRDY == 1 ) { GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1; rxData = ( SciaRegs.SCIRXBUF.all & 0x00FF ); // Read data PieCtrlRegs.PIEACK.bit.ACK9 = 1; // Issue PIE ACK } } void scia_fifo_init() { // SCI Communication Control Register (SCICCR) SciaRegs.SCICCR.bit.STOPBITS = 0; // One stop bits SciaRegs.SCICCR.bit.PARITY = 0; // Odd Parity if parity is enabled SciaRegs.SCICCR.bit.PARITYENA = 0; // Parity disabled! SciaRegs.SCICCR.bit.LOOPBKENA = 0; // Loopback disabled SciaRegs.SCICCR.bit.ADDRIDLE_MODE = 0; // Idle-line mode: One microproccessor SciaRegs.SCICCR.bit.SCICHAR = 7; // Char Lenght: 8 // SCI Control Register 1 (SCICTL1) SciaRegs.SCICTL1.bit.RXERRINTENA = 1; // Rx Error Interrupt disabled SciaRegs.SCICTL1.bit.SWRESET = 0; // Sw Reset SCI -> RESET SciaRegs.SCICTL1.bit.SLEEP = 0; // Sleep mode disabled SciaRegs.SCICTL1.bit.TXENA = 1; // Transmit enabled SciaRegs.SCICTL1.bit.RXENA = 1; // Reception enabled // SCI Baud-Select Registers (SCIHBAUD, SCILBAUD) SciaRegs.SCIHBAUD = ( (mBaudRate(38400) >> 8) & 0x00FF ); SciaRegs.SCILBAUD = ( mBaudRate(38400) & 0x00FF ); // SCI Control Register 2 (SCICTL2) SciaRegs.SCICTL2.bit.TXINTENA = 0; // Disable TXRDY interrupt SciaRegs.SCICTL2.bit.RXBKINTENA = 1; // Enable RXRDY/BRKDT interrupt // SCI Receiver Status Register (SCIRXST) // SciaRegs.SCIRXST.all = 0; // Clear the RX status flags -> Read-Only // FIFO DISABLED! // SCI FIFO Transmit (SCIFFTX) // SciaRegs.SCIFFTX.bit.SCIRST = 1; // SCI Reset -> NOT RESET // SciaRegs.SCIFFTX.bit.TXFIFOXRESET = 0; // TX FIFO Reset -> RESET // SciaRegs.SCIFFTX.bit.TXFFINTCLR = 1; // Clear Interrupt flag // SciaRegs.SCIFFTX.bit.SCIFFENA = 1; // SCI FIFO enhancements are enabled // SciaRegs.SCIFFTX.bit.TXFFIENA = 1; // TX FIFO interrupt is enabled. // SciaRegs.SCIFFTX.bit.TXFFIL = 1; // TX FIFO Interrupt level is 1/Simple Rx-Tx // SCI FIFO Receive (SCIFFRX) // SciaRegs.SCIFFRX.bit.RXFIFORESET = 0; // RX FIFO Reset -> RESET // SciaRegs.SCIFFRX.bit.RXFFOVRCLR = 1; // Clear Overflow flag // SciaRegs.SCIFFRX.bit.RXFFINTCLR = 1; // Clear Interrupt flag // SciaRegs.SCIFFRX.bit.RXFFIENA = 1; // RX FIFO interrupt is enabled. // SciaRegs.SCIFFRX.bit.RXFFIL = 1; // RX FIFO Interrupt level is 1/Simple Rx-Tx // SCI FIFO Control (SCIFFCT) // SciaRegs.SCIFFCT.all = 0x0000; // Auto-baud detect disabled -> Read-Only // Auto-baud alignment disabled // None delay // SCI Priority Control Register (SCIPRI) SciaRegs.SCIPRI.bit.FREE = 1; // SCI Free Running SciaRegs.SCICTL1.bit.SWRESET = 1; // Re-enabling SCI // SciaRegs.SCIFFTX.bit.SCIRST = 1; // SCI Reset: Tx and Rx can be resumed // SciaRegs.SCIFFTX.bit.TXFIFOXRESET=1; // Re-enabling TX FIFO // SciaRegs.SCIFFRX.bit.RXFIFORESET=1; // Re-enabling RX FIF } /*EOF*/
Best regards,
Zeynel Abidin Kiremitci
Electronics Design Engineer