Content originally posted in LPCWare by TKoe on Tue Sep 18 00:41:24 MST 2012
Hello!
As the title says I have a problem with receiving data at higher speeds. I have tested the UART with the speed of 3 Mbaud and sending data is not a problem. The reason for trying out the 3 Mbaud is that the FTDI chip which the UART is connected to supports those speeds.
So when I try to receive data with the normal RBR interrupt I can receive data, but only the first byte is correct, the rest is completely wrong, not just single bits. I found that plausible because the whole interrupt would need less than 40 cycles to finish to not lose any data, possibly less.
So I figured I'd use DMA instead. The following test program expects five bytes which it will echo together with some debug data. This program works just fine with i.e. 750 kbaud. Sending "hello" will return "00 01 FF 00 ff 'hello' 00".
However, when I set it to the desired 3 Mbaud it will return some weird stuff:
"00 01 FF 00 FF 90 29 12 BB B8 00"
"00 02 FF 00 FF F9 F3 D0 29 13 00"
etc.
What am I doing wrong?
Regards,
Tim
Here's my code:
<code>
#ifdef __USE_CMSIS
#include "LPC177x_8x.h"
#endif
#include <cr_section_macros.h>
#include <NXP/crp.h>
// Variable to store CRP value in. Will be placed automatically
// by the linker when "Enable Code Read Protect" selected.
// See crp.h header for more information
__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;
#include <stdbool.h>
#include "lpc177x_8x_uart.h"
#include "lpc177x_8x_pinsel.h"
#include "lpc177x_8x_nvic.h"
#include "lpc177x_8x_gpdma.h"
// UART definitions
#define UART_ID UART_0
#define UART LPC_UART0
#define UART_IRQ UART0_IRQn
// DMA definition
#define DMA_CH_NUM 0
#define DMA_CH LPC_GPDMACH0
#define DMA_SIZE 5
UART_CFG_Type uart_cfg =
{
.Baud_rate = 3000000, // Yes, that's 3 Mbaud
.Parity = UART_PARITY_NONE,
.Databits = UART_DATABIT_8,
.Stopbits = UART_STOPBIT_1,
};
UART_FIFO_CFG_Type uart_fifo_cfg =
{
.FIFO_ResetRxBuf = ENABLE,
.FIFO_ResetTxBuf = ENABLE,
.FIFO_DMAMode = ENABLE,
.FIFO_Level = UART_FIFO_TRGLEV0,
};
GPDMA_Channel_CFG_Type dma_cfg =
{
.ChannelNum = DMA_CH_NUM,
.TransferSize = 0,
.TransferWidth = GPDMA_WIDTH_BYTE,
.SrcMemAddr = 0,
.DstMemAddr = 0,
.TransferType = GPDMA_TRANSFERTYPE_P2M,
.SrcConn = GPDMA_CONN_UART0_Rx,
.DstConn = 0,
.DMALLI = 0,
};
uint8_t buffer[100];
bool dmaflag = false;
int dma_counter = 0;
int dma_error = 0;
void DMA_IRQHandler()
{
if (GPDMA_IntGetStatus(GPDMA_STAT_INTTC, DMA_CH_NUM))
{
dmaflag = true;
dma_counter++;
GPDMA_ClearIntPending(GPDMA_STATCLR_INTTC, DMA_CH_NUM);
}
else
{
dma_error++;
GPDMA_ClearIntPending(GPDMA_STATCLR_INTERR, DMA_CH_NUM);
}
}
void DisableDMAch(void)
{
GPDMA_ChannelCmd(DMA_CH_NUM, DISABLE);
NVIC_DisableIRQ(DMA_IRQn);
}
void EnableDMAch(uint32_t count, uint8_t * memp)
{
if (DMA_CH->CConfig & 0x00000001)
{
// if the channel is enabled we need to disable
// it, set the parameters and re-enable it!
DisableDMAch();
}
// dma_cfg-modifications
dma_cfg.DstMemAddr = (uint32_t)memp;
dma_cfg.TransferSize = count;
GPDMA_Setup(&dma_cfg);
NVIC_SetPriority(DMA_IRQn, 1);
dmaflag = false;
NVIC_EnableIRQ(DMA_IRQn);
GPDMA_ChannelCmd(DMA_CH_NUM, ENABLE);
}
int main(void)
{
GPDMA_Init();
PINSEL_ConfigPin(0, 2, 0b001);
PINSEL_ConfigPin(0, 3, 0b001);
UART_Init(UART, &uart_cfg);
UART_FIFOConfig(UART_ID, &uart_fifo_cfg);
UART_TxCmd(UART, ENABLE);
EnableDMAch(DMA_SIZE, buffer);
while(1)
{
while (!dmaflag);
{
uint8_t txbuf[200];
int i;
txbuf[0] = 0x00;
txbuf[1] = dma_counter & 0xFF;
txbuf[2] = 0xFF;
txbuf[3] = dma_error & 0xFF;
txbuf[4] = 0xFF;
for (i = 0; i < DMA_SIZE; i++)
txbuf[5 + i] = buffer;
txbuf[5 + DMA_SIZE] = 0x00;
UART_Send(UART, txbuf, 6 + DMA_SIZE, BLOCKING);
EnableDMAch(DMA_SIZE, buffer);
}
}
return 0 ;
}
</code>