Skip to content

Latest commit

 

History

History
210 lines (181 loc) · 9.91 KB

systick.md

File metadata and controls

210 lines (181 loc) · 9.91 KB

MCU SYSTICK timer configuration and access (mcutl/systick/systick.h)

This header provides facilities to configure and use the MCU SYSTICK timer facilities (if supported by the MCU). All of the definitions are in the mcutl::systick namespace, unless otherwise stated.

Public definitions

template<bool Enable>
struct enable {};

This struct is used to enable or disable the SYSTICK timer.

namespace clock_source
{
struct processor {};
struct external {};
} //namespace clock_source

These structs may be used to set the clock source for the SYSTICK timer: either processor (MCU core clock, which is the default) or external. Some MCUs may not support all of these options or support more clock sources.

namespace interrupt
{
struct tick {};
} //namespace interrupt

This is a common interrupt which fires when the SYSTICK timer overflows (or underflows, depending on count direction). The tick struct is used to enable or disable the interrupt when configuring the SYSTICK timer. To enable an interrupt and set its priority/subpriority, use mcutl::interrupt::interrupt wrapper. To disable an interrupt, wrap the related interrupt structure into the mcutl::interrupt::disabled wrapper structure.

Add the mcutl::interrupt::priority_count option to explicitly set the interrupt priority count. Use this option if you explicitly changed the interrupt priority count when calling mcutl::interrupt::initialize_controller.

Some MCUs may support more SYSTICK interrupts.

template<typename Interrupt>
using interrupt_type = ...;

This typedef indicates a corresponding interrupt controller interrupt type for the specified SYSTICK interrupt.

template<typename Channel>
using peripheral_type = ...;

This typedef indicates a corresponding peripheral type or type list (or mcutl::periph::no_periph) for the SYSTICK hardware. This peripheral must be enabled before accessing SYSTICK.

using value_type = device::systick::value_type;

This is the type wide enough to hold the SYSTICK value.

Traits

There are several traits to determine the capabilities of the SYSTICK for the MCU of your choice:

//SYSTICK counting direction
enum class direction_type
{
	top_down,
	bottom_up
};

//mcutl::systick::direction_type, indicates SYSTICK counting direction
constexpr auto count_direction = ...;
//Minimum possible SYSTICK value
constexpr auto min_value = ...;
//Maximum possible SYSTICK value
constexpr auto max_value = ...;
//True if the MCU SYSTICK supports overflow detection
constexpr auto supports_overflow_detection = ...;
//True if the MCU SYSTICK clears overflow flag after reading it
constexpr auto overflow_flag_cleared_on_read = ...;
//True if the MCU SYSTICK supports value requests
constexpr auto supports_value_request = ...;
//True if the MCU SYSTICK supports reading the reload value
constexpr auto supports_reload_value = ...;
//True if the MCU SYSTICK supports changing the reload value
constexpr auto supports_reload_value_change = ...;
//True if the MCU SYSTICK supports value reset
constexpr auto supports_reset_value = ...;
//True if the MCU supports clear_pending_flags_atomic function
constexpr auto supports_atomic_clear_pending_flags = ...;

configure

template<typename... Options>
void configure() noexcept;

This function is used to configure the SYSTICK. It configures the SYSTICK, resetting all of its options to their default values and setting the explicitly specified option values. Here are several examples:

Enable the systick and set its clock source to external:

mcutl::systick::configure<
	mcutl::systick::clock_source::external,
	mcutl::systick::enable<true>
>();

Disable the systick (as no enable option specified), set its clock source to processor (as the clock_source option is absent) and enable its tick interrupt with priority 3 and subpriority 5:

mcutl::systick::configure<
	mcutl::interrupt::interrupt<mcutl::systick::interrupt::tick, 3, 5>
>();

reconfigure

template<typename... Options>
void reconfigure() noexcept;

This function is used to reconfigure the SYSTICK. It reconfigures the SYSTICK, keeping all of its options and changing the explicitly specified option values. Here are several examples:

Keep all the SYSTICK options as is and disable its tick interrupt:

mcutl::systick::configure<
	mcutl::interrupt::disable<mcutl::systick::interrupt::tick>
>();

Keep all the SYSTICK options as is and disable it:

mcutl::systick::reconfigure<
	mcutl::systick::enable<false>
>();

clear_pending_flags, clear_pending_flags_atomic

template<typename... Interrupts>
void clear_pending_flags() noexcept;
template<typename... Interrupts>
void clear_pending_flags_atomic() noexcept;

These functions are used to clear the pending Interrupts flags to prevent the interrupt from firing again in an infinite loop. The clear_pending_flags_atomic function is atomic and thus requires no locking. It is available when the supports_atomic_clear_pending_flags trait is true.

get_value

template<typename T = void>
auto get_value() noexcept;

Returns current SYSTICK value. Available when the supports_value_request trait is true. Do not specity the T argument, it's used to make the function compile only when explicitly used.

reset_value

template<typename T = void>
void reset_value() noexcept;

Resets the SYSTICK value to its default. Available when the supports_reset_value trait is true. Do not specity the T argument, it's used to make the function compile only when explicitly used.

has_overflown

template<typename T = void>
bool has_overflown() noexcept;

Returns true if the SYSTICK value has overflown. Available when the supports_overflow_detection is true. Note that when the overflow_flag_cleared_on_read is true, this call will clear the overflow flag. Do not specity the T argument, it's used to make the function compile only when explicitly used.

clear_overflow_flag

template<typename T = void>
void clear_overflow_flag() noexcept;

Clears the SYSTICK overflow flag. Available when the supports_overflow_detection is true. Do not specity the T argument, it's used to make the function compile only when explicitly used.

get_reload_value

template<typename T = void>
auto get_reload_value() noexcept;

Returns the SYSTICK reload value. This value is loaded to SYSTICK every time when it underflows (or the value the SYSTICK count up to). Available when the supports_reload_value trait is true. Do not specity the T argument, it's used to make the function compile only when explicitly used.

get_default_reload_value

template<typename T = void>
constexpr auto get_default_reload_value() noexcept;

Returns the SYSTICK default reload value. This value is loaded to SYSTICK every time when it overflows (or the value the SYSTICK count up to). Available when the supports_reload_value trait is true. Do not specity the T argument, it's used to make the function compile only when explicitly used.

set_reload_value

template<typename T = void>
void set_reload_value(value_type value) noexcept;

Sets the SYSTICK reload value. This value is loaded to SYSTICK every time when it overflows (or the value the SYSTICK count up to). Available when the supports_reload_value_change trait is true. Do not specity the T argument, it's used to make the function compile only when explicitly used.

reset_reload_value

template<typename T = void>
void reset_reload_value() noexcept;

Resets the SYSTICK reload value to its default. This value is loaded to SYSTICK every time when it overflows (or the value the SYSTICK count up to). Available when the supports_reload_value_change trait is true. Do not specity the T argument, it's used to make the function compile only when explicitly used.

Wait helpers (mcutl/systick/systick_wait.h)

This header defines several helpers to synchronously wait for the defined period of time. These helpers utilize the SYSTICK timer and thus require it to be configured and enabled.

wait_msec, wait_usec, wait_nsec, wait

template<uint64_t SysTickFrequency, uint16_t MSec, typename TickType = value_type>
void wait_msec() noexcept;
template<uint64_t SysTickFrequency, uint16_t USec, typename TickType = value_type>
void wait_usec() noexcept;
template<uint64_t SysTickFrequency, uint16_t NSec, typename TickType = value_type>
void wait_nsec() noexcept;
template<uint64_t SysTickFrequency, typename ConstDuration, typename TickType = value_type>
void wait() noexcept;

These functions can be used to wait for a period of milliseconds, microseconds or nanoseconds. The last wait function is used to wait for a period of any units. These functions guarantee to synchronously delay execution for at least the specified period.

They are generally not compatible with interrupts, especially when there are several OS threads synchronously waiting at the same time, as these functions change the state of the SYSTICK timer overflow flag. If this happens, the delay may be much longer than requested (as the interrupted wait call may miss the SYSTICK overflow event, and will have to wait for it again). You may use these functions in OS environment if you're good with extending the delay, but better use the OS-specific delay functions.

  • SysTickFrequency - the SYSTICK frequency in Hertz.
  • MSec, USec, NSec - a period in milliseconds, microseconds or nanoseconds.
  • TickType - type of the variable to hold the required amount ticks to wait. Must be at least of the mcutl::systick::value_type size. If you get an overflow error when trying to compile the code, you may want to make this type larger (or reduce the delay period).
  • ConstDuration - a mcutl::types::duration type or mcutl::types::milliseconds, mcutl::types::microseconds, mcutl::types::nanoseconds or mcutl::types::seconds (see the mcutl/utils/duration.h header).