test/xtimer_hang: DEBUG_PINS

Add the option to use debug pins to investigate timing issues.
This commit is contained in:
josar 2018-10-16 21:35:15 +02:00
parent 6ed11de354
commit 162d17c5a2
3 changed files with 49 additions and 0 deletions

View File

@ -6,4 +6,18 @@ USEMODULE += xtimer
TEST_ON_CI_WHITELIST += all TEST_ON_CI_WHITELIST += all
# Port and pin configuration for probing with oscilloscope
# Define Test pin for hardware timer interrupt, hardware dependent
# For all ATmega Platforms
#CFLAGS += -DDEBUG_TIMER_PORT=PORTF
#CFLAGS += -DDEBUG_TIMER_DDR=DDRF
#CFLAGS += -DDEBUG_TIMER_PIN=PORTF4
# Define test probing pins GPIO API based.
# Port number should be found in port enum e.g in cpu/include/periph_cpu.h
#FEATURES_REQUIRED += periph_gpio
# Jiminy probing Pins
#CFLAGS += -DWORKER_THREAD_PIN=GPIO_PIN\(5,7\)
#CFLAGS += -DMAIN_THREAD_PIN=GPIO_PIN\(5,6\)
include $(RIOTBASE)/Makefile.include include $(RIOTBASE)/Makefile.include

View File

@ -9,3 +9,14 @@ the test has failed.
Please note (again), this is a runtime test to check if xtimer runs into a Please note (again), this is a runtime test to check if xtimer runs into a
deadlock, it is not about clock stability nor accuracy of timing intervals. deadlock, it is not about clock stability nor accuracy of timing intervals.
When debug pins are used and observed the expected output is as follows:
The MAIN_THREAD_PIN is on for ca. 100ms and that in a regular interval. If this interval is not regular or has gaps this
is an error. The WORKER_THREAD_PIN should toggle after 1ms and 1.1ms. (As this might fall in the XTIMER_ISR_BACKOFF the
first pin toggle is delayed untill the second is ready. Thus the time interval can be longer.)
If the Timer fall in the same interrupt there might be a interrupt before the second worker thread timer is set.
This leads to a separation of the timer interrupts until they again fall in the same interrupt.
It might happen that from the seperation of the interrupts till the merge there is only a uneven count of
WORKER_THREAD_PIN toggles, which means a loss of one worker time 2, which is expected as it has a lower priority then
worker timer 1. And thus in the moment when the hardware interrupt for the 2 worker is executet it has to wait for the
1 worker timer because of the XTIMER_ISR_BACKOFF and so the first timer is executed first as it has the higher priority.

View File

@ -29,6 +29,11 @@
#include "thread.h" #include "thread.h"
#include "log.h" #include "log.h"
#if defined(MAIN_THREAD_PIN) || defined(WORKER_THREAD_PIN)
#include "board.h"
#include "periph/gpio.h"
#endif
#define TEST_TIME_S (10LU) #define TEST_TIME_S (10LU)
#define TEST_INTERVAL_MS (100LU) #define TEST_INTERVAL_MS (100LU)
#define TEST_TIMER_STACKSIZE (THREAD_STACKSIZE_DEFAULT) #define TEST_TIMER_STACKSIZE (THREAD_STACKSIZE_DEFAULT)
@ -38,14 +43,27 @@ char stack_timer2[TEST_TIMER_STACKSIZE];
void* timer_func(void* arg) void* timer_func(void* arg)
{ {
#if defined(WORKER_THREAD_PIN)
gpio_t worker_pin = WORKER_THREAD_PIN;
gpio_init(worker_pin, GPIO_OUT);
#endif
LOG_DEBUG("run thread %" PRIkernel_pid "\n", thread_getpid()); LOG_DEBUG("run thread %" PRIkernel_pid "\n", thread_getpid());
while(1) { while(1) {
#if defined(WORKER_THREAD_PIN)
gpio_set(worker_pin);
gpio_clear(worker_pin);
#endif
xtimer_usleep(*(uint32_t *)(arg)); xtimer_usleep(*(uint32_t *)(arg));
} }
} }
int main(void) int main(void)
{ {
#if defined(MAIN_THREAD_PIN)
gpio_t main_pin = MAIN_THREAD_PIN;
gpio_init(main_pin, GPIO_OUT);
#endif
LOG_DEBUG("[INIT]\n"); LOG_DEBUG("[INIT]\n");
uint32_t sleep_timer1 = 1000; uint32_t sleep_timer1 = 1000;
uint32_t sleep_timer2 = 1100; uint32_t sleep_timer2 = 1100;
@ -63,7 +81,13 @@ int main(void)
puts("[START]"); puts("[START]");
while((now = xtimer_now_usec()) < until) { while((now = xtimer_now_usec()) < until) {
unsigned percent = (100 * (now - start)) / (until - start); unsigned percent = (100 * (now - start)) / (until - start);
#if defined(MAIN_THREAD_PIN)
gpio_set(main_pin);
#endif
xtimer_usleep(TEST_INTERVAL_MS * US_PER_MS); xtimer_usleep(TEST_INTERVAL_MS * US_PER_MS);
#if defined(MAIN_THREAD_PIN)
gpio_clear(main_pin);
#endif
printf("Testing (%3u%%)\n", percent); printf("Testing (%3u%%)\n", percent);
} }
puts("Testing (100%)"); puts("Testing (100%)");