cancel
Showing results for 
Search instead for 
Did you mean: 

Non Blocking programming

techdesk
Associate III

I have a STM32F411 board connected with a GPS module connected onto USART2
I also have Tim1 and Tim3 configured for PWM generation on their channels respectively.

I am running a list of commands (from an array) to execute line for line.

Most of the execution is in the form of assigning new values to the Timer channels

Eg: __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, motor1_speed); Motor speed is a variable assigned from the list. As the program executes the list (by iterating  line for line, these variables get assigned those values.)

The GPS on the other hand is being polled via USART2

The problem is that I need both the execution of the array as well as the GPS to continue running.

However, the array execution is causing a "blocking issue". I have about 15 lines of instructions in the executing array. The GPS will only work AFTER ALL the commands of the array has been executed due to its blocking issue.

I investigated from many sources who advised:

  1. Use RTOS - this did not work. It still blocks
  2. Use another Timer to run the GPS. - Still did not work.

Any assistance here?

1 ACCEPTED SOLUTION

Accepted Solutions

@techdesk wrote:

As the execution iterates (after the time in seconds) it assigns the values to motor2 and motor3 respectively. 
That said, these executing lines are blocking the GPS


That doesn't make sense:  those __HAL_TIM_SET_COMPARE are simply writing a value to a register - the time for which they "block" is minuscule.

Or are you saying you do that continuously in a tight loop?

 


@techdesk wrote:

Here is the code:

 

#define UART_QUEUE_SIZE 64 QueueHandle_t uartQueue;

void GPS_Task(void *pvParameters) { uint8_t received_byte; while (1) { // Wait for a byte from the queue if (xQueueReceive(uartQueue, &received_byte, portMAX_DELAY) == pdPASS) { // Process the byte processGPSData(&received_byte, 1); } } }

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart->Instance == USART2) { // Send received byte to the queue xQueueSendFromISR(uartQueue, &received_char, NULL); // Re-enable UART interrupt for next byte HAL_UART_Receive_IT(&huart2, &received_char, 1); } }
In the HAL_UART_RxCpltCallback() I have this:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart->Instance == USART2) { // Send received byte to the queue xQueueSendFromISR(uartQueue, &received_char, NULL); // Re-enable UART interrupt for next byte HAL_UART_Receive_IT(&huart2, &received_char, 1); } }

 


Please would you re-post that - each function seems to have got compressed onto a single line!

View solution in original post

15 REPLIES 15
TDK
Guru

There is no reason you can't have these in two different tasks in FreeRTOS.

Note that only one thread can run at a time, it will switch back and forth between them at a relatively fast rate.

> However, the array execution is causing a "blocking issue".

Too vague. Step through the code. What is happening? What do you expect to happen instead?

If you feel a post has answered your question, please click "Accept as Solution".

Ok, firstly the answer to your question:
"Too vague. Step through the code. What is happening? What do you expect to happen instead?"
Here is the array:

MotorInstruction instructions[] = {

{'F', {900, 900}, 10}, // Move forward at speed 900 for 10 seconds

{'F', {100, 600}, 3}, // Turn with speeds 500 and 600 for 3 seconds

{'F', {600, 600}, 10}, // Move forward at speed 600 for 10 seconds

{'F', {700, 700}, 3},// Move forward at speed 1000 for 3 seconds

{'F', {900, 900}, 3},

// etc etc.....

};

These figures are assigned to the respective timer channels 
eg: 

__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, motor2_speed);
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, motor3_speed);


As the execution iterates (after the time in seconds) it assigns the values to motor2 and motor3 respectively. 
That said, these executing lines are blocking the GPS which is automatically coming through the USART2.
You mention RTOS.
I spent hours with the RTOS task. Maybe I was not doing things correctly.

Here is the code:

#define UART_QUEUE_SIZE 64 QueueHandle_t uartQueue;

void GPS_Task(void *pvParameters) { uint8_t received_byte; while (1) { // Wait for a byte from the queue if (xQueueReceive(uartQueue, &received_byte, portMAX_DELAY) == pdPASS) { // Process the byte processGPSData(&received_byte, 1); } } }

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart->Instance == USART2) { // Send received byte to the queue xQueueSendFromISR(uartQueue, &received_char, NULL); // Re-enable UART interrupt for next byte HAL_UART_Receive_IT(&huart2, &received_char, 1); } }
In the HAL_UART_RxCpltCallback() I have this:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart->Instance == USART2) { // Send received byte to the queue xQueueSendFromISR(uartQueue, &received_char, NULL); // Re-enable UART interrupt for next byte HAL_UART_Receive_IT(&huart2, &received_char, 1); } }

Then in my INT Main
I have this:

 // Initialize the FreeRTOS queue
    uartQueue = xQueueCreate(UART_QUEUE_SIZE, sizeof(uint8_t));
    if (uartQueue == NULL) {
        // Handle queue creation error
        Error_Handler();    }
    // Create the GPS task
    xTaskCreate(GPS_Task, "GPS_Task", 128, NULL, 2, NULL);  // Stack size = 128, priority = 2
    // Start the scheduler
    vTaskStartScheduler();

Like I said, this code ought to work. But nothing happens

The __HAL_TIM_SET_COMPARE statements do not block. Must be some other reason.

In your FreeRTOS code, you're only creating a task for the GPS. You should have another task for the motor control, if you want them to run concurrently.

If you feel a post has answered your question, please click "Accept as Solution".

@techdesk wrote:

As the execution iterates (after the time in seconds) it assigns the values to motor2 and motor3 respectively. 
That said, these executing lines are blocking the GPS


That doesn't make sense:  those __HAL_TIM_SET_COMPARE are simply writing a value to a register - the time for which they "block" is minuscule.

Or are you saying you do that continuously in a tight loop?

 


@techdesk wrote:

Here is the code:

 

#define UART_QUEUE_SIZE 64 QueueHandle_t uartQueue;

void GPS_Task(void *pvParameters) { uint8_t received_byte; while (1) { // Wait for a byte from the queue if (xQueueReceive(uartQueue, &received_byte, portMAX_DELAY) == pdPASS) { // Process the byte processGPSData(&received_byte, 1); } } }

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart->Instance == USART2) { // Send received byte to the queue xQueueSendFromISR(uartQueue, &received_char, NULL); // Re-enable UART interrupt for next byte HAL_UART_Receive_IT(&huart2, &received_char, 1); } }
In the HAL_UART_RxCpltCallback() I have this:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart->Instance == USART2) { // Send received byte to the queue xQueueSendFromISR(uartQueue, &received_char, NULL); // Re-enable UART interrupt for next byte HAL_UART_Receive_IT(&huart2, &received_char, 1); } }

 


Please would you re-post that - each function seems to have got compressed onto a single line!

What exactly is "not working"?

What exactly is "blocking" here?

Break the problem down, is the GPS reading and parsing successfully?

This type of one byte queuing is going to be very burdensome. Perhaps make a bigger buffer you fill in the interrupt handler, QUICKLY,  and the process the buffer as you have occasion to do some, perhaps after you've done the super-critical stuff. Parsing shouldn't take a lot of time, unless you hang it up with other output, or code that spins to accomodately slower processes.

What you've described to this point could be done with very light weight code, with some time critical stuff handled in interrupts, and others is a main loop. General rule would be to do stuff you can, don't stall, come back and check later.

Most difficult thing for most people to break free of is linear code execution, and simply move it to multiple threads enforcing similar knock-on dependencies and sequencing.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

I accidentally pressed the "accepted".  Sorry
Any case, I am still trying to work around RTOS. 
Regarding the GPS, I have reverted to buffer mode. So I get bigger chunks.
Look, the GPS function WORKS 100%. But like I said the execution of the Array is blocking it. Until the array is finished, the gps shows again. RTOS in my opinion is maybe for lrager processors. Boards like the STMF411 may not be suitable. Also, the RTOS works. but execution is SLOW. Very Slow. 10 seconds turn into almost 60 seconds 
Anycase, I will just battle on. I will retry and juggle between the USART DMA etc. I will find some solution. And belive me I have tried abundantly. 
Many responders to this thread give advice, but no sample code to test. Best not to respond rather than give fresh air code 



@techdesk wrote:

I accidentally pressed the "accepted".  Sorry


You can un-mark it:

https://community.st.com/t5/community-guidelines/help-others-to-solve-their-issues/ta-p/575256#:~:text=If%20you%20accidentally%20chose%20the%20wrong%20post%20as%20solution%2C%20you%20can%20always%20revert%20this%20action%20by%20clicking%20%22Not%20the%20Solution%22

 


@techdesk wrote:

 the execution of the Array is blocking it. 


So make it non-blocking.

It's still not at all clear what all this "execution of the Array" stuff is about, and why your code to do it is "blocking"

You're going to have to give more detail if you want specific suggestions.

Yeah, but not seeing any of the Array processing code, nor how it's blocking. Perhap use HAL_GetTick(), leave, and then delta the time difference at the next iteration, stepping to the next in the sequence as each time elapses.

Don't sit waiting for each section to complete.

The F411 should certainly be capable of parsing GPS and driving two PWM concurrently.

>>Many responders to this thread give advice, but no sample code to test. Best not to respond rather than give fresh air code 

And presumably none are paid to do your job either?

Sort of things you should expect of your supervisor or collegues?

 

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Blocking can be understood as:
If you have a shopkeeper that is serving another customer and filling his basket, despite that the shopkeeper hears your request will ONLY be served you once he completes his business with his customer.
Although a  Non blocking shopkeeper does not  exist, In a hypothetical case he will serve you too - simultaneously.