2015-12-22 04:25 AM
trying to use binary semaphore on STM32F4 discovery board with FreeRTOS gives some strange (even wrong) results.
First and foremost, documentation for FreeRTOS says:
SemaphoreHandle_t xSemaphoreCreateBinary( void );
Function that creates a binary semaphore. Binary semaphores are either available, or not available, hence binary.
The semaphore is created in the 'empty' state, meaning the semaphore must first be given before it can be taken (obtained) using the xSemaphoreTake() function.
Which is great, because in that case some Thread1 waits for semaphore that was created earlier until it unblocks (Thread2 gives semaphore), so it sound Excellent!!
So starting with stm32f4 discovery board running FreeRTOS and code below, person would expect that call to osSemaphoreWait(myBinarySem01Handle,osWaitForever) would block thread until another thread unblocks it with osSemaphoreRelease, but it doesn't work. It seems that after semaphore creation it is need to call osSemaphoreWait twice to make it work.
/* Includes ------------------------------------------------------------------*/ #include ''FreeRTOS.h'' #include ''task.h'' #include ''cmsis_os.h'' /* USER CODE BEGIN Includes */ #include ''gpio.h'' /* USER CODE END Includes */ /* Variables -----------------------------------------------------------------*/ osThreadId defaultTaskHandle; osThreadId myTask02Handle; osSemaphoreId myBinarySem01Handle; osSemaphoreId myBinarySem02Handle; osSemaphoreId myCountingSem01Handle; osSemaphoreId myCountingSem02Handle; /* USER CODE BEGIN Variables */ /* USER CODE END Variables */ /* Function prototypes -------------------------------------------------------*/ void StartDefaultTask(void const * argument); void StartTask02(void const * argument); void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */ /* USER CODE BEGIN FunctionPrototypes */ /* USER CODE END FunctionPrototypes */ /* Hook prototypes */ /* Init FreeRTOS */ void MX_FREERTOS_Init(void) { /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* USER CODE BEGIN RTOS_MUTEX */ /* add mutexes, ... */ /* USER CODE END RTOS_MUTEX */ /* Create the semaphores(s) */ /* definition and creation of myBinarySem01 */ osSemaphoreDef(myBinarySem01); myBinarySem01Handle = osSemaphoreCreate(osSemaphore(myBinarySem01), 1); /* definition and creation of myBinarySem02 */ osSemaphoreDef(myBinarySem02); myBinarySem02Handle = osSemaphoreCreate(osSemaphore(myBinarySem02), 1); /* definition and creation of myCountingSem01 */ osSemaphoreDef(myCountingSem01); myCountingSem01Handle = osSemaphoreCreate(osSemaphore(myCountingSem01), 2); /* definition and creation of myCountingSem02 */ osSemaphoreDef(myCountingSem02); myCountingSem02Handle = osSemaphoreCreate(osSemaphore(myCountingSem02), 2); /* USER CODE BEGIN RTOS_SEMAPHORES */ /* add semaphores, ... */ /* USER CODE END RTOS_SEMAPHORES */ /* USER CODE BEGIN RTOS_TIMERS */ /* start timers, add new ones, ... */ /* USER CODE END RTOS_TIMERS */ /* Create the thread(s) */ /* definition and creation of defaultTask */ osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128); defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL); /* definition and creation of myTask02 */ osThreadDef(myTask02, StartTask02, osPriorityNormal, 0, 128); myTask02Handle = osThreadCreate(osThread(myTask02), NULL); /* USER CODE BEGIN RTOS_THREADS */ /* add threads, ... */ /* USER CODE END RTOS_THREADS */ /* USER CODE BEGIN RTOS_QUEUES */ /* add queues, ... */ /* USER CODE END RTOS_QUEUES */ } /* StartDefaultTask function */ void StartDefaultTask(void const * argument) { HAL_GPIO_TogglePin(LD6_GPIO_Port,LD6_Pin); osSemaphoreWait(myBinarySem01Handle,osWaitForever); /* USER CODE BEGIN StartDefaultTask */ /* Infinite loop */ for(;;) { HAL_GPIO_TogglePin(LD6_GPIO_Port,LD6_Pin); osDelay(1000); } /* USER CODE END StartDefaultTask */ } /* StartTask02 function */ void StartTask02(void const * argument) { HAL_GPIO_TogglePin(LD5_GPIO_Port,LD5_Pin); osDelay(5000); osSemaphoreRelease(myBinarySem01Handle); /* USER CODE BEGIN StartTask02 */ /* Infinite loop */ for(;;) { HAL_GPIO_TogglePin(LD5_GPIO_Port,LD5_Pin); osDelay(2000); } /* USER CODE END StartTask02 */ } /* USER CODE BEGIN Application */ /* USER CODE END Application */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
2015-12-22 05:28 AM
Hello,
the problem is that
osSemaphoreCreate() calls vSemaphoreCreateBinary() and
not the newer
xSemaphoreCreateBinary
()
some description from semphr.h from freertos
...
/**
*
semphr
. h
* <pre>SemaphoreHandle_t xSemaphoreCreateBinary( void )</pre>
*
* The old vSemaphoreCreateBinary() macro is now deprecated in
favour
of this
* xSemaphoreCreateBinary() function. Note that binary semaphores created using
* the vSemaphoreCreateBinary() macro are created in a state such that the
* first call to 'take' the semaphore would pass, whereas binary semaphores
* created using xSemaphoreCreateBinary() are created in a state such that the
* the semaphore must first be 'given' before it can be 'taken'.
*
...
my initialization of semphores is
...
osSemaphoreDef(binarySem);
binarySemHandle =
osSemaphoreCreate
(...), 1);
osSemaphoreWait(binarySemHandle,0);
...
2015-12-22 07:34 AM
It seems that error was in between ears :)
Function isvSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore )
is changed for:
x
SemaphoreCreateBinary( SemaphoreHandle_t xSemaphore ) http://www.freertos.org/a00121.html2015-12-22 10:53 AM
Big thanks Thomas for quick reply.