>>>Longan Nano GD32VF103<<<
Illustration 1: Longan Nano test bench
1Introduction
The blink example went up quite painlessly, and I was also able to compile and execute the Bad Apple example that takes a stream of bitmap images from the SD Card and shows them on the screen.
With the basics out of the way, I focused on the interrupts.
1.1Arduino Framework Compatibility
The product page claims compatibility with the Arduino Framework, so I wanted to try the Arduino like interrupt handling.
Early on it was obvious that the Arduino framework has not been completed as the time of writing, with basic HAL functions like the digitalRead() empty. There was no hope of getting Arduino style interrupts to work without doing the framework HAL myself, so I dropped the thing.
2Interrupts
The Risc-V ISA specifies the interrupt handling as part of the core. Details about the ECLIC can be found in this excellent post from Kevin Sangeelee.
The GD32VF103 support an interrupt vector table defined as weak symbols in Start.S in the GD32 framework, it supports tiered priority where high priority interrupts can interrupt low priority ones and has hardware acceleration for them inside the MCU, on top of the special instructions and registers inside the core, as per Risc-V ISA specifications.
The GD32VF103 provides special interrupts from all sort of sources, including a reset vector, an error vector and a watchdog vector, on top of interrupts from almost every peripheral.
2.1Difficulties
Getting the interrupts to work was not easy.
In theory, all I had to do was to define a function with the same name as the symbol in start.S, and the C++ linker should have automagically linked the definitions by overriding the default .weak symbols.
After lots of testing, stack overflow came through with the answer: I need to use the keyword extern “C” to tell the C++ compiler not to change the name of the function and allow the linker to do its job and link the address of the interrupt service routine to the interrupt vector table.
3Example: PA8 EXTI
The Boot button is also wired to the PA8 pin. The EXTI in combination with the ECLIC is used to sense an edge on PA8 and trigger an ISR.
#include <gd32vf103.h> | |
#define EVER (;;) | |
void init() | |
{ | |
//Clock the GPIO banks | |
rcu_periph_clock_enable(RCU_GPIOA); | |
rcu_periph_clock_enable(RCU_GPIOC); | |
//Setup the R, G and B LEDs | |
gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_1); | |
gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_2); | |
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ,GPIO_PIN_8); | |
//Setup the boot button | |
gpio_init(GPIOC, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_13); | |
//Initialize the LEDs to: OFF | |
gpio_bit_set(GPIOC,GPIO_PIN_13); | |
gpio_bit_set(GPIOA,GPIO_PIN_1); | |
gpio_bit_set(GPIOA,GPIO_PIN_2); | |
//Clock the alternate functions | |
rcu_periph_clock_enable(RCU_AF); | |
//Initialize the ECLIC IRQ lines | |
eclic_priority_group_set(ECLIC_PRIGROUP_LEVEL3_PRIO1); | |
eclic_irq_enable(EXTI5_9_IRQn, 1, 1); | |
//Initialize the EXTI. IRQ can be generated from GPIO edge detectors | |
gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOA, GPIO_PIN_SOURCE_8); | |
exti_init(EXTI_8, EXTI_INTERRUPT, EXTI_TRIG_BOTH); | |
//Clear interrupt flag. Ensure no spurious execution at start | |
exti_interrupt_flag_clear(EXTI_8); | |
//Enable the interrupts. From now on interrupt handlers can be executed | |
eclic_global_interrupt_enable(); | |
return; | |
} | |
extern "C" | |
void EXTI5_9_IRQHandler() | |
{ | |
//If: interrupt from PA8 boot button | |
if (exti_interrupt_flag_get(EXTI_8) != RESET) | |
{ | |
//Clear the interrupt from PA8 boot button | |
exti_interrupt_flag_clear(EXTI_8); | |
//Toggle the blue led | |
gpio_bit_write(GPIOA, GPIO_PIN_2, (bit_status)(1-gpio_input_bit_get(GPIOA, GPIO_PIN_2))); | |
} | |
//Default: interrupt from an unhandled GPIO | |
else | |
{ | |
//Do nothing (should clear the interrupt flags) | |
} | |
} | |
void delay_us(unsigned int us) | |
{ | |
uint64_t start_mtime, delta_mtime; | |
uint64_t tmp = get_timer_value(); | |
do | |
{ | |
start_mtime = get_timer_value(); | |
} | |
while (start_mtime == tmp); | |
do | |
{ | |
delta_mtime = get_timer_value() - start_mtime; | |
} | |
while(delta_mtime <(SystemCoreClock/4000000.0 *us )); | |
return; | |
} | |
int main() | |
{ | |
init(); | |
for EVER | |
{ | |
//Toggle the RED LED | |
gpio_bit_write(GPIOC, GPIO_PIN_13, (bit_status)(1-gpio_input_bit_get(GPIOC, GPIO_PIN_13))); | |
//2Hz blink | |
delay_us(250000); | |
} | |
return 0; | |
} |
4Example: RTC Interrupt
The RTC timer is initialized to emit a “second” interrupt every 250ms. The interrupt toggles the RED LED.
/**************************************************************************** | |
** OrangeBot Project | |
***************************************************************************** | |
** / | |
** / | |
** / | |
** ______ \ | |
** \ | |
** \ | |
***************************************************************************** | |
** Longan Nano Example - Blink RTC IST | |
***************************************************************************** | |
** Author: Orso Eric | |
** Version: | |
****************************************************************************/ | |
/**************************************************************************** | |
** DESCRIPTION | |
***************************************************************************** | |
** Blink the LEDs using the interrupt service rutine generated by the RTC timer | |
****************************************************************************/ | |
/**************************************************************************** | |
** HYSTORY VERSION | |
***************************************************************************** | |
** 2020-07-05 | |
** Interrupt Service Routine working! | |
** 2020-07-06 | |
** Format source code | |
****************************************************************************/ | |
/**************************************************************************** | |
** KNOWN BUG | |
***************************************************************************** | |
** | |
****************************************************************************/ | |
/**************************************************************************** | |
** INCLUDE | |
****************************************************************************/ | |
#include <gd32vf103.h> | |
//Onboard RBG LEDs of the Longan Nano | |
#include "longan_nano_led.hpp" | |
/**************************************************************************** | |
** NAMESPACES | |
****************************************************************************/ | |
//using namespace std; | |
/**************************************************************************** | |
** DEFINES | |
****************************************************************************/ | |
//forEVER | |
#define EVER (;;) | |
/**************************************************************************** | |
** GLOBAL VARIABILE | |
****************************************************************************/ | |
/**************************************************************************** | |
** FUNCTION PROTOTYPES | |
****************************************************************************/ | |
//Initialize the board | |
extern bool init( void ); | |
//Busy delay using the SysTick timer | |
extern void delay_us(unsigned int us); | |
/**************************************************************************** | |
** FUNCTION | |
****************************************************************************/ | |
/***************************************************************************/ | |
//! @brief maim | |
//! main | void | |
/***************************************************************************/ | |
//! @param delay | unsigned int | how long to wait for in microseconds | |
//! @return void | | |
//! @details \n | |
//! Handles the ISR lines generated by the GPIO lines 5 to 9 | |
/***************************************************************************/ | |
int main( void ) | |
{ | |
//---------------------------------------------------------------- | |
// VARS | |
//---------------------------------------------------------------- | |
bool f_ret = false; | |
//---------------------------------------------------------------- | |
// INIT | |
//---------------------------------------------------------------- | |
//Initialize the board and return success status | |
f_ret |= init(); | |
//---------------------------------------------------------------- | |
// MAIN LOOP | |
//---------------------------------------------------------------- | |
for EVER | |
{ | |
//Toggle the RED LED | |
//Longan_nano::Leds::toggle( Longan_nano::Led_color::RED ); | |
//2Hz blink | |
//delay_us(250000); | |
} | |
//---------------------------------------------------------------- | |
// RETURN | |
//---------------------------------------------------------------- | |
return 0; | |
} //End function: main | |
/***************************************************************************/ | |
//! @brief utility | |
//! delay_us | |
/***************************************************************************/ | |
//! @param delay | unsigned int | how long to wait for in microseconds | |
//! @return void | | |
//! @details \n | |
//! Use the SysTic timer counter to busy wait for the correct number of microseconds | |
/***************************************************************************/ | |
void delay_us(unsigned int delay) | |
{ | |
//---------------------------------------------------------------- | |
// VARS | |
//---------------------------------------------------------------- | |
uint64_t start_mtime, delta_mtime; | |
//---------------------------------------------------------------- | |
// BODY | |
//---------------------------------------------------------------- | |
// Wait for the first tick | |
// Wait for the correct number of ticks | |
uint64_t tmp = get_timer_value(); | |
do | |
{ | |
start_mtime = get_timer_value(); | |
} | |
while (start_mtime == tmp); | |
do | |
{ | |
delta_mtime = get_timer_value() - start_mtime; | |
} | |
while(delta_mtime <(SystemCoreClock/4000000.0 *delay )); | |
//---------------------------------------------------------------- | |
// RETURN | |
//---------------------------------------------------------------- | |
return; | |
} //End function: main |
/**************************************************************************** | |
** init.cpp | |
***************************************************************************** | |
** Board initializations | |
** >GPIO | |
** >EXTI | |
** >ECLIC | |
****************************************************************************/ | |
/**************************************************************************** | |
** INCLUDE | |
****************************************************************************/ | |
#include <gd32vf103.h> | |
//Onboard RBG LEDs of the Longan Nano | |
#include "longan_nano_led.hpp" | |
/**************************************************************************** | |
** NAMESPACES | |
****************************************************************************/ | |
//using namespace std; | |
/**************************************************************************** | |
** GLOBAL VARIABILE | |
****************************************************************************/ | |
/**************************************************************************** | |
** FUNCTION PROTOTYPES | |
****************************************************************************/ | |
//Initialize the board | |
extern bool init( void ); | |
//Initialize RTC Timer to generate a system tick | |
extern bool init_rtc( void ); | |
//Initialize the EXTI edge detection interrupt from the GPIO | |
extern bool init_exti(void); | |
//Initialize the ECLIC interrupt controller | |
extern bool init_eclic(void); | |
/**************************************************************************** | |
** FUNCTION | |
****************************************************************************/ | |
/***************************************************************************/ | |
//! @brief init | |
//! init | | |
/***************************************************************************/ | |
//! @return bool | false = OK | true = ERR | |
//! @details | |
//! initialize the longan nano pheriperals | |
/***************************************************************************/ | |
bool init( void ) | |
{ | |
//---------------------------------------------------------------- | |
// VARS | |
//---------------------------------------------------------------- | |
//Return | |
bool f_ret = false; | |
//---------------------------------------------------------------- | |
// BODY | |
//---------------------------------------------------------------- | |
// GPIO | |
// ECLIC | |
// EXTI | |
//Initialize the Longan Nano builtin RBG LEDs | |
f_ret |= Longan_nano::Leds::init(); | |
//Initialize LEDs to OFF | |
Longan_nano::Leds::set_color( Longan_nano::Led_color::BLACK ); | |
//EXTI GPIO interrupt: PA8 R/F -> EXTI_5_9 | |
f_ret |= init_exti(); | |
//RTC system tick | |
f_ret |= init_rtc(); | |
//Initialize ECLIC Interrupt controller. Interrupts can now be generated | |
f_ret |= init_eclic(); | |
//if: initialization failed | |
if (f_ret == true) | |
{ | |
} | |
//---------------------------------------------------------------- | |
// RETURN | |
//---------------------------------------------------------------- | |
return f_ret; | |
} //end init: init | | |
/***************************************************************************/ | |
//! @brief init | |
//! init_exti | | |
/***************************************************************************/ | |
//! @return bool | false = OK | true = ERR | |
//! @details | |
//! initialize the EXTI edge detection interrupt from the GPIO | |
//! PA8 R/F -> EXTI_5_9 | |
/***************************************************************************/ | |
bool init_exti(void) | |
{ | |
//---------------------------------------------------------------- | |
// VARS | |
//---------------------------------------------------------------- | |
//---------------------------------------------------------------- | |
// BODY | |
//---------------------------------------------------------------- | |
//Setup the boot button | |
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ,GPIO_PIN_8); | |
//Clock the alternate functions | |
rcu_periph_clock_enable(RCU_AF); | |
//Initialize the EXTI. IRQ can be generated from GPIO edge detectors | |
gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOA, GPIO_PIN_SOURCE_8); | |
exti_init(EXTI_8, EXTI_INTERRUPT, EXTI_TRIG_BOTH); | |
//Clear interrupt flag. Ensure no spurious execution at start | |
exti_interrupt_flag_clear(EXTI_8); | |
//---------------------------------------------------------------- | |
// RETURN | |
//---------------------------------------------------------------- | |
return false; //OK | |
} //end init: init_exti | | |
/***************************************************************************/ | |
//! @brief init | |
//! init_rtc | | |
/***************************************************************************/ | |
//! @return bool | false = OK | true = ERR | |
//! @details | |
//! initialize the RTC Real Time Counter | |
//! setup to emit a 4Hz SECOND interrupt | |
//! | |
//! RTC Interrupts: | |
//! RTC_INT_SECOND: Generated every time RTC_CNT changes (after the prescaler RTC_PSC) | |
//! RTC_INT_ALARM: Generated when RTC_CNT equals RTC_ALRM | |
//! RTC_INT_OV: Generated when the 32b RTC_CNT counter overflows to zero | |
/***************************************************************************/ | |
bool init_rtc(void) | |
{ | |
//---------------------------------------------------------------- | |
// VARS | |
//---------------------------------------------------------------- | |
//---------------------------------------------------------------- | |
// BODY | |
//---------------------------------------------------------------- | |
//Backup Clock | |
rcu_periph_clock_enable(RCU_BKPI); | |
// | |
rcu_periph_clock_enable(RCU_PMU); | |
//Enter configuration mode | |
pmu_backup_write_enable(); | |
// | |
bkp_deinit(); | |
//Enable LX crystal 32768 [Hz] | |
rcu_osci_on(RCU_LXTAL); | |
//Wait for crystal to stabilize | |
rcu_osci_stab_wait(RCU_LXTAL); | |
//Clock the RTC with the LX Crystal | |
rcu_rtc_clock_config(RCU_RTCSRC_LXTAL); | |
rcu_periph_clock_enable(RCU_RTC); | |
//wait for RTC registers synchronization | |
rtc_register_sync_wait(); | |
//wait until last write operation on RTC registers has finished | |
rtc_lwoff_wait(); | |
//Set the RTC Prescaler | |
rtc_prescaler_set(8192); | |
//wait until last write operation on RTC registers has finished | |
rtc_lwoff_wait(); | |
//Emit an interrupt each time RTC_CNT counts | |
rtc_interrupt_enable(RTC_INT_SECOND); | |
//wait until last write operation on RTC registers has finished | |
rtc_lwoff_wait(); | |
//---------------------------------------------------------------- | |
// RETURN | |
//---------------------------------------------------------------- | |
return false; //OK | |
} //end init: init_rtc | | |
/***************************************************************************/ | |
//! @brief init | |
//! init_eclic | | |
/***************************************************************************/ | |
//! @return bool | false = OK | true = ERR | |
//! @details | |
//! Initialize the ECLIC interrupt controller | |
/***************************************************************************/ | |
bool init_eclic(void) | |
{ | |
//---------------------------------------------------------------- | |
// VARS | |
//---------------------------------------------------------------- | |
//---------------------------------------------------------------- | |
// BODY | |
//---------------------------------------------------------------- | |
//Initialize the ECLIC IRQ lines | |
eclic_priority_group_set(ECLIC_PRIGROUP_LEVEL3_PRIO1); | |
eclic_irq_enable(EXTI5_9_IRQn, 1, 1); | |
//Enable the RTC Interrupt | |
eclic_priority_group_set(ECLIC_PRIGROUP_LEVEL1_PRIO3); | |
eclic_irq_enable(RTC_IRQn, 1, 0); | |
//Enable the interrupts. From now on interrupt handlers can be executed | |
eclic_global_interrupt_enable(); | |
//---------------------------------------------------------------- | |
// RETURN | |
//---------------------------------------------------------------- | |
return false; //OK | |
} //end init: init_eclic | |
/**************************************************************************** | |
** int.cpp | |
***************************************************************************** | |
** Interrupt Service Routines | |
** NOTE: | |
** extern "C" keyword tells the C++ compiler not to mangle the ISR nfunction name | |
** the Interrupt Vector Table is declared in Start.S and requires special names | |
** for the ISRs without mangling to link correctly | |
****************************************************************************/ | |
/**************************************************************************** | |
** Interrupt Vectors | |
***************************************************************************** | |
** EXTI5_9_IRQHandler GPIO edge detectors 5 to 9 | |
** RTC_IRQHandler RTC Second | |
****************************************************************************/ | |
/**************************************************************************** | |
** INCLUDE | |
****************************************************************************/ | |
#include <gd32vf103.h> | |
//Onboard RBG LEDs of the Longan Nano | |
#include "longan_nano_led.hpp" | |
/***************************************************************************/ | |
//! @brief ISR | |
//! EXTI5:9 LINES | |
/***************************************************************************/ | |
//! @return void | | |
//! @details \n | |
//! Handles the ISR lines generated by the GPIO lines 5 to 9 | |
/***************************************************************************/ | |
extern "C" | |
void EXTI5_9_IRQHandler() | |
{ | |
//---------------------------------------------------------------- | |
// VARS | |
//---------------------------------------------------------------- | |
//---------------------------------------------------------------- | |
// BODY | |
//---------------------------------------------------------------- | |
//If: interrupt from PA8 boot button | |
if (exti_interrupt_flag_get(EXTI_8) != RESET) | |
{ | |
//Clear the interrupt from PA8 boot button | |
exti_interrupt_flag_clear(EXTI_8); | |
//Toggle the green led | |
Longan_nano::Leds::toggle( Longan_nano::Led_color::GREEN ); | |
} | |
//Default: interrupt from an unhandled GPIO | |
else | |
{ | |
//Do nothing (should clear the interrupt flags) | |
} | |
//---------------------------------------------------------------- | |
// RETURN | |
//---------------------------------------------------------------- | |
} //End ISR: EXTI5_9_IRQHandler | |
/***************************************************************************/ | |
//! @brief ISR | |
//! RTC | |
/***************************************************************************/ | |
//! @return void | | |
//! @details \n | |
//! Handles the ISR lines generated by the RTC | |
//! Includes three vectors: | |
//! RTC_INT_SECOND: Generated every time RTC_CNT changes (after the prescaler RTC_PSC) | |
//! RTC_INT_ALARM: Generated when RTC_CNT equals RTC_ALRM | |
//! RTC_INT_OV: Generated when the 32b RTC_CNT counter overflows to zero | |
/***************************************************************************/ | |
extern "C" | |
void RTC_IRQHandler(void) | |
{ | |
//SECOND interrupt, generated by a change in RTC:CNT | |
if (rtc_flag_get(RTC_FLAG_SECOND) != RESET) | |
{ | |
//Clear flag | |
rtc_flag_clear(RTC_FLAG_SECOND); | |
Longan_nano::Leds::toggle( Longan_nano::Led_color::RED ); | |
} | |
//ALARM interrupt, generated when RTC_CNT equals RTC_ALRM | |
if (rtc_flag_get(RTC_FLAG_ALARM) != RESET) | |
{ | |
//Clear flag | |
rtc_flag_clear(RTC_FLAG_ALARM); | |
} | |
//---------------------------------------------------------------- | |
// RETURN | |
//---------------------------------------------------------------- | |
} //End ISR: RTC_IRQHandler |
/********************************************************************************** | |
** ENVIROMENT VARIABILE | |
**********************************************************************************/ | |
#ifndef LONGAN_NANO_LED_H_ | |
#define LONGAN_NANO_LED_H_ | |
/********************************************************************************** | |
** GLOBAL INCLUDES | |
**********************************************************************************/ | |
#include <gd32vf103.h> | |
/********************************************************************************** | |
** DEFINES | |
**********************************************************************************/ | |
/********************************************************************************** | |
** MACROS | |
**********************************************************************************/ | |
/********************************************************************************** | |
** NAMESPACE | |
**********************************************************************************/ | |
//! @namespace User My custom namespace | |
namespace Longan_nano | |
{ | |
/********************************************************************************** | |
** TYPEDEFS | |
**********************************************************************************/ | |
typedef enum _Led_color | |
{ | |
BLACK, | |
RED, | |
GREEN, | |
BLUE, | |
WHITE | |
} Led_color; | |
typedef enum _Led_gpio | |
{ | |
RED_GPIO = GPIOC, | |
GREEN_GPIO = GPIOA, | |
BLUE_GPIO = GPIOA, | |
} Led_gpio; | |
typedef enum _Led_pin | |
{ | |
RED_PIN = GPIO_PIN_13, | |
GREEN_PIN = GPIO_PIN_1, | |
BLUE_PIN = GPIO_PIN_2, | |
} Led_pin; | |
/********************************************************************************** | |
** PROTOTYPE: STRUCTURES | |
**********************************************************************************/ | |
/********************************************************************************** | |
** PROTOTYPE: GLOBAL VARIABILES | |
**********************************************************************************/ | |
/********************************************************************************** | |
** PROTOTYPE: CLASS | |
**********************************************************************************/ | |
/************************************************************************************/ | |
//! @class Longan_nano_led | |
/************************************************************************************/ | |
//! @author Orso Eric | |
//! @version 0.1 alpha | |
//! @date 2019/05 | |
//! @brief Dummy Library | |
//! @details | |
//! Verbose description \n | |
//! xxx | |
//! @pre No prerequisites | |
//! @bug None | |
//! @warning No warnings | |
//! @copyright License ? | |
//! @todo todo list | |
/************************************************************************************/ | |
class Leds | |
{ | |
//Visible to all | |
public: | |
//-------------------------------------------------------------------------- | |
// CONSTRUCTORS | |
//-------------------------------------------------------------------------- | |
//! Default constructor | |
Leds( void ); | |
//-------------------------------------------------------------------------- | |
// DESTRUCTORS | |
//-------------------------------------------------------------------------- | |
//!Default destructor | |
~Leds( void ); | |
//-------------------------------------------------------------------------- | |
// OPERATORS | |
//-------------------------------------------------------------------------- | |
//-------------------------------------------------------------------------- | |
// SETTERS | |
//-------------------------------------------------------------------------- | |
//-------------------------------------------------------------------------- | |
// GETTERS | |
//-------------------------------------------------------------------------- | |
//-------------------------------------------------------------------------- | |
// TESTERS | |
//-------------------------------------------------------------------------- | |
//-------------------------------------------------------------------------- | |
// PUBLIC METHODS | |
//-------------------------------------------------------------------------- | |
/***************************************************************************/ | |
//! @brief public static method | |
//! init | | |
/***************************************************************************/ | |
//! @return bool | false = OK | true = ERR | |
//! @details | |
//! initialize the longan nano GPIO LEDs | |
/***************************************************************************/ | |
static inline bool init( void ) | |
{ | |
//---------------------------------------------------------------- | |
// VARS | |
//---------------------------------------------------------------- | |
//---------------------------------------------------------------- | |
// BODY | |
//---------------------------------------------------------------- | |
//Clock the GPIO banks | |
rcu_periph_clock_enable(RCU_GPIOA); | |
rcu_periph_clock_enable(RCU_GPIOC); | |
//Setup the R (PC13), G (PA1) and B (PA2) LEDs | |
gpio_init(Led_gpio::RED_GPIO, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,Led_pin::RED_PIN); | |
gpio_init(Led_gpio::GREEN_GPIO, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,Led_pin::GREEN_PIN); | |
gpio_init(Led_gpio::BLUE_GPIO, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,Led_pin::BLUE_PIN); | |
//---------------------------------------------------------------- | |
// RETURN | |
//---------------------------------------------------------------- | |
return false; //OK | |
} //End public static method: init | |
/***************************************************************************/ | |
//! @brief public static method | |
//! set_color | Led_color | |
/***************************************************************************/ | |
//! @param Led_color | color of the LED | |
//! @return bool | false = OK | true = ERR | |
//! @details | |
//! initialize the longan nano GPIO LEDs | |
/***************************************************************************/ | |
static inline bool set_color( Led_color color ) | |
{ | |
//---------------------------------------------------------------- | |
// VARS | |
//---------------------------------------------------------------- | |
//LED are inverted. SET turn them OFF | |
bit_status led_r = FlagStatus::SET; | |
bit_status led_g = FlagStatus::SET; | |
bit_status led_b = FlagStatus::SET; | |
//---------------------------------------------------------------- | |
// BODY | |
//---------------------------------------------------------------- | |
//Switch: Color | |
switch(color) | |
{ | |
case (Led_color::BLACK): | |
{ | |
break; | |
} | |
case (Led_color::WHITE): | |
{ | |
led_r = FlagStatus::RESET; | |
led_g = FlagStatus::RESET; | |
led_b = FlagStatus::RESET; | |
break; | |
} | |
default: | |
{ | |
return true; //FAIL | |
} | |
} //End Switch: Color | |
//Apply the color setting | |
gpio_bit_write( Led_gpio::RED_GPIO, Led_pin::RED_PIN, (bit_status)led_r ); | |
gpio_bit_write( Led_gpio::GREEN_GPIO, Led_pin::GREEN_PIN, (bit_status)led_g ); | |
gpio_bit_write( Led_gpio::BLUE_GPIO, Led_pin::BLUE_PIN, (bit_status)led_b ); | |
//---------------------------------------------------------------- | |
// RETURN | |
//---------------------------------------------------------------- | |
return false; //OK | |
} //End public static method: set_color | |
/***************************************************************************/ | |
//! @brief public static method | |
//! toggle | | |
/***************************************************************************/ | |
//! @return bool | false = OK | true = ERR | |
//! @details | |
//! initialize the longan nano GPIO LEDs | |
/***************************************************************************/ | |
static inline bool toggle( Led_color color ) | |
{ | |
//---------------------------------------------------------------- | |
// VARS | |
//---------------------------------------------------------------- | |
//---------------------------------------------------------------- | |
// BODY | |
//---------------------------------------------------------------- | |
//Switch: Color | |
switch(color) | |
{ | |
case (Led_color::RED): | |
{ | |
gpio_bit_write(Led_gpio::RED_GPIO, Led_pin::RED_PIN, (bit_status)(1-gpio_input_bit_get(Led_gpio::RED_GPIO, Led_pin::RED_PIN))); | |
break; | |
} | |
case (Led_color::GREEN): | |
{ | |
gpio_bit_write(Led_gpio::GREEN_GPIO, Led_pin::GREEN_PIN, (bit_status)(1-gpio_input_bit_get(Led_gpio::GREEN_GPIO, Led_pin::GREEN_PIN))); | |
break; | |
} | |
case (Led_color::BLUE): | |
{ | |
gpio_bit_write(Led_gpio::BLUE_GPIO, Led_pin::BLUE_PIN, (bit_status)(1-gpio_input_bit_get(Led_gpio::BLUE_GPIO, Led_pin::BLUE_PIN))); | |
break; | |
} | |
default: | |
{ | |
return true; //FAIL | |
} | |
} //End Switch: Color | |
//---------------------------------------------------------------- | |
// RETURN | |
//---------------------------------------------------------------- | |
return false; //OK | |
} //End public static method: toggle | |
//-------------------------------------------------------------------------- | |
// PUBLIC STATIC METHODS | |
//-------------------------------------------------------------------------- | |
//-------------------------------------------------------------------------- | |
// PUBLIC VARS | |
//-------------------------------------------------------------------------- | |
//Visible to derived classes | |
protected: | |
//-------------------------------------------------------------------------- | |
// PROTECTED METHODS | |
//-------------------------------------------------------------------------- | |
//-------------------------------------------------------------------------- | |
// PROTECTED VARS | |
//-------------------------------------------------------------------------- | |
//Visible only inside the class | |
private: | |
//-------------------------------------------------------------------------- | |
// PRIVATE METHODS | |
//-------------------------------------------------------------------------- | |
//-------------------------------------------------------------------------- | |
// PRIVATE VARS | |
//-------------------------------------------------------------------------- | |
}; //End Class: Longan_nano_led | |
/********************************************************************************** | |
** NAMESPACE | |
**********************************************************************************/ | |
} //End Namespace: Longan_nano | |
#else | |
#warning "Multiple inclusion of hader file" | |
#endif |
5Conclusions
Interrupts are fundamental in an hard real time MCU application and the GD32VF103 is equipped with a refined system to handle interrupts.
This document shows how to generate interrupts from the EXTI and RTC. interrupts can be generated from all sort of sources, and there are even sources for reset, watchdog, errors, etc...
No comments:
Post a Comment