Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@OrsoEric
Last active August 2, 2020 09:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OrsoEric/5d3801d5492efe08c8a2a884c1c6fff1 to your computer and use it in GitHub Desktop.
Save OrsoEric/5d3801d5492efe08c8a2a884c1c6fff1 to your computer and use it in GitHub Desktop.
Longan Nano GD32VF103 Chrono Scheduler Demo
/****************************************************************************
** 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