Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pabigot/60d82b2f1633e47d905d644b8104e56c to your computer and use it in GitHub Desktop.
Save pabigot/60d82b2f1633e47d905d644b8104e56c to your computer and use it in GitHub Desktop.
diagnostics patch for zephyrproject-rtos/zephyr issue 17965
From 56036a278ba819bdabf3b32f580d9ecd51123db7 Mon Sep 17 00:00:00 2001
From: Peter Bigot <peter.bigot@nordicsemi.no>
Date: Mon, 19 Aug 2019 11:00:00 -0500
Subject: [PATCH] drivers/timer/nrf_rtc_timer: clarify intent of ZLI
compensation
The variable enabling entry to the zero latency interrupt compensation
loop was named generically, and its logic inverted, making the code
difficult to understand. Change the name and initial value to more
clearly indicate its role.
Signed-off-by: Peter Bigot <peter.bigot@nordicsemi.no>
---
drivers/timer/nrf_rtc_timer.c | 16 +++++++++
kernel/idle.c | 2 ++
kernel/sched.c | 61 +++++++++++++++++++++++++++++++--
kernel/timeout.c | 10 ++++++
tests/kernel/sleep/src/main.c | 2 +-
tests/kernel/sleep/src/usleep.c | 6 ++--
6 files changed, 91 insertions(+), 6 deletions(-)
diff --git a/drivers/timer/nrf_rtc_timer.c b/drivers/timer/nrf_rtc_timer.c
index a83aa13ddb..6955d40cab 100644
--- a/drivers/timer/nrf_rtc_timer.c
+++ b/drivers/timer/nrf_rtc_timer.c
@@ -52,6 +52,7 @@ void rtc1_nrf_isr(void *arg)
ARG_UNUSED(arg);
RTC->EVENTS_COMPARE[0] = 0;
+ NRF_P1->OUTSET = (1U << 4);
k_spinlock_key_t key = k_spin_lock(&lock);
u32_t t = counter();
u32_t dticks = counter_sub(t, last_count) / CYC_PER_TICK;
@@ -71,6 +72,7 @@ void rtc1_nrf_isr(void *arg)
}
k_spin_unlock(&lock, key);
+ NRF_P1->OUTCLR = (1U << 4);
z_clock_announce(IS_ENABLED(CONFIG_TICKLESS_KERNEL) ? dticks : 1);
}
@@ -114,6 +116,7 @@ void z_clock_set_timeout(s32_t ticks, bool idle)
ARG_UNUSED(idle);
#ifdef CONFIG_TICKLESS_KERNEL
+ NRF_P1->OUTSET = (1U << 3);
ticks = (ticks == K_FOREVER) ? MAX_TICKS : ticks;
ticks = MAX(MIN(ticks - 1, (s32_t)MAX_TICKS), 0);
@@ -121,6 +124,8 @@ void z_clock_set_timeout(s32_t ticks, bool idle)
u32_t cyc, dt, t = counter();
bool flagged = false;
+ counter_sub(t, last_count);
+
/* Round up to next tick boundary */
cyc = ticks * CYC_PER_TICK + 1 + counter_sub(t, last_count);
cyc += (CYC_PER_TICK - 1);
@@ -154,19 +159,29 @@ void z_clock_set_timeout(s32_t ticks, bool idle)
* interrupt. The docs say two cycles, they mean two cycles.
*/
if (counter_sub(cyc, t) > 2) {
+ NRF_P1->OUTSET = (1U << 2);
set_comparator(cyc);
+ NRF_P1->OUTCLR = (1U << 2);
} else {
set_comparator(cyc);
dt = counter_sub(cyc, counter());
if (dt == 0 || dt > 0x7fffff) {
/* Missed it! */
+ NRF_P1->OUTSET = (1U << 2) | (1U << 8);
NVIC_SetPendingIRQ(RTC1_IRQn);
if (IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS)) {
flagged = true;
}
+ NRF_P1->OUTCLR = (1U << 2) | (1U << 8);
} else if (dt == 1) {
/* Too soon, interrupt won't arrive. */
+ NRF_P1->OUTSET = (1U << 2);
set_comparator(cyc + 2);
+ NRF_P1->OUTCLR = (1U << 2);
+ NRF_P1->OUTSET = (1U << 2);
+ NRF_P1->OUTCLR = (1U << 2);
+ NRF_P1->OUTSET = (1U << 2);
+ NRF_P1->OUTCLR = (1U << 2);
}
/* Otherwise it was two cycles out, we're fine */
}
@@ -191,6 +206,7 @@ void z_clock_set_timeout(s32_t ticks, bool idle)
#endif
k_spin_unlock(&lock, key);
+ NRF_P1->OUTCLR = (1U << 3);
#endif /* CONFIG_TICKLESS_KERNEL */
}
diff --git a/kernel/idle.c b/kernel/idle.c
index 2172c077c2..1466b9b254 100644
--- a/kernel/idle.c
+++ b/kernel/idle.c
@@ -75,7 +75,9 @@ static void sys_power_save_idle(void)
* API we need to honor...
*/
#ifdef CONFIG_SYS_CLOCK_EXISTS
+ //NRF_P1->OUTSET = (1U << 8);
z_set_timeout_expiry((ticks < IDLE_THRESH) ? 1 : ticks, true);
+ //NRF_P1->OUTCLR = (1U << 8);
#endif
set_kernel_idle_time_in_ticks(ticks);
diff --git a/kernel/sched.c b/kernel/sched.c
index 026804d057..7a892a4ec3 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -800,8 +800,46 @@ int z_unpend_all(_wait_q_t *wait_q)
return need_sched;
}
+#define LOGIC 1
+
void z_sched_init(void)
{
+#if (LOGIC - 0)
+ NRF_P1->OUTCLR = (0xFFU << 1);
+ NRF_P1->PIN_CNF[1] = ((GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
+ | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
+ | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos)
+ | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos));
+ NRF_P1->PIN_CNF[2] = ((GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
+ | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
+ | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos)
+ | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos));
+ NRF_P1->PIN_CNF[3] = ((GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
+ | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
+ | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos)
+ | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos));
+ NRF_P1->PIN_CNF[4] = ((GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
+ | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
+ | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos)
+ | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos));
+ NRF_P1->PIN_CNF[5] = ((GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
+ | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
+ | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos)
+ | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos));
+ NRF_P1->PIN_CNF[6] = ((GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
+ | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
+ | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos)
+ | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos));
+ NRF_P1->PIN_CNF[7] = ((GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
+ | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
+ | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos)
+ | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos));
+ NRF_P1->PIN_CNF[8] = ((GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
+ | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
+ | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos)
+ | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos));
+#endif
+
#ifdef CONFIG_SCHED_DUMB
sys_dlist_init(&_kernel.ready_q.runq);
#endif
@@ -981,13 +1019,30 @@ Z_SYSCALL_HANDLER(k_sleep, ms)
}
#endif
+#define MEASURE 0
+extern s32_t xxx_nto;
+
s32_t z_impl_k_usleep(int us)
{
s32_t ticks;
- ticks = z_us_to_ticks(us);
- ticks = z_tick_sleep(ticks);
- return __ticks_to_us(ticks);
+#if (MEASURE - 0)
+ u32_t now = NRF_RTC1->COUNTER; // k_cycle_get_32();
+#endif /* MEASURE */
+ ticks = z_us_to_ticks(us); /* 1 */
+#if (LOGIC - 0)
+ NRF_P1->OUTSET = (1U << 1);
+#endif /* LOGIC */
+ z_tick_sleep(ticks); /* 0 */
+ ticks = xxx_nto;
+#if (LOGIC - 0)
+ NRF_P1->OUTCLR = (1U << 1);
+#endif /* LOGIC */
+#if (MEASURE - 0)
+ ticks = (NRF_RTC1->COUNTER - now) & ((1U << 24) - 1);
+ return ticks; // __ticks_to_us(ticks);
+#endif /* MEASURE */
+ return ticks; // __ticks_to_us(ticks);
}
#ifdef CONFIG_USERSPACE
diff --git a/kernel/timeout.c b/kernel/timeout.c
index 99f3d24c85..a4457bd50a 100644
--- a/kernel/timeout.c
+++ b/kernel/timeout.c
@@ -16,6 +16,7 @@
k_spin_unlock(lck, __key), __i.key = 1)
static u64_t curr_tick;
+s32_t xxx_nto;
static sys_dlist_t timeout_list = SYS_DLIST_STATIC_INIT(&timeout_list);
@@ -106,7 +107,9 @@ void z_add_timeout(struct _timeout *to, _timeout_func_t fn, s32_t ticks)
}
if (to == first()) {
+ NRF_P1->OUTSET = (1U << 5); /* first */
z_clock_set_timeout(next_timeout(), false);
+ NRF_P1->OUTCLR = (1U << 5);
}
}
}
@@ -159,6 +162,7 @@ void z_set_timeout_expiry(s32_t ticks, bool idle)
{
LOCKED(&timeout_lock) {
int next = next_timeout();
+ xxx_nto = next;
bool sooner = (next == K_FOREVER) || (ticks < next);
bool imminent = next <= 1;
@@ -168,9 +172,13 @@ void z_set_timeout_expiry(s32_t ticks, bool idle)
* that will bump the timeout to the "next" tick if
* it's not considered to be settable as directed.
*/
+ NRF_P1->OUTSET = (1U << 6); /* expiry */
if (sooner && !imminent) {
+ NRF_P1->OUTCLR = (1U << 6);
z_clock_set_timeout(ticks, idle);
+ NRF_P1->OUTSET = (1U << 6);
}
+ NRF_P1->OUTCLR = (1U << 6);
}
}
@@ -181,6 +189,7 @@ void z_clock_announce(s32_t ticks)
#endif
k_spinlock_key_t key = k_spin_lock(&timeout_lock);
+ NRF_P1->OUTSET = (1U << 7); /* announce */
announce_remaining = ticks;
@@ -207,6 +216,7 @@ void z_clock_announce(s32_t ticks)
z_clock_set_timeout(next_timeout(), false);
+ NRF_P1->OUTCLR = (1U << 7);
k_spin_unlock(&timeout_lock, key);
}
diff --git a/tests/kernel/sleep/src/main.c b/tests/kernel/sleep/src/main.c
index 0675b5a1f1..843033cf59 100644
--- a/tests/kernel/sleep/src/main.c
+++ b/tests/kernel/sleep/src/main.c
@@ -239,7 +239,7 @@ extern void test_usleep(void);
void test_main(void)
{
ztest_test_suite(sleep,
- ztest_unit_test(test_sleep),
+ //ztest_unit_test(test_sleep),
ztest_user_unit_test(test_usleep));
ztest_run_test_suite(sleep);
}
diff --git a/tests/kernel/sleep/src/usleep.c b/tests/kernel/sleep/src/usleep.c
index 29cd6ec236..df53e169d4 100644
--- a/tests/kernel/sleep/src/usleep.c
+++ b/tests/kernel/sleep/src/usleep.c
@@ -52,6 +52,7 @@ void test_usleep(void)
{
int retries = 0;
s64_t elapsed_ms;
+ s32_t delay = 0;
while (retries < RETRIES) {
s64_t start_ms;
@@ -62,7 +63,7 @@ void test_usleep(void)
start_ms = k_uptime_get();
for (i = 0; i < LOOPS; ++i) {
- k_usleep(1);
+ delay = k_usleep(1);
}
end_ms = k_uptime_get();
@@ -70,13 +71,14 @@ void test_usleep(void)
/* if at first you don't succeed, keep sucking. */
+ printk("elapsed_ms = %lld delay %d ticks\n", elapsed_ms, delay);
+
if ((elapsed_ms >= LOWER_BOUND_MS) &&
(elapsed_ms <= UPPER_BOUND_MS)) {
break;
}
}
- printk("elapsed_ms = %lld\n", elapsed_ms);
zassert_true(elapsed_ms >= LOWER_BOUND_MS, "short sleep");
zassert_true(elapsed_ms <= UPPER_BOUND_MS, "overslept");
}
--
2.17.1
This file has been truncated, but you can view the full file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment