This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Only get a few bytes RX on the UART then just stops... (OMAP-L138)

Other Parts Discussed in Thread: OMAP-L138

Using the PSP (3.0.1.00) driver ported to the ARM on OMAP-L138.  Using BIOS 6.33.5.46 (CCS 5.2.0.293).

The only thing running is the UART and some test code.  I inject bytes via a laptop into the expOMAP-L138 at a rate of about 1 byte/sec.  I seem to get a few bytes, then the GIO layer starts reporting IOM_ETIMEOUT.  The number of bytes recieved seems to very from none to about 10.  I have setup 100 buffers and issued them.

Digging into the registers for the UART, it looks like it has bytes in the FIFO and the Interrupt is pending.  But going to the ARMINTC0ARM registers, the ECR2 is set correctly but nothing in the SECR2.  For some reason it looks like the ARM has stopped recognizing the ISR.

I seem to have a similure issue in the McASP.  I get several samples from it but then it just stops.

Thought I would concentrat on the UART since it is much simpler then the McASP.

Thanks,

 

  • Mike,

    How are you configuring the UART interrupt?

    Alan

  • I am in the process of turning into a polled driver to see if that helps, so please excuse any commented or #ifdef code...

    But here is what I got...

    This code is in the create function.

    /// Setup HWI for the UART both TX and RX

    Hwi_Params_init(&osu_uarts[uart].hwi_params);
    osu_uarts[uart].hwi_params.arg = (UArg) uart;
    osu_uarts[uart].hwi_params.enableInt = TRUE;
    osu_uarts[uart].hwi_params.eventId = -1;
    osu_uarts[uart].hwi_params.maskSetting = Hwi_MaskingOption_SELF;
    /// The UART \b shall [5] be an interrupt driven [SRS-22053]
    osu_uarts[uart].hwi_handle = Hwi_create((S32) osu_uarts[uart].isr_num,
    osu_uart_hwi, &osu_uarts[uart].hwi_params, NULL);
    osu_uarts[uart].in_use = TRUE;
    Hwi_enableInterrupt(osu_uarts[uart].isr_num);

    isr num is 61 for UART 2 (or the 3rd UART).

    The open function has a call to

    Hwi_enableInterrupt(osu_uarts[uart].isr_num);

    There is also a "interrupt_disable" and "interrupt_enable" that effect only the UART ISR.

    The submit function only calls the UART ISR enable and disable.

    A quick search of the code for "Hwi_" did not find any calls to "Hwi_disableInterrupt".

    Thanks so much for your time...

  • I'm trouble by the application's use of interrupt_disable() and interrupt_enable().

    Where and when are these being invoked?

    You should use Hwi_disable() and Hwi_restore() in your code to surround atomic sections.

    These APIs preserve the original state of the global interrupt enable flag.

    Alan

  • My Bad - Hwi_disable and restore are used for Atomic opperations.

    The other calls are used when shutting down the UART, for example when there are no IOP packets available.  Such as inside the SWI they shut off the UART ISR and then renable them if there are more IOPs.

    Inside submit when an IOP is added to the list.

    Thanks,

  • How are you acknowledging the UART rx character interrupt in the ISR handler?

    Alan

  • HWI: (Note we are not using the TX side at all)

    status = osu_uarts[uart].
    regs_p->iir_fcr & 0x0F;
    Log_info1("HWI status 0x%08x",status);
    if ((!(status & OSU_IIR_INTID_NO_IPEND)) && ((intr_cnt) < (OSU_UART_MAX_ISR_LOOP))) {
    intr_cnt = intr_cnt + 1;
    if (OSU_IIR_INTID_RX_LINE == (OSU_IIR_INTID_RX_LINE & status)) {
    Log_info0("HWI Line error");
    osu_uart_handle_rx_error(&(osu_uarts[uart].rx));
    } else {
    if (OSU_IIR_INTID_RX_DATA == (OSU_IIR_INTID_RX_DATA & status)) {
    Log_info0("HWI RX Data");
    if (OSU_IIR_INTID_CH_TIMEOUT == (OSU_IIR_INTID_CH_TIMEOUT & status)) {
    Log_info0("RX HWI - TIMEOUT!");
    osu_uarts[uart].stats.rx_timeout = osu_uarts[uart].stats.rx_timeout + 1;
    osu_uarts[uart].rx.errors = osu_uarts[uart].rx.errors + 1;
    osu_uarts[uart].rx.active_iop_p->status = IOM_ETIMEOUT;
    xfer = osu_uart_fifo_read(&osu_uarts[uart].rx,osu_uarts[uart].rx.active_buf_p,osu_uarts[uart].rx.bytes_remaining);
    osu_uarts[uart].rx.bytes_remaining = osu_uarts[uart].rx.bytes_remaining - xfer;
    osu_uarts[uart].rx.active_buf_p = osu_uarts[uart].rx.active_buf_p + xfer;
    osu_uarts[uart].stats.rx_bytes = osu_uarts[uart].stats.rx_bytes + (U32) xfer;
    osu_uart_interrupt_disable(uart, (OSU_IER_ERBI | OSU_IER_ELSI));
    osu_uart_local_complete_current_io(&osu_uarts[uart].rx);
    if (FALSE == Queue_empty(Queue_handle(&(osu_uarts[uart].rx.queue_pending_list)))) {
    io_packet_p = (IOM_Packet *) Queue_get(Queue_handle(&(osu_uarts[uart].rx.queue_pending_list)));
    if (NULL != io_packet_p) {
    osu_uarts[uart].rx.active_iop_p = io_packet_p;
    osu_uarts[uart].rx.active_buf_p = io_packet_p->addr;
    osu_uarts[uart].rx.bytes_remaining = io_packet_p->size;
    osu_uarts[uart].rx.errors = 0;
    }
    } else {
    osu_uarts[uart].rx.active_iop_p = NULL;
    Log_info0("No more packets to work on?");
    }
    osu_uart_interrupt_enable(uart, (OSU_IER_ERBI | OSU_IER_ELSI));
    } else {
    Swi_post(osu_uarts[uart].rx.swi_handle);
    }
    } else {
    Log_info0("HWI TX");
    if (OSU_IIR_INTID_TX_EMPTY & status) {
    Swi_post(osu_uarts[uart].tx.swi_handle);
    }
    }
    status = osu_uarts[uart].regs_p->iir_fcr & 0x0F;
    }
    }
     
    The RX SWI looks like this:

    OSU_UART_ENUM_T uart = (OSU_UART_ENUM_T) uart_enum;

    unused_arg = unused_arg;

    if (osu_uarts[uart].rx.active_iop_p) {

    osu_uart_interrupt_disable(uart, (OSU_IER_ERBI | OSU_IER_ELSI));

    xfer = osu_uart_fifo_read(&osu_uarts[uart].rx,osu_uarts[uart].rx.active_buf_p, osu_uarts[uart].rx.bytes_remaining);

    osu_uarts[uart].rx.bytes_remaining = osu_uarts[uart].rx.bytes_remaining - xfer;

    osu_uarts[uart].rx.active_buf_p = osu_uarts[uart].rx.active_buf_p + xfer;

    osu_uarts[uart].stats.rx_bytes = osu_uarts[uart].stats.rx_bytes + (U32) xfer;

    if (0 == osu_uarts[uart].rx.bytes_remaining) {

    if (0 != osu_uarts[uart].rx.errors) {

    osu_uarts[uart].rx.active_iop_p->status = IOM_EBADIO;

    } else {

    osu_uarts[uart].rx.active_iop_p->status = IOM_COMPLETED;

    }

    osu_uart_local_complete_current_io(&osu_uarts[uart].rx);

    osu_uart_load_pended_iops(&osu_uarts[uart].rx);

    }

    osu_uart_interrupt_enable(uart, (OSU_IER_ERBI | OSU_IER_ELSI));

    }

  • Should this:

       regs_p->iir_fcr & 0x0F;

    be this:

       regs_p->iir_fcr &= 0x0F;

    Alan

  • Copy and past error.  The line is:

    status = osu_uarts[uart].regs_p->iir_fcr & 0x0F;
    Log_info1("HWI status 0x%08x",status);
    if ((!(status & OSU_IIR_INTID_NO_IPEND))
  • I've just asked someone from the PSP team to take a look at this issue.

    Alan

  • Hi Mike,

    Looking at your sequence of handling Receive timeout error, you seem to call "osu_uart_handle_rx_error(&(osu_uarts[uart].rx));" and "osu_uart_fifo_read" which is as well done in the PSP.  This is a right thing to do. Whenever there is a timeout, all the remanant bytes in the FIFO should be read out until the FIFO becomes empty and status cleared. Then, to recover from the timeout error you can call the following IOCTL's.

    "Uart_IOCTL_RESET_RX_FIFO"

    "Uart_IOCTL_CANCEL_CURRENT_IO"

    For similar info regarding the timeout error recover, please refer -

    http://e2e.ti.com/support/embedded/f/355/p/92463/321901.aspx#321901

    Hope this answers your question and helps to solve the issue..

    Best Regards,

    Raghavendra