Skip to content

Commit

Permalink
Merge branch 'main' into python-11
Browse files Browse the repository at this point in the history
  • Loading branch information
cmnrd committed Jul 26, 2023
2 parents c0d4be3 + 586a98f commit ac9ba76
Show file tree
Hide file tree
Showing 10 changed files with 280 additions and 19 deletions.
7 changes: 7 additions & 0 deletions core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ if(DEFINED FEDERATED_AUTHENTICATED)
target_link_libraries(core PUBLIC OpenSSL::SSL)
endif()

if(DEFINED _LF_CLOCK_SYNC_ON)
find_library(MATH_LIBRARY m)
if(MATH_LIBRARY)
target_link_libraries(core PUBLIC ${MATH_LIBRARY})
endif()
endif()

# Link with thread library
if(DEFINED LF_THREADED OR DEFINED LF_TRACE)
find_package(Threads REQUIRED)
Expand Down
7 changes: 3 additions & 4 deletions core/federated/federate.c
Original file line number Diff line number Diff line change
Expand Up @@ -2031,20 +2031,19 @@ void handle_tagged_message(int socket, int fed_id) {
// Before that, if the current time >= stop time, discard the message.
// But only if the stop time is not equal to the start time!
if (lf_tag_compare(env->current_tag, env->stop_tag) >= 0) {
lf_mutex_unlock(&env->mutex);
lf_print_error("Received message too late. Already at stop tag.\n"
"Current tag is " PRINTF_TAG " and intended tag is " PRINTF_TAG ".\n"
"Discarding message.",
env->current_tag.time - start_time, env->current_tag.microstep,
intended_tag.time - start_time, intended_tag.microstep);
return;
goto release;
}

LF_PRINT_LOG("Calling schedule with tag " PRINTF_TAG ".", intended_tag.time - start_time, intended_tag.microstep);
schedule_message_received_from_network_locked(env, action->trigger, intended_tag, message_token);
}


release:
#ifdef FEDERATED_DECENTRALIZED // Only applicable for federated programs with decentralized coordination
// Finally, decrement the barrier to allow the execution to continue
// past the raised barrier
Expand Down Expand Up @@ -2333,7 +2332,7 @@ void handle_stop_granted_message() {
env[i].stop_tag.time - start_time,
env[i].stop_tag.microstep);

_lf_decrement_tag_barrier_locked(&env[i]);
if (env[i].barrier.requestors) _lf_decrement_tag_barrier_locked(&env[i]);
// We signal instead of broadcast under the assumption that only
// one worker thread can call wait_until at a given time because
// the call to wait_until is protected by a mutex lock
Expand Down
3 changes: 3 additions & 0 deletions core/platform/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ lf_macos_support.c
lf_windows_support.c
lf_nrf52_support.c
lf_zephyr_support.c
lf_rp2040_support.c
)

if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
Expand All @@ -18,6 +19,8 @@ elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Nrf52")
target_compile_definitions(core PUBLIC PLATFORM_NRF52)
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Zephyr")
target_compile_definitions(core PUBLIC PLATFORM_ZEPHYR)
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Rp2040")
target_compile_definitions(core PUBLIC PLATFORM_RP2040)
endif()

# Add sources to the list for debug info
Expand Down
3 changes: 3 additions & 0 deletions core/platform/Platform.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
message("Using Windows SDK version ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}")
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Zephyr")
set(LF_PLATFORM_FILE lf_zephyr_support.c)
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Rp2040")
message("Using pico-sdk for RP2040 target")
set(LF_PLATFORM_FILE lf_rp2040_support.c)
else()
message(FATAL_ERROR "Your platform is not supported! The C target supports Linux, MacOS and Windows.")
endif()
220 changes: 220 additions & 0 deletions core/platform/lf_rp2040_support.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
#if defined(PLATFORM_RP2040)
/*************
Copyright (c) 2022, The University of California at Berkeley.
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 RP2040 mcu support for the C target of Lingua Franca.
* This utilizes the pico-sdk which provides C methods for a light runtime
* and a hardware abstraction layer.
*
* @author{Abhi Gundrala <gundralaa@berkeley.edu>}
*/

#include "lf_rp2040_support.h"
#include "platform.h"
#include "utils/util.h"
#include "tag.h"

#include <pico/stdlib.h>
#include <pico/multicore.h>
#include <pico/sync.h>

/**
* critical section struct
* disables external irq and core execution
* provides mutual exclusion using hardware spin-locks
*/
static critical_section_t _lf_crit_sec;

/**
* binary semaphore for lf event notification
* used by external isr or second core thread.
* used to interact with the lf runtime thread
*/
static semaphore_t _lf_sem_irq_event;

// nested critical section counter
static uint32_t _lf_num_nested_crit_sec = 0;

/**
* Initialize basic runtime infrastructure and
* synchronization structs for an unthreaded runtime.
*/
void _lf_initialize_clock(void) {
// init stdio lib
stdio_init_all();
// init sync structs
critical_section_init(&_lf_crit_sec);
sem_init(&_lf_sem_irq_event, 0, 1);
}

/**
* Write the time since boot in nanoseconds into
* the time variable pointed to by the argument
* and return 0.
*
* @param t pointer to the time variable to write to.
* @return error code or 0 on success.
*/
int _lf_clock_now(instant_t* t) {
if (!t) {
return -1;
}
// time struct
absolute_time_t now;
uint64_t ns_from_boot;

now = get_absolute_time();
ns_from_boot = to_us_since_boot(now) * 1000;
*t = (instant_t) ns_from_boot;
return 0;
}

/**
* Pause execution of the calling core for
* a nanosecond duration specified by the argument.
* Floor the specified duration to the nearest microsecond
* duration before sleeping and return 0.
*
* @param sleep_duration time to sleep in nanoseconds
* @return error code or 0 on success
*/
int lf_sleep(interval_t sleep_duration) {
if (sleep_duration < 0) {
return -1;
}
sleep_us((uint64_t) (sleep_duration / 1000));
return 0;
}

/**
* Sleep until the target time since boot in nanoseconds provided
* by the argument or return early if the binary
* _lf_sem_irq_event semaphore is released before the target time.
*
* The semaphore is released using the _lf_unthreaded_notify_of_event
* which is called by lf_schedule in the unthreaded runtime for physical actions.
*
* @param env pointer to environment struct this runs in.
* @param wakeup_time time in nanoseconds since boot to sleep until.
* @return -1 when interrupted or 0 on successful timeout
*/
int _lf_interruptable_sleep_until_locked(environment_t* env, instant_t wakeup_time) {
int ret_code = 0;
// return immediately
if (wakeup_time < 0) {
return ret_code;
}
// time struct
absolute_time_t target;

// reset event semaphore
sem_reset(&_lf_sem_irq_event, 0);
// create us boot wakeup time
target = from_us_since_boot((uint64_t) (wakeup_time / 1000));
// allow interrupts
lf_critical_section_exit(env);
// blocked sleep
// return on timeout or on processor event
if(sem_acquire_block_until(&_lf_sem_irq_event, target)) {
ret_code = -1;
}
// remove interrupts
lf_critical_section_enter(env);
return ret_code;
}

#ifdef LF_UNTHREADED
/**
* The single thread RP2040 platform support treats second core
* routines similar to external interrupt routine threads.
*
* Second core activity is disabled at the same times as
* when interrupts are disabled.
*/

/**
* Enter a critical section where the second core is disabled
* and interrupts are disabled. Enter only if the critical section
* hasn't previously been entered.
*
* @return error code or 0 on success
*/
int lf_disable_interrupts_nested() {
if (!critical_section_is_initialized(&_lf_crit_sec)) {
return 1;
}
// check crit sec count
// enter non-rentrant state by disabling interrupts
// lock second core execution
if (_lf_num_nested_crit_sec == 0) {
// block if associated spin lock in use
critical_section_enter_blocking(&_lf_crit_sec);
}
// add crit sec count
_lf_num_nested_crit_sec++;
return 0;
}

/**
* Exit a critical section which will resume second core
* execution and enable interrupts.
* Exit only if no other critical sections are left to exit.
*
* @return error code or 0 on success
*/
int lf_enable_interrupts_nested() {
if (!critical_section_is_initialized(&_lf_crit_sec) ||
_lf_num_nested_crit_sec <= 0) {
return 1;
}
// remove from crit sec count
_lf_num_nested_crit_sec--;
// check crit sec count
// release spin-lock
if (_lf_num_nested_crit_sec == 0) {
critical_section_exit(&_lf_crit_sec);
}
return 0;
}

/**
* Release the binary event semaphore to notify
* the runtime of a physical action being scheduled.
*
* @return error code or 0 on success
*/
int _lf_unthreaded_notify_of_event() {
// notify main sleep loop of event
sem_release(&_lf_sem_irq_event);
return 0;
}
#endif //LF_UNTHREADED

#ifdef LF_THREADED
#error "Threading for baremetal RP2040 not supported"
#endif //LF_THREADED

#endif // PLATFORM_RP2040

14 changes: 7 additions & 7 deletions core/utils/semaphore.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Create a new semaphore.
*
* @param count The count to start with.
* @return semaphore_t* Can be NULL on error.
* @return lf_semaphore_t* Can be NULL on error.
*/
semaphore_t* lf_semaphore_new(int count) {
semaphore_t* semaphore = (semaphore_t*)malloc(sizeof(semaphore_t));
lf_semaphore_t* lf_semaphore_new(int count) {
lf_semaphore_t* semaphore = (lf_semaphore_t*)malloc(sizeof(lf_semaphore_t));
lf_mutex_init(&semaphore->mutex);
lf_cond_init(&semaphore->cond, &semaphore->mutex);
semaphore->count = count;
Expand All @@ -54,7 +54,7 @@ semaphore_t* lf_semaphore_new(int count) {
* @param semaphore Instance of a semaphore
* @param i The count to add.
*/
void lf_semaphore_release(semaphore_t* semaphore, int i) {
void lf_semaphore_release(lf_semaphore_t* semaphore, int i) {
assert(semaphore != NULL);
lf_mutex_lock(&semaphore->mutex);
semaphore->count += i;
Expand All @@ -67,7 +67,7 @@ void lf_semaphore_release(semaphore_t* semaphore, int i) {
*
* @param semaphore Instance of a semaphore.
*/
void lf_semaphore_acquire(semaphore_t* semaphore) {
void lf_semaphore_acquire(lf_semaphore_t* semaphore) {
assert(semaphore != NULL);
lf_mutex_lock(&semaphore->mutex);
while (semaphore->count == 0) {
Expand All @@ -82,7 +82,7 @@ void lf_semaphore_acquire(semaphore_t* semaphore) {
*
* @param semaphore Instance of a semaphore.
*/
void lf_semaphore_wait(semaphore_t* semaphore) {
void lf_semaphore_wait(lf_semaphore_t* semaphore) {
assert(semaphore != NULL);
lf_mutex_lock(&semaphore->mutex);
while (semaphore->count == 0) {
Expand All @@ -96,7 +96,7 @@ void lf_semaphore_wait(semaphore_t* semaphore) {
*
* @param semaphore Instance of a semaphore.
*/
void lf_semaphore_destroy(semaphore_t* semaphore) {
void lf_semaphore_destroy(lf_semaphore_t* semaphore) {
assert(semaphore != NULL);
free(semaphore);
}
Expand Down
2 changes: 2 additions & 0 deletions include/core/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ int lf_critical_section_exit(environment_t* env);
#include "platform/lf_zephyr_support.h"
#elif defined(PLATFORM_NRF52)
#include "platform/lf_nrf52_support.h"
#elif defined(PLATFORM_RP2040)
#include "platform/lf_rp2040_support.h"
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
// Windows platforms
#include "lf_windows_support.h"
Expand Down
27 changes: 27 additions & 0 deletions include/core/platform/lf_rp2040_support.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* RP2040 API support for the C target of Lingua Franca */

/**
* @brief pico support for reactor-c
*/

#ifndef LF_RP2040_SUPPORT_H
#define LF_RP2040_SUPPORT_H

#include <pico/stdlib.h>
#include <pico/sync.h>

#define NO_TTY

// Defines for formatting time in printf for pico
#define PRINTF_TAG "(" PRINTF_TIME ", " PRINTF_MICROSTEP ")"
#define PRINTF_TIME "%lld"
#define PRINTF_MICROSTEP "%d"

#define LF_TIME_BUFFER_LENGTH 80
#define _LF_TIMEOUT 1

#ifdef LF_THREADED
#error "Threading for baremetal RP2040 not supported"
#endif // LF_THREADED

#endif // LF_PICO_SUPPORT_H
2 changes: 1 addition & 1 deletion include/core/threaded/scheduler_instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ typedef struct lf_scheduler_t {
*
* FIXME: specific comment
*/
semaphore_t* semaphore;
lf_semaphore_t* semaphore;

/**
* @brief Indicate whether the program should stop
Expand Down
Loading

0 comments on commit ac9ba76

Please sign in to comment.