Re: uart_pipe spinning problem for stm32


Michael Hope
 

Hi Dmitry.  If it helps, uart_console is also used by the qemu_cortex_m3 board for the host networking interface. The serial driver [1] uses the masked interrupt status reg (UARTMIS) [2 pg 460] and not the raw status (UARTRIS).

-- Michael



On 30 November 2017 at 18:48, Dmitry Shmidt via Zephyr-devel <zephyr-devel@...> wrote:
Hi Erwan,

On Thu, Nov 30, 2017 at 1:28 AM, Erwan Gouriou <erwan.gouriou@...> wrote:
> Hi Dmitri,
>
>
> Can you explicit the functional issue, before we do any change?
>
> About TXE:
> TXE is "TX ready", hence indeed likely to be often 1 indeed.
>
> Then, this code is located in isr callback, hence it is hit only on UART
> IRQ.
> Having TXE set to TRUE at this step should not be an issue since we check
> rx_ready before read to discriminate if IRQ was actually raised for RX.
>
> Did I missed something?

The problem is in uart_pipe_isr() logic. It is never-ending (spinning)
after first
time entrance: it is still processing RX but its nature doesn't allow any user
threads to get control.

uart_pipe_isr() is called on RX interrupt:

static void uart_pipe_isr(struct device *unused) {
         while (uart_irq_update(uart_pipe_dev)
                   && uart_irq_is_pending(uart_pipe_dev)) {
                ...
         }

uart_irq_update() is always 1 and uart_irq_is_pending()
is also always 1 (at least in case of stm32):
         return (LL_USART_IsActiveFlag_RXNE(UartInstance) ||
                     LL_USART_IsActiveFlag_TXE(UartInstance));

So possible solutions as I can see are:
1) Use uart_irq_rx_ready() instead of  uart_irq_is_pending() in
    while() in uart_pipe.c
 2) Change uart_stm32_irq_is_pending() to return only RNXE -
   however other drivers also return RXE || TXE
3) Mask TXE as Michael suggested that is actually (2).

> Erwan
>
> On 30 November 2017 at 01:07, Dmitry Shmidt via Zephyr-devel
> <zephyr-devel@lists.zephyrproject.org> wrote:
>>
>> Hello,
>>
>> In uart_pipe.c code:
>> static void uart_pipe_isr(struct device *unused)
>> {
>>         ARG_UNUSED(unused);
>>
>>         while (uart_irq_update(uart_pipe_dev)
>>                   && uart_irq_is_pending(uart_pipe_dev)) {
>> ...
>> }
>>
>> uart_irq_update() is returning 1 and
>> uart_irq_is_pending() is always TRUE for stm32, because
>> despite RXNE is cleared, TXE is always 1.
>> static int uart_stm32_irq_is_pending(struct device *dev)
>> {
>>         USART_TypeDef *UartInstance = UART_STRUCT(dev);
>>
>>         return (LL_USART_IsActiveFlag_RXNE(UartInstance) ||
>>                    LL_USART_IsActiveFlag_TXE(UartInstance));
>>
>> TXE is always 1 probably by design because poll_out is working
>> properly:
>> static unsigned char uart_stm32_poll_out(struct device *dev,
>>
>> unsigned char c)
>> {
>>         USART_TypeDef *UartInstance = UART_STRUCT(dev);
>>
>>         /* Wait for TXE flag to be raised */
>>         while (!LL_USART_IsActiveFlag_TXE(UartInstance))
>>                 ;
>>
>> Please advise what is the right way to fix this issue:
>> 1) Use uart_irq_rx_ready() instead of  uart_irq_is_pending() in
>> while() in uart_pipe.c
>> 2) Change uart_stm32_irq_is_pending() to return only RNXE -
>> however other drivers also return RXE || TXE
>> 3) Clear TXE during input processing
>>
>> Thanks,
>> Dmitry
>> _______________________________________________
>> Zephyr-devel mailing list
>> Zephyr-devel@lists.zephyrproject.org
>> https://lists.zephyrproject.org/mailman/listinfo/zephyr-devel
>
>
_______________________________________________
Zephyr-devel mailing list
Zephyr-devel@lists.zephyrproject.org
https://lists.zephyrproject.org/mailman/listinfo/zephyr-devel

Join devel@lists.zephyrproject.org to automatically receive all group messages.