Test session

Dependencies:   FatFileSystem MCP23017 WattBob_TextLCD mbed

Fork of Assignment_2_herpe by Xavier Herpe

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