Hello everyone i am working on an application for DSK6713 that requires serial communication.for this i have purchase a daughter card by link research they shipped demo programs with them.As far as code is concern it works fine for serial transmission but have problem in serial reception.The problem is as follow.
The code which i am going to share is loop-back which serially receive data from PC(Docklight application) and echos it back to pc.
1.When i send a string of 13 or less bytes it echo back correctly.
2.By increasing the number of bytes to transmit from pc it send first 10 or 13 bytes correct back to pc and garbage the other.
eg:
TX:A B C D E F G H I J O P
RX: A B C D E F G H I J O P
TX:1 2 3 4 5 6 7 8 9 1 0 A B C D E F G H I J O P
RX:1 2 3 4 5 6 7 8 9 1 0 A B ; < 8 @ ^ e i h g * | <NUL>
//////////////////////////////////////////////////////////////////////////////////CODE FOR LOOP BACK///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////SHIPPED WITH DAUGHTER CARD//////////////////////////////////////////////////////////////////////////////////////////////////
/************************************************************
*
* Copyright 2009 by Link Research. ALL RIGHTS RESERVED
* This software is provided for demonstration purposes only
* and is not guaranteed in any way as to its form or function.
* There are no restrictions for its use provided this disclaimer
* is included with all distributions of this source code.
*
************************************************************/
/* UART daughtercard demo software for the 6713 DSK */
#include "main6713.h"
#include <csl.h>
unsigned char buf[130]; // temporary data buffer
int len;
main ()
{
CE2_CONTROL = 0x03d00f21; // set up CE2 memory space access timing
DC_REG |= 0x08; // raise daughtercard reset signal
delay(8000L*250); // delay ~ 250 milliseconds
DC_REG &= ~0x08; // remove daughtercard reset signal
delay(8000L*250); // delay ~ 250 milliseconds
CSL_init(); // initialize the Chip Support Library
initialize_UART(1,DATA_RATE_19200); // initialize the uart channels
initialize_UART(2,DATA_RATE_19200); // initialize the uart channels
initialize_UART(3,DATA_RATE_19200); // initialize the uart channels
initialize_UART(4,DATA_RATE_19200); // initialize the uart channels
I2821.LR-232-Tech_Ref.pdfRQ_enable(DC_INTERRUPT_SOURCE); // enable external interrupt
// exit main() and fall into DSP/BIOS idle loop
} // end of main()
/* The following routine is executed every millisecond */
void main_loop(void)
{
if(len = UART_recv_count(1))
{
UART_recv_block (1, buf, len);
UART_send_block (1, buf, len);
}
if(len = UART_recv_count(2))
{
UART_recv_block (2, buf, len);
UART_send_block (2, buf, len);
}
if(len = UART_recv_count(3))
{
UART_recv_block (3, buf, len);
UART_send_block (3, buf, len);
}
if(len = UART_recv_count(4))
{
UART_recv_block (4, buf, len);
UART_send_block (4, buf, len);
}
}
/************************************************************
Below are the subroutines described in the documentation
************************************************************/
void initialize_UART (int chn, unsigned char divisor)
{
switch (chn)
{
case 1:
// channel 1
UART_LCR1 = 0x80; // Set "Divisor Latch Access Bit"
UART_DLL1 = divisor; // Lower 8 bits of divisor
UART_DLM1 = 0x00; // Upper 8 bits of divisor
UART_LCR1 = 0x00; // Clear DLAB bit in Line Control Register
UART_LCR1 = 0x03; // 8 data bits, 1 stop bit, no parity
UART_IER1 = 0x01; // Enable RX int.
UART_FCR1 = 0x09; // Enable FIFO
UART_MCR1 = 0x0b; // Take Interrupt signals out of 3-state
break;
case 2:
// channel 2
UART_LCR2 = 0x80; // Set "Divisor Latch Access Bit"
UART_DLL2 = divisor; // Lower 8 bits of divisor
UART_DLM2 = 0x00; // Upper 8 bits of divisor
UART_LCR2 = 0x00; // Clear DLAB bit in Line Control Register
UART_LCR2 = 0x03; // 8 data bits, 1 stop bit, no parity
UART_IER2 = 0x01; // Enable RX int.
UART_FCR2 = 0x09; // Enable FIFO
UART_MCR2 = 0x0b; // Take Interrupt signals out of 3-state
break;
case 3:
// channel 3
UART_LCR3 = 0x80; // Set "Divisor Latch Access Bit"
UART_DLL3 = divisor; // Lower 8 bits of divisor
UART_DLM3 = 0x00; // Upper 8 bits of divisor
UART_LCR3 = 0x00; // Clear DLAB bit in Line Control Register
UART_LCR3 = 0x03; // 8 data bits, 1 stop bit, no parity
UART_IER3 = 0x01; // Enable RX int.
UART_FCR3 = 0x09; // Enable FIFO
UART_MCR3 = 0x0b; // Take Interrupt signals out of 3-state
break;
case 4:
// channel 4
UART_LCR4 = 0x80; // Set "Divisor Latch Access Bit"
UART_DLL4 = divisor; // Lower 8 bits of divisor
UART_DLM4 = 0x00; // Upper 8 bits of divisor
UART_LCR4 = 0x00; // Clear DLAB bit in Line Control Register
UART_LCR4 = 0x03; // 8 data bits, 1 stop bit, no parity
UART_IER4 = 0x01; // Enable RX int.
UART_FCR4 = 0x09; // Enable FIFO
UART_MCR4 = 0x0b; // Take Interrupt signals out of 3-state
break;
}
}
/********************************************************
The following routine first checks if there is space
in the UART transmit buffer for one byte. If there is, it
places that single character (byte) into the buffer.
If there is no room in the transmit buffer,
the routine returns -1.
The actual sending of the byte to the UART will be
handled transparently by the interrupt routine when
the UART is free to accept the byte.
********************************************************/
int UART_send_byte (int chn, unsigned char byte)
{
switch (chn)
{
case 1:
if (uiUART_xmit_count1 >= XMIT_BUF_SIZE) return (-1);
ucUART_xmit_buffer1[uiUART_xmit_nextin1++]=byte;
if (uiUART_xmit_nextin1 >= XMIT_BUF_SIZE) uiUART_xmit_nextin1=0;
/* disable interrupts around the following 2 statements */
IRQ_disable(DC_INTERRUPT_SOURCE); // disable external interrupt
uiUART_xmit_count1++;
UART_IER1 = 0x03;
IRQ_enable(DC_INTERRUPT_SOURCE); // enable external interrupt
break;
case 2:
if (uiUART_xmit_count2 >= XMIT_BUF_SIZE) return (-1);
ucUART_xmit_buffer2[uiUART_xmit_nextin2++]=byte;
if (uiUART_xmit_nextin2 >= XMIT_BUF_SIZE) uiUART_xmit_nextin2=0;
/* disable interrupts around the following 2 statements */
IRQ_disable(DC_INTERRUPT_SOURCE); // disable external interrupt
uiUART_xmit_count2++;
UART_IER2 = 0x03;
IRQ_enable(DC_INTERRUPT_SOURCE); // enable external interrupt
break;
case 3:
if (uiUART_xmit_count3 >= XMIT_BUF_SIZE) return (-1);
ucUART_xmit_buffer3[uiUART_xmit_nextin3++]=byte;
if (uiUART_xmit_nextin3 >= XMIT_BUF_SIZE) uiUART_xmit_nextin3=0;
/* disable interrupts around the following 2 statements */
IRQ_disable(DC_INTERRUPT_SOURCE); // disable external interrupt
uiUART_xmit_count3++;
UART_IER3 = 0x03;
IRQ_enable(DC_INTERRUPT_SOURCE); // enable external interrupt
break;
case 4:
if (uiUART_xmit_count4 >= XMIT_BUF_SIZE) return (-1);
ucUART_xmit_buffer4[uiUART_xmit_nextin4++]=byte;
if (uiUART_xmit_nextin4 >= XMIT_BUF_SIZE) uiUART_xmit_nextin4=0;
/* disable interrupts around the following 2 statements */
IRQ_disable(DC_INTERRUPT_SOURCE); // disable external interrupt
uiUART_xmit_count4++;
UART_IER4 = 0x03;
IRQ_enable(DC_INTERRUPT_SOURCE); // enable external interrupt
break;
}
return (0);
}
/********************************************************
The following routine reads a single character (byte)
from the UART receive buffer. If the receive buffer is
empty, -1 is returned.
********************************************************/
int UART_recv_byte (int chn, unsigned char* byte)
{
switch (chn)
{
case 1:
if (uiUART_recv_count1 == 0) return (-1);
*byte = ucUART_recv_buffer1[uiUART_recv_nextout1++];
if (uiUART_recv_nextout1 >= RECV_BUF_SIZE) uiUART_recv_nextout1=0;
/* disable interrupts around the following statement */
IRQ_disable(DC_INTERRUPT_SOURCE); // disable external interrupt
uiUART_recv_count1--;
IRQ_enable(DC_INTERRUPT_SOURCE); // enable external interrupt
break;
case 2:
if (uiUART_recv_count2 == 0) return (-1);
*byte = ucUART_recv_buffer2[uiUART_recv_nextout2++];
if (uiUART_recv_nextout2 >= RECV_BUF_SIZE) uiUART_recv_nextout2=0;
/* disable interrupts around the following statement */
IRQ_disable(DC_INTERRUPT_SOURCE); // disable external interrupt
uiUART_recv_count2--;
IRQ_enable(DC_INTERRUPT_SOURCE); // enable external interrupt
break;
case 3:
if (uiUART_recv_count3 == 0) return (-1);
*byte = ucUART_recv_buffer3[uiUART_recv_nextout3++];
if (uiUART_recv_nextout3 >= RECV_BUF_SIZE) uiUART_recv_nextout3=0;
/* disable interrupts around the following statement */
IRQ_disable(DC_INTERRUPT_SOURCE); // disable external interrupt
uiUART_recv_count3--;
IRQ_enable(DC_INTERRUPT_SOURCE); // enable external interrupt
break;
case 4:
if (uiUART_recv_count4 == 0) return (-1);
*byte = ucUART_recv_buffer4[uiUART_recv_nextout4++];
if (uiUART_recv_nextout4 >= RECV_BUF_SIZE) uiUART_recv_nextout4=0;
/* disable interrupts around the following statement */
IRQ_disable(DC_INTERRUPT_SOURCE); // disable external interrupt
uiUART_recv_count4--;
IRQ_enable(DC_INTERRUPT_SOURCE); // enable external interrupt
break;
}
return (0);
}
/********************************************************
The following routine first checks if there is space
in the UART transmit buffer for 'length' characters.
If there is, it places the characters (bytes) into
the buffer. If there is not enough room in the
transmit buffer, the routine returns -1, and does
not place anything in the transmit buffer.
The actual sending of the bytes to the UART will be
handled transparently by the interrupt routine when
the UART is free to accept data.
********************************************************/
int UART_send_block (int chn, unsigned char* buf, unsigned int length)
{
unsigned int index;
switch (chn)
{
case 1:
if ((uiUART_xmit_count1+length-1) >= XMIT_BUF_SIZE) return (-1);
for (index=0; index<length; index++)
{
ucUART_xmit_buffer1[uiUART_xmit_nextin1++]=buf[index];
if (uiUART_xmit_nextin1 >= XMIT_BUF_SIZE) uiUART_xmit_nextin1=0;
}
/* disable interrupts around the following statement */
IRQ_disable(DC_INTERRUPT_SOURCE); // disable external interrupt
uiUART_xmit_count1 += length;
UART_IER1 = 0x03;
IRQ_enable(DC_INTERRUPT_SOURCE); // enable external interrupt
break;
case 2:
if ((uiUART_xmit_count2+length-1) >= XMIT_BUF_SIZE) return (-1);
for (index=0; index<length; index++)
{
ucUART_xmit_buffer2[uiUART_xmit_nextin2++]=buf[index];
if (uiUART_xmit_nextin2 >= XMIT_BUF_SIZE) uiUART_xmit_nextin2=0;
}
/* disable interrupts around the following statement */
IRQ_disable(DC_INTERRUPT_SOURCE); // disable external interrupt
uiUART_xmit_count2 += length;
UART_IER2 = 0x03;
IRQ_enable(DC_INTERRUPT_SOURCE); // enable external interrupt
break;
case 3:
if ((uiUART_xmit_count3+length-1) >= XMIT_BUF_SIZE) return (-1);
for (index=0; index<length; index++)
{
ucUART_xmit_buffer3[uiUART_xmit_nextin3++]=buf[index];
if (uiUART_xmit_nextin3 >= XMIT_BUF_SIZE) uiUART_xmit_nextin3=0;
}
/* disable interrupts around the following statement */
IRQ_disable(DC_INTERRUPT_SOURCE); // disable external interrupt
uiUART_xmit_count3 += length;
UART_IER3 = 0x03;
IRQ_enable(DC_INTERRUPT_SOURCE); // enable external interrupt
break;
case 4:
if ((uiUART_xmit_count4+length-1) >= XMIT_BUF_SIZE) return (-1);
for (index=0; index<length; index++)
{
ucUART_xmit_buffer4[uiUART_xmit_nextin4++]=buf[index];
if (uiUART_xmit_nextin4 >= XMIT_BUF_SIZE) uiUART_xmit_nextin4=0;
}
/* disable interrupts around the following statement */
IRQ_disable(DC_INTERRUPT_SOURCE); // disable external interrupt
uiUART_xmit_count4 += length;
UART_IER4 = 0x03;
IRQ_enable(DC_INTERRUPT_SOURCE); // enable external interrupt
break;
}
return (0);
}
/********************************************************
The following routine first checks to see if there are
at least 'length' bytes in the receive buffer.
If there are, it reads the characters (bytes) into a
memory buffer pointed to by the passed argument: *buf.
If there are not enough characters in the receive buffer
to satisy the requested block length,
the routine returns -1.
********************************************************/
int UART_recv_block (int chn, unsigned char* buf, unsigned int length)
{
unsigned int index;
switch (chn)
{
case 1:
if (uiUART_recv_count1 < length) return (-1);
for (index=0; index<length; index++)
{
buf[index] = ucUART_recv_buffer1[uiUART_recv_nextout1++];
if (uiUART_recv_nextout1 >= RECV_BUF_SIZE) uiUART_recv_nextout1=0;
}
/* disable interrupts around the following statement */
IRQ_disable(DC_INTERRUPT_SOURCE); // disable external interrupt
uiUART_recv_count1 -= length;
IRQ_enable(DC_INTERRUPT_SOURCE); // enable external interrupt
break;
case 2:
if (uiUART_recv_count2 < length) return (-1);
for (index=0; index<length; index++)
{
buf[index] = ucUART_recv_buffer2[uiUART_recv_nextout2++];
if (uiUART_recv_nextout2 >= RECV_BUF_SIZE) uiUART_recv_nextout2=0;
}
/* disable interrupts around the following statement */
IRQ_disable(DC_INTERRUPT_SOURCE); // disable external interrupt
uiUART_recv_count2 -= length;
IRQ_enable(DC_INTERRUPT_SOURCE); // enable external interrupt
break;
case 3:
if (uiUART_recv_count3 < length) return (-1);
for (index=0; index<length; index++)
{
buf[index] = ucUART_recv_buffer3[uiUART_recv_nextout3++];
if (uiUART_recv_nextout3 >= RECV_BUF_SIZE) uiUART_recv_nextout3=0;
}
/* disable interrupts around the following statement */
IRQ_disable(DC_INTERRUPT_SOURCE); // disable external interrupt
uiUART_recv_count3 -= length;
IRQ_enable(DC_INTERRUPT_SOURCE); // enable external interrupt
break;
case 4:
if (uiUART_recv_count4 < length) return (-1);
for (index=0; index<length; index++)
{
buf[index] = ucUART_recv_buffer4[uiUART_recv_nextout4++];
if (uiUART_recv_nextout4 >= RECV_BUF_SIZE) uiUART_recv_nextout4=0;
}
/* disable interrupts around the following statement */
IRQ_disable(DC_INTERRUPT_SOURCE); // disable external interrupt
uiUART_recv_count4 -= length;
IRQ_enable(DC_INTERRUPT_SOURCE); // enable external interrupt
break;
}
return (0);
}
/********************************************************
The following routine returns the number of characters
in the receive memory buffer. Note that the interrupt
service routine (ISR) could potentially add a character to
the receive buffer immediately after this function is
called. This will not harm the integrity of the data.
Any characters placed in the receive buffer by the
ISR in this way will be picked up the next time this
function is called.
********************************************************/
unsigned int UART_recv_count(int chn)
{
switch (chn)
{
case 1:
return (uiUART_recv_count1);
case 2:
return (uiUART_recv_count2);
case 3:
return (uiUART_recv_count3);
case 4:
return (uiUART_recv_count4);
default:
return (0);
}
}
/********************************************************
The following routine returns the number of characters
in the transmit memory buffer. Note that the interrupt
service routine (ISR) could potentially remove a character from
the receive buffer immediately after this function is
called. This will not harm the integrity of the data.
********************************************************/
unsigned int UART_xmit_count(int chn)
{
switch (chn)
{
case 1:
return (uiUART_xmit_count1);
case 2:
return (uiUART_xmit_count2);
case 3:
return (uiUART_xmit_count3);
case 4:
return (uiUART_xmit_count4);
default:
return (0);
}
}
/*****************************************
The following interrupt routine is triggered by a rising edge on
External Interrupt #4. This ISR handles the UART's transmit data and
receive data interrupts for all UART channels.
*****************************************/
void ext_int(void)
{
unsigned char temp;
volatile unsigned char trash;
// If the uart is ready to accept a char, AND there is something
// to send, send it, and adjust the pointer and count
while(1)
{ // service channel 1 transmitter
temp = UART_LSR1;
if (((temp & 0x20) == 0x20) && uiUART_xmit_count1)
{
if(uiUART_xmit_count1 == 1) UART_IER1 = 0x01; // if last byte, disable tx int
UART_THR1 = ucUART_xmit_buffer1[uiUART_xmit_nextout1++];
if(uiUART_xmit_nextout1 >= XMIT_BUF_SIZE) uiUART_xmit_nextout1 = 0;
uiUART_xmit_count1--;
}
// service channel 2 transmitter
temp = UART_LSR2;
if (((temp & 0x20) == 0x20) && uiUART_xmit_count2)
{
if(uiUART_xmit_count2 == 1) UART_IER2 = 0x01; // if last byte, disable tx int
UART_THR2 = ucUART_xmit_buffer2[uiUART_xmit_nextout2++];
if(uiUART_xmit_nextout2 >= XMIT_BUF_SIZE) uiUART_xmit_nextout2 = 0;
uiUART_xmit_count2--;
}
// service channel 3 transmitter
temp = UART_LSR3;
if (((temp & 0x20) == 0x20) && uiUART_xmit_count3)
{
if(uiUART_xmit_count3 == 1) UART_IER3 = 0x01; // if last byte, disable tx int
UART_THR3 = ucUART_xmit_buffer3[uiUART_xmit_nextout3++];
if(uiUART_xmit_nextout3 >= XMIT_BUF_SIZE) uiUART_xmit_nextout3 = 0;
uiUART_xmit_count3--;
}
// service channel 4 transmitter
temp = UART_LSR4;
if (((temp & 0x20) == 0x20) && uiUART_xmit_count4)
{
if(uiUART_xmit_count4 == 1) UART_IER4 = 0x01; // if last byte, disable tx int
UART_THR4 = ucUART_xmit_buffer4[uiUART_xmit_nextout4++];
if(uiUART_xmit_nextout4 >= XMIT_BUF_SIZE) uiUART_xmit_nextout4 = 0;
uiUART_xmit_count4--;
}
// If a character is waiting in the UART FIFO, and there
// is room in the receive buffer, get the character, and
// adjust the pointer and count.
// service channel 1 receiver
temp = UART_ISR1;
if ((temp & 0x05) == 0x04)
{
if (uiUART_recv_count1 < RECV_BUF_SIZE)
{
ucUART_recv_buffer1[uiUART_recv_nextin1++] = UART_RBR1;
if(uiUART_recv_nextin1 >= RECV_BUF_SIZE) uiUART_recv_nextin1 = 0;
uiUART_recv_count1++;
}
else
trash = UART_RBR1; // discard char if buffer is full
}
// service channel 2 receiver
temp = UART_ISR2;
if ((temp & 0x05) == 0x04)
{
if (uiUART_recv_count2 < RECV_BUF_SIZE)
{
ucUART_recv_buffer2[uiUART_recv_nextin2++] = UART_RBR2;
if(uiUART_recv_nextin2 >= RECV_BUF_SIZE) uiUART_recv_nextin2 = 0;
uiUART_recv_count2++;
}
else
trash = UART_RBR2; // discard char if buffer is full
}
// service channel 3 receiver
temp = UART_ISR3;
if ((temp & 0x05) == 0x04)
{
if (uiUART_recv_count3 < RECV_BUF_SIZE)
{
ucUART_recv_buffer3[uiUART_recv_nextin3++] = UART_RBR3;
if(uiUART_recv_nextin3 >= RECV_BUF_SIZE) uiUART_recv_nextin3 = 0;
uiUART_recv_count3++;
}
else
trash = UART_RBR3; // discard char if buffer is full
}
// service channel 4 receiver
temp = UART_ISR4;
if ((temp & 0x05) == 0x04)
{
if (uiUART_recv_count4 < RECV_BUF_SIZE)
{
ucUART_recv_buffer4[uiUART_recv_nextin4++] = UART_RBR4;
if(uiUART_recv_nextin4 >= RECV_BUF_SIZE) uiUART_recv_nextin4 = 0;
uiUART_recv_count4++;
}
else
trash = UART_RBR4; // discard char if buffer is full
}
// It is imperative that no interrupts are pending when this ISR
// exits. So check if any more interrupts are pending and service them.
if ((UART_ISR1 & 0x01) == 0) continue;
if ((UART_ISR2 & 0x01) == 0) continue;
if ((UART_ISR3 & 0x01) == 0) continue;
if ((UART_ISR4 & 0x01) == 0) continue;
break;
}
}
/* The following delay routine is used to eat up some tine during
initialization. For a 6713 running at 225 MHz (i.e. the 6713 DSK),
a value of 8000 passed to this routine causes a delay of
approximately 1 millisecond.
*/
void delay(long value)
{
volatile double x;
long i;
for(i=0;i< value; i++)
{
x=1;
}
}