From: Nathael Pajani Date: Wed, 9 Sep 2015 19:13:42 +0000 (+0200) Subject: Improve usleep function and add a "usleep_short()" function, to be used only for... X-Git-Url: http://git.techno-innov.fr/?a=commitdiff_plain;h=3b622181d9daad534d146bd7cc65c758bd0056c6;p=soft%2Flpc122x%2Fcore Improve usleep function and add a "usleep_short()" function, to be used only for usleep under 1000us and which does not check that systick is running. --- diff --git a/core/systick.c b/core/systick.c index 35adfb6..81872ec 100644 --- a/core/systick.c +++ b/core/systick.c @@ -36,6 +36,7 @@ static volatile uint32_t sleep_count = 0; static volatile uint32_t tick_ms = 0; static volatile uint32_t systick_running = 0; static volatile uint32_t tick_reload = 0; +static uint32_t usleep_us_count = 0; /* Wraps every 50 days or so with a 1ms tick */ static volatile uint32_t global_wrapping_system_ticks = 0; @@ -237,6 +238,11 @@ void systick_timer_on(uint32_t ms) systick->control = LPC_SYSTICK_CTRL_TICKINT; systick_running = 0; + /* Perform this division now for the usleep function. */ + usleep_us_count = get_main_clock() / (1000 * 1000); + /* For the LPC1224 the system tick clock is fixed to half the frequency of the system clock */ + usleep_us_count = (usleep_us_count >> 1); /* Divide by two */ + /* FIXME : document this */ NVIC_SetPriority(SYSTICK_IRQ, ((1 << LPC_NVIC_PRIO_BITS) - 1)); } @@ -299,6 +305,9 @@ void msleep(uint32_t ms) sleep(); } +/* This usleep function tries to sleep at most the required amount of time. + * The setup is so long that it cannot sleep for less than 10us when running at 48MHz + */ void usleep(uint32_t us) { struct lpc_system_tick* systick = LPC_SYSTICK; @@ -318,11 +327,32 @@ void usleep(uint32_t us) systick_start(); } } - count = get_main_clock() / (1000 * 1000) * us; + count = usleep_us_count * us; + /* Remember that systick is a decrementing counter */ + if (count > start) { + end = (systick->reload_val - (count - start)); + do { } while (systick_counted_to_zero() == 0); /* Wait for timer loop */ + do { } while (systick->value > end); /* Wait for remaining part of sleep duration */ + } else { + end = start - count; + /* Wait for sleep duration. + * If the counter looped, it means we already waited too much */ + do { } while ((systick->value > end) && (systick_counted_to_zero() == 0)); + } +} + +void usleep_short(uint32_t us) +{ + struct lpc_system_tick* systick = LPC_SYSTICK; + uint32_t start = systick->value; /* Grab the starting (call time) value now */ + uint32_t count = usleep_us_count * us; + uint32_t end = systick_counted_to_zero(); /* Erase loop indicator */ + + /* Remember that systick is a decrementing counter */ if (count > start) { end = (systick->reload_val - (count - start)); do { } while (systick_counted_to_zero() == 0); /* Wait for timer loop */ - do { } while (systick->value > end); /* Wait for sleep duration */ + do { } while (systick->value > end); /* Wait for remaining part of sleep duration */ } else { end = start - count; /* Wait for sleep duration. diff --git a/include/core/systick.h b/include/core/systick.h index f36f05a..f643414 100644 --- a/include/core/systick.h +++ b/include/core/systick.h @@ -95,4 +95,11 @@ int add_systick_callback(void (*callback) (uint32_t), uint16_t period); int remove_systick_callback(void (*callback) (uint32_t)); + +/* This function can be used when you are absolutly certain that systick timer is running, and when + * you need to sleep less than 1000us (1ms) + */ +void usleep_short(uint32_t us); + + #endif /* CORE_SYSTEM_H */