From 89817d71ed4114562e55df3139c87b6372af9b4b Mon Sep 17 00:00:00 2001 From: Maximilian Stiefel Date: Tue, 12 Dec 2017 18:11:43 +0100 Subject: [PATCH] OS up and running. Not perfect yet, though. --- software/os/error.c | 92 +++++++++------ software/os/error.h | 49 +++++++- software/os/heap.c | 60 ++++++++-- software/os/heap.h | 57 ++++++--- software/os/helpers.c | 9 +- software/os/helpers.h | 13 ++ software/os/mainyyy.c | 134 --------------------- software/os/ossettings.h | 47 ++++++++ software/os/ostypes.h | 49 ++++++-- software/os/printf.c | 44 ++++--- software/os/printf.h | 23 ++++ software/os/queues.h | 16 +-- software/os/scheduler.c | 197 ++++++++++++++++++++----------- software/os/scheduler.h | 45 +++++-- software/os/settings.h | 22 ---- software/platform/system_timer.c | 38 +++--- software/platform/system_timer.h | 5 +- 17 files changed, 546 insertions(+), 354 deletions(-) delete mode 100644 software/os/mainyyy.c create mode 100644 software/os/ossettings.h delete mode 100644 software/os/settings.h diff --git a/software/os/error.c b/software/os/error.c index e0ffcd9..c3cea46 100644 --- a/software/os/error.c +++ b/software/os/error.c @@ -2,37 +2,14 @@ #include #include #include"error.h" -#include"settings.h" +#include"helpers.h" +#include"printf.h" +#include"ossettings.h" -uint8_t osItoa(int iint, char* iochar, size_t ibuffsize) -{ - int i = 0; - int j = 0; - char z[10]; - size_t buff_size_1 = ibuffsize; - size_t buff_size_2 = sizeof(z); - while(iint > 0) - { - z[i] = (char)('0' + iint % 10); - iint /= 10; - i++; - if( ((buff_size_1 - 1) < i) || ((buff_size_2 - 1) < i)) - return 0; - } - j = i-1; - while(j >= 0) - { - iochar[j] = z[i-j-1]; - j--; - } - iochar[i] = '\0'; - return 1; -} - -uint8_t osExplainError(const char* ifile, const int iline, const osError_t ierror, char* iomessage) +uint8_t osExplainError(const char* ifile, const uint8_t iline, const osError_t ierror, char* iomessage) { char z[10]; - if(!osItoa(iline, z, sizeof(z))) + if( !osItoa(iline, z, sizeof(z), NULL) ) return 0; strcat(iomessage, ifile); strcat(iomessage, ":"); @@ -42,22 +19,65 @@ uint8_t osExplainError(const char* ifile, const int iline, const osError_t ierro { case E_MAX_NUMBER_OF_TASKS: strcat(iomessage, "Maximum number of tasks (N = "); - if(!osItoa(MAX_NUMBER_OF_TASKS, z, sizeof(z))) - return 0; - strcat(iomessage, z); - strcat(iomessage, ") is reached.\n"); + if( !osItoa(MAX_NUMBER_OF_TASKS, z, sizeof(z), NULL) ) + return 0; + strcat(iomessage, z); + strcat(iomessage, ") is reached.\n"); + break; + case E_NULL_FORBIDDEN: + strcat(iomessage, "A NULL pointer is forbidden in this place.\n"); + break; + case E_HEAP_OVERLFOW: + strcat(iomessage, "Maximum heap size (N = "); + if( !osItoa(HEAP_SIZE, z, sizeof(z), NULL) ) + return 0; + strcat(iomessage, z); + strcat(iomessage, ") is reached.\n"); + break; + default: + strcat(iomessage, "Unknown error or no explanation implemented yet.\n"); + } + return 1; +} + +uint8_t osPrintError(const char* ifile, const int iline, const osError_t ierror) +{ + char iomessage[MAX_MESSAGE_SIZE] = {'\0'}; + osExplainError(ifile, iline, ierror, iomessage); + #ifdef X86_TEST_ENVIRONMENT + return printf("%s", iomessage); + #else + return osPrintf("%s", iomessage); + #endif +} + +uint8_t osExplainWarning(const char* ifile, const uint8_t iline, const osWarning_t ierror, char* iomessage) +{ + char z[10]; + if( !osItoa(iline, z, sizeof(z), NULL) ) + return 0; + strcat(iomessage, ifile); + strcat(iomessage, ":"); + strcat(iomessage, z); + strcat(iomessage, ": warning: "); + switch(ierror) + { + case W_SYS_TIMER_OVERFLOW: + strcat(iomessage, "System timer variable just had an overflow."); break; default: - strcat(iomessage, "Unknown error.\n"); + strcat(iomessage, "Unknown warning or no explanation implemented yet.\n"); } return 1; } -void osPrintError(const char* ifile, const int iline, const osError_t ierror) +uint8_t osPrintWarning(const char* ifile, const int iline, const osWarning_t ierror) { char iomessage[MAX_MESSAGE_SIZE] = {'\0'}; - osExplainError(ifile, iline, ierror, iomessage); + osExplainError(ifile, iline, ierror, iomessage); #ifdef X86_TEST_ENVIRONMENT - printf("%s", iomessage); + return printf("%s", iomessage); + #else + return osPrintf("%s", iomessage); #endif } diff --git a/software/os/error.h b/software/os/error.h index 846441e..1ce7df0 100644 --- a/software/os/error.h +++ b/software/os/error.h @@ -2,16 +2,59 @@ #define OS_ERROR_H //--------------Includes----------------- -#include +#include"ostypes.h" //--------------Preprocessor Hacks------- +/** Throws an error given an error type. + * + */ #define THROW_ERROR(ERROR_TYPE)\ osPrintError(__FILE__, __LINE__, ERROR_TYPE) +/** Throws a warning given a warning type. + * + */ +#define THROW_WARNING(WARNING_TYPE)\ + osPrintWarning(__FILE__, __LINE__, WARNING_TYPE) //--------------Funtions----------------- -uint8_t osExplainError(const char* ifile, const int iline, const osError_t ierror, char* message); -void osPrintError(const char* ifile, const int iline, const osError_t ierror); +/** Creating a error message string from inter alia an error code. + * + * @param ifile Filename where error occurs. + * @param iline Line where error occurs. + * @param ierror Error code. + * @param message Message related to the error. + * @retval 1 (SUCCESS) or 0 (FAILURE). + */ +uint8_t osExplainError(const char* ifile, const uint8_t iline, const osError_t ierror, char* iomessage); + +/** Print error. This is where the error output can be redirected (later). + * + * @param ifile Filename where error occurs. + * @param iline Line where error occurs. + * @param ierror Error code. + * @retval 1 (SUCCESS) or 0 (FAILURE). + */ +uint8_t osPrintError(const char* ifile, const int iline, const osError_t ierror); + +/** Creating a warning message string from inter alia a warning code. + * + * @param ifile Filename where warning occurs. + * @param iline Line where warning occurs. + * @param ierror Warning code. + * @param message Message related to the warning. + * @retval 1 (SUCCESS) or 0 (FAILURE). + */ +uint8_t osExplainWarning(const char* ifile, const uint8_t iline, const osWarning_t ierror, char* iomessage); + +/** Print warning. This is where the warning output can be redirected (later). + * + * @param ifile Filename where warning occurs. + * @param iline Line where warning occurs. + * @param ierror Warning code. + * @retval 1 (SUCCESS) or 0 (FAILURE). + */ +uint8_t osPrintWarning(const char* ifile, const int iline, const osWarning_t ierror); #endif diff --git a/software/os/heap.c b/software/os/heap.c index f30d622..f44ed10 100644 --- a/software/os/heap.c +++ b/software/os/heap.c @@ -5,24 +5,45 @@ #include"heap.h" #include"error.h" #include"ostypes.h" +#include"printf.h" //--------------Functions---------------- +/** Gives the index of the left child of a node. + * + * @param iind Index of the node itself. + * @retval Index of the left child of the node. + */ static inline uint8_t osHeapChildL(uint8_t iind) { return (2*iind + 1); } +/** Gives the index of the right child of a node. + * + * @param iind Index of the node itself. + * @retval Index of the left child of the node. + */ static inline uint8_t osHeapChildR(uint8_t iind) { return (2*iind + 2); } +/** Gives the index of the parent of a node. + * + * @param iind Index of the node itself. + * @retval Index of the left child of the node. + */ static inline uint8_t osHeapParent(uint8_t iind) { return (iind-1)/2; } +/** Gives the size of the heap. + * + * @param ioarray Array where the heap is stored. + * @retval Size of the heap. + */ static inline uint8_t osHeapSize(osHeapNode_t* ioarray) { int i; @@ -34,19 +55,22 @@ static inline uint8_t osHeapSize(osHeapNode_t* ioarray) return i; } +/** Delete one element in the heap. + * + * @param ioarray Array where the heap is stored. + * @retval Index of the left child of the node. + */ static inline void osHeapDelete(osHeapNode_t* ioarray, uint8_t ii) { ioarray[ii] = NULL; } -void osHeapInit(osHeapNode_t* ioarray) -{ - for(int i=0; ipriority); + #ifdef X86_TEST_ENVIRONMENT + printf("%d ", ioarray[i]->priority); + #else + osPrintf("%d ", ioarray[i]->priority); + #endif } - printf("\n"); + #ifdef X86_TEST_ENVIRONMENT + printf("\n"); + #else + osPrintf("\n\r"); + #endif } uint8_t osHeapIsEmpty(osHeapNode_t* ioarray) diff --git a/software/os/heap.h b/software/os/heap.h index 27bfe17..da4e906 100644 --- a/software/os/heap.h +++ b/software/os/heap.h @@ -1,5 +1,5 @@ -#ifndef H_HEAP -#define H_HEAP +#ifndef OS_H_HEAP_ +#define OS_H_HEAP_ //--------------Includes----------------- @@ -7,32 +7,59 @@ //--------------Functions---------------- -static inline uint8_t osHeapChildL(uint8_t iind); - -static inline uint8_t osHeapChildR(uint8_t iind); - -static inline uint8_t osHeapParent(uint8_t iind); - -static inline uint8_t osHeapSize(osHeapNode_t* ioarray); - -static inline void osHeapDelete(osHeapNode_t* ioarray, uint8_t ii); - +/** Initializes all heap elements by setting them to NULL. + * + * @param Array where the heap is stored. + */ void osHeapInit(osHeapNode_t* ioarray); -static inline void osHeapSwap(osHeapNode_t* ioarray, uint8_t ia, uint8_t ib); - +/** Classic heapify operation. + * + * @param ioarray Array where the heap is stored. + * @param iind Element to be put in the right place. + */ void osHeapHeapify(osHeapNode_t* ioarray, uint8_t iind); +/** Build the heap from the bottom up. Given an array which is not heapified at all. + * + * @param ioarray Array where the heap is stored. + */ void osHeapBuild(osHeapNode_t* ioarray); +/** Copy heap maximum. + * + * @param ioarray Array where the heap is stored. + * @param iomax Node, which is the maximum. + * @retval 1 (SUCCESS) or 0 (heap is empty). + */ uint8_t osHeapMaximum(osHeapNode_t* ioarray, osHeapNode_t* iomax); +/** Copy heap maximum and remove it (extract). + * + * @param ioarray Array where the heap is stored. + * @param iomax Node, which is the maximum. + * @retval 1 (SUCCESS) or 0 (heap is empty). + */ uint8_t osHeapExtractMaximum(osHeapNode_t* ioarray, osHeapNode_t* iomax); +/** Insert a node into the heap. + * + * @param ioarray Array where the heap is stored. + * @param x Node to be inserted into the heap. + * @retval 1 (SUCCESS) or 0 (heap is full). + */ uint8_t osHeapInsert(osHeapNode_t* ioarray, osHeapNode_t x); +/** Print heap all priorities for debugging purposes. + * + * @param ioarray Array where the heap is stored. + */ void osHeapPrintS(osHeapNode_t* ioarray); +/** Is the heap empty? + * + * @param ioarray Array where the heap is stored. + */ uint8_t osHeapIsEmpty(osHeapNode_t* ioarray); -#endif +#endif /* OS_H_HEAP_ */ diff --git a/software/os/helpers.c b/software/os/helpers.c index c63043f..0c06b9b 100644 --- a/software/os/helpers.c +++ b/software/os/helpers.c @@ -24,6 +24,12 @@ uint8_t osItoa(int iint, char* iochar, size_t ibuffsize, size_t* obuffsize) iint *= -1; isnegative = 1; } + + if(iint == 0) + { + z[i] = '0'; + i++; + } /* Take last digit and convert until iint is gone. */ while(iint > 0) { @@ -50,6 +56,7 @@ uint8_t osItoa(int iint, char* iochar, size_t ibuffsize, size_t* obuffsize) iochar[j] = z[i-j-1]; j--; } - *obuffsize = i; + if(obuffsize != NULL) + *obuffsize = i; return 1; } diff --git a/software/os/helpers.h b/software/os/helpers.h index 642e42f..e980831 100644 --- a/software/os/helpers.h +++ b/software/os/helpers.h @@ -11,6 +11,12 @@ #include "stm32f10x.h" #include +/** Simple inline power calculation. + * + * @param ibase Input base. + * @param iexponent Input exponent. + * @retval Result. + */ inline int osPowInt(int ibase, int iexponent) { int result =1; @@ -21,6 +27,13 @@ inline int osPowInt(int ibase, int iexponent) return result; } +/** Simple Interger to ASCII conversion. + * + * @param iint Input integer. + * @param iochar C string where the result ends up. + * @param ibuffsize Size of the C string for security reasons. + * @param obuffsize Size of the string created by the function. + */ uint8_t osItoa(int iint, char* iochar, size_t ibuffsize, size_t* obuffsize); #endif /* OS_HELPERS_H_ */ diff --git a/software/os/mainyyy.c b/software/os/mainyyy.c deleted file mode 100644 index 1537dc2..0000000 --- a/software/os/mainyyy.c +++ /dev/null @@ -1,134 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include"heap.h" -#include"ostypes.h" -#include"settings.h" -#include"scheduler.h" -#include"error.h" - -// core_id = 0, 1, ... n-1, where n is the system's number of cores - -int stick_this_thread_to_core(int core_id) { - int num_cores = sysconf(_SC_NPROCESSORS_ONLN); - if (core_id < 0 || core_id >= num_cores) - return EINVAL; - - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - CPU_SET(core_id, &cpuset); - - pthread_t current_thread = pthread_self(); - return pthread_setaffinity_np(current_thread, sizeof(cpu_set_t), &cpuset); -} - - -void myTask1(void *params) -{ - char *str = (char*)params; - volatile int i; - static int counter = 0; - printf("%s. Executed task %d times.\n", str, ++counter); - for (i = 0; i < 100000; ++i); - osTaskDelay(10); -} - -void myTask2(void *params) -{ - char *str = (char*)params; - volatile int i; - static int counter = 0; - printf("%s. Executed task %d times.\n", str, ++counter); - for (i = 0; i < 100000; ++i); - osTaskDelay(20); -} - -void myTask3(void *params) -{ - char *str = (char*)params; - volatile int i; - static int counter = 0; - printf("%s. Executed task %d times.\n", str, ++counter); - for (i = 0; i < 100000; ++i); - osTaskDelay(5); -} - -#ifdef X86_TEST_ENVIRONMENT -void* simulatedTimer(void* iarg) -{ - uint8_t id = *( (uint8_t*) iarg ); - volatile int j=0; - stick_this_thread_to_core(1); - printf("Thread %d starts.\n", id); - for (j = 0; j < 10e6; ++j); - printf("Thread %d finishs.\n", id); - //osRunScheduler(); -} -void timerCallback(int signum) -{ - static uint8_t cnt = 0; - static uint8_t ids[MAX_LEVEL_INT_NESTING]; - static struct sched_param scheduling_params[MAX_LEVEL_INT_NESTING]; - static struct sched_param probe1; - static int probe2 = 0; - int reture = 0; - static pthread_t threads[MAX_LEVEL_INT_NESTING]; - if(cnt > (MAX_LEVEL_INT_NESTING-1)) - { - //THROW_ERROR(E_MAX_LEVEL_INT_NESTING); - //exit(EXIT_FAILURE); - } - else - { - ids[cnt] = cnt; - scheduling_params[cnt].sched_priority = sched_get_priority_min(SCHED_FIFO) + cnt*2; - printf("Thread %d has priority %d.\n", cnt, scheduling_params[cnt].sched_priority); - pthread_create(&threads[cnt], NULL, &simulatedTimer, &ids[cnt]); - reture = pthread_setschedparam(threads[cnt], SCHED_FIFO, &scheduling_params[cnt]); - if(reture!=0) - printf("Error setting the priority: %d.\n", reture); - cnt++; - } -} -#endif - -int main(void) -{ - #ifdef X86_TEST_ENVIRONMENT - struct sigaction sa; - struct itimerval timer; - /* Install timer_handler as the signal handler for SIGVTALRM. */ - memset (&sa, 0, sizeof (sa)); - sa.sa_handler = &timerCallback; - sigaction (SIGVTALRM, &sa, NULL); - /* Configure the timer to expire after 250 msec... */ - timer.it_value.tv_sec = 0; - timer.it_value.tv_usec = CLOCK_TICK_RATE_MS * 1000; - /* ... and every 250 msec after that. */ - timer.it_interval.tv_sec = 0; - timer.it_interval.tv_usec = CLOCK_TICK_RATE_MS; - /* Start a virtual timer. It counts down whenever this process is executing. */ - setitimer (ITIMER_VIRTUAL, &timer, NULL); - #endif - - /* Add some tasks. */ - osTaskCreate(&myTask1, "Task1", "This is Task1.", 1, NULL); - osTaskCreate(&myTask2, "Task2", "This is Task2.", 2, NULL); - osTaskCreate(&myTask3, "Task3", "This is Task3.", 3, NULL); - - osPrintAllTasks(); - - #ifdef X86_TEST_ENVIRONMENT - /* Do busy work. */ - while (1); - #endif - return 0; -} diff --git a/software/os/ossettings.h b/software/os/ossettings.h new file mode 100644 index 0000000..da6bd28 --- /dev/null +++ b/software/os/ossettings.h @@ -0,0 +1,47 @@ +#ifndef OS_SETTINGS_H +#define OS_SETTINGS_H + +/* Error */ +#define MAX_MESSAGE_SIZE 255 + +/* X86 */ +//#define X86_TEST_ENVIRONMENT +/* Only needed for X86 simulation. */ +#define MAX_LEVEL_INT_NESTING 3 + +/* Timing */ +// TODO: Adjust this: +#define SYS_TICK_MS 1000 +/* Don't adjust this ;) */ +#if (SYS_TICK_MS <= 100) +#define SYS_TICK_PERIOD_MS SYS_TICK_MS +#else +#define SYS_TICK_PERIOD_MS 100 +#endif +#define MS_2_TICKS(MS)\ + (MS/SYS_TICK_PERIOD_MS) +#if (SYS_TICK_MS < 0) + #error "SYS_TICK_MS can not be smaller than 1." +#endif +#if ( (SYS_TICK_MS%1) != 0) + #error "SYS_TICK_MS has to be a natural number." +#endif + +/* Scheduler */ +// TODO: Adjust this: +#define MAX_SIZE_TASK_NAME 20 +#define MAX_NUMBER_OF_TASKS 4 +#define HEAP_SIZE 4 +/* Don't adjust this ;) */ +#if (MAX_NUMBER_OF_TASKS > HEAP_SIZE) + #warning "HEAP_SIZE < MAX_NUMER_OF_TASKS: This might lead to problems." +#endif + +/* Alive LED */ +#define ALIVE_PULSE_LENGTH MS_2_TICKS(200) + +/* printf */ +/* Convert every \n to \n\r */ +#define CONVERT_NEWLINE + +#endif diff --git a/software/os/ostypes.h b/software/os/ostypes.h index 8d71abf..9d3c1f5 100644 --- a/software/os/ostypes.h +++ b/software/os/ostypes.h @@ -2,13 +2,16 @@ #define H_OS_TYPES //--------------Includes----------------- + #include -#include + +#include "ossettings.h" //--------------Scheduler---------------- /** Enum for scheduler state. -*/ + * + */ typedef enum { S_INIT, @@ -18,14 +21,16 @@ typedef enum } osSchedulerState_t; /** Enum for task states. -*/ + * + */ typedef enum { READY, RUNNING, SUSPENDED, BLOCKED } osTaskState_t; /** Struct representing the task control block. -*/ + * + */ typedef struct { void (*fnc_ptr)(void*); @@ -36,23 +41,47 @@ typedef struct uint32_t wake_up; } osTCB_t; - -//--------------Errors------------------- +//--------------Errors & Warnings-------- /** Enum to hold all possible error codes. -*/ + * + */ typedef enum { E_MAX_NUMBER_OF_TASKS, E_HEAP_OVERLFOW, - E_NULL_FORBIDDEN, - E_MAX_LEVEL_INT_NESTING + E_MAX_LEVEL_INT_NESTING, + E_BUFFER_OVERFLOW, + E_NULL_FORBIDDEN } osError_t; +/** Enum to hold all possible warning codes. + * + */ +typedef enum +{ + W_SYS_TIMER_OVERFLOW +} osWarning_t; + //--------------Heaps-------------------- /** Data type to hold a pointer to a TCB. -*/ + * + */ typedef osTCB_t* osHeapNode_t; +//--------------Queues------------------- + +/** Data type holds a void pointer to an array to be able to use the queues for many data types. + * + */ +typedef struct +{ + uint8_t write_p; + uint8_t read_p; + /* Gives you the possibility to use the q with every data type. */ + void* start; + size_t varsize; +} osQUEUE_t; + #endif diff --git a/software/os/printf.c b/software/os/printf.c index 1e4076d..81c3238 100644 --- a/software/os/printf.c +++ b/software/os/printf.c @@ -12,9 +12,13 @@ #include "helpers.h" #include "printf.h" #include "../platform/usart.h" +#include "ossettings.h" /** Increment index for a char buffer savely, preventing overflows. * + * @param ioindex Index, that is supposed to be manipulated. + * @param ibuffsize Buffer size, which should not be exceeded. + * @retval 1 (SUCCESS) or 0 (FAILURE). */ static inline uint8_t osPreventBuffOv(uint* ioindex, size_t ibuffsize) { @@ -27,8 +31,15 @@ static inline uint8_t osPreventBuffOv(uint* ioindex, size_t ibuffsize) /** Parsing for floats within printf. * + * @param iobuffer Buffer where the formated string ends up. + * @param ibuffsize Size of the iobuffer for security reasons. + * @param iformat Pointer to the format string from the user. + * @param i Pointer to the index where to write in the iobuffer. + * @param ifloat Float which shall be printed nicely. + * @param iflag Indicator if the user wants a certain amount of decimals. + * @retval Characters printed (SUCCESS) or -1 (FAILURE). */ -static void osParseFloat(char* iobuffer, size_t ibuffsize, const char** iformat, uint* i, double ifloat, uint8_t flag) +static void osParseFloat(char* iobuffer, size_t ibuffsize, const char** iformat, uint* i, double ifloat, uint8_t iflag) { int temp_int; size_t temp_buffsize; @@ -47,7 +58,7 @@ static void osParseFloat(char* iobuffer, size_t ibuffsize, const char** iformat, iobuffer[*i] = temp_string[j]; osPreventBuffOv(i, ibuffsize); } - if(!flag) + if(!iflag) float_decimals = 4; else { @@ -76,13 +87,10 @@ static void osParseFloat(char* iobuffer, size_t ibuffsize, const char** iformat, osPreventBuffOv(i, ibuffsize); } /* Get rid of the f. */ - if(flag) + if(iflag) (*iformat)++; } -/** printf implementation where the magic happens. - * - */ int osVPrintf(va_list iarguments, char* iobuffer, size_t ibuffsize, const char* iformat) { uint i = 0; @@ -150,6 +158,19 @@ int osVPrintf(va_list iarguments, char* iobuffer, size_t ibuffsize, const char* } else { + /* If you are too lazy to always type \r\n */ + #ifdef CONVERT_NEWLINE + if( (*iformat) == '\n' ) + { + /* Copy \n */ + iobuffer[i] = *iformat; + iformat++; + osPreventBuffOv(&i, ibuffsize); + /* Add \r */ + iobuffer[i] = '\r'; + osPreventBuffOv(&i, ibuffsize); + } + #endif /* Copy characters into buffer. */ iobuffer[i] = *iformat; iformat++; @@ -161,17 +182,6 @@ int osVPrintf(va_list iarguments, char* iobuffer, size_t ibuffsize, const char* return (i+1); } -/** printf to be used by the OS user. Can be ported to another platform easily - * by just using another function to transmit one string with the USART. - * - * @param iformat Currently supported are - %d integers - %c single characters - %s C strings - %f Floats with 4 decimals - %.xf Floats with x decimals - * @retval Returns the number of characters printed (SUCCESS) or -1 (FAILURE). - */ int osPrintf(const char* iformat, ...) { va_list arguments; diff --git a/software/os/printf.h b/software/os/printf.h index 35f84bb..36cb929 100644 --- a/software/os/printf.h +++ b/software/os/printf.h @@ -8,11 +8,34 @@ #ifndef OS_PRINTF_H_ #define OS_PRINTF_H_ +//--------------Includes----------------- #include #include #include "stm32f10x.h" +//--------------Funtions----------------- + +/** printf to be used by the OS user. Can be ported to another platform easily + * by just using another function to transmit one string with the USART. + * + * @param iformat Currently supported are + %d integers + %c single characters + %s C strings + %f Floats with 4 decimals + %.xf Floats with x decimals + * @retval Returns the number of characters printed (SUCCESS) or -1 (FAILURE). + */ int osPrintf(const char* iformat, ...); + +/** printf implementation where the magic happens. + * + * @param iarguments Variable arguments list. + * @param iobuffer Buffer where the formated string ends up. + * @param ibuffsize Size of the iobuffer for security reasons. + * @param iformat Format string from the user. + * @retval Characters printed (SUCCESS) or -1 (FAILURE). + */ int osVPrintf(va_list iarguments, char* iobuffer, size_t ibuffsize, const char* iformat); #endif /* OS_PRINTF_H_ */ diff --git a/software/os/queues.h b/software/os/queues.h index f9b276f..f50a84f 100644 --- a/software/os/queues.h +++ b/software/os/queues.h @@ -8,19 +8,15 @@ #ifndef OS_QUEUES_H_ #define OS_QUEUES_H_ -#include "stm32f10x.h" -#include +//--------------Include------------------ + +#include +#include"ostypes.h" +#include #define MAX_QUEUE_SIZE 64 -typedef struct -{ - uint8_t write_p; - uint8_t read_p; - /* Gives you the possibility to use the q with every data type. */ - void* start; - size_t varsize; -} osQUEUE_t; +//--------------Functions---------------- void osQInit(osQUEUE_t* q, size_t ivarsize, void* istart); diff --git a/software/os/scheduler.c b/software/os/scheduler.c index be0c707..1446675 100644 --- a/software/os/scheduler.c +++ b/software/os/scheduler.c @@ -1,11 +1,15 @@ +//--------------Includes----------------- + #include #include #include #include #include"scheduler.h" #include"error.h" -#include"settings.h" #include"heap.h" +#include"printf.h" +#include"ossettings.h" +#include"../platform/system_timer.h" /* TCBs */ static osTCB_t tasks[MAX_NUMBER_OF_TASKS]; @@ -19,18 +23,26 @@ static osHeapNode_t current = NULL; /* Timing */ static uint32_t sys_clk = 0; -/* Queues */ +/* Priority queues */ static osHeapNode_t ready_q[HEAP_SIZE]; +/** Get the task which is running. + * + * @retval Pointer to TCB of the running task. + */ static inline osTCB_t* osSchedulerGetRunningT(void) { for(int i=0; istate = BLOCKED; task_running->wake_up = sys_clk + idelay; } @@ -87,66 +102,112 @@ void osTaskDelay(uint8_t idelay) void osTaskDelayUntil(uint32_t iwakeup_time, uint8_t idelay) { osTCB_t* task_running = osSchedulerGetRunningT(); + if( task_running == NULL ) + THROW_ERROR(E_NULL_FORBIDDEN); task_running->state = BLOCKED; task_running->wake_up = iwakeup_time + idelay; } -uint8_t osRunScheduler(void) +void osRunScheduler(void) { - printf("System clock: %d\n", ++sys_clk); - /* Are any tasks becomming ready? */ - for(int i=0; istate = RUNNING; - state = S_EXECUTING_TASK; - (*(current->fnc_ptr))(current->arguments); - state = S_EXECUTING_NO_TASK; - break; - case S_IDELING: - printf("S_IDELING\n"); - if(!osHeapIsEmpty(ready_q)) - state = S_EXECUTING_NO_TASK; - break; - } + uint32_t sys_clk_old = sys_clk; + static uint8_t flag = 0; + /* The Cortex-M3 system timer for instance + * can not handle a very high period needed + * e.g. for debugging as the register is + * simply too small. */ + #if (SYS_TICK_MS >= 100) + static uint16_t cnt = 0; + if(cnt != SYS_TICK_MS/SYS_TICK_PERIOD_MS) + { + /* Don't execute scheduler. */ + cnt++; + return; + } + else + cnt = 0; + #endif + + osPrintf("System clock: %d\n", ++sys_clk); + if(sys_clk < sys_clk_old) + THROW_WARNING(W_SYS_TIMER_OVERFLOW); + if( (sys_clk % ALIVE_PULSE_LENGTH) == 0) + toggleAliveLED(); + /* Are any tasks becomming ready? */ + if(flag) + { + osPrintf("Hej!\n"); + for(int i=0; i0; i--) + { + if( tasks[i].state == BLOCKED) + { + if(tasks[i].wake_up <= sys_clk) + { + /* Wake up task and put + it into ready queue. */ + tasks[i].state = READY; + osHeapInsert(ready_q, &tasks[i]); + } + } + } + } + flag ^= 1; + switch(state) + { + case S_INIT: + osPrintf("S_INIT\n"); + state = S_EXECUTING_NO_TASK; + break; + case S_EXECUTING_TASK: + osPrintf("S_EXECUTING_TASK\n"); + break; + case S_EXECUTING_NO_TASK: + osPrintf("S_EXECUTING_NO_TASK\n"); + /* Check if queue is empty. */ + if(osHeapIsEmpty(ready_q)) + { + state = S_IDELING; + break; + } + osHeapExtractMaximum(ready_q, ¤t); + current->state = RUNNING; + state = S_EXECUTING_TASK; + (*(current->fnc_ptr))(current->arguments); + state = S_EXECUTING_NO_TASK; + break; + case S_IDELING: + osPrintf("S_IDELING\n"); + if(!osHeapIsEmpty(ready_q)) + state = S_EXECUTING_NO_TASK; + break; + } } -void osPrintTask(uint8_t index) +void osPrintTask(uint8_t iindex) { - printf("Function Pointer:\t%p\n", tasks[index].fnc_ptr); - printf("Name:\t\t\t%s\n", tasks[index].name); - printf("Arguments Pointer:\t%p\n", tasks[index].fnc_ptr); - printf("Priority:\t\t%d\n", tasks[index].priority); - printf("State:\t\t\t%d\n", tasks[index].state); - printf("Wake up:\t\t%d\n", tasks[index].wake_up); + //osPrintf("Function Pointer:\t%d\n", tasks[iindex].fnc_ptr); + osPrintf("Name:\t\t\t%s\n", tasks[iindex].name); + //osPrintf("Arguments Pointer:\t%d\n", tasks[iindex].fnc_ptr); + //osPrintf("Priority:\t\t%d\n", tasks[iindex].priority); + //osPrintf("State:\t\t\t%d\n", tasks[iindex].state); + //osPrintf("Wake up:\t\t%d\n", tasks[iindex].wake_up); } void osPrintAllTasks(void) @@ -154,6 +215,6 @@ void osPrintAllTasks(void) for(int i=0; i #include -#include"settings.h" + +#include "ossettings.h" #include"ostypes.h" //--------------Functions---------------- -static inline osTCB_t* osSchedulerGetRunningT(void); - -static void osSchedulerInit(void); - +// TODO: Schedule round robin when two or more tasks have the same priority. + +/** Spawn a task. + * + * @param ifnc_ptr Pointer to the task function. + * @param itask_name Internal task name. + * @param iarguments Enables passing user-defined arguments to the task. + * @param ipriority A higher value means a higher priority of the task. + * @param oTaskHandle Pointer to TCB. + * @retval 1 (task has been spawned) or 0 (FAILED) + */ uint8_t osTaskCreate(void (*ifnc_ptr)(void*), char* itask_name, void* iarguments, uint8_t ipriority, const osTCB_t* oTaskHandle); +/** Simply delete task by setting the function pointer to NULL. + * + * @param iotask Pointer to TCB. + */ void osTaskDelete(osTCB_t* iotask); +/** Delay function. DO NOT USE FOR PERIODIC TASKS! + * + * @param idelay Delay in system ticks. + */ void osTaskDelay(uint8_t idelay); +/** Delay until function. DO USE FOR PERIODIC TASKS! + * + * @param iwakeup_time Time when the task execution started. + * @param idelay Number of system ticks until the task shall be executed again. + */ void osTaskDelayUntil(uint32_t iwakeup_time, uint8_t idelay); -uint8_t osRunScheduler(void); +/** System core. Scheduler needs to be executed by a timer interrupt. + * + */ +void osRunScheduler(void); -void osPrintTask(uint8_t index); +/** Print all information about one task. + * + * @param iindex Index in the TCB array. + */ +void osPrintTask(uint8_t iindex); +/** Print all information about all tasks. + * + */ void osPrintAllTasks(void); #endif diff --git a/software/os/settings.h b/software/os/settings.h deleted file mode 100644 index 7217ec9..0000000 --- a/software/os/settings.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef OS_SETTINGS_H -#define OS_SETTINGS_H - -/* Error */ -#define MAX_MESSAGE_SIZE 255 - -/* Porting */ -#define X86_TEST_ENVIRONMENT -/* Only needed for X86 simulation. */ -#define MAX_LEVEL_INT_NESTING 3 - -/* Scheduler */ -#define MAX_SIZE_TASK_NAME 20 -#define MAX_NUMBER_OF_TASKS 4 -#define CLOCK_TICK_RATE_MS 10 -#define HEAP_SIZE 6 - -#if (MAX_NUMBER_OF_TASKS > HEAP_SIZE) - #warning "HEAP_SIZE < MAX_NUMER_OF_TASKS: This might lead to problems." -#endif - -#endif diff --git a/software/platform/system_timer.c b/software/platform/system_timer.c index b2972b9..e3563ab 100644 --- a/software/platform/system_timer.c +++ b/software/platform/system_timer.c @@ -5,15 +5,15 @@ * Author: maximilian */ -#include "stm32f10x.h" -#include "stm32f10x_flash.h" -#include "stm32f10x_rcc.h" +//--------------Includes----------------- -#define ALIVE_PULSE_LENGTH 200 +#include +#include +#include +#include"../os/scheduler.h" +#include"../os/ossettings.h" -static volatile uint32_t ticky = 0; - -void InitAliveLED(void) +void initAliveLED(void) { /* Activate clock for peripheral. */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); @@ -27,7 +27,14 @@ void InitAliveLED(void) GPIO_Init (GPIOA , & GPIO_InitStructure ); } -void InitClock(void) +void toggleAliveLED(void) +{ + static volatile uint8_t led_stat = 0; + led_stat = !led_stat; + GPIO_WriteBit(GPIOA, GPIO_Pin_5, led_stat); +} + +void initClock(void) { /* Configure all clocks to max for best performance. If there are EMI, power, or noise problems, try slowing the clocks.*/ @@ -51,20 +58,13 @@ void InitClock(void) RCC_PCLK1Config(RCC_HCLK_Div8); RCC_PCLK2Config(RCC_HCLK_Div8); - /* Configure Cortex-M System Tick Timer to tick every ms.*/ + /* Configure Cortex-M System Tick Timer to tick as the os user defined.*/ SystemCoreClockUpdate(); - SysTick_Config(SystemCoreClock / 1000); + SysTick_Config( (SystemCoreClock/1000) * SYS_TICK_PERIOD_MS ); } void SysTick_Handler(void) { - static volatile uint8_t led_stat = 0; - if(ticky == ALIVE_PULSE_LENGTH) - { - led_stat = !led_stat; - GPIO_WriteBit(GPIOA, GPIO_Pin_5, led_stat); - ticky = 0; - } - else - ticky++; + // TODO: For porting use another timer here to call the scheduler. + osRunScheduler(); } diff --git a/software/platform/system_timer.h b/software/platform/system_timer.h index c8453e4..df979b5 100644 --- a/software/platform/system_timer.h +++ b/software/platform/system_timer.h @@ -8,7 +8,8 @@ #ifndef PLATFORM_SYSTEM_TIMER_H_ #define PLATFORM_SYSTEM_TIMER_H_ -void InitAliveLED(void); -void InitClock(void); +void initAliveLED(void); +void toggleAliveLED(void); +void initClock(void); #endif /* PLATFORM_SYSTEM_TIMER_H_ */