cancel
Showing results for 
Search instead for 
Did you mean: 

I am using the nucleoH743ZI with Free RTOS. Try to send data via UART from each TASK.In Round robin scheduling, First task sends the data via UART, then context switch Second task tried to send the data via UART, handle of the UART was in Busy always.

Vel
Associate III

In "prioritized preemptive scheduling", able to send the data to UART from each task.

For the round robin, I set the time slice of 200 ms.Have the doubt like how much time taken to change the state of UART handle from "Busy" to "Ready"?.

7 REPLIES 7
Bob S
Principal

Without posting your code (which would be a big help), all we can do is guess. Are you using HAL? Do you have some kind of semaphore regulating access to the UART? My guess us that, for whatever reason, the UART is still transmitting from one task when the round robin scheduler switches tasks. But like I said, posting your code would be helpful.

Vel
Associate III

Thanks for the response,

I am using the HAL function for transmit the data, and use the semaphore variable to access the UART. Attached the code for reference.

Bob S
Principal

Check the return values from your HAL_UART_Transmit() calls and somehow report anything other than HAL_OK. If they ever return anything other than HAL_OK the UART will still be marked as "busy". Though WHY they would do that is a puzzle. A timeout of 100ms should be more than plenty for 7 bytes at 115020 buad with no flow control enabled on the UART (RTS/CTS). Unless the HAL_GetTick() returns some value other than "milliseconds". Are you sure TIM6 is giving you 1ms interrupts? Of course that doesn't explain why it works with a different scheduling scheme.

Vel
Associate III

Thank you for the response.

a) I checked the return value of HAL_UART_Transmit(), it returns HAL_BUSY always.

b) Checked HAL_GetTick() which returns the values in milliseconds.

c) Checked the 1ms interrupt of TIM6 inside HAL_TIM_PeriodElapsedCallback function using oscilloscope and it is 1 ms

-I did not understand the TIM6 relevance as suggested.

I am not sure how else to check or understand this issue

It looked like you code was configured to use TIM6 as the source of the sys tick clock (see HAL_TIM_PeriodElapsedCallback), so I was wildly guessing that maybe an interrupt period that was much less that 1ms might be messing with things. I obviously hadn't had my coffee yet yesterday as that wasn't the best suggestion.

Which HAL_UART_Transmit() call always returns HAL_BUSY? The one in task2? Both of them? Does the call in task1 always return HAL_OK? If HAL_UART_Transmit() returns HAL_OK then it **should** have reset the UART state to "not busy". So maybe add a test in task1 after HAL_UART_Transmit() that checks the value of huart1->gState (should be HAL_UART_STATE_READY) - I'm grasping at straws here.

With round robin scheduling, what do you see on the UART output? Is it a series of "Task1" strings, or only 1 string?

Hmmm... I just noticed this - your code ALWAYS calls xSemaphoreGive(), even if the xSemaphoreTake() times out. Is that allowed? I would suspect not, but I don't know the details of FreeRTOS. Most systems you can only release an semaphore that you own.

I don't know how round robin scheduling handles two tasks of equal priority where one task is waiting for a semaphore that that other task owns and then releases. Does it then immediately switch to the other task so it can take the semaphore? Or does it always wait for the 200ms time slice?

What happens if you add a delay after releasing the semaphore (using the FreeRTOS delay or sleep or whatever it is called function)?

You've obviously cut out some of the code in the sample you posted. Is there ANY other task that is trying to access this UART, perhaps to receive data?

Sorry - that's about all I've got, other than to suggest running your debugger and tracing into both HAL_UART_Transmit calls and see why they are failing. When looking at the code, keep in mind that the __HAL_LOCK() macro can cause a return from HAL_UART_Transmit() with a HAL_BUSY status.

Vel
Associate III

Hi. To answer your questions:

Which HAL_UART_Transmit() call always returns HAL_BUSY? The one in Task 2? Both of them?

a) First Task 2 gets the UART handle, "Task 2" string is sent to UART once, then it status is updated to "HAL_UART_STATE_READY". To checks the value of huart1->gState,I add a test

(while(HAL_UART_GetState(&huart1)!= HAL_UART_STATE_READY)) in Task 2 after HAL_UART_Transmit(),

then context switch occurs to "Task 1" . Inside Task 1, while checking the haurt1 at the HAL_UART_Transmit function,

huart1->gState is in "HAL_UART_STATE_BUSY_TX" state.

With round robin scheduling, what do you see on the UART output? Is it a series of "Task1" strings, or only 1 string?

b) Always Task 2 sends a series of "Task2" strings to UART.

your code ALWAYS calls xSemaphoreGive(), even if the xSemaphoreTake() times out. Is that allowed? 

To my understading that should not be an issue as the give will just wait for a take to happen. https://www.freertos.org/FreeRTOS_Support_Forum_Archive/March_2016/freertos_What_happens_if_semaphore_is_given_before_it_is_taken_e3c5856aj.html suggests the same

I don't know how round robin scheduling handles two tasks of equal priority where one task is waiting for a semaphore that that other task owns and then releases. Does it then immediately switch to the other task so it can take the semaphore? Or does it always wait for the 200ms time slice?

The way round robin works is if context switch is triggered then the task will change else the the context switch will be anyways triggered at the given time slice. It executes the entire task and then switches context (at the time slice)is what i think since I have given a 'give' before anyways. The only time i feel it will switch context before the time slice is when in 'take' the handle is busy, so it goes to wait state and because of going into wait state the context is switched.

What happens if you add a delay after releasing the semaphore (using the FreeRTOS delay or sleep or whatever it is called function)?

Using a delay means the task goes in wait state so it will context switch itself and the next tast will run. I did the same and the context switch happened but the uart handle became free as well. Both the strings are now printed but, the point was to print the strings for the entire time slice(200ms) which is still not achieved

Another observation was while I tried to set the value of timeout to zero in HAL_UART_Transmit(), both tasks able to access the handle of huart1 and sends the series of "1" and "2" to UART alternatively. '1' referrers to task 1 and '2' is task 2 string. Only a single string is sent since 0 is the time out. Now here with 0 as timeout the handle becomes free by itself but not otherwise when the entire string is to be printed.

Thanks for your suggestions and questions!!

Piranha
Chief II
if(xSemaphoreTake(UARTAccess,10))
{
	HAL_UART_Transmit(&huart1, "Task1\n\r", 7,100);
}
xSemaphoreGive(UARTAccess);

To use semaphore for lock/unlock functionality, it must be given back only if it was taken successfully, not timed out. And why do You need timeout in this example at all?

Read the documentation for vSemaphoreCreateBinary:

NOTE: The vSemaphoreCreateBinary() macro remains in the source code to ensure backward compatibility, but it should not be used in new designs. Use the xSemaphoreCreateBinary() function instead.

And also this:

Binary semaphores and mutexes are very similar but have some subtle differences: Mutexes include a priority inheritance mechanism, binary semaphores do not. This makes binary semaphores the better choice for implementing synchronisation (between tasks or between tasks and an interrupt), and mutexes the better choice for implementing simple mutual exclusion.

Therefore the best choice is xSemaphoreCreateMutex.