Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding HT (half-transfer) callback #6

Open
ranshalit opened this issue Jan 7, 2020 · 4 comments
Open

Adding HT (half-transfer) callback #6

ranshalit opened this issue Jan 7, 2020 · 4 comments

Comments

@ranshalit
Copy link

ranshalit commented Jan 7, 2020

Hello,

I would please like to ask:
Isn't HC (half-transfer complete) actually must be used with circular buffer ? (I see that it is disabled in your example).
I mean, if we have continuous bursts and we process the bytes only when transfer complete (I ignore IDLE for now), it means that during process the start of buffer might get corrupted with new bytes. I think that half transfer should be deal with that.

Another thing, if I may ask, why do you use a software timer after detecting an idle line, instead of calling the uart callback immediately on detection of idle line interrupt ?

Thanks

@akospasztor
Copy link
Owner

Hi there,

You are absolutely right, it is strongly advised to utilize and use the half-transfer complete interrupt if the application constantly receives data in a relatively high speed (that the application cannot process in the "worst-case" scheduling scenario). While one "half" is ready to be processed, the other "half" is available for receiving more data while the application is processing the already received data.

On a sidenote: this code is originated from a project where raw GPS data needed to be processed. Meaning, in a given period a defined (but not fixed size) data-burst was received in this given period. Furthermore, the application had enough resources and time to safely process all the received data even in the worst-case scheduling scenario. That is the reason why the half-transfer complete event is not implemented in this demonstration.

To answer your second question: you need to somehow detect the idle event. This is non-trivial, because you can either receive a bunch of bytes with some delay between the bytes, or you can receive a chunk of data which is entirely continuous (there is zero delay between the bytes). The application cannot know this (and should not!). Of course, you can process an interrupt service routine after each received bytes, however that is exactly the reason why this methos was implemented: to avoid this overhead. Therefore, you need to somehow detect when the Rx line is idle. Some MCU-s, for example the L4-series MCUs from ST have a built-in functionality for exactly this purpose (take a look at the UART RTOR register in the reference manual). However, some MCUs don't have this built-in functionality, meaning the user has to utilize some kind of software-based timer solution. This project is a generic demonstration, this is why this implementation utilizes a software timer-based solution.

@akospasztor
Copy link
Owner

I just saw that your original question was whether you can use the same callback function for the HT complete interrupt. The answer is yes, but you need to implement an additional buffer-handling mechanism to handle the two half-buffers appropriately during processing the data.

@ranshalit
Copy link
Author

ranshalit commented Jan 9, 2020

Hi,

Thanks for the reply.
I use the demonstration with slight modifications:

  1. I've enabled the HT event, and added HT callback as following
    void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart) { dma_uart_rx.flag = 1; HAL_UART_RxCpltCallback(huart); }
    It seems to work well.
  2. I also use the IDLE event in uart, but without using a timer
    2.1 adding in hal a new callback HAL_UART_RxIdleCallback , which is detected in
    HAL_UART_IRQHandler
    ......flag= __HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE); flag_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_IDLE); if((flag!= RESET) && (flag_source != RESET)) { __HAL_UART_CLEAR_IDLEFLAG(huart); HAL_UART_RxIdleCallback(huart); }
    and
    void HAL_UART_RxIdleCallback(UART_HandleTypeDef *huart) { dma_uart_rx.flag = 1; HAL_UART_RxCpltCallback(huart); }
    It also seems also to work well (simulate it by simply clicking on terminal).

Thanks for this great demonstration, it is very helpful, I think ST should add this into their example package.

@ranshalit ranshalit changed the title Adding HC callback Adding HT (half-transfer) callback Jan 9, 2020
@ranshalit
Copy link
Author

Just to add,
In my half-transfer complete callback, I actually just set the flag (dma_uart_rx.flag = 1) and call the same routine HAL_UART_RxCpltCallback, which means that it expects to find the start somewhere in the middle (just as what happens in idle case).
Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants