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?

23 REPLIES 23

@Andrew Neil wrote:

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"


@techdesk so in this:

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.....
};

are  those timings all done with blocking delays?

If so, then you need to make that non-blocking.

You could use the same principle as here:

https://docs.arduino.cc/built-in-examples/digital/BlinkWithoutDelay/

HAL_GetTick() is equivalent to the Arduino millis() ...

 


@techdesk wrote:

Blocking can be understood as...


Yes, we know what the term means.

What's unclear is how/why your code is blocking.

Remember: we can't see your code! 

"executing" an array doesn't really mean anything.

 


While I was typing, @Tesla DeLorean wrote:

Perhap use HAL_GetTick(), leave, and then delta the time difference at the next iteration,


@techdesk  - That's essentially what the Arduino example I pointed to does.


@Andrew Neil wrote:

You could use the same principle as here:

https://docs.arduino.cc/built-in-examples/digital/BlinkWithoutDelay/

HAL_GetTick() is equivalent to the Arduino millis() ...


Here you go - blinking two LEDs with unrelated periods:

 

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */

  uint32_t ld4_blu_interval = 2000;
  uint32_t ld3_grn_interval = 3000;

  uint32_t ld4_blu_previous_tick = 0;
  uint32_t ld3_grn_previous_tick = 0;

  while (1)
  {
	  uint32_t current_tick = HAL_GetTick();

	  if( current_tick - ld4_blu_previous_tick >= ld4_blu_interval )
	  {
		  ld4_blu_previous_tick = current_tick;
		  HAL_GPIO_TogglePin( ld4_blu_GPIO_Port, ld4_blu_Pin );
	  }

	  if( current_tick - ld3_grn_previous_tick >= ld3_grn_interval )
	  {
		  ld3_grn_previous_tick = current_tick;
		  HAL_GPIO_TogglePin( ld3_grn_GPIO_Port, ld3_grn_Pin );
	  }

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

 

(Tested on an F0-DISCOVERY board, with User LEDs LD3 Green and LD4 Blue)

I've just duplicated everything for the 2 LEDs there; more generally, it'd be better to factor that into a function (or functions) ...

 

#NonBlockingDelay #NonBlockingBlinky #NoDelayBlinky

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

You haven't presented any code which blocks or illustrates the issue. This forum is not a code writing service.

The air of entitlement in this post is offputting.

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

Like I said, I finally manged to:
1. Read GPS via USART2,
2. Send/Receive text commands via USART1.
3. Execute a list of commands in the Main()
ALL simultaneously!
I. I enabled Interrupts for both USARTs
2. added this also in the Main() (just an example of my code)

HAL_UART_Receive_IT(&huart1, (uint8_t *)&received_char, 1);

HAL_UART_Receive_IT(&huart2, (uint8_t *)&received_char, 1);
Without these lines in the Main(), it will NEVER work
This is a super feat especially for projects requiring autonomous mode.
If anyone needs further details, I will provide.
In any case, thank you all for your helping attempts


@techdesk wrote:

Like I said, I finally manged to:
1. Read GPS via USART2,
2. Send/Receive text commands via USART1.
3. Execute a list of commands in the Main()
ALL simultaneously!
I. I enabled Interrupts for both USARTs
2. added this also in the Main() (just an example of my code)

HAL_UART_Receive_IT(&huart1, (uint8_t *)&received_char, 1);

HAL_UART_Receive_IT(&huart2, (uint8_t *)&received_char, 1);
Without these lines in the Main(), it will NEVER work
This is a super feat especially for projects requiring autonomous mode.
If anyone needs further details, I will provide.
In any case, thank you all for your helping attempts


You say you added HAL_UART_Receive_IT to main. But you don't say where in main. 

Show MORE of your complete code so we can see the bigger picture, not just snippets

Tips and Tricks with TimerCallback https://www.youtube.com/@eebykarl
If you find my solution useful, please click the Accept as Solution so others see the solution.

@techdesk wrote:

3. Execute a list of commands in the Main()


So is that your "execute an array" part?

And that's the part that was "blocking" originally?

 


@techdesk wrote:

Like I said, I finally manged to:


So you've now solved the issue? If so, please mark the actual solution.

It would be helpful for future readers if you would describe what, exactly, was causing the "blocking" originally, and how you solved that.

Basically as you know sometime a simple overlooked code causes tons of headaches.
My program flow

Int Main ()
.....
......
instructionsexecute(): //This function used to run and complete then only other functions used to run. This was causing the blocking

HAL_UART_Receive_IT(&huart1, (uint8_t *)&received_char, 1);

HAL_UART_Receive_IT(&huart2, (uint8_t *)&received_char, 1);


Then I enabled the USART1 and 2 global interrupts and ran the functions in the automatic 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

My initial mistake was that I mistakenly unchecked the global Interrupt for USART2
Thus the solution is very simple.
However, it took me me hours to discover that these two lines had to be placed in the Int Main() otherwise it will NEVER work

HAL_UART_Receive_IT(&huart1, (uint8_t *)&received_char, 1);
HAL_UART_Receive_IT(&huart2, (uint8_t *)&received_char, 1);


Did I clarify myself well??


@techdesk wrote:

Did I clarify myself well??


Not really.

 


@techdesk wrote:

instructionsexecute(): //This function used to run and complete then only other functions used to run. This was causing the blocking


What was that doing? Why was it blocking?

How, exactly, did enabling UART interrupts fix that?

 

 


"What was it doing? Why was it blocking?"

To answer this question:
The program wasn't doing anything unusual—it was simply executing the function as written. By default, all programming languages, including those used for STM32, operate sequentially unless explicitly programmed for concurrency.

For example, in C++ or Delphi, programs execute instructions sequentially. To allow other tasks to run concurrently, you might add a command like Application.ProcessMessages (in Delphi) or similar constructs in other languages.

In my case, the instructionsexecute() function was running sequentially, and so was my USART polling. Both were handled in a linear, step-by-step manner.

To achieve concurrency—allowing something like GPS polling to run in parallel with instructionsexecute()—you need to enable global interrupts for the USART. This lets the processor handle incoming USART data (like GPS polling) while continuing to execute the main instructionsexecute() function.