3
\$\begingroup\$

I use an ATSAMD21 to generate a custom signal with the help of a PWM generator.

Basically, I set up TCC0 as a PWM generator, and use its overflow interrupt to set up the CC registers for the next pulse. It all works fine, the signal looks as it should look like. However, as it is important for the interrupt to occur before the shortest possible polarity change in my signal, I wanted to check the interrupt latency, to detect a possible failure case. That should be as simple as checking the COUNT register at the beginning of the interrupt, shouldn't it?

However, the COUNT register always reads as zero.

It doesn't matter whether I use REG_TCC0_COUNT or TCC0->COUNT.bit.COUNT, it always reads as 0. I can be sure that the actual value of the counter is not zero, because the timer is set to a very fast clock generator, and on the oscilloscope I can see that the typical interrupt latency is where the counter should already be around 100.

Interestingly, I can write to the COUNT register. If I do so, I can verify that the next pulse is shortened by the respective amount. And after the write, if I read it back, I read the value I just wrote.

As the same processor is used in the Arduino Zero, this issue was already asked on the Arduino forums a few years ago, but there is still no answer:

One of the proposed solutions was to wait for the SYNCBUSY to be cleared, but it didn't work, neither for the poster on the Arduino forum, nor for me.

\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

There is a command in the Control B register of the TCC peripherals,

  • READSYNC – Force a read synchronization of COUNT

The value of the COUNT register is not valid until this command is issued and fully executed.

Sample code, tested on a SAMD21E17A device:

// Step 1: Issue READYSYNC command TCC0->CTRLBSET.reg = TCC_CTRLBSET_CMD_READSYNC; // Step 2: Wait until the command is fully executed while (TCC0->SYNCBUSY.bit.CTRLB); // or while (TCC0->SYNCBUSY.reg); // Step 3: Now we can read the value of the COUNT register int count = TCC0->COUNT.reg; 

The resulting value of the variable count corresponds to the value of the counter when the READSYNC command was actually executed.

For additional information, check chapter 31 of the SAM D21/DA1 Family datasheet

\$\endgroup\$
0
0
\$\begingroup\$

You might also check the CTRLBSET.bit.CMD as well.

As stated in section 31.8.3 of the SAMD21 documentation:

Bits 7:5 – CMD[2:0] TCC Command
These bits can be used for software control of re-triggering and stop commands of the TCC. When a command has been executed, the CMD bit field will be read back as zero. The commands are executed on the next prescaled GCLK_TCC clock cycle.

So in addition to this answer:

// Step 1: Issue READYSYNC command TCC0->CTRLBSET.reg = TCC_CTRLBSET_CMD_READSYNC; // Step 2: Wait until the command register has been well commited while (TCC0->SYNCBUSY.bit.CTRLB); // Step 3: Wait until the command is fully executed while (TCC0->CTRLBSET.bit.CMD); // Step 4: Now we can read the value of the COUNT register int count = TCC0->COUNT.reg; 
\$\endgroup\$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.