Test session

Dependencies:   FatFileSystem MCP23017 WattBob_TextLCD mbed

Fork of Assignment_2_herpe by Xavier Herpe

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers task_manager.cpp Source File

task_manager.cpp

00001 /**
00002  * This class manages all the tasks and ensures they are correctly executed.
00003  * It contains various error reporting for schedule issues.
00004  * 
00005  * Currently it checks for tasks inside the called interrupt, delaying the tasks
00006  * execution slightly. This gets worse with an increasing number of tasks.
00007  * As such this should only used with a small number of tasks.
00008  * 
00009  * Author: Jacob Baungard Hansen
00010  */
00011 
00012 #include "task_manager.h"
00013 
00014 /**
00015  *
00016  * @param ticker_freq_ms        how often we should check for tasks
00017  */
00018 TaskManager::TaskManager(int ticker_freq_ms) {
00019     this->current_time=0;
00020     this->ticker_freq_ms = ticker_freq_ms;
00021 }
00022 
00023 /**
00024  *
00025  * @param ticker_freq_ms        how often we should check for tasks
00026  * @param lcd                               pointer to LCDHelper object, used to display errors
00027  */
00028 TaskManager::TaskManager(int ticker_freq_ms, LCDHelper * lcd) {
00029     this->current_time=0;
00030     this->ticker_freq_ms = ticker_freq_ms;
00031     this->lcd = lcd;
00032 }
00033 
00034 // empty
00035 TaskManager::~TaskManager() {}
00036 
00037 /**
00038  * Checks if any tasks needs to run, and if so run them.
00039  * Also checks for any scheduling conflicts, and ensures
00040  * the tasks execution time is not too long.
00041  */
00042 void TaskManager::find_and_run(){
00043     // start timer
00044     t.start();
00045     
00046     // increase current time
00047     this->current_time += this->ticker_freq_ms;
00048     
00049     // if no tasks, give an error
00050     if (this->tasks.empty()) {
00051         this->schedule_error("No tasks");
00052         this->stop();
00053     }
00054     
00055     Task * task_to_run = NULL;
00056     // check if there's any tasks to run this timetamp
00057     for (unsigned int i=0; i<this->tasks.size(); i++) {
00058         if (this->tasks[i]->get_next_run_ms() == this->current_time) {
00059             if (task_to_run == NULL ) {
00060                 task_to_run = this->tasks[i];
00061             } else { // if more than one task this timestamp, it is an error
00062                 this->schedule_error("Conflict");
00063                 this->stop();
00064                 break;
00065             }
00066         }
00067     }
00068     
00069     // run the found task, if any
00070     if (task_to_run != NULL) {
00071         task_to_run->increment_next_run();
00072         task_to_run->action();
00073     } 
00074     
00075     // Ensure task didn't take too long
00076     // asume messuring code taskes at least 2ms.
00077     t.stop();
00078     if (t.read_ms() > (this->ticker_freq_ms)-2) {
00079         this->schedule_error("Task too long");
00080         this->stop();
00081     }
00082     // reset timer for next timeaaround
00083     t.reset();
00084     
00085 }
00086 
00087 /**
00088  * Prints a scheduling error
00089  * 
00090  * @param msg       message to print on line2 of lcd display
00091  */
00092 void TaskManager::schedule_error(std::string msg) {
00093     if (this->lcd != NULL) {
00094         this->lcd->print("Schedule error:", msg);
00095     }
00096     this->stop();
00097 }
00098 
00099 /**
00100  * Adds a task to the exeuction cycle
00101  * 
00102  * @param task      pointer to the task to add
00103  */
00104 void TaskManager::add_task(Task * task) {
00105     // we need to ensure that the frequency for the task
00106     // and the ticker frequency is a match
00107     if (task->get_frequency_ms() % this->ticker_freq_ms != 0) {
00108         this->schedule_error("Bad task freq");
00109     } 
00110     // first possible slot for a task to run is at ticker_freq_ms (maybe this should be changed)
00111     // ensure tasks do not start earlier
00112     else if (task->get_next_run_ms() < this->ticker_freq_ms) {
00113         this->schedule_error("start<tickerfreq");
00114     } 
00115     // add task 
00116     else {
00117         this->tasks.push_back(task);
00118     }
00119 }
00120 
00121 /**
00122  * Removes a task to the exeuction cycle
00123  * 
00124  * @param task      pointer to the task to remove
00125  */
00126 void TaskManager::remove_task(Task * task) {
00127     for (unsigned int i=0; i<this->tasks.size(); i++) {
00128         if (this->tasks[i] == task) {
00129             this->tasks.erase(this->tasks.begin()+i);
00130             break;
00131         }
00132     }
00133 }
00134 
00135 /** 
00136  * Starts running
00137  */
00138 void TaskManager::start() {
00139     timestamp_t in_us = this->ticker_freq_ms*1000.0;
00140     // need to change priority in case of using
00141     // interupts in the activities.
00142     // a bit nasty
00143     NVIC_SetPriority(TIMER3_IRQn, 200);
00144     this->ticker.attach_us<TaskManager>(this, &TaskManager::find_and_run, in_us);
00145     
00146     while(1) {} 
00147 }
00148 
00149 /**
00150  * Stops running
00151  */
00152 void TaskManager::stop() {
00153     this->ticker.detach();
00154     // might not want this in a general case (not sure)
00155     // although for this case it seems appropiate. 
00156     while(1) {}
00157 }