This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

read two input via usart without losing anything

Hello
In my project I should read two usart input ports without losing my input data.Each input should gets a string's length of 120 each 10ms.How can I handle both of them?

I think I can do with two thread such as this diagram
obrazki.elektroda.pl/7019832800_1473252743.png
(does it possible easily or not?)

Or can do it with a simple approach instead of using multi-threading?

Thanks

  • You can poll the two ports quickly.

    Especially if you enable the FIFO so each UART can store multiple characters.

    You can use an interrupt handler that gets trigged whenever the UART has data available. Also then, it's best to use the FIFO to allow larger latencies without character loss.

    You can configure DMA so the UART sends received data directly to a memory buffer.

    Two tasks aren't really well suited for picking up characters from a UART. They are much better for handling the received data at a later stage - such as decoding a protocol. You would want an interrupt handler to pick up the characters and then notify the two tasks that there are data available - having the two tasks poll means they need a huge amount of task switching while lots of poll attempts doesn't find any characters.

  • A pair of buffers filled via UART receive interrupts would suffice.

  • A pair of buffers filled via UART receive interrupts would suffice.

    This is a perfectly acceptable method for two or more UARTS; really only limited by the number of physical ports available and the speed of communication.

    For something so trivial, DMA seems like a massive overkill.

  • "For something so trivial, DMA seems like a massive overkill."

    This depends on what other tasks the program should perform. The main reason for using DMA is if the program needs to do something where you get too big latencies to extract the data before you get a FIFO overflow. DMA also give better option to decide when to take the cost of clearing out the data since the DMA memory buffer can be seen as a huge FIFO.

    In this case, each UART receives 120 characters per 10ms or 12000 characters/second. So with a 16-character FIFO the program must manage a worst-case response time of about 1ms for each UART. So a normal interrupt handler should be fast enough - even without FIFO if no other interrupt handler blocks for too long.

  • Thank you Per Westermark,Westonsupermare Pier,A Person
    I'm going to use DMA as Per Westermark said, because I have some other tasks to do.

    is it possible to increase FIFO of usart of stm32f10x MCU?

  • You don't need DMA because you have other things to do. Interrupt handlers are run 'below' the scheduling of the tasks. So they can pick up the data and store in buffers and then signal to the proper tasks that there is data to process in the buffers.

    Almost all newer processors have FIFO support so they don't need service for every single character received, but can instead cache a number of characters and issue an interrupt when the FIFO watermark is reached or after timeout.

    While there are normally many ways to do things, it's usually best to aim for the simplest solution that is good enough. Save your time for the parts of the program that really needs all attention.

  • By the way - what do you mean by increase FIFO? The size of the FIFO is locked in hardware. But it's often possible to configure the send and receive watermarks. How empty/full the FIFO should be before interrupts are flagged.

    To simulate really huge FIFO, you would need DMA where you register a block of normal RAM and have the hardware pick up received characters and store in the RAM buffer. But it's seldom needed for "slow" UART communications unless there are very special needs that must be accounted for.

  • The design only has a single holding register for each of the transmit and receive paths, so no FIFO. You'd need to create your own buffering behind the hardware, either with IRQ or DMA, depending on the rates, and your appreciation of how to manage/solve the problem. Given the situation, I think you should keep things simple until you have a grasp of the relative complexities, and benefits.

    Using DMA with the Tx paths, either with chains or scatter-gather lists, would be most viable.

  • Thank you for your good explanation
    As matter of fact my MCU should do different jobs such as Ethernet and serial communication and some other jobs.
    a)At the first I thought about using USART IRQ interrupts but I see it wastes my cpu time to collect each receiving bytes (is there any way to buffer 120 characters in a buffer and after it receives all data it arise an interrupt flag? not for each chars)
    b)on the second thought I want to use different threads but it gets more flash volume for cmsis_os library and it's commands.In addition it gets too complex
    c)According to "Per Westermark" and "Westonsupermare Pier" posts I think the best way is USART with DMA.

    what do you think? is there any simple way that I didn't think about it?

  • "The design only has a single holding register for each of the transmit and receive paths, so no FIFO."

    I haven't seen any CPU mentioned.

    With FIFO you would often manage maybe one interrupt per 10 characters - it's quite common with around 16 character long FIFO. Without, you need to pick up every character one-by-one one and has less margin to overrun where a character is lost.

    With DMA, it's the buffer size that decides how often you need to react and chain in a new buffer. A traditional DMA implementation runs doublebuffered so you get an interrupt when the DMA channel switched to the second buffer. Then you can pick up the data from the first buffer and relink it as third buffer.

  • "In addition it gets too complex"

    Having one protocol thread per channel doesn't complicate things. It helps to keep the logic simple. You need to sleep before sending a response? Just sleep. The other threads will manage their own tasks.

  • "I haven't seen any CPU mentioned."

    "is it possible to increase FIFO of usart of stm32f10x MCU?"

  • Thanks for your help
    I started DMA with USART successfully.
    I was wondering if I set input buffer to(for example a packet)100 chars and I receive 50 chars instead of 100 chars (because of any disconnection).After that it will add the new packet with the old one and the arise an interrupt.(half from the old connection and half from new connection)

    I think to use an interrupt to detect the start bit of USART communication and then initialize DMA but as I see my CPU should check each input byte and active dma (it's too boring)

    what's your idea to save DMA's advantages and prevent the above problem?

            DMAStruc.DMA_PeripheralBaseAddr=(uint32_t) &USART1->DR;
            DMAStruc.DMA_MemoryBaseAddr=(uint32_t) buffer;
            DMAStruc.DMA_DIR=DMA_DIR_PeripheralSRC;
            DMAStruc.DMA_BufferSize=sizeof(buffer)-1;
            DMAStruc.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
            DMAStruc.DMA_MemoryInc = DMA_MemoryInc_Enable;
            DMAStruc.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
            DMAStruc.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
            DMAStruc.DMA_Mode=DMA_Mode_Circular;
            DMAStruc.DMA_Priority=DMA_Priority_High;
            DMAStruc.DMA_M2M = DMA_M2M_Disable;
            DMA_Init(DMA1_Channel5,&DMAStruc);
            USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
            DMA_ITConfig(DMA1_Channel5, DMA_IT_TC | DMA_IT_TE, ENABLE);
            DMA_Cmd(DMA1_Channel5, ENABLE);
    
    

  • Hello
    You assume I connect to board to each other with a long wire and under usart communication.

    Now you assume we send a string with this format

    [Start char][98 chars , don't contain start and stop char][Stop char]
    


    and we can rely on our buffer value by checking start and stop chars.
    Now we suppose In receiver we lost one char from 98 chars therefore we get DMA interrupt when it fill up the buffer variable such as this new string
    [Start char][97 chars , don't contain start and stop char][Stop char][Start char]
    so we check start and stop chars and finally we ignore this packet and other packets ( because their first and end chars position have changed in all strings)
    if we don't use DMA we can fill up the buffer with incoming chars and check start and stop chars and also string length and ignore fault string without any effect on other input strings.