I'm attempting to set the DMA for the RX of the UART/ESCI.
The DMA finishes but the destination buffer never received the that was received.
Why is it the DMA finishes but doesn't put the data in the destination buffer address?
Edit: I can receive over the uart by polling the CR1 register or interrupting when the UART received.
Edit: After the DMA is finished, I print of the status register. The status register is 0xE0_01_C0_00
// DMA channel used for ESCI
#define DMA_ESCIA_TX 18
#define DMA_ESCIA_RX 19
#define DMA_ESCIB_TX 34
#define DMA_ESCIB_RX 35
void esci_init_default(struct ESCI_tag pEsci)
pEsci->CR1.R = 0x0005000C;
// SCI Baud rate : 1000.0000 khz
// Loop Selected : Disable
// Receiver Source : Transmitter connected Internal
// Data Format : 8 bits long
// Wake-up condition : Idle Line wakeup
// Idle Line Type : Count at Start bit
// Parity Bit : Disable
// Parity Type : Even
// Transmit Interrupt Enable : Disable
// Transmission Complete Interrupt : Disable
// Receive Full Interrupt : Enable
// Idle Line Interrupt : Disable
// Transmitter : Enable
// Receiver : Enable
uint8_t tx_channel = pEsci == &ESCI_A ? DMA_ESCIA_TX : DMA_ESCIB_TX;
uint8_t rx_channel = pEsci == &ESCI_A ? DMA_ESCIA_RX : DMA_ESCIB_RX;
EDMA.TCD[tx_channel].DONE = 1;
EDMA.TCD[rx_channel].DONE = 1;
pEsci->CR2.R = 0x2C00; // enable DMA
// Fast Bit Error detection : Disable
// Bit-Error Stop : Enable
// Bit Error Interrupt : Disable
// Activate Rx DMA Channel : Enable
// Activate Tx DMA Channel : Enable
// Break Transmit Character Length : 10 bit
// Bit Error Sample Mode : RT clock 9
// SCI bit error stop : Disable
// Overrun error Interrupt : Disable
// Noise flag Interrupt : Disable
// Frame Error Interrupt : Disable
// Parity flag Interrupt : Disable
pEsci->LCR.R = 0x00000000;
// LIN bus wake-up : Enabled
// Wake-up delimiter time : 4
// LIN Debug Mode : Disabled
// LIN Mode : Disabled
// Double Stop Flags : Disabled
// Activate Parity Generation : Disabled
// RxREG Ready Interrupt : Disabled
// TxREG Ready Interrupt : Disabled
// Rx Wakeup Interrupt : Disabled
// Slave timeout error Interrupt : Disabled
// Physical bus error Interrupt : Disabled
// CRC Error Interrupt : Disabled
// Checksum error Interrupt : Disabled
// Frame Complete Interrupt : Disabled
// Overflow Interrupt : Disabled
}
void EDMA_ESCI_Receive(struct ESCI_tag* eSCI, uint8_t *bufptr, uint32_t count)
{
uint8_t rx_channel = eSCI == &ESCI_A ? DMA_ESCIA_RX : DMA_ESCIB_RX;
EDMA.TCD[rx_channel].SADDR = (vuint32_t)&eSCI->DR + 1; // Load address of source data
EDMA.TCD[rx_channel].SSIZE = 0; // Read 2**0 = 1 byte per transfer
EDMA.TCD[rx_channel].SOFF = 0; // Do not increment source addr
EDMA.TCD[rx_channel].SLAST = 0; // After major loop, reset src addr
EDMA.TCD[rx_channel].SMOD = 0; // Source modulo feature not used
EDMA.TCD[rx_channel].DADDR = (vuint32_t)bufptr; // Load address of destination
EDMA.TCD[rx_channel].DSIZE = 0; // Write 2**0 = 1 byte per transfer
EDMA.TCD[rx_channel].DOFF = 1; // Increment destination addr
EDMA.TCD[rx_channel].DLAST_SGA = 0; // After major loop, no dest addr change
EDMA.TCD[rx_channel].DMOD = 0; // Destination modulo feature not used
EDMA.TCD[rx_channel].NBYTES = 1; // Transfer 1 byte per minor loop
EDMA.TCD[rx_channel].BITER = count; // Number of minor loop iterations
EDMA.TCD[rx_channel].CITER = count; // Number of minor loop iterations
EDMA.TCD[rx_channel].DREQ = 1; // Disable channel when major loop is done
EDMA.TCD[rx_channel].INTHALF = 0; // Interrupts is not used
EDMA.TCD[rx_channel].INTMAJ = 1; // Interrupt is enabled
EDMA.TCD[rx_channel].MAJORELINK = 0; // Dynamic program is not used
EDMA.TCD[rx_channel].ESG = 0;
EDMA.TCD[rx_channel].BWC = 0; // Default bandwidth control- no stalls
EDMA.TCD[rx_channel].START = 0; // Initialize status flags
EDMA.TCD[rx_channel].DONE = 0;
EDMA.TCD[rx_channel].ACTIVE = 0;
// Enable the rx_channel
EDMA.SERQR.R = rx_channel;
}
int EDMA_ESCI_IsRxDMADone(struct ESCI_tag* eSCI)
{
uint8_t rx_channel = eSCI == &ESCI_A ? DMA_ESCIA_RX : DMA_ESCIB_RX;
return (EDMA.TCD[rx_channel].DONE == 1);
}
int esci_setBaudRate(struct ESCI_tag* pEsci , int baudRate)
{
if (pEsci == NULL) return -1;
pEsci->CR1.B.SBR = (BD_CPU_CLK_HZ / (16 * baudRate)); //set baud rate
return ((BD_CPU_CLK_HZ)/(16 * pEsci->CR1.B.SBR));
}
#define COMMAND_BUFFER_SIZE 3
uint8_t dma_buffer[COMMAND_BUFFER_SIZE] = {0};
void main(void)
{
esci_init_default(&ESCI_A);
esci_setBaudRate(&ESCI_A, 9600); // works
memset(dma_buffer, 0x55, COMMAND_BUFFER_SIZE);
EDMA_ESCI_Receive(&ESCI_A, dma_buffer, 1);
while(1)
{
if(EDMA_ESCI_IsRxDMADone(&ESCI_A))
{
WriteUARTN(&ESCI_A.SR.R, 4);
//this just prints whatever was memset :(
WriteUARTN(dma_buffer, COMMAND_BUFFER_SIZE);
memset(dma_buffer, 0x55, COMMAND_BUFFER_SIZE);
EDMA_ESCI_Receive(&ESCI_A, dma_buffer, 1);
}
}
}
已解决! 转到解答。
Hi,
I'm not sure what's wrong on your side but this minimalist code is working as expected. Loop mode is used in this test:
unsigned char rec_data[10];
void ESCI_A_Init(void)
{
ESCI_A.CR1.B.SBR = 64000000/16/9600;
ESCI_A.CR1.B.LOOPS = 1;
ESCI_A.CR1.B.TE = 1;
ESCI_A.CR1.B.RE = 1;
ESCI_A.CR2.R = 0x2800;
}
void EDMA_ESCI_Receive(void)
{
uint8_t rx_channel = 19;
EDMA.TCD[rx_channel].SADDR = (vuint32_t)&ESCI_A.DR.R + 1; // Load address of source data
EDMA.TCD[rx_channel].SSIZE = 0; // Read 2**0 = 1 byte per transfer
EDMA.TCD[rx_channel].SOFF = 0; // Do not increment source addr
EDMA.TCD[rx_channel].SLAST = 0; // After major loop, reset src addr
EDMA.TCD[rx_channel].SMOD = 0; // Source modulo feature not used
EDMA.TCD[rx_channel].DADDR = (vuint32_t)rec_data; // Load address of destination
EDMA.TCD[rx_channel].DSIZE = 0; // Write 2**0 = 1 byte per transfer
EDMA.TCD[rx_channel].DOFF = 1; // Increment destination addr
EDMA.TCD[rx_channel].DLAST_SGA = 0; // After major loop, no dest addr change
EDMA.TCD[rx_channel].DMOD = 0; // Destination modulo feature not used
EDMA.TCD[rx_channel].NBYTES = 1; // Transfer 1 byte per minor loop
EDMA.TCD[rx_channel].BITER = 5; // Number of minor loop iterations
EDMA.TCD[rx_channel].CITER = 5; // Number of minor loop iterations
EDMA.TCD[rx_channel].D_REQ = 1; // Disable channel when major loop is done
EDMA.TCD[rx_channel].INT_HALF = 0; // Interrupts is not used
EDMA.TCD[rx_channel].INT_MAJ = 0; // Interrupt is enabled
EDMA.TCD[rx_channel].MAJORE_LINK = 0; // Dynamic program is not used
EDMA.TCD[rx_channel].E_SG = 0;
EDMA.TCD[rx_channel].BWC = 0; // Default bandwidth control- no stalls
EDMA.TCD[rx_channel].START = 0; // Initialize status flags
EDMA.TCD[rx_channel].DONE = 0;
EDMA.TCD[rx_channel].ACTIVE = 0;
// Enable the rx_channel
EDMA.SERQR.R = rx_channel;
}
void main(void)
{
unsigned int j;
ESCI_A_Init();
EDMA_ESCI_Receive();
//send 5 characters and receive them via DMA
for (j=0; j< 5; j++)
{
while (ESCI_A.SR.B.TDRE == 0) {}
ESCI_A.SR.R = 0x80000000; /* Clear TDRE flag */
ESCI_A.DR.B.D = (unsigned char)j; /* Transmit 8 bits Data */
}
while(1)
{
}
}
Regards,
Lukas