Last active
August 2, 2020 09:58
-
-
Save OrsoEric/5d3801d5492efe08c8a2a884c1c6fff1 to your computer and use it in GitHub Desktop.
Longan Nano GD32VF103 Chrono Scheduler Demo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/**************************************************************************** | |
** OrangeBot Project | |
***************************************************************************** | |
** / | |
** / | |
** / | |
** ______ \ | |
** \ | |
** \ | |
***************************************************************************** | |
** Longan Nano Chrono Scheduler Demo | |
***************************************************************************** | |
** Show how to use the Chrono class to build a fixed function scheduler | |
** and use the Chrono class to measure elapsed time and accumulated time | |
****************************************************************************/ | |
/**************************************************************************** | |
** INCLUDES | |
****************************************************************************/ | |
//Longan Nano HAL | |
#include <gd32vf103.h> | |
//LED class | |
#include "longan_nano_led.hpp" | |
//Time class | |
#include "longan_nano_chrono.hpp" | |
/**************************************************************************** | |
** NAMESPACES | |
****************************************************************************/ | |
/**************************************************************************** | |
** DEFINES | |
****************************************************************************/ | |
//forever | |
#define EVER (;;) | |
/**************************************************************************** | |
** MACROS | |
****************************************************************************/ | |
/**************************************************************************** | |
** ENUM | |
****************************************************************************/ | |
//Configurations | |
typedef enum _Config | |
{ | |
//Microseconds between led toggles | |
RED_LED_BLINK_US = 250000, | |
GREEN_LED_BLINK_US = 750000, | |
} Config; | |
/**************************************************************************** | |
** STRUCT | |
****************************************************************************/ | |
//flags used by the hardwired scheduler | |
typedef struct _Scheduler | |
{ | |
bool f_red_led : 1; | |
bool f_green_led : 1; | |
bool f_overrun : 1; | |
} Scheduler; | |
/**************************************************************************** | |
** PROTOTYPES | |
****************************************************************************/ | |
/**************************************************************************** | |
** GLOBAL VARIABILES | |
****************************************************************************/ | |
//Scheduler for the tasks | |
Scheduler g_scheduler = { 0 }; | |
/**************************************************************************** | |
** FUNCTIONS | |
****************************************************************************/ | |
/**************************************************************************** | |
** @brief main | |
** main | void | |
****************************************************************************/ | |
//! @return int | | |
//! @details Entry point of program | |
/***************************************************************************/ | |
int main( void ) | |
{ | |
//---------------------------------------------------------------- | |
// VARS | |
//---------------------------------------------------------------- | |
//Systick timer used to schedule activities | |
Longan_nano::Chrono timer_scheduler; | |
//Systick timers to profile resource use | |
Longan_nano::Chrono timer_uptime; | |
Longan_nano::Chrono timer_cpu_use; | |
//Prescale the fastest task to generate other flags | |
static uint16_t scheduler_cnt; | |
//---------------------------------------------------------------- | |
// INIT | |
//---------------------------------------------------------------- | |
//Initialize LEDs | |
Longan_nano::Leds::init(); | |
Longan_nano::Leds::set_color( Longan_nano::Leds::Color::BLACK ); | |
//Snap start | |
timer_scheduler.start(); | |
timer_uptime.start(); | |
//---------------------------------------------------------------- | |
// BODY | |
//---------------------------------------------------------------- | |
for EVER | |
{ | |
//---------------------------------------------------------------- | |
// Scheduler | |
//---------------------------------------------------------------- | |
// Hardwired scheduler to release tasks | |
// Thanks to the Longan Nano SysTick timer there is no need to use peripherals for timekeeping | |
//Snap stop and get time since last start in microseconds | |
int elapsed_us = timer_scheduler.stop( Longan_nano::Chrono::Unit::microseconds ); | |
//If: for some reason, the timing is invalid. Algorithmic error | |
if (elapsed_us < 0) | |
{ | |
//Blue led means error | |
Longan_nano::Leds::set( Longan_nano::Leds::Color::BLUE ); | |
} | |
//If: enough time has passed between screen executions | |
else if (elapsed_us >= Config::RED_LED_BLINK_US) | |
{ | |
//---------------------------------------------------------------- | |
// LED | |
//---------------------------------------------------------------- | |
// The screen is the fastest task | |
//If: the previous task was not cleared | |
if (g_scheduler.f_red_led == true) | |
{ | |
//There was an overrun. Not enough CPU to keep up | |
g_scheduler.f_overrun = true; | |
} | |
else | |
{ | |
//Issue a LED BLINK update | |
g_scheduler.f_red_led = true; | |
} | |
//Snap start. Restart the timer | |
timer_scheduler.start(); | |
//---------------------------------------------------------------- | |
// Prescaler | |
//---------------------------------------------------------------- | |
// A prescaler is used to schedule the execution of slow tasks without the need of additional timers | |
//Prescaler counter | |
scheduler_cnt++; | |
//---------------------------------------------------------------- | |
// LED Blink | |
//---------------------------------------------------------------- | |
//If: enough ticks of the prescaler counter have elapsed | |
if (scheduler_cnt%(Config::GREEN_LED_BLINK_US /Config::RED_LED_BLINK_US) == 0) | |
{ | |
//If: the previous task was not cleared | |
if (g_scheduler.f_green_led == true) | |
{ | |
//There was an overrun. Not enough CPU to keep up | |
g_scheduler.f_overrun = true; | |
} | |
else | |
{ | |
//Issue a LED BLINK update | |
g_scheduler.f_green_led = true; | |
} | |
} | |
} //If: enough time has passed between screen executions | |
//Default | |
else | |
{ | |
//Nothing to do | |
} | |
//---------------------------------------------------------------- | |
// OVERRUN | |
//---------------------------------------------------------------- | |
// Triggered when a task is not completed before the next issue | |
//If: overrun | |
if (g_scheduler.f_overrun == true) | |
{ | |
//Clear error | |
g_scheduler.f_overrun = false; | |
//Blue led means error | |
Longan_nano::Leds::set( Longan_nano::Leds::Color::BLUE ); | |
} | |
//---------------------------------------------------------------- | |
// TASK: RED LED Blink | |
//---------------------------------------------------------------- | |
// If the RED LED Blink task is authorized to run | |
if (g_scheduler.f_red_led == true) | |
{ | |
//Reset flag | |
g_scheduler.f_red_led = false; | |
//Snap start to profile the CPU time spent in this task | |
timer_cpu_use.start(); | |
//Task code: in this calse blink the red led | |
Longan_nano::Leds::toggle( Longan_nano::Leds::Color::RED ); | |
//Accumulate DeltaT into the CPU timer accumulator | |
timer_cpu_use.accumulate(); | |
} | |
//---------------------------------------------------------------- | |
// TASK: GREEN LED Blink | |
//---------------------------------------------------------------- | |
// If the GREEN LED Blink task is authorized to run | |
if (g_scheduler.f_green_led == true) | |
{ | |
//Reset flag | |
g_scheduler.f_green_led = false; | |
//Snap start to profile the CPU time spent in this task | |
timer_cpu_use.start(); | |
//Task code: in this calse blink the red led | |
Longan_nano::Leds::toggle( Longan_nano::Leds::Color::GREEN ); | |
//Accumulate DeltaT into the CPU timer accumulator | |
timer_cpu_use.accumulate(); | |
} | |
//---------------------------------------------------------------- | |
// UPTIME | |
//---------------------------------------------------------------- | |
// At any moment the application can access to the time since application start | |
timer_uptime.stop( Longan_nano::Chrono::Unit::microseconds ); | |
//---------------------------------------------------------------- | |
// CPU use | |
//---------------------------------------------------------------- | |
// At any moment the application can access to the total time the CPU spent running tasks | |
timer_cpu_use.get_accumulator( Longan_nano::Chrono::Unit::microseconds ); | |
} //End forever | |
//---------------------------------------------------------------- | |
// RETURN | |
//---------------------------------------------------------------- | |
return 0; | |
} //end function: main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment