UART DMA code doesn't work

humptydumpty
Posts: 17
Joined: Thu Sep 07, 2017 10:26 am

Re: UART DMA code doesn't work

Postby humptydumpty » Tue Oct 10, 2017 12:32 pm

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

   }
}

humptydumpty
Posts: 17
Joined: Thu Sep 07, 2017 10:26 am

Re: UART DMA code doesn't work

Postby humptydumpty » Wed Nov 01, 2017 12:25 am

3 weeks later....

Did anyone look at this code?

humptydumpty
Posts: 17
Joined: Thu Sep 07, 2017 10:26 am

Re: UART DMA code doesn't work

Postby humptydumpty » Mon Jan 08, 2018 1:46 am

bump. still need to use dma with uart.

Ritesh
Posts: 607
Joined: Tue Sep 06, 2016 9:37 am
Location: India
Contact:

Re: UART DMA code doesn't work

Postby Ritesh » Thu Feb 15, 2018 5:25 pm

Hi,

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

We had also Requirement for DMA to use into UART communication.
Regards,
Ritesh Prajapati

humptydumpty
Posts: 17
Joined: Thu Sep 07, 2017 10:26 am

Re: UART DMA code doesn't work

Postby humptydumpty » Tue May 22, 2018 12:25 pm

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.

humptydumpty
Posts: 17
Joined: Thu Sep 07, 2017 10:26 am

Re: UART DMA code doesn't work

Postby humptydumpty » Tue May 22, 2018 2:11 pm

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?

humptydumpty
Posts: 17
Joined: Thu Sep 07, 2017 10:26 am

Re: UART DMA code doesn't work

Postby humptydumpty » Tue May 22, 2018 3:52 pm

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;
}

Ritesh
Posts: 607
Joined: Tue Sep 06, 2016 9:37 am
Location: India
Contact:

Re: UART DMA code doesn't work

Postby Ritesh » Sat May 26, 2018 6:49 pm

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.
Regards,
Ritesh Prajapati

Who is online

Users browsing this forum: No registered users and 5 guests