Page 2 of 2

Re: UART DMA code doesn't work

Posted: Tue Oct 10, 2017 12:32 pm
by humptydumpty
OK here is relevant code. Note that the UART functions correctly if I don't define USE_DMA:

Code: Select all


void uart_intr_setup(void){
	state = STARTUP;
	reset_mem();
	config();
	periph_module_enable(PERIPH_UHCI0_MODULE);
	init_dmaDesc();
	esp_err_t ret;
    uart_param_config(uart_num, &uart_config);
    ret = uart_set_pin(uart_num, 16, 17, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); 
    if (ret) {
        ESP_LOGI("MAIN_TAG", "ERROR SETTING UART PINS");
    }
	UART[uart_num]->idle_conf.tx_idle_num = 0;
	ESP_LOGI(TAG, "Starting to allocate interrupts on uart_num: %d", uart_num);
    UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); //Enable the UART interrupt
    UART[uart_num]->int_clr.rxfifo_full = 1;
    UART[uart_num]->conf1.rxfifo_full_thrhd = 1U;
    UART[uart_num]->int_ena.rxfifo_full = 1;
    UART[uart_num]->int_clr.brk_det = 1;
    UART[uart_num]->int_ena.brk_det = 1;
    UART[uart_num]->conf1.rx_tout_thrhd = 1;
    UART[uart_num]->int_clr.rxfifo_tout = 1;
    UART[uart_num]->int_ena.rxfifo_tout = 1;
    UART[uart_num]->int_clr.txfifo_empty = 1;
    UART[uart_num]->conf1.txfifo_empty_thrhd = 1U;
//    UART[uart_num]->int_ena.txfifo_empty = 1;
    UART[uart_num]->int_clr.tx_done = 1;
//    UART[uart_num]->int_ena.tx_done = 1;
    UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
    ESP_LOGI(TAG, "RX interrupt configured");
    ret= esp_intr_alloc(ETS_UART1_INTR_SOURCE, ESP_INTR_FLAG_LEVEL1, uart_isr, NULL, &s_uart_handle);
    ESP_LOGI(TAG, "UART 1 interrupt allocated");
    return;
}


void init_dmaDesc (void) {

	dmaDesc_Msg.length = 24;
	dmaDesc_Msg.size = 24;
	dmaDesc_Msg.owner = 1;
	dmaDesc_Msg.sosf = 0;
	dmaDesc_Msg.buf = (uint8_t *)Msg_8[0];
	dmaDesc_Msg.offset = 0; 
	dmaDesc_Msg.empty = 0;
	dmaDesc_Msg.eof = 1;

    UHCI0.conf0.val = ( UHCI_UART1_CE );
    //UART1.conf0.txfifo_rst = 1;
    UHCI0.int_clr.val = 0xFFFFFFFF;
}


void IRAM_ATTR send_msg (void) {

	dmaDesc_Msg.length = 24;

    UART1.conf0.txfifo_rst = 1;
	UHCI0.dma_out_link.start = 0;
	UHCI0.dma_in_link.start = 0;
    UART1.conf0.txfifo_rst = 0;
    UHCI0.dma_out_link.addr = (uint32_t)(&dmaDesc_Msg);
	UHCI0.dma_out_link.start = 1;
    UHCI0.int_clr.val = 0xFFFFFFFF;
}

void IRAM_ATTR timer_handler (void) {

	uint64_t ticks;
	switch (state) {
	/// ... edited for brevity

	case RESPOND:
		stop_timer_g0_t0 ();
#ifdef USE_DMA
		send_msg();
#else
		tx_cntr = 0;
		while (tx_cntr < 24) {
			WRITE_PERI_REG(UART_FIFO_AHB_REG(uart_num), Msg_8[tx_cntr++]); 
		}
#endif
		state = WAIT;

		ticks = 25 * TIMER_BYTE_TICKS;
		restart_timer_g0_t0 (ticks);
		break;
		// ... edited for brevity

	}
}

Re: UART DMA code doesn't work

Posted: Wed Nov 01, 2017 12:25 am
by humptydumpty
3 weeks later....

Did anyone look at this code?

Re: UART DMA code doesn't work

Posted: Mon Jan 08, 2018 1:46 am
by humptydumpty
bump. still need to use dma with uart.

Re: UART DMA code doesn't work

Posted: Thu Feb 15, 2018 5:25 pm
by Ritesh
Hi,

Anyone got success to use DMA for UART data send and receive?

We had also Requirement for DMA to use into UART communication.

Re: UART DMA code doesn't work

Posted: Tue May 22, 2018 12:25 pm
by humptydumpty
I got it to work.

There was a problem with the DMA descriptor. Checking the raw interrupt register was helpful. Also it turns out that resetting the fifo was not helpful.

Re: UART DMA code doesn't work

Posted: Tue May 22, 2018 2:11 pm
by humptydumpty
Let me qualify that. The DMA transfers data. But the 1st byte is not sent. And the 4th byte is not sent correctly.

Here is my code:

Code: Select all

lldesc_t widget_usb_Msg;

uint8_t dma_test_msg[8] __attribute__((aligned(32))) = {
		49,50,51,52,53,54,55,56
};

void init_dmaDesc() {
	periph_module_enable(PERIPH_UHCI0_MODULE);
	widget_usb_Msg.length = 8; // number valid bytes
	widget_usb_Msg.size = 8; // word aligned buffer size
	widget_usb_Msg.owner = 1; // DMA can operate buffer
	widget_usb_Msg.sosf = 0; // ??
	widget_usb_Msg.buf = dma_test_msg; // location of buffer
	widget_usb_Msg.eof = 1; // last DMA desc
	UHCI0.conf0.val = 0;
	UHCI0.conf0.uart0_ce = 1;
	UHCI0.int_clr.val = 0xFFFFFFFF;


}

void send_USB_DMA () {

    UHCI0.dma_out_link.addr = (uint32_t)(&widget_usb_Msg);
	UHCI0.dma_out_link.start = 1;
    UHCI0.int_clr.val = 0xFFFFFFFF;
}
This is what I expected to be sent:
12345678
And this is what actually gets sent:
23▒5678
Look like a silicon error?

Re: UART DMA code doesn't work

Posted: Tue May 22, 2018 3:52 pm
by humptydumpty
Problem solved. You have to initialize some bits to zero in UHCI_CONF1_REG as well. Note that setting the whole register to 0 causes a DMA Descriptor error. You have to set the bits individually. The code below works for me:

Code: Select all

lldesc_t widget_usb_Msg;

uint8_t dma_test_msg[8] __attribute__((aligned(32))) = {
		49,50,51,52,53,54,55,56
};

void init_dmaDesc() {
	periph_module_enable(PERIPH_UHCI0_MODULE);
	widget_usb_Msg.length = 7; // number valid bytes
	widget_usb_Msg.size = 8; // word aligned buffer size
	widget_usb_Msg.owner = 1; // DMA can operate buffer
	widget_usb_Msg.sosf = 0; // ??
	widget_usb_Msg.buf = dma_test_msg; // location of buffer
	widget_usb_Msg.eof = 1; // last DMA desc
	UHCI0.conf0.val = 0;
	UHCI0.conf1.check_seq_en = 0;
	UHCI0.conf1.check_sum_en = 0;
	UHCI0.conf1.tx_ack_num_re = 0;
	UHCI0.conf1.tx_check_sum_re = 0;
	UHCI0.conf0.uart0_ce = 1;
	UHCI0.dma_out_link.start = 1;
	UHCI0.int_clr.val = 0xFFFFFFFF;


}

void send_USB_DMA () {

    UHCI0.dma_out_link.addr = (uint32_t)(&widget_usb_Msg);
	UHCI0.dma_out_link.start = 1;
    UHCI0.int_clr.val = 0xFFFFFFFF;
}

Re: UART DMA code doesn't work

Posted: Sat May 26, 2018 6:49 pm
by Ritesh
humptydumpty wrote:Problem solved. You have to initialize some bits to zero in UHCI_CONF1_REG as well. Note that setting the whole register to 0 causes a DMA Descriptor error. You have to set the bits individually. The code below works for me:

Code: Select all

lldesc_t widget_usb_Msg;

uint8_t dma_test_msg[8] __attribute__((aligned(32))) = {
		49,50,51,52,53,54,55,56
};

void init_dmaDesc() {
	periph_module_enable(PERIPH_UHCI0_MODULE);
	widget_usb_Msg.length = 7; // number valid bytes
	widget_usb_Msg.size = 8; // word aligned buffer size
	widget_usb_Msg.owner = 1; // DMA can operate buffer
	widget_usb_Msg.sosf = 0; // ??
	widget_usb_Msg.buf = dma_test_msg; // location of buffer
	widget_usb_Msg.eof = 1; // last DMA desc
	UHCI0.conf0.val = 0;
	UHCI0.conf1.check_seq_en = 0;
	UHCI0.conf1.check_sum_en = 0;
	UHCI0.conf1.tx_ack_num_re = 0;
	UHCI0.conf1.tx_check_sum_re = 0;
	UHCI0.conf0.uart0_ce = 1;
	UHCI0.dma_out_link.start = 1;
	UHCI0.int_clr.val = 0xFFFFFFFF;


}

void send_USB_DMA () {

    UHCI0.dma_out_link.addr = (uint32_t)(&widget_usb_Msg);
	UHCI0.dma_out_link.start = 1;
    UHCI0.int_clr.val = 0xFFFFFFFF;
}
Thanks for update.

Would you please provide complete code so that we can get idea regarding DMA and can take reference for that.