Forum: Mikrocontroller und Digitale Elektronik STM32F103: DWT Timer stört Debugger?


von Chris J. (Gast)


Lesenswert?

Hallo,

habe ich da etwas überlesen? Ich benutze diese Routinen um 
Ausführunsgzeiten zu messen und eine MikroSec Timer zu verwenden aber 
seitdem spielt mein Debuger (swd) etwas verrückt, macht komische Sachen. 
Friert ab und zu ein usw. Hat der damit was zu tun?
1
#pragma GCC push_options
2
#pragma GCC optimize ("O3")
3
void delayUS_DWT(uint32_t us)
4
{
5
  volatile uint32_t cycles = (SystemCoreClock/1000000L)*us;
6
  __disable_irq();
7
  volatile uint32_t start = DWT->CYCCNT;
8
  do  {
9
  } while(DWT->CYCCNT - start < cycles);
10
  __enable_irq();
11
}
12
#pragma GCC pop_options
13
14
#pragma GCC push_options
15
#pragma GCC optimize ("O0")
16
uint32_t DWT_Delay_Init(void) {
17
  /* Disable TRC */
18
  CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk; // ~0x01000000;
19
  /* Enable TRC */
20
  CoreDebug->DEMCR |=  CoreDebug_DEMCR_TRCENA_Msk; // 0x01000000;
21
22
  /* Disable clock cycle counter */
23
  DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk; //~0x00000001;
24
  /* Enable  clock cycle counter */
25
  DWT->CTRL |=  DWT_CTRL_CYCCNTENA_Msk; //0x00000001;
26
27
  /* Reset the clock cycle counter value */
28
  DWT->CYCCNT = 0;
29
30
     /* 3 NO OPERATION instructions */
31
     __ASM volatile ("NOP");
32
     __ASM volatile ("NOP");
33
     __ASM volatile ("NOP");
34
35
  /* Check if clock cycle counter has started */
36
     if(DWT->CYCCNT)
37
     {
38
       return 0; /*clock cycle counter started*/
39
     }
40
     else
41
  {
42
    return 1; /*clock cycle counter not started*/
43
  }
44
}
45
#pragma GCC pop_options

von lange weiler (Gast)


Lesenswert?

Chris J. schrieb:
> mein Debuger (swd)

Der ist vermutlich geheim weil du dazu keine Angaben machst.

von Chris J. (Gast)


Lesenswert?

lange weiler schrieb:
> Chris J. schrieb:
>> mein Debuger (swd)
>
> Der ist vermutlich geheim weil du dazu keine Angaben machst.

St-Link V2 und alternativ ein Segger JLINK.

von Nop (Gast)


Lesenswert?

Chris J. schrieb:

> habe ich da etwas überlesen? Ich benutze diese Routinen um
> Ausführunsgzeiten zu messen und eine MikroSec Timer zu verwenden

Das geht auch super, nur heißt DWT doch schon "Data Watchpoint Trigger", 
und der befindet sich im Reference Manual nicht ohne Grund im Kapitel 
"Core Debug". Mit anderen Worten, natürlich kann das in Konflikt mit dem 
Debugger geraten.

von Chris J. (Gast)


Lesenswert?

Nop schrieb:
> Chris J. schrieb:
>
>> habe ich da etwas überlesen? Ich benutze diese Routinen um
>> Ausführunsgzeiten zu messen und eine MikroSec Timer zu verwenden
>
> Das geht auch super, nur heißt DWT doch schon "Data Watchpoint Trigger",
> und der befindet sich im Reference Manual nicht ohne Grund im Kapitel
> "Core Debug". Mit anderen Worten, natürlich kann das in Konflikt mit dem
> Debugger geraten.

Das war mir schon fast klar. Wäre es denn auch ein Problem, wenn ich den 
nur lesend verwende? Ihn also nicht zurücksetze. Dann habe ich zwar ein 
Übelaufproblem (evtl.) aber auch nicht wirklich oft. Den Systick 
verwende ich nicht, wäre aber ggf. auch ne Möglichkeit.

von Nop (Gast)


Lesenswert?

Noch ein Tip, dese Zeile hier:
volatile uint32_t cycles = (SystemCoreClock/1000000L)*us;

Da hast Du eine Division drin. Die würde ich aus dieser Routine 
rauslagern. Bau Dir eine Variable SystemCoreClock_Div_1e6 oder so, die 
Du immer dann updatest, wenn Du die Taktfrequenz des Systems verstellst.

Abgesehen davon ist es relativ sinnfrei, funktions-lokale Variablen als 
volatile zu deklarieren.

von Nop (Gast)


Lesenswert?

Chris J. schrieb:

> Das war mir schon fast klar. Wäre es denn auch ein Problem, wenn ich den
> nur lesend verwende?

Falls der Debugger den nicht auch noch schreibend verwendet. Sonst gehst 
Du in Dein Delay rein in gutem Glauben, der Debugger spielt damit 
schreibend herum, und heraus kommt irgendein Delay.

> Den Systick verwende ich nicht, wäre aber ggf. auch ne Möglichkeit.

Nicht im Mikrosekunden-Bereich, dann ist die CPU nur noch mit Systick 
beschäftigt. Den kannst Du für Delays im Bereich von Millisekunden 
nehmen, also per Softwaretimer.

von Nop (Gast)


Lesenswert?

Ach ja, und in der Delay-Routine sollte das Allererste sein, das 
Cyclecount-Register auf 0 zu setzen. Alles andere erst danach, weil dann 
der Overhead bereits sauber im Delay beinhaltet wird.

von Chris J. (Gast)


Lesenswert?

Nop schrieb:
> Ach ja, und in der Delay-Routine sollte das Allererste sein, das
> Cyclecount-Register auf 0 zu setzen.

Genau das erzeugt ja die Probleme ;-) Daher lasse ich das sein. Den Rest 
arbeite ich mal ein, vor allem die Division raus, einfach nur 2 Zeilen 
höher setzen und fertig, da die Taktfrequenz nie verändert wird. Ich 
benutze sleep zum Heia machen, damit er sich nicht "überhitzt" ;-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.