My external UART driver don't work

Hi all.

Test_GPS_Driver.zip

I have a problem with a driver that I wrote (it's the first driver I do). I attach an example code.
If in the gps2_thread_entry.cpp comment the line 58 the gps1 works well. If I try to initialize both gps the program gets stuck in the gps_init function. The interrupts seem to overlap.
It's probably wrong the way I did the driver, but I don't understand where I'm wrong :(

Thank ypu

Paolo

  • How is the external UART connected to the Synergy device, how are the chip select s CSA# and CSB# driven to select between the 2 UART channels in the external device?
  • In reply to Jeremy:

    Hi Jeremy.
    We use the same CS but with a multiplexer through the address signals we create the various CS of the uart.
    On a hardware level it seems to work (if I use only one uart. It doesn't matter whether it is one or the other).
    The problem should be in the driver (although I don't know where).

    Thanks
    Paolo
  • In reply to Paolo Miatto:

    Anyone have any suggestions?

    Thanks
    Paolo
  • In reply to Paolo Miatto:

    Can anyone help me?

    Paolo
  • In reply to Paolo Miatto:

    It looks OK to me.
    But your code is too complex for someone don't have much knowledge of TL16C752D.

    Give it a try adding mutex to keep from 2 external intterupts mix up completely.

    --------------------------------------------------------------------------
    void g_external_irq_gps1_callback(external_irq_callback_args_t *p_args)
    {
    SSP_PARAMETER_NOT_USED(p_args);

    tx_mutex_get(&_gps_mutex, TX_WAIT_FOREVER);
    uart_external_check_irq(gps1_uart);
    tx_mutex_put(&_gps_mutex);
    }

    void g_external_irq_gps2_callback(external_irq_callback_args_t *p_args)
    {
    SSP_PARAMETER_NOT_USED(p_args);

    tx_mutex_get(&_gps_mutex, TX_WAIT_FOREVER);
    uart_external_check_irq(gps2_uart);
    tx_mutex_put(&_gps_mutex);
    }
    --------------------------------------------------------------------------

    If this don't work well, I think you had better ask to Texas Instruments.
  • In reply to tenballs:

    You can't use the wait option TX_WAIT_FOREVER in an interrupt context, only TX_NO_WAIT can be used. Also you don't check the return value from the call to tx_mutex_get().
  • In reply to Jeremy:

    Hi tenballs and Jeremy.

    For Jeremy
    I write this code:

    void g_external_irq_gps1_callback(external_irq_callback_args_t *p_args)
    {
    SSP_PARAMETER_NOT_USED(p_args);
    UINT status = tx_mutex_get(&g_gps_mutex, TX_NO_WAIT);
    if (status == TX_SUCCESS) {
    uart_external_check_irq(gps1_uart);
    tx_mutex_put(&g_gps_mutex);
    }
    }


    void g_external_irq_gps2_callback(external_irq_callback_args_t *p_args)
    {
    SSP_PARAMETER_NOT_USED(p_args);
    UINT status = tx_mutex_get(&g_gps_mutex, TX_NO_WAIT);
    if (status == TX_SUCCESS) {
    uart_external_check_irq(gps2_uart);
    tx_mutex_put(&g_gps_mutex);
    }
    }

    But now the program no longer crashes, but now I lose gps data (So if the mutex is already taken, I go out without reading the data, but by not reading, the interrupt signal is not reset and I am not return in the routine.).
    How should I write the code?

    For Tenballs.

    The problem is not with the TI chip, but with how I manage the two ICs. I think

    Best Regards
    Paolo
  • In reply to Jeremy:

    Hi Jeremy,

    Thank you for supplement about my lack of consideration.
  • In reply to Paolo Miatto:

    Hi Paolo,

    >But now the program no longer crashes, but now I lose gps data (So if the mutex is already taken, I go out without reading the data, but by not reading, the interrupt signal is not reset and I am not return in the routine.).

    Which means, one interrupt callback try running during the other callback is executing.
    If interrupt cutting in never occur, tx_mutex_get() always returns success code.
    It is common problem if the reentrancy of intterupt callback is not considered efficiently.

    >The problem is not with the TI chip, but with how I manage the two ICs. I think
    Do you mean you can handle if only single chip is used?
    TL16C752D has dual UARTs, so I think you use one chip.

    Reentrancy problem often occur when the following conditions is satisfied.

    1. Two or more callback functions uses same global variables.

    To resolve that issue, rewrite as that any function call made each callback never overlap.
    And also modify function parameter from pointer to direct access.

    It may takes time, but it is necessary to find out bugs.

  • In reply to tenballs:

    >Do you mean you can handle if only single chip is used?
    >TL16C752D has dual UARTs, so I think you use one chip
    TL16C75D has 2 uart, but the other has been scheduled to use it for the modem (the code for the modem I have not yet done).

    If you see the code for the 2 uarts, I used separate variables, and those used in the callback are declared volatile.

    Renesas support made me try to put semaphores in callbacks and read the data in the thread. But the problem remains if I use the two uart.

    void gps2_thread_entry(void)
    {


    /* TODO: add your own code here */
    while (1)
    {
    process_irq(&gps1_uart);
    process_irq(&gps2_uart);
    tx_thread_sleep(1);
    }
    }

    void g_external_irq_gps1_callback(external_irq_callback_args_t *p_args)
    {
    SSP_PARAMETER_NOT_USED(p_args);

    // uart_external_check_irq(&gps1_uart);
    tx_semaphore_put(gps1_uart.irq_sem);
    }

    void g_external_irq_gps2_callback(external_irq_callback_args_t *p_args)
    {
    SSP_PARAMETER_NOT_USED(p_args);

    // uart_external_check_irq(&gps2_uart);
    tx_semaphore_put(gps2_uart.irq_sem);
    }

    void process_irq(uart_external_cfg *uart_cfg)
    {
    UINT status;

    status = tx_semaphore_get((*uart_cfg).irq_sem, TX_NO_WAIT);
    if( TX_SUCCESS == status )
    {
    uart_external_check_irq(uart_cfg);
    }
    }

    Paolo
  • In reply to Paolo Miatto:

    >Renesas support made me try to put semaphores in callbacks and read the data in the thread. But the problem remains if I use the two uart.

    Let me get this straight.
    Are this "two uart" interrupts caused by same chip?

    >Renesas support made me try to put semaphores in callbacks and read the data in the thread. But the problem remains if I use the two uart.

    Semaphores are useful for overlap access prevention, but often helpless for interrupt collision.

    I have read your code, but finding bugs are very difficult without real unit.


    In my case, I often add debug variables to analyze such problems.

  • In reply to tenballs:

    > Are this "two uart" interrupts caused by same chip?
    No, the two interrupts are generated by two chips.

    > I have read your code, but finding bugs are very difficult without real unit.
    I know :(

    > In my case, I often add debug variables to analyze such problems.
    That's what I'm trying to do.

    Thanks
    Paolo
  • In reply to Paolo Miatto:

    I may have found suspicious places.
    Why do you set same channel number "CH_B" to both gps units?
    It seems subroutines called by interrupt access same regiters and buffers.

    --------------------------------------------------------------
    // Init UART
    gps1_uart.uart_addr = ADDR_GPS1_CS;
    gps1_uart.speed = 38400; // 38.4Kbps
    gps1_uart.channel_num = CH_B;
    gps1_uart.tx_max_data_size = TX_BUFFER_SIZE;
    gps1_uart.tx_buff = gps1_uart_tx_buff;
    gps1_uart.rx_buff_size = RX_BUFFER_SIZE;
    gps1_uart.rx_buff = gps1_uart_rx_buff;
    gps1_uart.rx_data_size = 0;
    gps1_uart.irq = (external_irq_instance_t *)&g_external_irq_gps1;

    gps2_uart.uart_addr = ADDR_GPS2_CS;
    gps2_uart.speed = 38400; // 38.4Kbps
    gps2_uart.channel_num = CH_B;
    gps2_uart.tx_max_data_size = TX_BUFFER_SIZE;
    gps2_uart.tx_buff = gps2_uart_tx_buff;
    gps2_uart.rx_buff_size = RX_BUFFER_SIZE;
    gps2_uart.rx_buff = gps2_uart_rx_buff;
    gps2_uart.rx_data_size = 0;
    gps2_uart.irq = (external_irq_instance_t *)&g_external_irq_gps2;
    --------------------------------------------------------------

     

    --------------------------------------------------------------

    void uart_external_read(uart_external_cfg &uart_cfg)
    {
    TL16C752D_REGISTER volatile * const uart = (TL16C752D_REGISTER volatile * const) uart_cfg.uart_addr;

    while (r_tl16c752d_rx_data_present(uart, uart_cfg.channel_num)) {
    if (uart_cfg.rx_data_size == uart_cfg.rx_buff_size) {
    // RX buffer overflow
    uart_cfg.rx_buffer_overflow = true;
    // I provisionally throw away all the data
    uart_cfg.rx_data_size = 0;
    // --uart_cfg.rx_data_size;
    // memcpy((void *)uart_cfg.rx_buff, (void *)(uart_cfg.rx_buff + 1), uart_cfg.rx_data_size - 1);
    }

    uart_cfg.rx_buff[uart_cfg.rx_data_size++] = r_tl16c752d_read_byte(uart);
    }
    }

    --------------------------------------------------------------

  • In reply to tenballs:

    > Why do you set same channel number "CH_B" to both gps units?
    Because the gps are on the second uart of each ic. The registers are different because the two gps have different chip addresses (ADDR_GPS1_CS and ADDR_GPS2_CS).

    Paolo
  • In reply to Paolo Miatto:

    Though I don't know if it's the cause, Some places which are easy to crash system was found.

    1. You call same functions such as uart_external_read/write which accesses global variables from both thread function and interrupt service in spite of auto interrupt enabling.
    Maybe it causes memcpy problem you asked before in forum's other thread.
    For the time being, I recommend you set "Interrupt enabled after initialization" of 2 IRQs to "False" and enable them manually after gps_init() is called.

    2. It's better not to access global flags such as "uart.rx_data_size" in both thread function and interrupt service.
    Especially on multi-thread OS.


    >Because the gps are on the second uart of each ic. The registers are different because the two gps have different chip addresses (ADDR_GPS1_CS and ADDR_GPS2_CS).
    I see.
    You mean you use one channel per chip.