tdse-tp0_03-hw_sw_test

FIUBA - Electrónica - Taller de Sistemas Embebidos - Trabajo Práctico N°: 0 - Proyecto N°: 03
Index Commits Files Refs README
app/src/app_commented_read.me (18333B)
   1 /*
   2  * Copyright (c) 2023 Juan Manuel Cruz <jcruz@fi.uba.ar> <jcruz@frba.utn.edu.ar>.
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions are met:
   7  *
   8  * 1. Redistributions of source code must retain the above copyright
   9  *    notice, this list of conditions and the following disclaimer.
  10  *
  11  * 2. Redistributions in binary form must reproduce the above copyright
  12  *    notice, this list of conditions and the following disclaimer in the
  13  *    documentation and/or other materials provided with the distribution.
  14  *
  15  * 3. Neither the name of the copyright holder nor the names of its
  16  *    contributors may be used to endorse or promote products derived from
  17  *    this software without specific prior written permission.
  18  *
  19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  23  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  25  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  26  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  28  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  29  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  30  * POSSIBILITY OF SUCH DAMAGE.
  31  *
  32  * @file   : app.c
  33  * @date   : Set 26, 2023
  34  * @author : Juan Manuel Cruz <jcruz@fi.uba.ar> <jcruz@frba.utn.edu.ar>
  35  * @version    v1.0.0
  36  */
  37 
  38 /* Development on Bare Metal vs. RTOS
  39  * (https://www.sysgo.com/professional-articles/bare-metal-vs-rtos)
  40  */
  41 /*
  42  * When developing embedded systems that are to be real-time capable, one of
  43  * the first and most important questions is whether the applications should
  44  * run under a real-time operating system (RTOS) or whether a bare-metal
  45  * solution should be developed.
  46  *
  47  * Bare-metal programming is generally understood
  48  * to mean that an application is written directly on the hardware without
  49  * using an external programming interface, i.e. an operating system.
  50  *
  51  * Applications access here directly hardware registers of microcontrollers.
  52  * Here one helps oneself with approaches such as endless loops, which execute
  53  * tasks with fixed computing time. This sequential execution is only deviated
  54  * from when an interrupt event occurs. This bare-metal development approach
  55  * for embedded systems is therefore also known as super-loop.
  56  */
  57 
  58 /* Event-Triggered Systems (ETS) and Time-Triggered (TTS)
  59  * (https://ebrary.net/51334/computer_science/time_event_triggered_systems)
  60  */
  61 /*
  62  * A trigger is an event that causes the start of some action in the control
  63  * system. The action may be the execution of a task reading a variable and
  64  * computing a new value of a correcting variable, or the sending of a message
  65  * reporting current values of variables like pressure or temperature.
  66  *
  67  * In event-triggered control, an action is started only if a significant event
  68  * occurs. For instance, a sensor would send a message only if the temperature
  69  * has changed by more than 3°C since the last message was sent.
  70  *
  71  * In time-triggered control, all actions are initiated periodically by a
  72  * real-time clock. The sensor from our example would send a message every
  73  * clock cycle even if the temperature remains constant.
  74  */
  75 
  76 /* C Programming Language Tutorial (https://www.geeksforgeeks.org/) */
  77 /*
  78  *  C Basics - C Variables and Constants - C Data Types - C Input/Output
  79  *  C Operators - C Control Statements Decision-Making - C Functions
  80  *  C Arrays & Strings - C Pointers - C User-Defined Data Types
  81  *  C Storage Classes - C Memory Management - C Preprocessor - C File Handling
  82  *  Miscellaneous
  83  */
  84 
  85 /* Embedded C Coding Standard by Michael Barr
  86  * www.barrgroup.com/embedded-systems/books/embedded-c-coding-standard */
  87 /*
  88  *  Introduction - General Rules - Comment Rules - White Space Rules -
  89  *  Module Rules - Data Type Rules - Procedure Rules - Variable Rules
  90  *  Statement Rules - Appendices - Bibliography - Index
  91  */
  92 
  93 /* Spaghetti Code (https://www.geeksforgeeks.org/) */
  94 /*
  95  * Spaghetti Code is nothing but a generalized common-usage term for
  96  * unstructured and difficult-to-read code.
  97  *
  98  * Such a type of code in any large code-base can create problems of its own,
  99  * if not resolved on time. It can lead to a huge wastage of important
 100  * resources like time and energy to find bugs and fix them because the code
 101  * has no structure.
 102  */
 103 
 104 /* Structured Programming Approach with Advantages and Disadvantages
 105  * (https://www.geeksforgeeks.org/)
 106  */
 107 /*
 108  * , as the word suggests, can be defined as a programming approach in which
 109  * the program is made as a single structure.
 110  *
 111  * It means that the code will execute the instruction by instruction one after
 112  * the other. It doesn’t support the possibility of jumping from one
 113  * instruction to some other with the help of any statement like GOTO, etc.
 114  * Therefore, the instructions in this approach will be executed in a serial
 115  * and structured manner. The languages that support Structured programming
 116  * approach are:
 117  *
 118  *  C
 119  *  C++
 120  *  Java
 121  *  C#
 122  *  ..etc
 123  */
 124 
 125 /* Introduction of Programming Paradigms
 126  * (https://www.geeksforgeeks.org/)
 127  */
 128 /*
 129  * Paradigm can also be termed as method to solve some problem or do some task.
 130  * Programming paradigm is an approach to solve problem using some programming
 131  * language or also we can say it is a method to solve a problem using tools
 132  * and techniques that are available to us following some approach.
 133  *
 134  * There are lots for programming language that are known but all of them need
 135  * to follow some strategy when they are implemented and this methodology/
 136  * strategy is paradigms. Apart from varieties of programming language there
 137  * are lots of paradigms to fulfill each and every demand.
 138  */
 139 
 140 /* Differences between Procedural and Object Oriented Programming
 141  * (https://www.geeksforgeeks.org/)
 142  */
 143 /*
 144  * Procedural Programming can be defined as a programming model which is
 145  * derived from structured programming, based upon the concept of calling
 146  * procedure.
 147  *
 148  * Procedures, also known as routines, subroutines or functions,
 149  * simply consist of a series of computational steps to be carried out. During
 150  * a program’s execution, any given procedure might be called at any point,
 151  * including by other procedures or itself.
 152  */
 153 
 154 /* Modular Approach in Programming (https://www.geeksforgeeks.org/) */
 155 /*
 156  * Modular programming is the process of subdividing a computer program into
 157  * separate sub-programs. A module is a separate software component.
 158  * It can often be used in a variety of applications and functions with other
 159  * components of the system.
 160  */
 161 
 162 /* Features of C Programming Language (https://www.geeksforgeeks.org/) */
 163 /*
 164  * C language is lavishly portable as programs that are written in C language
 165  * can run and compile on any system with either no or small changes.
 166  */
 167 
 168 /* Static functions in C (https://www.geeksforgeeks.org/) */
 169 /*
 170  * Unlike global functions in C, access to static functions is restricted to
 171  * the file where they are declared. Therefore, when we want to restrict
 172  * access to functions, we make them static. Another reason for making
 173  * functions static can be the reuse of the same function name in other files.
 174  */
 175 
 176 /* Referencias */
 177 /*
 178  * SW
 179  * (https://campusgrado.fi.uba.ar/course/view.php?id=1217&section=10#tabs-tree-start)
 180  *
 181  * HW & FW/MW
 182  * (https://campusgrado.fi.uba.ar/course/view.php?id=1217&section=11#tabs-tree-start)
 183  *
 184  * Files & Folders
 185  * (https://campusgrado.fi.uba.ar/course/view.php?id=1217&section=12#tabs-tree-start)
 186  */
 187 
 188 /********************** inclusions *******************************************/
 189 
 190 /* C Preprocessors (https://www.geeksforgeeks.org/) */
 191 /*
 192  * The #include preprocessor directive is used to include the header files in
 193  * the C program.
 194  */
 195 /* Project includes. */
 196 #include "main.h"
 197 
 198 /* Demo includes. */
 199 #include "logger.h"
 200 #include "dwt.h"
 201 
 202 /* Application & Tasks includes. */
 203 #include "board.h"
 204 #include "task_a.h"
 205 #include "task_b.h"
 206 #include "task_c.h"
 207 
 208 /********************** macros and definitions *******************************/
 209 
 210 /* #define in C (https://www.geeksforgeeks.org/) */
 211 /* Macros and its types in C (https://www.geeksforgeeks.org/) */
 212 /*
 213  * In C programming, #define is a preprocessor directive that is used to define
 214  * macros. The macros are the identifiers defined by #define which are replaced
 215  * by their value before compilation. We can define constants and functions
 216  * like macros using #define. The generics in C are also implemented using the
 217  * #define preprocessor directive along with _Generic.
 218  *
 219  * In C, a macro is a piece of code in a program that is replaced by the value
 220  * of the macro. Macro is defined by #define directive. Whenever a macro name
 221  * is encountered by the compiler, it replaces the name with the definition of
 222  * the macro. Macro definitions need not be terminated by a semi-colon(;).
 223  */
 224 #define G_APP_CNT_INI        0ul
 225 #define G_APP_TICK_CNT_INI    0ul
 226 
 227 #define TASK_X_WCET_INI        0ul
 228 #define TASK_X_DELAY_MIN    0ul
 229 
 230 /* C Structures (https://www.geeksforgeeks.org/) */
 231 /*
 232  * The structure in C is a user-defined data type that can be used to group
 233  * items of possibly different types into a single type. The struct keyword is
 234  * used to define the structure in the C programming language. The items in
 235  * the structure are called its member and they can be of any valid data type.
 236  */
 237 
 238 /* Function Pointer in C - How to declare a pointer to a function?
 239  * (https://www.geeksforgeeks.org/)
 240  */
 241 /*
 242  * In C, like normal data pointers (int *, char *, etc), we can have
 243  * pointers to functions.
 244  *
 245  * While a pointer to a variable or an object is used to access them
 246  * indirectly, a pointer to a function is used to invoke a function indirectly.
 247  */
 248 typedef struct {
 249     void (*task_init)(void *);        // Pointer to task (must be a
 250                                     // 'void (void *)' function)
 251     void (*task_update)(void *);    // Pointer to task (must be a
 252                                     // 'void (void *)' function)
 253     void *parameters;                // Pointer to parameters
 254 } task_cfg_t;
 255 
 256 typedef struct {
 257     uint32_t WCET;            // Worst-case execution time (microseconds)
 258 } task_dta_t;
 259 
 260 /********************** internal data declaration ****************************/
 261 
 262 /* C Arrays (https://www.geeksforgeeks.org/) */
 263 /*
 264  * Array in C is one of the most used data structures in C programming. It is a
 265  * simple and fast way of storing multiple values under a single name.
 266  */
 267 const task_cfg_t task_cfg_list[]    = {
 268         {task_a_init,     task_a_update,     NULL},
 269         {task_b_init,     task_b_update,     NULL},
 270         {task_c_init,    task_c_update,     NULL}
 271 };
 272 
 273 #define TASK_QTY    (sizeof(task_cfg_list)/sizeof(task_cfg_t))
 274 
 275 /********************** internal functions declaration ***********************/
 276 
 277 /********************** internal data definition *****************************/
 278 
 279 /* Memory Layout of C Programs (https://www.geeksforgeeks.org/) */
 280 /* Storage Classes in C (https://www.geeksforgeeks.org/) */
 281 /* C Variables (https://www.geeksforgeeks.org/) */
 282 /* Constants in C (https://www.geeksforgeeks.org/) */
 283 /* Const Qualifier in C (https://www.geeksforgeeks.org/) */
 284 /*
 285  * The constants in C are the read-only variables whose values cannot be
 286  * modified once they are declared in the C program. The type of constant can
 287  * be an integer constant, a floating pointer constant, a string constant, or
 288  * a character constant. In C language, the const keyword is used to define the
 289  * constants.
 290  *
 291  * The qualifier const can be applied to the declaration of any variable to
 292  * specify that its value will not be changed (which depends upon where const
 293  * variables are stored, we may change the value of the const variable by
 294  * using a pointer).
 295  * The result is implementation-defined if an attempt is made to change a
 296  * const.
 297  * Using the const qualifier in C is a good practice when we want to ensure
 298  * that some values should remain constant and should not be accidentally
 299  * modified.
 300  */
 301 const char *p_sys    = " Bare Metal - Event-Triggered Systems (ETS)";
 302 const char *p_app    = " App - retarget_printf_to_Console";
 303 
 304 /********************** external data declaration ****************************/
 305 
 306 /* Memory Layout of C Programs (https://www.geeksforgeeks.org/) */
 307 /* Storage Classes in C (https://www.geeksforgeeks.org/) */
 308 /* C Variables (https://www.geeksforgeeks.org/) */
 309 /* Global Variables in C (https://www.geeksforgeeks.org/) */
 310 /*
 311  * A variable declared outside any function or a block of code is called a
 312  * global variable. Global variables are frequently used to permanently store
 313  * data in a defined scope where they can be accessed and manipulated.
 314  *
 315  * Global variables do not stay limited to a specific function, which means
 316  * that one can use any given function to access and modify the global
 317  * variables. The initialization of these variables occurs automatically to 0
 318  * during the time of declaration. Also, we generally write the global
 319  * variables before the main() function.
 320  */
 321 uint32_t g_app_cnt;
 322 uint32_t g_app_runtime_us;
 323 
 324 /* Understanding “volatile” qualifier in C | Set 1 (Introduction)
 325  * Understanding “volatile” qualifier in C | Set 2 (Examples)
 326  * (https://www.geeksforgeeks.org/)
 327  */
 328 /*
 329  * The volatile keyword is intended to prevent the compiler from applying any
 330  * optimizations on objects that can change in ways that cannot be determined
 331  * by the compiler.
 332  * Objects declared as volatile are omitted from optimization because their
 333  * values can be changed by code outside the scope of current code at any time.
 334  * The system always reads the current value of a volatile object from the
 335  * memory location rather than keeping its value in a temporary register at the
 336  * point it is requested, even if a previous instruction asked for the value
 337  * from the same object.
 338  */
 339 volatile uint32_t g_app_tick_cnt;
 340 
 341 task_dta_t task_dta_list[TASK_QTY];
 342 
 343 /********************** external functions definition ************************/
 344 
 345 /* Memory Layout of C Programs (https://www.geeksforgeeks.org/) */
 346 /* Storage Classes in C (https://www.geeksforgeeks.org/) */
 347 /* C Functions (https://www.geeksforgeeks.org/) */
 348 /*
 349  * The function definition consists of actual statements which are executed
 350  * when the function is called (i.e. when the program control comes to the
 351  * function).
 352  */
 353 void app_init(void)
 354 {
 355     uint32_t index;
 356 
 357     /* Print out: Application Initialized */
 358     LOGGER_INFO(" ");
 359     LOGGER_INFO("%s is running - Tick [mS] = %lu", GET_NAME(app_init), HAL_GetTick());
 360 
 361     LOGGER_INFO(p_sys);
 362     LOGGER_INFO(p_app);
 363 
 364     /* Init & Print out: Application execution counter */
 365     g_app_cnt = G_APP_CNT_INI;
 366     LOGGER_INFO(" %s = %lu", GET_NAME(g_app_cnt), g_app_cnt);
 367 
 368     /* Init Cycle Counter */
 369     cycle_counter_init();
 370 
 371     /* Go through the task arrays */
 372     for (index = 0; TASK_QTY > index; index++)
 373     {
 374         /* C Functions (https://www.geeksforgeeks.org/) */
 375         /*
 376          * A function call is a statement that instructs the compiler to execute
 377          * the function.
 378          * We use the function name and parameters in the function call.
 379          */
 380         /* Run task_x_init */
 381         (*task_cfg_list[index].task_init)(task_cfg_list[index].parameters);
 382 
 383         /* Init variables */
 384         task_dta_list[index].WCET = TASK_X_WCET_INI;
 385     }
 386 
 387     /* Protect shared resource */
 388     __asm("CPSID i");    /* disable interrupts */
 389     /* Init Tick Counter */
 390     g_app_tick_cnt = G_APP_TICK_CNT_INI;
 391     g_task_c_tick_cnt = G_APP_TICK_CNT_INI;
 392     __asm("CPSIE i");    /* enable interrupts */
 393 }
 394 
 395 void app_update(void)
 396 {
 397     uint32_t index;
 398     bool b_time_update_required = false;
 399     uint32_t cycle_counter_time_us;
 400 
 401     /* Protect shared resource */
 402     __asm("CPSID i");    /* disable interrupts */
 403     if (G_APP_TICK_CNT_INI < g_app_tick_cnt)
 404     {
 405         /* Update Tick Counter */
 406         g_app_tick_cnt--;
 407         b_time_update_required = true;
 408     }
 409     __asm("CPSIE i");    /* enable interrupts */
 410 
 411     /* Check if it's time to run tasks */
 412     while (b_time_update_required)
 413     {
 414         /* Update App Counter */
 415         g_app_cnt++;
 416         g_app_runtime_us = 0;
 417 
 418         /* Go through the task arrays */
 419         for (index = 0; TASK_QTY > index; index++)
 420         {
 421             cycle_counter_reset();
 422 
 423             /* C Functions (https://www.geeksforgeeks.org/) */
 424             /*
 425              * A function call is a statement that instructs the compiler to execute
 426              * the function.
 427              * We use the function name and parameters in the function call.
 428              */
 429             /* Run task_x_update */
 430             (*task_cfg_list[index].task_update)(task_cfg_list[index].parameters);
 431 
 432             cycle_counter_time_us = cycle_counter_get_time_us();
 433 
 434             /* Update variables */
 435             g_app_runtime_us += cycle_counter_time_us;
 436 
 437             if (task_dta_list[index].WCET < cycle_counter_time_us)
 438             {
 439                 task_dta_list[index].WCET = cycle_counter_time_us;
 440             }
 441         }
 442 
 443         /* Protect shared resource */
 444         __asm("CPSID i");    /* disable interrupts */
 445         if (G_APP_TICK_CNT_INI < g_app_tick_cnt)
 446         {
 447             /* Update Tick Counter */
 448             g_app_tick_cnt--;
 449             b_time_update_required = true;
 450         }
 451         else
 452         {
 453             b_time_update_required = false;
 454         }
 455         __asm("CPSIE i");    /* enable interrupts */
 456     }
 457 }
 458 
 459 /* Callbacks in C (https://www.geeksforgeeks.org/) */
 460 /*
 461  * A callback is any executable code that is passed as an argument to another
 462  * code, which is expected to call back (execute) the argument at a given time.
 463  * In simple language, If a reference of a function is passed to another
 464  * function as an argument to call it, then it will be called a Callback
 465  * function.
 466  */
 467 
 468 void HAL_SYSTICK_Callback(void)
 469 {
 470     /* Update Tick Counter */
 471     g_app_tick_cnt++;
 472 
 473     g_task_c_tick_cnt++;
 474 }
 475 
 476 /********************** end of file ******************************************/