The behavior of SysTick RELOAD measured does not conform to the Datasheet description

Atmel-11057-32-bit-Cortex-M3-Microcontroller-SAM3X-SAM3A_Datasheet
On page 193:

When ENABLE is set to 1, the counter loads the RELOAD value from the LOAD register and then counts down.

However,

void setup() {
  Serial.begin(9600);
  Serial.print("VAL before LOAD: ");
  Serial.println(SysTick->VAL);
  SysTick->LOAD = -1;
  SysTick->CTRL = SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk;
  Serial.println("VAL after LOAD: ");
}
void loop() {
  Serial.println(SysTick->VAL);
}

Serial output:

VAL before LOAD: 81390
VAL after LOAD: 
77539
76051
74563
73075
71587
70099
68611
67123
65538
64050
62562
61074
59586
……

You can see that setting ENABLE does not immediately load the LOAD value into VAL as indicated by the Datasheet. In fact, the only way I found to load LOAD immediately is to manually set VAL to 0:

void setup() {
  Serial.begin(9600);
  Serial.print("VAL before LOAD: ");
  Serial.println(SysTick->VAL);
  SysTick->LOAD = -1;
  SysTick->VAL = 0;  //SysTick->CTRL = SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk;
  Serial.println("VAL after LOAD: ");
}
void loop() {
  Serial.println(SysTick->VAL);
}

You can actually set VAL to any value, because according to Datasheet:

A write of any value clears the field to 0

Then the serial output:

VAL before LOAD: 81369
VAL after LOAD:
16774708
16772787
16770866
16768945
16767024
16765103
16763090
16761169
……

This topic is probably more of a conclusion than a question, posted here because there are no similar posts that may help future generations.

The Arduino core will already have enabled systick for use by millis()/etc (presumably with LOAD set to 84000 to get 1kHz from a 84MHz clock.)
So your setting of SysTick->CTRL does nothing new, and the timer won't use the new value from SysTick->LOAD until it counts down to zero.

I see what you mean, but anyway it doesn't match the Datasheet description, does it?

I would say that writing a 1 to the ENABLE bit when it is already 1 is not really "setting" it, so at worst the sentence if badly worded.

SysTick is an ARM core component, and AFAIK that section of the SAM3 datasheet is lifted directly from (an old version?) ARM documentation. My current ARMv7m Architecture Reference Manual (Section B3.3.1 "SysTick operation") has SYST_RVR (Reload Value Register) rather than LOAD (huh. Still LOAD in the ARM CMSIS files...) and use the somewhat less ambiguous "when enabled":

  • Before enabling the SysTick counter, software must write the required counter value to SYST_RVR, and then write to SYST_CVR. This clears SYST_CVR to zero. When enabled, the counter reloads the value from SYST_RVR, and counts down from that value, rather than from an arbitrary value.

Then let's try:

void setup() {
  Serial.begin(9600);
  Serial.print("VAL before LOAD: ");
  Serial.println(SysTick->VAL);
  SysTick->LOAD = -1;
  SysTick->CTRL = 0;
  while (SysTick->CTRL)
    ;
  Serial.print("SysTick->CTRL: ");
  Serial.println(SysTick->CTRL);
  SysTick->CTRL = SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk;
  Serial.println("VAL after LOAD: ");
}
void loop() {
  Serial.println(SysTick->VAL);
}

In this example, CTRL ENABLE has been set to 0 and then reset to 1. Do you think it will load LOAD this time?

VAL before LOAD: 81392
SysTick->CTRL: 0
VAL after LOAD: 
77538
76050
74562
73074
71586
70098
68513
67025
65537
64049
……

No, apparently not. This further proves that setting CTRL has no effect on VAL, regardless of whether the state before setting is 0 or not.

I've got no explanation for that.
You should print out systick->load and systick->val before you restart the timer as well. Perhaps disabling the timer does not reset VAL, and enabling does not immediately load the new LOAD value. (which would make the Atmel documentation wrong, as you say.)

The ARM ARM says:

When enabled, the timer counts down from the value in SYST_CVR, see SysTick Current Value Register, SYST_CVR on page B3-622. When the counter reaches zero, it reloads the value in SYST_RVR on the next clock edge, see SysTick Reload Value Register, SYST_RVR on page B3-622. It then decrements on subsequent clocks. This reloading when the counter reaches zero is called wrapping.

I guess that'd be unfortunate if you're trying to use SysTick for a one-shot timer, although it looks like you'd be fine if you write the new LOAD value to both LOAD and VAL. (and then "immediatel" write 0 to LOAD, since:

Writing a value of zero to SYST_RVR [ie LOAD] disables the counter on the next wrap. The SysTick counter logic maintains this counter value of zero after the wrap.

I did do fairly extensive testing before posting, so I'm quite confident that the restart of timer does not immediately affect VAL and LOAD values - it just stops the countdown of VAL.