Test session
Dependencies: FatFileSystem MCP23017 WattBob_TextLCD mbed
Fork of Assignment_2_herpe by
Diff: task_manager.cpp
- Revision:
- 4:48761259552a
diff -r 5883d1a2c5b0 -r 48761259552a task_manager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/task_manager.cpp Tue Mar 14 14:46:43 2017 +0000 @@ -0,0 +1,157 @@ +/** + * This class manages all the tasks and ensures they are correctly executed. + * It contains various error reporting for schedule issues. + * + * Currently it checks for tasks inside the called interrupt, delaying the tasks + * execution slightly. This gets worse with an increasing number of tasks. + * As such this should only used with a small number of tasks. + * + * Author: Jacob Baungard Hansen + */ + +#include "task_manager.h" + +/** + * + * @param ticker_freq_ms how often we should check for tasks + */ +TaskManager::TaskManager(int ticker_freq_ms) { + this->current_time=0; + this->ticker_freq_ms = ticker_freq_ms; +} + +/** + * + * @param ticker_freq_ms how often we should check for tasks + * @param lcd pointer to LCDHelper object, used to display errors + */ +TaskManager::TaskManager(int ticker_freq_ms, LCDHelper * lcd) { + this->current_time=0; + this->ticker_freq_ms = ticker_freq_ms; + this->lcd = lcd; +} + +// empty +TaskManager::~TaskManager() {} + +/** + * Checks if any tasks needs to run, and if so run them. + * Also checks for any scheduling conflicts, and ensures + * the tasks execution time is not too long. + */ +void TaskManager::find_and_run(){ + // start timer + t.start(); + + // increase current time + this->current_time += this->ticker_freq_ms; + + // if no tasks, give an error + if (this->tasks.empty()) { + this->schedule_error("No tasks"); + this->stop(); + } + + Task * task_to_run = NULL; + // check if there's any tasks to run this timetamp + for (unsigned int i=0; i<this->tasks.size(); i++) { + if (this->tasks[i]->get_next_run_ms() == this->current_time) { + if (task_to_run == NULL ) { + task_to_run = this->tasks[i]; + } else { // if more than one task this timestamp, it is an error + this->schedule_error("Conflict"); + this->stop(); + break; + } + } + } + + // run the found task, if any + if (task_to_run != NULL) { + task_to_run->increment_next_run(); + task_to_run->action(); + } + + // Ensure task didn't take too long + // asume messuring code taskes at least 2ms. + t.stop(); + if (t.read_ms() > (this->ticker_freq_ms)-2) { + this->schedule_error("Task too long"); + this->stop(); + } + // reset timer for next timeaaround + t.reset(); + +} + +/** + * Prints a scheduling error + * + * @param msg message to print on line2 of lcd display + */ +void TaskManager::schedule_error(std::string msg) { + if (this->lcd != NULL) { + this->lcd->print("Schedule error:", msg); + } + this->stop(); +} + +/** + * Adds a task to the exeuction cycle + * + * @param task pointer to the task to add + */ +void TaskManager::add_task(Task * task) { + // we need to ensure that the frequency for the task + // and the ticker frequency is a match + if (task->get_frequency_ms() % this->ticker_freq_ms != 0) { + this->schedule_error("Bad task freq"); + } + // first possible slot for a task to run is at ticker_freq_ms (maybe this should be changed) + // ensure tasks do not start earlier + else if (task->get_next_run_ms() < this->ticker_freq_ms) { + this->schedule_error("start<tickerfreq"); + } + // add task + else { + this->tasks.push_back(task); + } +} + +/** + * Removes a task to the exeuction cycle + * + * @param task pointer to the task to remove + */ +void TaskManager::remove_task(Task * task) { + for (unsigned int i=0; i<this->tasks.size(); i++) { + if (this->tasks[i] == task) { + this->tasks.erase(this->tasks.begin()+i); + break; + } + } +} + +/** + * Starts running + */ +void TaskManager::start() { + timestamp_t in_us = this->ticker_freq_ms*1000.0; + // need to change priority in case of using + // interupts in the activities. + // a bit nasty + NVIC_SetPriority(TIMER3_IRQn, 200); + this->ticker.attach_us<TaskManager>(this, &TaskManager::find_and_run, in_us); + + while(1) {} +} + +/** + * Stops running + */ +void TaskManager::stop() { + this->ticker.detach(); + // might not want this in a general case (not sure) + // although for this case it seems appropiate. + while(1) {} +} \ No newline at end of file