![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Test session
Dependencies: FatFileSystem MCP23017 WattBob_TextLCD mbed
Fork of Assignment_2_herpe by
task_manager.cpp@4:48761259552a, 2017-03-14 (annotated)
- Committer:
- xouf2114
- Date:
- Tue Mar 14 14:46:43 2017 +0000
- Revision:
- 4:48761259552a
Test of Assignment 2
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
xouf2114 | 4:48761259552a | 1 | /** |
xouf2114 | 4:48761259552a | 2 | * This class manages all the tasks and ensures they are correctly executed. |
xouf2114 | 4:48761259552a | 3 | * It contains various error reporting for schedule issues. |
xouf2114 | 4:48761259552a | 4 | * |
xouf2114 | 4:48761259552a | 5 | * Currently it checks for tasks inside the called interrupt, delaying the tasks |
xouf2114 | 4:48761259552a | 6 | * execution slightly. This gets worse with an increasing number of tasks. |
xouf2114 | 4:48761259552a | 7 | * As such this should only used with a small number of tasks. |
xouf2114 | 4:48761259552a | 8 | * |
xouf2114 | 4:48761259552a | 9 | * Author: Jacob Baungard Hansen |
xouf2114 | 4:48761259552a | 10 | */ |
xouf2114 | 4:48761259552a | 11 | |
xouf2114 | 4:48761259552a | 12 | #include "task_manager.h" |
xouf2114 | 4:48761259552a | 13 | |
xouf2114 | 4:48761259552a | 14 | /** |
xouf2114 | 4:48761259552a | 15 | * |
xouf2114 | 4:48761259552a | 16 | * @param ticker_freq_ms how often we should check for tasks |
xouf2114 | 4:48761259552a | 17 | */ |
xouf2114 | 4:48761259552a | 18 | TaskManager::TaskManager(int ticker_freq_ms) { |
xouf2114 | 4:48761259552a | 19 | this->current_time=0; |
xouf2114 | 4:48761259552a | 20 | this->ticker_freq_ms = ticker_freq_ms; |
xouf2114 | 4:48761259552a | 21 | } |
xouf2114 | 4:48761259552a | 22 | |
xouf2114 | 4:48761259552a | 23 | /** |
xouf2114 | 4:48761259552a | 24 | * |
xouf2114 | 4:48761259552a | 25 | * @param ticker_freq_ms how often we should check for tasks |
xouf2114 | 4:48761259552a | 26 | * @param lcd pointer to LCDHelper object, used to display errors |
xouf2114 | 4:48761259552a | 27 | */ |
xouf2114 | 4:48761259552a | 28 | TaskManager::TaskManager(int ticker_freq_ms, LCDHelper * lcd) { |
xouf2114 | 4:48761259552a | 29 | this->current_time=0; |
xouf2114 | 4:48761259552a | 30 | this->ticker_freq_ms = ticker_freq_ms; |
xouf2114 | 4:48761259552a | 31 | this->lcd = lcd; |
xouf2114 | 4:48761259552a | 32 | } |
xouf2114 | 4:48761259552a | 33 | |
xouf2114 | 4:48761259552a | 34 | // empty |
xouf2114 | 4:48761259552a | 35 | TaskManager::~TaskManager() {} |
xouf2114 | 4:48761259552a | 36 | |
xouf2114 | 4:48761259552a | 37 | /** |
xouf2114 | 4:48761259552a | 38 | * Checks if any tasks needs to run, and if so run them. |
xouf2114 | 4:48761259552a | 39 | * Also checks for any scheduling conflicts, and ensures |
xouf2114 | 4:48761259552a | 40 | * the tasks execution time is not too long. |
xouf2114 | 4:48761259552a | 41 | */ |
xouf2114 | 4:48761259552a | 42 | void TaskManager::find_and_run(){ |
xouf2114 | 4:48761259552a | 43 | // start timer |
xouf2114 | 4:48761259552a | 44 | t.start(); |
xouf2114 | 4:48761259552a | 45 | |
xouf2114 | 4:48761259552a | 46 | // increase current time |
xouf2114 | 4:48761259552a | 47 | this->current_time += this->ticker_freq_ms; |
xouf2114 | 4:48761259552a | 48 | |
xouf2114 | 4:48761259552a | 49 | // if no tasks, give an error |
xouf2114 | 4:48761259552a | 50 | if (this->tasks.empty()) { |
xouf2114 | 4:48761259552a | 51 | this->schedule_error("No tasks"); |
xouf2114 | 4:48761259552a | 52 | this->stop(); |
xouf2114 | 4:48761259552a | 53 | } |
xouf2114 | 4:48761259552a | 54 | |
xouf2114 | 4:48761259552a | 55 | Task * task_to_run = NULL; |
xouf2114 | 4:48761259552a | 56 | // check if there's any tasks to run this timetamp |
xouf2114 | 4:48761259552a | 57 | for (unsigned int i=0; i<this->tasks.size(); i++) { |
xouf2114 | 4:48761259552a | 58 | if (this->tasks[i]->get_next_run_ms() == this->current_time) { |
xouf2114 | 4:48761259552a | 59 | if (task_to_run == NULL ) { |
xouf2114 | 4:48761259552a | 60 | task_to_run = this->tasks[i]; |
xouf2114 | 4:48761259552a | 61 | } else { // if more than one task this timestamp, it is an error |
xouf2114 | 4:48761259552a | 62 | this->schedule_error("Conflict"); |
xouf2114 | 4:48761259552a | 63 | this->stop(); |
xouf2114 | 4:48761259552a | 64 | break; |
xouf2114 | 4:48761259552a | 65 | } |
xouf2114 | 4:48761259552a | 66 | } |
xouf2114 | 4:48761259552a | 67 | } |
xouf2114 | 4:48761259552a | 68 | |
xouf2114 | 4:48761259552a | 69 | // run the found task, if any |
xouf2114 | 4:48761259552a | 70 | if (task_to_run != NULL) { |
xouf2114 | 4:48761259552a | 71 | task_to_run->increment_next_run(); |
xouf2114 | 4:48761259552a | 72 | task_to_run->action(); |
xouf2114 | 4:48761259552a | 73 | } |
xouf2114 | 4:48761259552a | 74 | |
xouf2114 | 4:48761259552a | 75 | // Ensure task didn't take too long |
xouf2114 | 4:48761259552a | 76 | // asume messuring code taskes at least 2ms. |
xouf2114 | 4:48761259552a | 77 | t.stop(); |
xouf2114 | 4:48761259552a | 78 | if (t.read_ms() > (this->ticker_freq_ms)-2) { |
xouf2114 | 4:48761259552a | 79 | this->schedule_error("Task too long"); |
xouf2114 | 4:48761259552a | 80 | this->stop(); |
xouf2114 | 4:48761259552a | 81 | } |
xouf2114 | 4:48761259552a | 82 | // reset timer for next timeaaround |
xouf2114 | 4:48761259552a | 83 | t.reset(); |
xouf2114 | 4:48761259552a | 84 | |
xouf2114 | 4:48761259552a | 85 | } |
xouf2114 | 4:48761259552a | 86 | |
xouf2114 | 4:48761259552a | 87 | /** |
xouf2114 | 4:48761259552a | 88 | * Prints a scheduling error |
xouf2114 | 4:48761259552a | 89 | * |
xouf2114 | 4:48761259552a | 90 | * @param msg message to print on line2 of lcd display |
xouf2114 | 4:48761259552a | 91 | */ |
xouf2114 | 4:48761259552a | 92 | void TaskManager::schedule_error(std::string msg) { |
xouf2114 | 4:48761259552a | 93 | if (this->lcd != NULL) { |
xouf2114 | 4:48761259552a | 94 | this->lcd->print("Schedule error:", msg); |
xouf2114 | 4:48761259552a | 95 | } |
xouf2114 | 4:48761259552a | 96 | this->stop(); |
xouf2114 | 4:48761259552a | 97 | } |
xouf2114 | 4:48761259552a | 98 | |
xouf2114 | 4:48761259552a | 99 | /** |
xouf2114 | 4:48761259552a | 100 | * Adds a task to the exeuction cycle |
xouf2114 | 4:48761259552a | 101 | * |
xouf2114 | 4:48761259552a | 102 | * @param task pointer to the task to add |
xouf2114 | 4:48761259552a | 103 | */ |
xouf2114 | 4:48761259552a | 104 | void TaskManager::add_task(Task * task) { |
xouf2114 | 4:48761259552a | 105 | // we need to ensure that the frequency for the task |
xouf2114 | 4:48761259552a | 106 | // and the ticker frequency is a match |
xouf2114 | 4:48761259552a | 107 | if (task->get_frequency_ms() % this->ticker_freq_ms != 0) { |
xouf2114 | 4:48761259552a | 108 | this->schedule_error("Bad task freq"); |
xouf2114 | 4:48761259552a | 109 | } |
xouf2114 | 4:48761259552a | 110 | // first possible slot for a task to run is at ticker_freq_ms (maybe this should be changed) |
xouf2114 | 4:48761259552a | 111 | // ensure tasks do not start earlier |
xouf2114 | 4:48761259552a | 112 | else if (task->get_next_run_ms() < this->ticker_freq_ms) { |
xouf2114 | 4:48761259552a | 113 | this->schedule_error("start<tickerfreq"); |
xouf2114 | 4:48761259552a | 114 | } |
xouf2114 | 4:48761259552a | 115 | // add task |
xouf2114 | 4:48761259552a | 116 | else { |
xouf2114 | 4:48761259552a | 117 | this->tasks.push_back(task); |
xouf2114 | 4:48761259552a | 118 | } |
xouf2114 | 4:48761259552a | 119 | } |
xouf2114 | 4:48761259552a | 120 | |
xouf2114 | 4:48761259552a | 121 | /** |
xouf2114 | 4:48761259552a | 122 | * Removes a task to the exeuction cycle |
xouf2114 | 4:48761259552a | 123 | * |
xouf2114 | 4:48761259552a | 124 | * @param task pointer to the task to remove |
xouf2114 | 4:48761259552a | 125 | */ |
xouf2114 | 4:48761259552a | 126 | void TaskManager::remove_task(Task * task) { |
xouf2114 | 4:48761259552a | 127 | for (unsigned int i=0; i<this->tasks.size(); i++) { |
xouf2114 | 4:48761259552a | 128 | if (this->tasks[i] == task) { |
xouf2114 | 4:48761259552a | 129 | this->tasks.erase(this->tasks.begin()+i); |
xouf2114 | 4:48761259552a | 130 | break; |
xouf2114 | 4:48761259552a | 131 | } |
xouf2114 | 4:48761259552a | 132 | } |
xouf2114 | 4:48761259552a | 133 | } |
xouf2114 | 4:48761259552a | 134 | |
xouf2114 | 4:48761259552a | 135 | /** |
xouf2114 | 4:48761259552a | 136 | * Starts running |
xouf2114 | 4:48761259552a | 137 | */ |
xouf2114 | 4:48761259552a | 138 | void TaskManager::start() { |
xouf2114 | 4:48761259552a | 139 | timestamp_t in_us = this->ticker_freq_ms*1000.0; |
xouf2114 | 4:48761259552a | 140 | // need to change priority in case of using |
xouf2114 | 4:48761259552a | 141 | // interupts in the activities. |
xouf2114 | 4:48761259552a | 142 | // a bit nasty |
xouf2114 | 4:48761259552a | 143 | NVIC_SetPriority(TIMER3_IRQn, 200); |
xouf2114 | 4:48761259552a | 144 | this->ticker.attach_us<TaskManager>(this, &TaskManager::find_and_run, in_us); |
xouf2114 | 4:48761259552a | 145 | |
xouf2114 | 4:48761259552a | 146 | while(1) {} |
xouf2114 | 4:48761259552a | 147 | } |
xouf2114 | 4:48761259552a | 148 | |
xouf2114 | 4:48761259552a | 149 | /** |
xouf2114 | 4:48761259552a | 150 | * Stops running |
xouf2114 | 4:48761259552a | 151 | */ |
xouf2114 | 4:48761259552a | 152 | void TaskManager::stop() { |
xouf2114 | 4:48761259552a | 153 | this->ticker.detach(); |
xouf2114 | 4:48761259552a | 154 | // might not want this in a general case (not sure) |
xouf2114 | 4:48761259552a | 155 | // although for this case it seems appropiate. |
xouf2114 | 4:48761259552a | 156 | while(1) {} |
xouf2114 | 4:48761259552a | 157 | } |