diff --git a/core/platform/CMakeLists.txt b/core/platform/CMakeLists.txt index 7a8c591a6..8ee47a9b5 100644 --- a/core/platform/CMakeLists.txt +++ b/core/platform/CMakeLists.txt @@ -9,6 +9,8 @@ lf_macos_support.c lf_windows_support.c lf_nrf52_support.c lf_zephyr_support.c +lf_zephyr_clock_counter.c +lf_zephyr_clock_kernel.c lf_rp2040_support.c ) diff --git a/core/platform/lf_zephyr_clock_counter.c b/core/platform/lf_zephyr_clock_counter.c new file mode 100644 index 000000000..e292e2715 --- /dev/null +++ b/core/platform/lf_zephyr_clock_counter.c @@ -0,0 +1,220 @@ +#if defined(PLATFORM_ZEPHYR) +#include "lf_zephyr_board_support.h" +#if defined(LF_ZEPHYR_CLOCK_COUNTER) +/************* +Copyright (c) 2023, Norwegian University of Science and Technology. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***************/ + +/** + * @brief This implements the timing-related platform API ontop of the Zephyr + * Counter API. The Counter API is a generic interface to a timer peripheral. It + * gives the best timing performance and allows actual sleeping rather than + * busy-waiting which is performed with the Kernel API. + * + * @author{Erling Jellum } + * @author{Marten Lohstroh } + */ +#include +#include + +#include "lf_zephyr_support.h" +#include "platform.h" +#include "util.h" + +static int64_t epoch_duration_nsec; +static int64_t epoch_duration_usec; +static uint32_t counter_max_ticks; +static volatile int64_t last_epoch_nsec = 0; +static uint32_t counter_freq; +static volatile bool async_event = false; + +K_SEM_DEFINE(semaphore,0,1) + +static struct counter_alarm_cfg alarm_cfg; +const struct device *const counter_dev = DEVICE_DT_GET(LF_TIMER); +static volatile bool alarm_fired; + +/** + * This callback is invoked when the underlying Timer peripheral overflows. + * Handled by incrementing the epoch variable. + */ +static void overflow_callback(const struct device *dev, void *user_data) { + last_epoch_nsec += epoch_duration_nsec; +} + +/** + * This callback is invoked when the alarm configured for sleeping expires. + * The sleeping thread is released by giving it the semaphore. + */ +static void alarm_callback(const struct device *counter_dev, + uint8_t chan_id, uint32_t ticks, + void *user_data) { + alarm_fired=true; + k_sem_give(&semaphore); +} + +/** + * Initialize the Counter device. Check its frequency and compute epoch + * durations. + */ +void _lf_initialize_clock() { + struct counter_top_cfg counter_top_cfg; + uint32_t counter_max_ticks=0; + int res; + + // Verify that we have the device + if (!device_is_ready(counter_dev)) { + lf_print_error_and_exit("ERROR: counter device not ready.\n"); + } + + // Verify that it is working as we think + if(!counter_is_counting_up(counter_dev)) { + lf_print_error_and_exit("ERROR: Counter is counting down \n"); + } + + // Get the frequency of the timer + counter_freq = counter_get_frequency(counter_dev); + + // Calculate the duration of an epoch. Compute both + // nsec and usec now at boot to avoid these computations later + counter_max_ticks = counter_get_max_top_value(counter_dev); + epoch_duration_usec = counter_ticks_to_us(counter_dev, counter_max_ticks); + epoch_duration_nsec = epoch_duration_usec * 1000LL; + + // Set the max_top value to be the maximum + counter_top_cfg.ticks = counter_max_ticks; + counter_top_cfg.callback = overflow_callback; + res = counter_set_top_value(counter_dev, &counter_top_cfg); + if (res != 0) { + lf_print_error_and_exit("ERROR: Timer couldnt set top value\n"); + } + + LF_PRINT_LOG("--- Using LF Zephyr Counter Clock with a frequency of %u Hz and wraps every %u sec\n", + counter_freq, counter_max_ticks/counter_freq); + + // Prepare the alarm config + alarm_cfg.flags = 0; + alarm_cfg.ticks = 0; + alarm_cfg.callback = alarm_callback; + alarm_cfg.user_data = &alarm_cfg; + + // Start counter + counter_start(counter_dev); +} + +/** + * The Counter device tracks current physical time. Overflows are handled in an + * ISR. + */ +int _lf_clock_now(instant_t* t) { + static uint64_t last_nsec = 0; + uint32_t now_cycles; + int res; + uint64_t now_nsec; + + res = counter_get_value(counter_dev, &now_cycles); + now_nsec = counter_ticks_to_us(counter_dev, now_cycles)*1000ULL + last_epoch_nsec; + + // Make sure that the clock is monotonic. We might have had a wrap but the + // epoch has not been updated because interrupts are disabled. + if (now_nsec < last_nsec) { + now_nsec = last_nsec + 1; + } + + *t = now_nsec; + last_nsec = now_nsec; + return 0; +} + +/** + * Handle interruptable sleep by configuring a future alarm callback and waiting + * on a semaphore. Make sure we can handle sleeps that exceed an entire epoch + * of the Counter. + */ +int _lf_interruptable_sleep_until_locked(environment_t* env, instant_t wakeup) { + // Reset flags + alarm_fired = false; + async_event = false; + k_sem_reset(&semaphore); + + // Calculate the sleep duration + uint32_t now_cycles, sleep_duration_ticks; + counter_get_value(counter_dev, &now_cycles); + instant_t now; + _lf_clock_now(&now); + interval_t sleep_for_us = (wakeup - now)/1000; + + while ( !async_event && + sleep_for_us > (LF_WAKEUP_OVERHEAD_US + LF_MIN_SLEEP_US) + ) { + if (sleep_for_us < epoch_duration_usec) { + sleep_duration_ticks = counter_us_to_ticks(counter_dev, ((uint64_t) sleep_for_us) - LF_WAKEUP_OVERHEAD_US); + } else { + sleep_duration_ticks = UINT32_MAX; + } + + alarm_cfg.ticks = sleep_duration_ticks; + int err = counter_set_channel_alarm(counter_dev, LF_TIMER_ALARM_CHANNEL, &alarm_cfg); + + if (err != 0) { + lf_print_error_and_exit("Could not setup alarm for sleeping. Errno %i", err); + } + + lf_critical_section_exit(env); + k_sem_take(&semaphore, K_FOREVER); + lf_critical_section_enter(env); + + // Then calculating remaining sleep, unless we got woken up by an event + if (!async_event) { + _lf_clock_now(&now); + sleep_for_us = (wakeup - now)/1000; + } + } + + // Do remaining sleep in busy_wait + if (!async_event && + sleep_for_us > LF_RUNTIME_OVERHEAD_US) { + k_busy_wait((uint32_t) (sleep_for_us - LF_RUNTIME_OVERHEAD_US)); + } + + if (async_event) { + // Cancel the outstanding alarm + counter_cancel_channel_alarm(counter_dev, LF_TIMER_ALARM_CHANNEL); + async_event = false; + return -1; + } else { + return 0; + } +} + +/** + * We notify of async events by setting the flag and giving the semaphore. + */ +int _lf_unthreaded_notify_of_event() { + async_event = true; + k_sem_give(&semaphore); + return 0; +} + +#endif +#endif diff --git a/core/platform/lf_zephyr_clock_kernel.c b/core/platform/lf_zephyr_clock_kernel.c new file mode 100644 index 000000000..fae932742 --- /dev/null +++ b/core/platform/lf_zephyr_clock_kernel.c @@ -0,0 +1,103 @@ +#if defined(PLATFORM_ZEPHYR) +#include "lf_zephyr_board_support.h" +#if defined(LF_ZEPHYR_CLOCK_KERNEL) + +/************* +Copyright (c) 2023, Norwegian University of Science and Technology. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***************/ + +/** + * @brief This implements the timing-related platform API ontop of the kernel + * timer of Zephyr. This is less precise, but more portable than the alternative + * Counter based implementation. + * + * @author{Erling Jellum } + * @author{Marten Lohstroh } + */ + +#include + +#include "lf_zephyr_support.h" +#include "platform.h" +#include "util.h" + +static int64_t epoch_duration_nsec; +static volatile int64_t last_epoch_nsec = 0; +static uint32_t timer_freq; +static volatile bool async_event = false; + +void _lf_initialize_clock() { + timer_freq = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; + LF_PRINT_LOG("--- Using LF Zephyr Kernel Clock with a frequency of %u Hz\n", timer_freq); + last_epoch_nsec = 0; + epoch_duration_nsec = ((1LL << 32) * SECONDS(1))/CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; +} + +/** + * Detect wraps by storing the previous clock readout. When a clock readout is + * less than the previous we have had a wrap. This only works of `_lf_clock_now` + * is invoked at least once per epoch. + */ +int _lf_clock_now(instant_t* t) { + static uint32_t last_read_cycles=0; + uint32_t now_cycles = k_cycle_get_32(); + if (now_cycles < last_read_cycles) { + last_epoch_nsec += epoch_duration_nsec; + } + *t = (SECOND(1)/CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC)*now_cycles + last_epoch_nsec; + last_read_cycles = now_cycles; + return 0; +} + +/** + * Interruptable sleep is implemented using busy-waiting. + */ +int _lf_interruptable_sleep_until_locked(environment_t* env, instant_t wakeup) { + async_event=false; + + lf_critical_section_exit(env); + instant_t now; + do { + _lf_clock_now(&now); + } while ( (now -#include -#include - -// Combine 2 32-bit words to a 64-bit word -#define COMBINE_HI_LO(hi,lo) ((((uint64_t) hi) << 32) | ((uint64_t) lo)) - -// Keep track of overflows to keep clocks monotonic -static int64_t _lf_timer_epoch_duration_nsec; -static int64_t _lf_timer_epoch_duration_usec; -static uint32_t _lf_timer_max_ticks; -static volatile int64_t _lf_timer_last_epoch_nsec = 0; -static uint32_t _lf_timer_freq; - -#if defined(LF_ZEPHYR_CLOCK_HI_RES) -// Create semaphore for async wakeup from physical action -K_SEM_DEFINE(_lf_sem,0,1) - -static struct counter_alarm_cfg _lf_alarm_cfg; -const struct device *const _lf_counter_dev = DEVICE_DT_GET(LF_TIMER); -static volatile bool _lf_alarm_fired; - -// Timer overflow callback -static void _lf_timer_overflow_callback(const struct device *dev, void *user_data) { - _lf_timer_last_epoch_nsec += _lf_timer_epoch_duration_nsec; -} - -static void _lf_wakeup_alarm(const struct device *counter_dev, - uint8_t chan_id, uint32_t ticks, - void *user_data) -{ - _lf_alarm_fired=true; - k_sem_give(&_lf_sem); -} - -#endif // Keep track of nested critical sections -static uint32_t _lf_num_nested_critical_sections=0; -// Keep track of physical actions being entered into the system -static volatile bool _lf_async_event = false; +static uint32_t num_nested_critical_sections=0; // Keep track of IRQ mask when entering critical section so we can enable again after -static volatile unsigned _lf_irq_mask = 0; - -void _lf_initialize_clock() { - - #if defined(LF_ZEPHYR_CLOCK_HI_RES) - struct counter_top_cfg counter_top_cfg; - uint32_t counter_max_ticks=0; - int res; - LF_PRINT_LOG("Using High resolution Zephyr Counter. Initializing HW timer"); - - // Verify that we have the device - // FIXME: Try lf_print_error_and_exit? Or terminate in some way? Maybe return non-zero from this function - if (!device_is_ready(_lf_counter_dev)) { - lf_print_error_and_exit("ERROR: counter device not ready.\n"); - } - - // Verify that it is working as we think - if(!counter_is_counting_up(_lf_counter_dev)) { - lf_print_error_and_exit("ERROR: Timer is counting down \n"); - } - - // Get the frequency of the timer - _lf_timer_freq = counter_get_frequency(_lf_counter_dev); - - // Calculate the duration of an epoch. Compute both - // nsec and usec now at boot to avoid these computations later - _lf_timer_max_ticks = counter_get_max_top_value(_lf_counter_dev); - _lf_timer_epoch_duration_usec = counter_ticks_to_us(_lf_counter_dev, _lf_timer_max_ticks); - _lf_timer_epoch_duration_nsec = _lf_timer_epoch_duration_usec * 1000LL; - - // Set the max_top value to be the maximum - counter_top_cfg.ticks = _lf_timer_max_ticks; - counter_top_cfg.callback = _lf_timer_overflow_callback; - res = counter_set_top_value(_lf_counter_dev, &counter_top_cfg); - if (res != 0) { - lf_print_error_and_exit("ERROR: Timer couldnt set top value\n"); - } - - LF_PRINT_LOG("HW Clock has frequency of %u Hz and wraps every %u sec\n", _lf_timer_freq, _lf_timer_max_ticks/_lf_timer_freq); - - // Prepare the alarm config - _lf_alarm_cfg.flags = 0; - _lf_alarm_cfg.ticks = 0; - _lf_alarm_cfg.callback = _lf_wakeup_alarm; - _lf_alarm_cfg.user_data = &_lf_alarm_cfg; - - // Start counter - counter_start(_lf_counter_dev); - #else - LF_PRINT_LOG("Using Low resolution zephyr kernel clock"); - _lf_timer_freq = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; - LF_PRINT_LOG("Kernel Clock has frequency of %u Hz\n", _lf_timer_freq); - _lf_timer_last_epoch_nsec = 0; - // Compute the duration of an epoch. Compute both - // nsec and usec now at boot to avoid these computations later - _lf_timer_epoch_duration_nsec = ((1LL << 32) * SECONDS(1))/CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; - _lf_timer_epoch_duration_usec = _lf_timer_epoch_duration_nsec/1000; - #endif -} - -#if defined(LF_ZEPHYR_CLOCK_HI_RES) -// Clock and sleep implementation for the HI_RES clock based on -// Zephyrs Counter API - -/* Return the current time in nanoseconds. It gets the current value - * of the hi-res counter device and also keeps track of overflows - * to deliver a monotonically increasing clock. - */ -int _lf_clock_now(instant_t* t) { - uint32_t now_cycles; - int res; - uint64_t now_nsec; - - res = counter_get_value(_lf_counter_dev, &now_cycles); - now_nsec = counter_ticks_to_us(_lf_counter_dev, now_cycles)*1000ULL; - *t = now_nsec + _lf_timer_last_epoch_nsec; - return 0; -} - -int _lf_interruptable_sleep_until_locked(environment_t* env, instant_t wakeup) { - // Reset flags - _lf_alarm_fired = false; - _lf_async_event = false; - k_sem_reset(&_lf_sem); - - // Calculate the sleep duration - uint32_t now_cycles, sleep_duration_ticks; - counter_get_value(_lf_counter_dev, &now_cycles); - instant_t now; - _lf_clock_now(&now); - interval_t sleep_for_us = (wakeup - now)/1000; - - - while ( !_lf_async_event && - sleep_for_us > (LF_WAKEUP_OVERHEAD_US + LF_MIN_SLEEP_US) - ) { - if (sleep_for_us < _lf_timer_epoch_duration_usec) { - sleep_duration_ticks = counter_us_to_ticks(_lf_counter_dev, ((uint64_t) sleep_for_us) - LF_WAKEUP_OVERHEAD_US); - } else { - sleep_duration_ticks = UINT32_MAX; - } - - _lf_alarm_cfg.ticks = sleep_duration_ticks; - int err = counter_set_channel_alarm(_lf_counter_dev, LF_TIMER_ALARM_CHANNEL, &_lf_alarm_cfg); - - if (err != 0) { - lf_print_error_and_exit("Could not setup alarm for sleeping. Errno %i", err); - } - - lf_critical_section_exit(env); - k_sem_take(&_lf_sem, K_FOREVER); - lf_critical_section_enter(env); - - // Then calculating remaining sleep, unless we got woken up by an event - if (!_lf_async_event) { - _lf_clock_now(&now); - sleep_for_us = (wakeup - now)/1000; - } - } - - // Do remaining sleep in busy_wait - if (!_lf_async_event && - sleep_for_us > LF_RUNTIME_OVERHEAD_US) { - k_busy_wait((uint32_t) (sleep_for_us - LF_RUNTIME_OVERHEAD_US)); - } - - if (_lf_async_event) { - // Cancel the outstanding alarm - counter_cancel_channel_alarm(_lf_counter_dev, LF_TIMER_ALARM_CHANNEL); - _lf_async_event = false; - return -1; - } else { - return 0; - } -} -#else -// Clock and sleep implementation for LO_RES clock. Handle wraps -// by checking if two consecutive reads are monotonic -static uint32_t last_read_cycles=0; -int _lf_clock_now(instant_t* t) { - uint32_t now_cycles = k_cycle_get_32(); - - if (now_cycles < last_read_cycles) { - _lf_timer_last_epoch_nsec += _lf_timer_epoch_duration_nsec; - } - - *t = (SECOND(1)/CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC)*now_cycles + _lf_timer_last_epoch_nsec; - - last_read_cycles = now_cycles; - return 0; -} - -int _lf_interruptable_sleep_until_locked(environment_t* env, instant_t wakeup) { - _lf_async_event=false; - lf_critical_section_exit(env); - - instant_t now; - do { - _lf_clock_now(&now); - } while ( (now} */ @@ -31,52 +31,58 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef LF_ZEPHYR_BOARD_SUPPORT_H #define LF_ZEPHYR_BOARD_SUPPORT_H +// Default options +#define LF_ZEPHYR_THREAD_PRIORITY_DEFAULT 5 +#define LF_ZEPHYR_STACK_SIZE_DEFAULT 1024 -#if defined(CONFIG_SOC_FAMILY_NRF) - #define LF_ZEPHYR_CLOCK_HI_RES - #define LF_TIMER DT_NODELABEL(timer1) - #define LF_WAKEUP_OVERHEAD_US 100 - #define LF_MIN_SLEEP_US 10 - #define LF_RUNTIME_OVERHEAD_US 19 -#elif defined(CONFIG_BOARD_ATSAMD20_XPRO) - #define LF_TIMER DT_NODELABEL(tc4) - #define LF_ZEPHYR_CLOCK_HI_RES -#elif defined(CONFIG_SOC_FAMILY_SAM) - #define LF_TIMER DT_NODELABEL(tc0) - #define LF_ZEPHYR_CLOCK_HI_RES -#elif defined(CONFIG_COUNTER_MICROCHIP_MCP7940N) - #define LF_ZEPHYR_CLOCK_HI_RES - #define LF_TIMER DT_NODELABEL(extrtc0) -#elif defined(CONFIG_COUNTER_RTC0) - #define LF_ZEPHYR_CLOCK_HI_RES - #define LF_TIMER DT_NODELABEL(rtc0) -#elif defined(CONFIG_COUNTER_RTC_STM32) - #define LF_TIMER DT_INST(0, st_stm32_rtc) - #define LF_ZEPHYR_CLOCK_HI_RES -#elif defined(CONFIG_COUNTER_NATIVE_POSIX) - #define LF_ZEPHYR_CLOCK_LO_RES -#elif defined(CONFIG_COUNTER_XLNX_AXI_TIMER) - #define LF_TIMER DT_INST(0, xlnx_xps_timer_1_00_a) - #define LF_ZEPHYR_CLOCK_HI_RES -#elif defined(CONFIG_COUNTER_TMR_ESP32) - #define LF_TIMER DT_NODELABEL(timer0) - #define LF_ZEPHYR_CLOCK_HI_RES -#elif defined(CONFIG_COUNTER_MCUX_CTIMER) - #define LF_TIMER DT_NODELABEL(ctimer0) - #define LF_ZEPHYR_CLOCK_HI_RES -#elif defined(CONFIG_SOC_MIMXRT1176_CM7) - #define LF_TIMER DT_NODELABEL(gpt2) - #define LF_ZEPHYR_CLOCK_HI_RES -#else - #warning Using low-res Kernel timer because hi-res Counter timer is not ported yet for this board. - #define LF_ZEPHYR_CLOCK_LO_RES -#endif // BOARD - -#define FREQ_16MHZ 16000000 - - +// Unless the user explicitly asks for the kernel clock, then we use a counter +// clock because it is more precise. +#if !defined(LF_ZEPHYR_CLOCK_KERNEL) + #if defined(CONFIG_SOC_FAMILY_NRF) + #define LF_ZEPHYR_CLOCK_COUNTER + #define LF_TIMER DT_NODELABEL(timer1) + #define LF_WAKEUP_OVERHEAD_US 100 + #define LF_MIN_SLEEP_US 10 + #define LF_RUNTIME_OVERHEAD_US 19 + #elif defined(CONFIG_BOARD_ATSAMD20_XPRO) + #define LF_TIMER DT_NODELABEL(tc4) + #define LF_ZEPHYR_CLOCK_COUNTER + #elif defined(CONFIG_SOC_FAMILY_SAM) + #define LF_TIMER DT_NODELABEL(tc0) + #define LF_ZEPHYR_CLOCK_COUNTER + #elif defined(CONFIG_COUNTER_MICROCHIP_MCP7940N) + #define LF_ZEPHYR_CLOCK_COUNTER + #define LF_TIMER DT_NODELABEL(extrtc0) + #elif defined(CONFIG_COUNTER_RTC0) + #define LF_ZEPHYR_CLOCK_COUNTER + #define LF_TIMER DT_NODELABEL(rtc0) + #elif defined(CONFIG_COUNTER_RTC_STM32) + #define LF_TIMER DT_INST(0, st_stm32_rtc) + #define LF_ZEPHYR_CLOCK_COUNTER + #elif defined(CONFIG_COUNTER_XLNX_AXI_TIMER) + #define LF_TIMER DT_INST(0, xlnx_xps_timer_1_00_a) + #define LF_ZEPHYR_CLOCK_COUNTER + #elif defined(CONFIG_COUNTER_TMR_ESP32) + #define LF_TIMER DT_NODELABEL(timer0) + #define LF_ZEPHYR_CLOCK_COUNTER + #elif defined(CONFIG_COUNTER_MCUX_CTIMER) + #define LF_TIMER DT_NODELABEL(ctimer0) + #define LF_ZEPHYR_CLOCK_COUNTER + #elif defined(CONFIG_SOC_MIMXRT1176_CM7) + #define LF_TIMER DT_NODELABEL(gpt2) + #define LF_ZEPHYR_CLOCK_COUNTER + #else + // This board does not have support for the counter clock. If the user + // explicitly asked for this cock, then throw an error. + #if defined(LF_ZEPHYR_CLOCK_COUNTER) + #error "LF_ZEPHYR_CLOCK_COUNTER was requested but it is not supported by the board" + #else + #define LF_ZEPHYR_CLOCK_KERNEL + #endif + #endif // BOARD +#endif -#if defined(LF_ZEPHYR_CLOCK_HI_RES) +#if defined(LF_ZEPHYR_CLOCK_COUNTER) #ifndef LF_WAKEUP_OVERHEAD_US #define LF_WAKEUP_OVERHEAD_US 0 #endif @@ -93,9 +99,9 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define LF_TIMER_ALARM_CHANNEL 0 #endif #else - #if !defined(LF_ZEPHYR_CLOCK_LO_RES) + #if !defined(LF_ZEPHYR_CLOCK_KERNEL) #error Neither hi-res nor lo-res clock specified #endif -#endif // LF_ZEPHYR_CLOCK_HI_RES +#endif // LF_ZEPHYR_CLOCK_COUNTER #endif diff --git a/python/lib/pythontarget.c b/python/lib/pythontarget.c index 47baa685a..77dcdebcf 100644 --- a/python/lib/pythontarget.c +++ b/python/lib/pythontarget.c @@ -437,7 +437,7 @@ void destroy_action_capsule(PyObject* capsule) { PyObject* convert_C_port_to_py(void* port, int width) { // Create the port struct in Python PyObject* cap = - (PyObject*)PyObject_GC_New(generic_port_capsule_struct, &py_port_capsule_t); + (PyObject*)PyObject_New(generic_port_capsule_struct, &py_port_capsule_t); if (cap == NULL) { lf_print_error_and_exit("Failed to convert port."); } @@ -506,7 +506,7 @@ PyObject* convert_C_action_to_py(void* action) { trigger_t* trigger = ((lf_action_base_t*)action)->trigger; // Create the action struct in Python - PyObject* cap = (PyObject*)PyObject_GC_New(generic_action_capsule_struct, &py_action_capsule_t); + PyObject* cap = (PyObject*)PyObject_New(generic_action_capsule_struct, &py_action_capsule_t); if (cap == NULL) { lf_print_error_and_exit("Failed to convert action."); }