RTEMS 7 BSP creation issue (based on stm32f4)

Hello, I’m having trouble understanding the configuration of the SysTick timer in a BSP. I decided to write a BSP for the Artery AT32F437 microcontroller, which has a Cortex-M4 core. There is an existing BSP for STM32F4, and I chose to use it as a starting point.

In the source code, there is a line that sets BSP_ARMV7M_SYSTICK_FREQUENCY to 16,000,000 Hz, or 16 MHz.

I also reviewed the documentation on writing BSPs and drivers but found the sections on linker scripts and other relevant topics unhelpful, as they contain statements like “This chapter contains outdated and confusing information.” I will formulate my questions as a list:

  1. I would greatly appreciate a concise explanation of how interrupts (specifically, the vector table I define in the BSP and the SysTick interrupts) are integrated into the RTEMS system from the BSP.
  2. Is it correct to assume that the SysTick interrupt frequency for the STM32F4 configuration I referenced would be 16,000,000 times per second (this seems like it would significantly impact performance)?
  3. If I configure the SysTick in the BSP, how do I inform the RTEMS kernel about the tick frequency?

Thank you in advance for your help!

I can only speak from my experience with ST’s STM32 series processors. What Artery did, well, you are now the go-to person.
So, I’ll assume a perfect clone…

  1. The vector table is stored in FLASH at compile time, starting at location 0 for about 400 bytes. At startup the vector table is copied to RAM in bsp_interrupt_facility_initialize and the VTOR is set to point at this RAM based vector table. At run time, your code can register interrupt routines and their addresses are patched into the RAM vector table.
  2. SysTick is normally a 1kHz interrupt, derived from an external crystal of 16MHz, divided down to give 1000 interrupts per second, within the precision of the crystal and load capacitors.
    The ARM Cortex M4 core has calibration registers that are altered in _ARMV7M_Clock_initialize_early with a value calculated with the processor clock frequency (like 168MHz) and the required tick frequency, setting the SysTick to the frequency that you want.
  3. SysTick is normally assumed to be 1kHz on STM32, so you’ll see that used quite a bit, and RTEMS uses 1kHZ unless you override it. At the bottom of init() you may see a define that looks like:
#define CONFIGURE_MICROSECONDS_PER_TICK				1000

This is the value that is used, along with the crystal frequency, and the PLL multiplier and divider values, to set the SysTick frequency.

1 Like

I will respond additionally.

  1. The macro BSP_ARMV7M_SYSTICK_FREQUENCY sets the SysTick clock frequency. It is important to note that some microcontrollers, such as the AT32F437ZMT, have clock dividers. Therefore, if you use a clock configuration generator, adjusting the SysTick divider may lead to errors. Since SysTick allows selecting the clock source, RTEMS for ARM by default (code below & clock tree) sets ARMV7M_SYSTICK_CSR_CLKSOURCE (CLKSOURCE = 1), indicating that the timer will be clocked directly from the core’s system clock signal (bypassing the divider).
#define ARMV7M_SYSTICK_CSR_COUNTFLAG (1U << 16)
#define ARMV7M_SYSTICK_CSR_CLKSOURCE (1U << 2)
#define ARMV7M_SYSTICK_CSR_TICKINT (1U << 1)
#define ARMV7M_SYSTICK_CSR_ENABLE (1U << 0)

static void _ARMV7M_Clock_initialize(void)
{
  volatile ARMV7M_Systick *systick;
  ARMV7M_Timecounter *tc;

  systick = _ARMV7M_Systick;
  tc = &_ARMV7M_TC;

  systick->csr = ARMV7M_SYSTICK_CSR_ENABLE
    | ARMV7M_SYSTICK_CSR_TICKINT
    | ARMV7M_SYSTICK_CSR_CLKSOURCE;

  tc->base.tc_get_timecount = _ARMV7M_TC_get_timecount;
  tc->base.tc_counter_mask = 0xffffffff;
  tc->base.tc_frequency = _ARMV7M_Clock_frequency();
  tc->base.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
  rtems_timecounter_install(&tc->base);
}

Thus, when discussing 16,000,000 Hz, it refers to the frequency of the system clock signal (core).