Debugging
Zeitmessung
Bestimmen der Zeit bis zu einem Haltepunkt:
Timer2 ist ein 32 Bit Timer, er kann verwendet werden, um die Mikrosekunden zu zähle (2^32=4*10^9 = 4000s = 71.6 Minuten).
Dazu muss allerdings der Timer angehalten werden, wenn ein Haltepunkt angesprungen wird.
Um also z.B. die Zeit für einen Interrupt von Timer1 zu bestimmen werden beide Timer beim Anspringen des Interrupts angehalten und mit TIM2->CNT der Zählerstand von Timer2, dessen Prescaler auf 1us gestellt wird (bei 84MHz z.B. auf 83) , ausgelesen.
Timer anhalten, wenn ein Haltepunkt erreicht wird.
DBGMCU->APB1FZ |= (DBGMCU_APB1_FZ_DBG_TIM2_STOP);
DBGMCU->APB2FZ |= (DBGMCU_APB2_FZ_DBG_TIM1_STOP);
// DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_WWDG_STOP; Watchdogs anhalten
// DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_IWDG_STOP;
ITM
Debugger properties
Die Instrumentation Macro Cell ist eine Hardwarekomponente, die Daten über eine Debug-Schnittstelle senden und empfangen kann; diese über Memory-Mapping, sodass die Übertragung viel schneller als über z.B: die Serielle Schnittstelle erfolgen kann. Bei ST Nucleo Boards ist diese ARM Komponente ist über SWO (Serial Wire Out) zugänglich.
Sie verfügt über ein 10 Byte FIFO, sodass bei zu hoher Schreibgeschwindigkeit auf diese Schnittstelle Daten verloren gehen können.
1)
Channel 0 … Text
Channel31 … RTOS
2) Databreakpoint: eine globale Variable kann beobachtet werden.
Ausgabe eines Characters
ITM_SendChar('A');
Ausgabe mit printf()
1. #include <stdio.h>
2. __io_putchar ersetzen:
/* USER CODE BEGIN 4 */
int __io_putchar(int ch)
{
uint8_t c[1];
c[0] = ch & 0x00FF;
//HAL_UART_Transmit(&huart2, &*c, 1, 10);
ITM_SendChar(c[0]);
return ch;d
}
/* USER CODE END 4 */
3. printf("Hallo\n"); !!!
funktioniert ohne \n nicht!!!! weil der Schreib-Puffer nicht ausgelesen wird; Abhilfe:
setvbuf(stdout, (char*)NULL, _IONBF, 0); schaltet den Puffer aus
ITM_Print und ITM_SendValue
https://github.com/PetteriAimonen/STM32_Trace_Example/blob/master/trace_example.c
// Print a given string to ITM.
// This uses 8 bit writes, as that seems to be the most common way to write text
// through ITM. Otherwise there is no good way for the PC software to know what
// is text and what is some other data.
void ITM_Print(int port, const char *p)
{
if ((ITM->TCR & ITM_TCR_ITMENA_Msk) && (ITM->TER & (1UL << port)))
{
while (*p)
{
while (ITM->PORT[port].u32 == 0);
ITM->PORT[port].u8 = *p++;
}
}
}
// Write a 32-bit value to ITM.
// This can be used as a fast way to log important values from code.
void ITM_SendValue (int port, uint32_t value)
{
if ((ITM->TCR & ITM_TCR_ITMENA_Msk) && (ITM->TER & (1UL << port)))
{
while (ITM->PORT[port].u32 == 0);
ITM->PORT[port].u32 = value;
}
}







