Reading from and writing to the GPTx_SR register takes incredibly long

Status
Not open for further replies.

LukasFun

Member
I have been working on a project where I use timer controlled interrupts. One of the things necessary for that is to reset the respective bits in the GPT Status Register. Reading a value from that register via

Code:
uint32_t value = GPT1_SR;

or writing to it via

Code:
GPT1_SR = 0x00000001;

takes both about 170 ns. Why is this so slow and is there any way to improve this?
 
It's probably because we're currently running those timers from the 24 MHz clock, and there's probably a multiple-cycle sync going on.
 
Update: With the 150 MHz clock it only takes about 80 ns. But that is still way too long for just setting or reading a value.

This is the sketch I used for testing this:

Code:
#include <Arduino.h>

void setup() {
  pinMode(13, OUTPUT);
  CCM_CSCMR1 &= 0xFFFFFFBF;// Use the Root-Clock
  CCM_CCGR1 |= 0x00F00000; // Activate Clock Module for GPT1
  GPT1_CR = 0;      // Reset Control Register
  GPT1_PR = 0;      // Prescaling = 1:1
  GPT1_CR |= 0x00000040;  // Use the peripheral Clock
  GPT1_CR |= 0x00000001;  // Activate Counter GPT1
}

void loop() {
  digitalWriteFast(13, HIGH);
  GPT1_SR = 0x00000001;
  digitalWriteFast(13, LOW);
  delayMicroseconds(1);
  digitalWriteFast(13, HIGH);
  uint32_t value = GPT1_SR;
  digitalWriteFast(13, LOW);
}

I then used an oscilloscope to analyse the signal which gave me the time of ~80 ns.
 
Here is what the reading of the oscilloscope looks like:
tek00001.png
 
Could you retest with
Code:
void loop() {
  digitalWriteFast(13, HIGH);
  GPT1_SR = 0x00000001;
  digitalWriteFast(13, LOW);
  delayMicroseconds(1);
  digitalWriteFast(13, HIGH);
  uint32_t value = GPT1_SR;
  digitalWriteFast(13, LOW);
  delayMicroseconds(1);
  digitalWriteFast(13, HIGH);
  digitalWriteFast(13, LOW);
}
adding a third pulse showing the digitalWriteFast() overhead?
 
The overhead of digitalWriteFast() is nothing compared to the problem here (3 ns = 150 MHz). Here is what your code produces:

tek00000.png
 
As Paul already wrote, the timer peripherals are only loosely coupled to the ARM core, thus there is significant time required to synchronize the busses. Writing is cached, so this is fast in principle but you need to wait until the register (e.g. GPT1_SR) actually gets the value, if you leave the ISR too quickly it might fire again. (Search for DSB in the beta thread) Here some in depth info from Joseph Yiu (scroll down to the discussion about slow peripherals): https://community.arm.com/developer/ip-products/processors/f/cortex-m-forum/10389/dmb-dsb-isb-on-cortex-m3-m4-m7-single-core-parts.

And here some forum links regarding the same issue with the interval timers (PIT). It turns out that having 4 interval timers flipping a pin at 100kHz already generate 40% processor load due to the required bus sync.
https://forum.pjrc.com/threads/57959-Teensy-4-IntervalTimer-Max-Speed?p=218577&viewfull=1#post218577
https://forum.pjrc.com/threads/58221-Fastest-possible-speed-on-IntervalTimer?p=220355&viewfull=1#post220355

So, looks like the timer interrupts are not made for high speed applications on this chip.

There are also measurement results and comparison to T3.6 with different bus clock speeds on the beta thread.
 
Status
Not open for further replies.
Back
Top