Skip to content

Commit

Permalink
drv/clock: move clock driver out of contiki
Browse files Browse the repository at this point in the history
This refactors the code base to use pbdrv_clock_* instead of clock_*
from contiki. This is a step towards eliminating contiki from the
public API, which will be nice if we ever have PBIO as a stand-alone
C library.

It also simplifies the code a bit since it gets rid of clock_from_msec()
and clock_to_msec() which were NOPs in the PBIO library anyway.

clock_delay_usec() is moved into the MicroPython code (as
mp_hal_delay_us()) since we want to avoid any blocking functions
in PBIO.
  • Loading branch information
dlech committed Sep 28, 2021
1 parent e82dd6a commit a21283c
Show file tree
Hide file tree
Showing 67 changed files with 309 additions and 332 deletions.
9 changes: 4 additions & 5 deletions bricks/cityhub/mphalport.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2018-2020 The Pybricks Authors
// Copyright (c) 2018-2021 The Pybricks Authors

#include <contiki.h>
#include <pbdrv/clock.h>

void mp_hal_set_interrupt_char(int c);
#define mp_hal_ticks_ms clock_time
#define mp_hal_ticks_us clock_usecs
#define mp_hal_delay_us clock_delay_usec
#define mp_hal_ticks_ms pbdrv_clock_get_ms
#define mp_hal_ticks_us pbdrv_clock_get_us
#define mp_hal_ticks_cpu() 0
9 changes: 4 additions & 5 deletions bricks/debug/mphalport.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2018-2020 The Pybricks Authors
// Copyright (c) 2018-2021 The Pybricks Authors

#include <contiki.h>
#include <pbdrv/clock.h>

void mp_hal_set_interrupt_char(int c);
#define mp_hal_ticks_ms clock_time
#define mp_hal_ticks_us clock_usecs
#define mp_hal_delay_us clock_delay_usec
#define mp_hal_ticks_ms pbdrv_clock_get_ms
#define mp_hal_ticks_us pbdrv_clock_get_us
#define mp_hal_ticks_cpu() 0
9 changes: 4 additions & 5 deletions bricks/essentialhub/mphalport.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2018-2020 The Pybricks Authors
// Copyright (c) 2018-2021 The Pybricks Authors

#include "sys/clock.h"
#include <pbdrv/clock.h>

void mp_hal_set_interrupt_char(int c);
#define mp_hal_ticks_ms clock_time
#define mp_hal_ticks_us clock_usecs
#define mp_hal_delay_us clock_delay_usec
#define mp_hal_ticks_ms pbdrv_clock_get_ms
#define mp_hal_ticks_us pbdrv_clock_get_us
#define mp_hal_ticks_cpu() 0
6 changes: 3 additions & 3 deletions bricks/ev3dev/ev3dev_mphal.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#include <unistd.h>
#include <sys/time.h>

#include <contiki.h>
#include <pbdrv/clock.h>

#include "py/mphal.h"
#include "py/runtime.h"
Expand Down Expand Up @@ -125,11 +125,11 @@ void mp_hal_stdout_tx_str(const char *str) {
}

mp_uint_t mp_hal_ticks_ms(void) {
return clock_to_msec(clock_time());
return pbdrv_clock_get_ms();
}

mp_uint_t mp_hal_ticks_us(void) {
return clock_usecs();
return pbdrv_clock_get_us();
}

uint64_t mp_hal_time_ns(void) {
Expand Down
9 changes: 4 additions & 5 deletions bricks/movehub/mphalport.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2018-2020 The Pybricks Authors
// Copyright (c) 2018-2021 The Pybricks Authors

#include <contiki.h>
#include <pbdrv/clock.h>

void mp_hal_set_interrupt_char(int c);
#define mp_hal_ticks_ms clock_time
#define mp_hal_ticks_us clock_usecs
#define mp_hal_delay_us clock_delay_usec
#define mp_hal_ticks_ms pbdrv_clock_get_ms
#define mp_hal_ticks_us pbdrv_clock_get_us
#define mp_hal_ticks_cpu() 0
9 changes: 4 additions & 5 deletions bricks/nxt/mphalport.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2018-2020 The Pybricks Authors
// Copyright (c) 2018-2021 The Pybricks Authors

#include <contiki.h>
#include <pbdrv/clock.h>

void mp_hal_set_interrupt_char(int c);
#define mp_hal_ticks_ms clock_time
#define mp_hal_ticks_us clock_usecs
#define mp_hal_delay_us clock_delay_usec
#define mp_hal_ticks_ms pbdrv_clock_get_ms
#define mp_hal_ticks_us pbdrv_clock_get_us
#define mp_hal_ticks_cpu() 0
15 changes: 15 additions & 0 deletions bricks/nxt/systick.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "py/mphal.h"
#include "py/mpconfig.h"

#include <nxt/at91sam7.h>
#include <nxt/interrupts.h>
#include <nxt/systick.h>

Expand All @@ -30,3 +31,17 @@ void mp_hal_delay_ms(mp_uint_t Delay) {
systick_wait_ms(Delay);
}
}

/* The inner loop takes 4 cycles. The outer 5+SPIN_COUNT*4. */

#define SPIN_TIME 2 /* us */
#define SPIN_COUNT (((CLOCK_FREQUENCY * SPIN_TIME / 1000000) - 5) / 4)

void mp_hal_delay_us(mp_uint_t t) {
#ifdef __THUMBEL__
__asm volatile ("1: mov r1,%2\n2:\tsub r1,#1\n\tbne 2b\n\tsub %0,#1\n\tbne 1b\n"
: "=l" (t) : "0" (t), "l" (SPIN_COUNT));
#else
#error Must be compiled in thumb mode
#endif
}
9 changes: 4 additions & 5 deletions bricks/primehub/mphalport.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2018-2020 The Pybricks Authors
// Copyright (c) 2018-2021 The Pybricks Authors

#include "sys/clock.h"
#include <pbdrv/clock.h>

void mp_hal_set_interrupt_char(int c);
#define mp_hal_ticks_ms clock_time
#define mp_hal_ticks_us clock_usecs
#define mp_hal_delay_us clock_delay_usec
#define mp_hal_ticks_ms pbdrv_clock_get_ms
#define mp_hal_ticks_us pbdrv_clock_get_us
#define mp_hal_ticks_cpu() 0
2 changes: 1 addition & 1 deletion bricks/stm32/configport.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
#define MICROPY_PY_SYS_STDIO_BUFFER (PYBRICKS_STM32_OPT_EXTRA_MOD)
#define MICROPY_PY_URANDOM (PYBRICKS_STM32_OPT_EXTRA_MOD)
#define MICROPY_PY_URANDOM_EXTRA_FUNCS (PYBRICKS_STM32_OPT_EXTRA_MOD)
#define MICROPY_PY_URANDOM_SEED_INIT_FUNC ({ extern unsigned long clock_usecs(void); clock_usecs(); })
#define MICROPY_PY_URANDOM_SEED_INIT_FUNC ({ extern uint32_t pbdrv_clock_get_us(void); pbdrv_clock_get_us(); })
#define MICROPY_PY_USELECT (PYBRICKS_STM32_OPT_EXTRA_MOD)
#define MICROPY_PY_UTIME_MP_HAL (0)
#define MICROPY_MODULE_BUILTIN_INIT (1)
Expand Down
22 changes: 19 additions & 3 deletions bricks/stm32/mphalport.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,21 @@
#include "py/stream.h"

// using "internal" pbdrv variable
extern volatile uint32_t clock_time_ticks;
extern volatile uint32_t pbdrv_clock_ticks;

// Core delay function that does an efficient sleep and may switch thread context.
// If IRQs are enabled then we must have the GIL.
void mp_hal_delay_ms(mp_uint_t Delay) {
if (__get_PRIMASK() == 0) {
// IRQs enabled, so can use systick counter to do the delay
uint32_t start = clock_time_ticks;
uint32_t start = pbdrv_clock_ticks;
// Wraparound of tick is taken care of by 2's complement arithmetic.
do {
// This macro will execute the necessary idle behaviour. It may
// raise an exception, switch threads or enter sleep mode (waiting for
// (at least) the SysTick interrupt).
MICROPY_EVENT_POLL_HOOK
} while (clock_time_ticks - start < Delay);
} while (pbdrv_clock_ticks - start < Delay);
} else {
// IRQs disabled, so need to use a busy loop for the delay.
// To prevent possible overflow of the counter we use a double loop.
Expand All @@ -39,6 +39,22 @@ void mp_hal_delay_ms(mp_uint_t Delay) {
}
}

// delay for given number of microseconds
void mp_hal_delay_us(mp_uint_t usec) {
if (__get_PRIMASK() == 1) {
// IRQs enabled, so can use systick counter to do the delay
uint32_t start = pbdrv_clock_get_us();
while (pbdrv_clock_get_us() - start < usec) {
}
} else {
// IRQs disabled, so need to use a busy loop for the delay
// sys freq is always a multiple of 2MHz, so division here won't lose precision
const uint32_t ucount = PBDRV_CONFIG_SYS_CLOCK_RATE / 2000000 * usec / 2;
for (uint32_t count = 0; ++count <= ucount;) {
}
}
}

#if PYBRICKS_HUB_DEBUG

#include "stm32f4xx.h"
Expand Down
9 changes: 4 additions & 5 deletions bricks/technichub/mphalport.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2018-2020 The Pybricks Authors
// Copyright (c) 2018-2021 The Pybricks Authors

#include <contiki.h>
#include <pbdrv/clock.h>

void mp_hal_set_interrupt_char(int c);
#define mp_hal_ticks_ms clock_time
#define mp_hal_ticks_us clock_usecs
#define mp_hal_delay_us clock_delay_usec
#define mp_hal_ticks_ms pbdrv_clock_get_ms
#define mp_hal_ticks_us pbdrv_clock_get_us
#define mp_hal_ticks_cpu() 0
70 changes: 3 additions & 67 deletions lib/contiki-core/sys/clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,56 +82,14 @@
#else
#define CLOCK_SECOND (clock_time_t)32
#endif

/**
* Converts milliseconds to clock ticks, rounding up so that the actual time
* span will be >= *msec*.
*
* \param msec the time in milliseconds
*
* \return a ::clock_time_t value
*/
static inline clock_time_t clock_from_msec(unsigned int msec) {
#if CLOCK_SECOND == 1000
return msec;
#else
return (msec * CLOCK_SECOND + 999) / 1000;
#endif
}

/**
* Converts clock ticks to milliseconds, rounding down so that the actual time
* span will be <= *ticks*.
*
* \param ticks a ::clock_time_t value
*
* \return the time in milliseconds
*/
static inline unsigned int clock_to_msec(clock_time_t ticks) {
#if CLOCK_SECOND == 1000
return ticks;
#else
return ticks * 1000 / CLOCK_SECOND;
#endif
}

/**
* Initialize the clock library.
*
* This function initializes the clock library and should be called
* from the main() function of the system.
*
*/
void clock_init(void);

/**
* Get the current clock time.
*
* This function returns the current system clock time.
*
* \return The current clock time, measured in system ticks.
*/
CCIF clock_time_t clock_time(void);
clock_time_t clock_time(void);

/**
* Get the current value of the platform seconds.
Expand All @@ -141,36 +99,14 @@ CCIF clock_time_t clock_time(void);
*
* \return The value.
*/
CCIF unsigned long clock_seconds(void);
uint32_t clock_seconds(void);

/**
* Get the current value of the platform microseconds.
*
* \return The value.
*/
CCIF unsigned long clock_usecs(void);

/**
* Set the value of the platform seconds.
* \param sec The value to set.
*
*/
void clock_set_seconds(unsigned long sec);

/**
* Wait for a given number of ticks.
* \param t How many ticks.
*
*/
void clock_wait(clock_time_t t);

/**
* Delay a given number of microseconds.
* \param dt How many microseconds to delay.
*
* \note Interrupts could increase the delay by a variable amount.
*/
void clock_delay_usec(uint16_t dt);
uint32_t clock_usecs(void);

#endif /* CLOCK_H_ */

Expand Down
3 changes: 2 additions & 1 deletion lib/ev3dev/src/ev3dev_stretch/nxtcolor.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <ev3dev_stretch/lego_sensor.h>
#include <ev3dev_stretch/sysfs.h>

#include <pbdrv/clock.h>
#include <pbio/color.h>
#include <pbio/port.h>
#include <pbio/iodev.h>
Expand Down Expand Up @@ -89,7 +90,7 @@ nxtcolor_t nxtcolorsensors[4];
// Simplistic nonbusy wait. May be called only once per blocking operation.
pbio_error_t nxtcolor_wait(nxtcolor_t *nxtcolor, uint32_t ms) {

uint32_t now = clock_usecs();
uint32_t now = pbdrv_clock_get_us();

// Wait for existing wait to complete
if (nxtcolor->waiting) {
Expand Down
2 changes: 1 addition & 1 deletion lib/pbio/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ for the various platform-specific hardware.

The `include/pbdrv` directory contains the public header files for the drivers
(`drv` directory). Generally, these header files should not be used outside of
this library.
this library. One common exception is clocks.

The `include/pbio` directory contains the public header files for the main
library (`src` directory). This is the API for user programs.
Expand Down
12 changes: 7 additions & 5 deletions lib/pbio/drv/bluetooth/bluetooth_btstack_run_loop_contiki.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2020 The Pybricks Authors
// Copyright (c) 2020-2021 The Pybricks Authors

// Contiki run loop integration for BlueKitchen BTStack.

Expand All @@ -14,6 +14,8 @@
#include <btstack.h>
#include <contiki.h>

_Static_assert(CLOCK_CONF_SECOND == 1000, "contiki clock must be configured for 1ms ticks");

PROCESS(btstack_run_loop_contiki_process, "btstack");
static struct etimer timer;
static btstack_linked_list_t timers;
Expand All @@ -30,7 +32,7 @@ static void schedule_timer(void) {
if (first_timer == NULL) {
etimer_stop(&timer);
} else {
etimer_set(&timer, clock_from_msec(first_timer->timeout - clock_to_msec(clock_time())));
etimer_set(&timer, first_timer->timeout - pbdrv_clock_get_ms());
}

PROCESS_CONTEXT_END();
Expand All @@ -57,7 +59,7 @@ static void btstack_run_loop_contiki_disable_data_source_callbacks(btstack_data_
}

static void btstack_run_loop_contiki_set_timer(btstack_timer_source_t *ts, uint32_t timeout_in_ms) {
ts->timeout = clock_to_msec(clock_time()) + timeout_in_ms;
ts->timeout = pbdrv_clock_get_ms() + timeout_in_ms;
}

static void btstack_run_loop_contiki_add_timer(btstack_timer_source_t *ts) {
Expand Down Expand Up @@ -100,7 +102,7 @@ static void btstack_run_loop_contiki_dump_timer(void) {
}

static uint32_t btstack_run_loop_contiki_get_time_ms(void) {
return clock_to_msec(clock_time());
return pbdrv_clock_get_ms();
}

static const btstack_run_loop_t btstack_run_loop_contiki = {
Expand Down Expand Up @@ -153,7 +155,7 @@ PROCESS_THREAD(btstack_run_loop_contiki_process, ev, data) {
// process all BTStack timers in list that have expired
while (timers) {
btstack_timer_source_t *ts = (void *)timers;
int32_t delta = btstack_time_delta(ts->timeout, clock_to_msec(clock_time()));
int32_t delta = btstack_time_delta(ts->timeout, pbdrv_clock_get_ms());
if (delta > 0) {
// we have reached unexpired timers
break;
Expand Down
Loading

0 comments on commit a21283c

Please sign in to comment.