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.

Problem about UART1 receive on DM6467

Hello~

I got a problem about receiving data from UART1 on DM6467.

By following the web page

http://www.mail-archive.com/davinci-linux-open-source@linux.davincidsp.com/msg09153.html

, UART1 can be enabled to transmit well.

But there are something wrong with receiving!

I can get the data that is transmited into UART1 Rx from RHR by accessing Rx FIFO directly.

If I attempt to use the read() function in my receive ap, it is always blocked.

I think the problem is the uart Interrupt Service Routine doesn't get the receive interrupt!?

Could anyone help me to set the PINMUX or UART registers correctly for UART receiving function?

Or there is another issus I don't consider?

Thank you very much!!

  • Other than UART1 peripheral registers, the following system registers need to be programmed.

    CLKCTL&=0xFCFFFFFF;

    PINMUX1.UART1CTL(i.e., =1 for no flow control);  

    VDD3P3VPWDN.UR1FC =0;

    VDD3P3VPWDN.UR1DAT =0;

    Is this on a TI EVM? I am assuming you are doing this under Linux?

    If you still need help, please be as detailed as possible when you ask a question.

     

  • Hi Paul,

    Thank you for your quick reply, and I am apologetic for rough description!!

    I was doing this on our custom board underMontaVista Linux 5.0.

    UART1 is connected to a RS485 chip. (I don't remember which one. Maybe I can check it later.)

    But I'm sure it works on half-duplex mode, and I have used GP25 pin to switch transmition or reception.

    Oscilloscope is also used to probed the input signal of DM6467 UART1 Rx pin.

    (Accessing the RHR of UART1 can get the expected data.)

    In <ti-davinci-kernel>/arch/arm/mach-davinci/board-dm6467.c file  "static void board_init(void) "

    I set VDD3P3V_PWDN = 0, PINMUX0REG  = 0x40000 and PINMUX1REG = 0x15 (UART1 without flow control).

    Then I set two UART1 registers as follow:

                   ptr_ier  = (volatile int *)IO_ADDRESS(DAVINCI_UART1_BASE+0x4);

                   *ptr_ier = 0x0; //disable int

                  ptr_pgmgt = (volatile int *) IO_ADDRESS(DAVINCI_UART1_BASE+0x20);

                  *ptr_pgmgt = 0x00;

    Finally, I also set SCR of UART1 to 0x08.

    Other registers of UART1 are as MontaVista5.0 Linux default setting.

    So, what should I do ? and is there any detail that I have to let you know?

    Again, thank you for your kindly help!!

    Ernest

  • OK. Do you mean data does come into the receive FIFO (since you can get it from RBR), but no interrupt is triggerred?

    It might be to do with FIFO threadhold levels. You can start by disabling fifo and see if you can get interrupt triggered

     

     

  • Hi Paul,

    In

    "ti-davinci/linux-2.6.18_pro500/arch/arm/mach-davinci/serial.c"   "static int __init dm646x_serial_reset()",

    I added some codes as following to disable fifo.

          #define UART1_DM6467_FCR __REG(DAVINCI_UART1_BASE + 0x08)

         UART1_DM6467_FCR = 0x00;

    Is it a right way to disable fifo?

    FCR seems only to be written. How could I make sure my setting works?

    After I did that like above, it still could not have the receive interrupt.

    Besides, I told you I used GP25 pin to switch RS485 chip transmit & receive.

    In "ti-davinci/linux-2.6.18_pro500/drivers/serial/serial_core.c" "uart_open()",

    I configured the GP25 pin  direction to be an output pin and set it outputed low (coz "Low" enables RS485 chip to receive).

    Then, in "ti-davinci/linux-2.6.18_pro500/drivers/serial/serial_core.c" "uart_write()",

    I set GP25 output high (coz "High" enables RS485 chip to transmit) in the start of uart_write() function.

    After the data are sent, I set GP25 output low to prepare for receiving the input data in the end of uart_write() function.

    All these settings about GP25 in "serial_core.c", I have checked if(tty->index == 1) to make sure it only works when UART1 is used.

    Does "GP25 setting" have influence on UART1 receive interrupt? Though it's suspicious, I just wanna let you know the detail.

    Thank you !!

     

  • Hi Paul,

    Sorry for I forgot to answer your question first!!

    Yes, I mean data does come into the receive FIFO (since I can get it from RHR), but no interrupt is triggerred.

  • Hi,

    This ia a HW forum, and we generally don't debug software (Linux or Bios) issues. Just wondering, do you have JTAG access on this board? Debugging this in CCS environment will be a lot easier.

    The way you are disabling FIFO should be OK, just make sure LCR[7:0] != BFh. Also, one thing I'd like you to make is the UART doesn't get reconfigured or re-initialized somewhere else after your modification. There is no good way to read FCR settings.

    I have some trouble understanding the section about GPIO setup, but I don't think GPIO caused this because data does come into your device.

    When you say no interrupt, you mean your ISR is never triggered while you recevie? It is indeed triggered when you transmit, correct?

    Please also check IIR register to make sure you don't have some error interrupt while you receive data. I believe the following sections in the user guide will help you identify the problem: 2.5.2.1 UART Mode Interrupts.

    In general, if you have to debug this under Linux, we should move this discussion to the Linux forum.

  • Hi Paul,

    Before I modified serial port driver of Linux, I used the ICE (through JTAG) to confirm the transmit & receive functions of UART1 on our customer board. (I modified HW test  code package "DaVinci HD Test Code" that was downloaded from Spectrum Digital Inc.) But the uart receive api. of this package got the input data with accessing RHR directly. It's different from under Linux (involved interrupt issue)!

    I'm also afraid the position that I modify UART1 registers is not the last setting before I start to use UART1.

    Yes, I mean my ISR is never triggered while I receive! And it's indeed triggered when I transmit! It's because the Tx of UART1 is connected to a PTZ camera through a RS485 transceiver. Any motion of PTZ that I want to do can be completed. But the response of PTZ can not be received under Linux.

     I'll accept your suggestion to check IIR while I receive data tomorrow.

    Finally, I'm really appreciate your kindly help. May I have the web site of Linux forum for DM6467?

    If I have any question, could I still discuss with you here?

    Thank you very much again!!

    Ernest

  • OK. I am moving this over to the Linux forum, and I will get an email whenever there is any activity in this thread.

  • Hi Paul,

    I don't know where I can add code to check IIR register while receiving data?

    But in "8250.c" serial8250_startup(), I dumped all registers of UART0 & UART1 to compare.

    UART0 : IER=0x05 ; LCR=0x03 ; MCR=0x08 ; MSR/TCR=0x10 ; MDR1=0x00 ; SFLSR=0x00 ; SFREGL=0x92 ; SFREGH=0x07 ; SCR=0x08 ; SSR=0x00 ; WER=0x7f ;   

    UART1 : IER=0x05 ; LCR=0x03 ; MCR=0x08 ; MSR/TCR=0x20 ; MDR1=0x00 ; SFLSR=0x00 ; SFREGL=0xff ; SFREGH=0x0f ; SCR=0x08 ; SSR=0x00 ; WER=0x7f ;  

    The initialization looks normal and there is no reason occurs those situations that I meet?!

    Ernest

  • I looked up one of the validation testcases (interrupt based UART1 testcase that has FIFO enabled). Here is the init portion:

     //UART 0 SW RESET
     CSL_UART_1_REGS->LCR=0xBF;// First write to the LCR register
     //EFR in this mode occupy same address as IIR in overlay structure
     CSL_UART_1_REGS->IIR|=0x10;// When LCR = 0xBF enable the enhanced feature register

     CSL_UART_1_REGS->LCR&=0x7F;// Here, access to IER and MCR is allowed.
     CSL_UART_1_REGS->IER=0;// Disable interrupt
     CSL_UART_1_REGS->MCR=0;// Force control signals inactive
     CSL_UART_1_REGS->LCR&=0xBF;// Here, UART breaks are removed
     CSL_UART_1_REGS->MDR1=0x07;// Here, UART is in reset or disabled
     CSL_UART_1_REGS->MCR=0x50; //Internal LB enabling + Enabling access to TCL, TLR
     //CSL_UART_1_REGS->TCR=0x0000000F;
     CSL_UART_1_REGS->MSR=0x0F;
     //CSL_UART_1_REGS->TLR=0x00000088;
     CSL_UART_1_REGS->SPR=0x88; //By doing so, TLR determines the FIFO level.
     //SCR enables using FCR to set trigger level
     CSL_UART_1_REGS->SCR&=0x3F;
     //FCR and IIR occupy same spot, clear FIFO, enable FIFO.
     CSL_UART_1_REGS->IIR=0x07;
     CSL_UART_1_REGS->LCR&=0x7F;
     CSL_UART_1_REGS->MCR&=0xBF;
     CSL_UART_1_REGS->LCR=0xBF;
     //EFR in this mode is the same as IIR in standard LCR mode
     CSL_UART_1_REGS->IIR&=0xEF;

     //////////////////////////////////////
     CSL_UART_1_REGS->LCR=0x83;
     //DLH in this mode is the same as IER in standard mode
     CSL_UART_1_REGS->IER=0;
     //DLL in this mode is the same as RHR in standard mode
     CSL_UART_1_REGS->RHR=0x1A; //p.94 of the spec
     CSL_UART_1_REGS->LCR&=0x7F;
     CSL_UART_1_REGS->IER=0x3;//Receiver interrupt
     CSL_UART_1_REGS->MDR1=0;

  • Hi Paul,

    1.

    I followed you suggestion to add the initial list setting in the end of serial8250_set_termios(). 

    /* I found serial8250_set_termios() in 8250.c is the last setting of UART before using it*/

    After doing that, I dumped the registers of UART1.  IER=0x03, IIR=0xc2, LCR=0x03, MCR=0x10, LSR=0x60, MSR/TCR=0x02, SPR/TLR=0x00, MDR1=0x00

    But it made UART1 didn't work. (neither transmit nor receive)

    The error message is "serial8250: too much work for irq41".

    What happen? Did I add the setting in the wrong position?

     

    2.

    I waanted to make the register setting of UART1 like UART0.

    (It was because I thought UART0 & UART1 using the same driver. And UART0 did work. If setting UART1 as UART0, maybe UART1 can work?)

    So I modified TCR of UART1 and I did it as following:

    LCR=0xBF;

    EFR=0x10;

    LCR=0x00;

    MCR=0x40;

    TCR=0x10;

    Then, I also dumped TCR and it still was 0x20 like I showed before.

    Ernest

     

     

  • Ernest said:

    But it made UART1 didn't work. (neither transmit nor receive)

    The error message is "serial8250: too much work for irq41".

     

    I had also seen this kind of error messages earlier on UART0. Setting SCR to 0x08 solved the issue for me.

    Regards, Sudhakar

  • Hello~

    I don’t know why I can receive the interrupt and into the  “receive_chars()” function in 8250.c now! Maybe I got a mistake before!? If I can figure it out, I would let you know. Anyway, there is another issue now. It’s about received data processing.

     

    I saw some difference between UART0 and UART1 about receiving data. When I enter a character on Hyper-terminal, the UART0 would go through the following steps to receive that character.

              1.serial8250_interrupt()

              2.serial8250_handle_port()

              3.receive_chars()

              4.uart_insert_char()

              5.tty_insert_filp_char()

                    tb->flag_buf_ptr[tb->used] = flag;

                    tb->char_buf_ptr[tb->used++] = ch;

     

    But, the UART1 would go through the following steps to receive data after camera sending 7 bytes to it.

             1.serial8250_interrupt()

             2.serial8250_handle_port()

             3.receive_chars()

             4.uart_insert_char()

             5.tty_insert_filp_char()

             6.tty_insert_flip_string_flags()

             memcpy(tb->char_buf_ptr + tb->used, chars, space);

             memcpy(tb->flag_buf_ptr + tb->used, flags, space);

             7.(repeat step8~step9 six times)

             8.uart_insert_char()

             9.tty_insert_filp_char()

                 tb->flag_buf_ptr[tb->used] = flag;

                 tb->char_buf_ptr[tb->used++] = ch;

     

    Is that the reason why I can’t receive data from linux application layer when I call read() system call? How could I make sure the driver write the received data to line discipline buffer for user?

     

    On the other side, the program seem to stop in “job_control()” function of “read_chan()” in “n_tty.c” when I call “read()” system call on linux application layer.

    I don't know the purpose of job_control()! And if the serial driver write received data to the buffer of "line discipline", what is the way that application layer get those data?

    Could anyone help me?

    Thank you very much!!

    Ernest

  • Hi, Ernest,

    I have the same problem: the uart1 can transmit but can't receive.

    Have you figured it out? Can you give me some hints?

    Thank you!

    Kevin

  • Hello Kevin,

    The serial driver will check the end of received data!

    If it find the <enter> is pressed to finish the transmited string from the transmitter, you would get the received data by calling system read() on Linux application layer.

    Therefore, you can add a character "a" in the end of received data and the driver will put them to user space.

     

    Ernest

  • Thanks, pal. But the serial8250_interrupt ISR will be triggered when there are characters flow in through the UART's RxD line, right? However, I can't see it can be triggered. Why?

     

    Thanks.

     

    Kevin

  • Hi Kevin and Earnest,

     

    I am facing the same problem on UART 1 on DM6467. I am able to transmit but unable to receive. No receive interrupts. I am able to see the data on Rx pin of UART1 but no Rx interrupts.

    Can you please let me know how did you solve this problem?

     


    Thanks,

    Amitkumar Solanki