Fehler im Datenblatt der SAM D5x/E5x Familie?

OP #7681766
Lesenswert?

Hallo,

ich will den Timer TCC0 vom ATSAME54P20A als Counter verwenden. Dabei ist es mir wichtig, dass ich den Timer stoppen und wieder starten kann, ohne dass der aktuelle Zählerstand zurückgesetzt wird. Laut Datenblatt kann man hierfür den Stop Command und den Re-Trigger Command. Im Kapitel 49.6.2.4 steht folgendes zum Stop Command:

When a stop is detected while the counter is running, the counter will maintain its current value.

Und folgendes zum Re-Trigger Command:

If the re-trigger command is detected when the counter is stopped, the counter will resume counting operation from the value in COUNT.

Theoretisch sollte also der Zählerstand nicht zurückgesetzt werden, wenn man den Timer vom laufenden Zustand in den gestoppten oder umgekehrt versetzt. Dieses scheint in der Praxis aber nicht so zu sein. Wenn der Timer TCC0 läuf und ein C/C++-Programm folgende Codezeilen durchläuft, wird der Zählerstand zurückgesetzt. Das Register TCC0.COUNT steht dann auf 0:

1
TCC0->CTRLBSET.bit.CMD = TCC_CTRLBSET_CMD_STOP_Val;
2
while (TCC0->SYNCBUSY.bit.CTRLB || !TCC0->STATUS.bit.STOP);
3

4
TCC0->CTRLBSET.bit.CMD = TCC_CTRLBSET_CMD_RETRIGGER_Val;
5
while (TCC0->SYNCBUSY.bit.CTRLB || TCC0->STATUS.bit.STOP);
6

7
TCC0->CTRLBSET.bit.CMD = TCC_CTRLBSET_CMD_READSYNC_Val;
8
while (TCC0->SYNCBUSY.bit.CTRLB);

Aber der Zählerstand wird auch nur zurückgesetzt, wenn diese Codezeilen im Release durchlaufen werden oder im Debug-Modus im Run-Betrieb durchlaufen werden. Geht man im Debug-Modus mit einzelnen Steps durch diese Codezeilen kommt es nicht zu einem Zurücksetzen des Zählerstand. Ich habe herausbekommen, dass das Zurücksetzen beim Stoppen des Timers auftritt. Weil wenn der Timer gestoppt ist, man einen Wert in TCC0.COUNT schreibt und dann den Timer startet, dann startet dieser auch von dem Wert den man vorher in TCC0.COUNT geschrieben hat.

Hier ist der vollständige Quellcode für eine main.cpp, mit der man das Problem sehen kann. Durchläuft an den Code zwischen den beiden Breakpoint-Kommentaren mit Steps kommt es nicht zu dem Rücksetzen, ansonsten schon:

1
#include "sam.h"
2

3
int main(void)
4
{
5
    OSCCTRL->XOSCCTRL[1].reg = OSCCTRL_XOSCCTRL_ENABLE | OSCCTRL_XOSCCTRL_IPTAT(0x03) | OSCCTRL_XOSCCTRL_IMULT(0x04) | OSCCTRL_XOSCCTRL_CFDPRESC(0x3);
6
    
7
    OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_REFCLK_XOSC1 | OSCCTRL_DPLLCTRLB_DIV(5);
8
    
9
    OSCCTRL->Dpll[0].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDR(119) | OSCCTRL_DPLLRATIO_LDRFRAC(0);
10
    while (OSCCTRL->Dpll[0].DPLLSYNCBUSY.bit.DPLLRATIO);
11
    
12
    OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE;
13
    while (OSCCTRL->Dpll[0].DPLLSYNCBUSY.bit.ENABLE | OSCCTRL->Dpll[0].DPLLSTATUS.bit.LOCK || OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY);
14
    
15
    GCLK->CTRLA.bit.SWRST = true;
16
    while (GCLK->SYNCBUSY.bit.SWRST);
17
    
18
    GCLK->GENCTRL[0].reg = GCLK_GENCTRL_SRC_DPLL0 | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_DIV(1);
19
    while (GCLK->SYNCBUSY.bit.GENCTRL0);
20
    
21
    GCLK->PCHCTRL[TCC0_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN;
22
    while (!GCLK->PCHCTRL[TCC0_GCLK_ID].bit.CHEN);
23
    
24
    MCLK->APBBMASK.bit.TCC0_ = true;
25
    
26
    TCC0->CTRLA.bit.ENABLE = false;
27
    while (TCC0->SYNCBUSY.bit.ENABLE);
28
    
29
    TCC0->WAVE.bit.WAVEGEN = TCC_WAVE_WAVEGEN_MFRQ_Val;
30
    while (TCC0->SYNCBUSY.bit.WAVE);
31
    
32
    TCC0->CC[0].bit.CC = 0x7270e;
33
    while (TCC0->SYNCBUSY.bit.CC0);
34
    
35
    TCC0->CTRLA.reg = TCC_CTRLA_PRESCALER_DIV256 | TCC_CTRLA_ENABLE;
36
    while (TCC0->SYNCBUSY.bit.ENABLE);
37
    
38
    uint32_t Count = 0;
39
    
40
    while (Count < 0x20000)
41
    {
42
        TCC0->CTRLBSET.bit.CMD = TCC_CTRLBSET_CMD_READSYNC_Val;
43
        while (TCC0->SYNCBUSY.bit.CTRLB);
44
        
45
        Count = TCC0->COUNT.bit.COUNT;;
46
    }
47
    
48
    if (!TCC0->STATUS.bit.STOP)
49
    {
50
        TCC0->CTRLBSET.bit.CMD = TCC_CTRLBSET_CMD_STOP_Val; //Breakpoint
51
        
52
        while (TCC0->SYNCBUSY.bit.CTRLB || !TCC0->STATUS.bit.STOP);
53
    }
54
    
55
    if (TCC0->STATUS.bit.STOP) //Breakpoint
56
    {
57
        TCC0->CTRLBSET.bit.CMD = TCC_CTRLBSET_CMD_RETRIGGER_Val;
58
        
59
        while (TCC0->SYNCBUSY.bit.CTRLB || TCC0->STATUS.bit.STOP);
60
    }
61
    
62
    while (true)
63
    {
64
        TCC0->CTRLBSET.bit.CMD = TCC_CTRLBSET_CMD_READSYNC_Val;
65
        
66
        while (TCC0->SYNCBUSY.bit.CTRLB);
67
        
68
        Count = TCC0->COUNT.bit.COUNT;
69
    }
70
}

Als letzte Information noch, ich verwende als IDE Mircrochipstudio mit der ARM GNU Toolchain 6.3.1. Und für das Beispiel habe ich den SAM E54 CURIOSITY ULTRA DEVELOPMENT BOARD verwendet.

Und jetzt die Frage. Könnt ihr bestätigen, dass es sich hierbei um einen Fehler im Datenblatt handelt oder ggf. sagen, warum es bei mir zu einem Zurücksetzen des Timers kommt, obwohl diese nicht sein soll? Habe ich ggf. ein Flag nicht gesetzt, dass man unbedingt setzen muss?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren