#define FREQ_MILLIS 1000
+static boolean_t stop_tasks = FALSE;
+static uint8_t tasks_running = 0;
+
/**
* FreeRTOS Task that read analog inputs and prints them on the SCI.
*/
static const portTickType freq_ticks = FREQ_MILLIS / portTICK_RATE_MS;
portTickType last_wake_time = xTaskGetTickCount();
- while(TRUE) {
+ while(!stop_tasks) {
// Update inputs
rpp_ain_update();
// Wait until next step
vTaskDelayUntil(&last_wake_time, freq_ticks);
}
+
+ // Delete myself
+ tasks_running--;
+ vTaskDelete(NULL);
}
{
xTaskHandle test_task_handle;
- rpp_sci_printf((const char*)"Try to create task.\r\n");
portBASE_TYPE task_created = xTaskCreate(ain_test_task,
(const signed char*)"ain_test_task",
TEST_TASK_STACK, NULL, TEST_TASK_PRIORITY,
&test_task_handle
);
- rpp_sci_printf((const char*)"After try to create task.\r\n");
if(task_created != pdPASS) {
return;
}
+ tasks_running = 1;
wait_for_quit();
- vTaskDelete(test_task_handle);
- vTaskDelay(4); // Allow the idle task to free memory
+
+ // Stop tasks
+ // Note: Not an easy task. If we preempt delete the task from this context
+ // using vTaskDelete and the task is holding a semaphore, like in the middle
+ // of a SCI send, printf, or similar, the semaphore will never be released
+ // and the application will deadlock in the next call to that function.
+ // As a general rule of thumb just allow vTaskDelete on the tasks themselves
+ // and implement a synchronization mecanism. Here we just wait for them to
+ // finish and set a flag because is simpler, a more correct approach will
+ // be to have a set of semaphores or a counting semaphore that all the tasks
+ // can share.
+ stop_tasks = TRUE;
+ while(tasks_running > 0) {
+ taskYIELD();
+ }
+ // Reset stop flag
+ stop_tasks = FALSE;
+ rpp_sci_printf((const char*)"\r\n");
// Reset module
// - Not required