Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Platform support for Embedded targets #106

Merged
merged 124 commits into from
Dec 21, 2022
Merged
Show file tree
Hide file tree
Changes from 115 commits
Commits
Show all changes
124 commits
Select commit Hold shift + click to select a range
15690bb
Added lock functions to use for unthreaded execution
edwardalee Aug 20, 2022
bdd3c1f
Moved comment to where it belongs
edwardalee Aug 20, 2022
6726fc9
Renamed functions (see Zulip)
edwardalee Aug 20, 2022
6c7e6c6
Work in progress toward moving critical section code into reactor_com…
lhstrh Sep 2, 2022
b70632c
Add file I forgot to check in
lhstrh Sep 2, 2022
b683e61
Get single-threaded build to work on Linux.
petervdonovan Sep 2, 2022
f77809e
Got to the point where Minimal compiles on Linux
lhstrh Sep 2, 2022
60304ce
Moving more functions into reactor_common.c
lhstrh Sep 2, 2022
cab3647
Treat the event queue as a critical section in reactor.c
lhstrh Sep 3, 2022
3faaad8
Silly workaround to get RTI to build again
lhstrh Sep 3, 2022
23673f0
Fix type error in POSIX thread support
lhstrh Sep 3, 2022
2994d08
Added implementations of critical section code for single-threaded Ar…
arengarajan99 Sep 3, 2022
ad619dd
Attempt to fix compilation issue
lhstrh Sep 3, 2022
44663da
Another fix
lhstrh Sep 3, 2022
bd20b2d
More tinkering with const keyword
lhstrh Sep 3, 2022
d23bd40
More tinkering with const keyword
lhstrh Sep 3, 2022
b2ddd98
Address more compilation issues
lhstrh Sep 3, 2022
922fe32
Update signatures of implementations
lhstrh Sep 3, 2022
ac0a936
Debugging serialization tests
lhstrh Sep 3, 2022
d5074cd
More const char * nonsense.
Sep 4, 2022
2ce7bd0
More const char * nonsense.
Sep 4, 2022
c8d6a17
More const char * nonsense.
Sep 4, 2022
7a6559c
Address failing tracing tests.
Sep 4, 2022
9729715
Address test failures on Windows.
petervdonovan Sep 4, 2022
1760bce
Fix races on Windows.
petervdonovan Sep 4, 2022
a7d2029
Make sure that if sleep is interrupted, we check the event queue to m…
lhstrh Sep 8, 2022
12cc014
Cleanup
lhstrh Sep 8, 2022
2749db8
Have ack events function instead of init critical section
lhstrh Sep 8, 2022
3607d67
Add missing implementation
lhstrh Sep 8, 2022
03ee757
Update lingua-franca-ref
lhstrh Sep 8, 2022
9901a5c
Comments and compile-time check
lhstrh Sep 8, 2022
3e1b8e7
Minor bug fix
lhstrh Sep 8, 2022
7ee7106
Refactoring to make the behavior of the function formerly known as lf…
lhstrh Sep 9, 2022
f65a562
Remove spurious text
lhstrh Sep 9, 2022
c0c8ab2
Fix another refactoring issue
lhstrh Sep 9, 2022
3798a3e
Update Lingua Franca ref
lhstrh Sep 9, 2022
e8bf66a
Update core/federated/net_util.c
lhstrh Sep 9, 2022
cbd9c2c
Fixes to concurrency bugs
lhstrh Sep 11, 2022
b38adba
Bring back lf_nanosleep as deprecated function
lhstrh Sep 11, 2022
6360b3b
Update docs of lf_nanosleep
lhstrh Sep 11, 2022
527959b
Changes vetted in experimentation with buckler/nrf52
lhstrh Sep 12, 2022
3c13193
Add declaration in platform.h
lhstrh Sep 12, 2022
a1e34da
Remove options for using 32bit precision and us resolution.
Sep 22, 2022
fbcbb6f
Check critical section before going to sleep
erlingrj Sep 24, 2022
9d5e2e4
First implementation of 64bit support for Arduino
erlingrj Sep 27, 2022
e1d8cda
Updated Arduino AVR constraints for Compilation
arengarajan99 Sep 29, 2022
0a3df59
Merge from Main Branch
arengarajan99 Sep 30, 2022
a7fd4aa
Fix mistake in lf_sleep_until
erlingrj Oct 1, 2022
672562c
Eliminate Arduino CMake dependency
arengarajan99 Oct 12, 2022
e92a153
Port changes from lf-buckler/platform/reactor.c
lhstrh Nov 4, 2022
2947e9e
Changes to reactor.c
lhstrh Dec 1, 2022
8521421
Added new NRF52 platform files.
lhstrh Dec 1, 2022
8711abd
Merge master into lock-time
lhstrh Dec 1, 2022
a4d822d
Remove stray conflict marker
lhstrh Dec 1, 2022
4e4f8f1
Remove extern definitions
lhstrh Dec 1, 2022
c48b3ad
Get threaded unit tests to compile.
petervdonovan Dec 1, 2022
8b1c518
Remove more stray merge makers
lhstrh Dec 1, 2022
d3a8f21
Get RTI to compile.
petervdonovan Dec 1, 2022
8b77ac7
Simplify Linux and macOS .c files.
petervdonovan Dec 1, 2022
468a5f4
Add Linux implementation for lf_sleep_until
lhstrh Dec 1, 2022
4638f21
Remove debug prints
lhstrh Dec 1, 2022
7b9b20f
Try to fix failing tests due to mutex and cond_var
erlingrj Dec 2, 2022
a0a15ad
Merge in strictly-nsec-64bit
erlingrj Dec 2, 2022
3e7e3f9
Small Arduino fixes
erlingrj Dec 2, 2022
102fc00
Fix Windows mutex/cond declaration issue
erlingrj Dec 2, 2022
488f6fd
Update comment about platforms
erlingrj Dec 2, 2022
d7797e8
Move mutex/cond definition var to platform support file
erlingrj Dec 2, 2022
3d96c9b
Remove mutex/cond from rti
erlingrj Dec 2, 2022
b05a5d7
Add compile flags for NRF52 and ARDUINO
erlingrj Dec 2, 2022
31db8a4
Move extern mutex/cond to platform
erlingrj Dec 2, 2022
2dba94b
lf_sleep_until on macos
erlingrj Dec 2, 2022
7c143d8
Fix duplicate code dealing with next_tag > stop_tag
erlingrj Dec 2, 2022
23526a0
Move mutexes and critical section out of thread lib headers
erlingrj Dec 3, 2022
4fdf264
Add lf_sleep_until to windows support
erlingrj Dec 3, 2022
b01ef8e
Fix mistake in windows support file
erlingrj Dec 3, 2022
a54a2e9
Include tag.h in support files to get USEC macro
erlingrj Dec 3, 2022
a7fb005
Update LF ref
erlingrj Dec 4, 2022
85ff383
Adding CI snippet to get SSH access
erlingrj Dec 5, 2022
d6e682d
Fix CI ssh
erlingrj Dec 6, 2022
09f336d
Fix CI ssh
erlingrj Dec 6, 2022
25dc3a6
Add SSH workflow
erlingrj Dec 6, 2022
192be4a
Add SSH workflow
erlingrj Dec 6, 2022
8bc911b
Add SSH workflow
erlingrj Dec 6, 2022
4614ec1
Add SSH workflow
erlingrj Dec 6, 2022
116d7ae
CI SSH
erlingrj Dec 6, 2022
0f00fc3
Add SSH workflow
erlingrj Dec 6, 2022
254c3cf
Move mutex and cond_var out of platform support files
erlingrj Dec 10, 2022
f4dfb63
Revert changes. mutex and cond var in reactor_threaded again
erlingrj Dec 10, 2022
7c09642
Reverted too much
erlingrj Dec 10, 2022
87aa018
The mutex and cond var must be defnied in rti also
erlingrj Dec 10, 2022
aa0efcb
Solve mutex/cond_var with indirection
erlingrj Dec 10, 2022
5f11544
Remove SSH stuff
erlingrj Dec 11, 2022
4d53c40
Have trace.c see another version of platform support files to enable …
erlingrj Dec 11, 2022
475235e
RTI sets LF_MULTI_THREADED flag
erlingrj Dec 11, 2022
dc77d20
Fix unit flags passed to unit tests
erlingrj Dec 11, 2022
446f0c8
Fix unit tests cmake args again
erlingrj Dec 11, 2022
640e69f
Rename some flags
erlingrj Dec 11, 2022
46329ef
Typo
erlingrj Dec 11, 2022
e96fddf
Set the LF_THREADED when building RTI
erlingrj Dec 11, 2022
0fd8fba
Fix some typos
erlingrj Dec 11, 2022
b30684a
Fix unit tests
erlingrj Dec 11, 2022
f1bcdc4
Apply suggestions from code review
lhstrh Dec 11, 2022
4754267
Move windows threading impl into the header-file
erlingrj Dec 11, 2022
22406e3
Merge branch 'lock-time' of https://github.com/lf-lang/reactor-c into…
erlingrj Dec 11, 2022
c8b03e3
Fix windows typo
erlingrj Dec 11, 2022
7057436
Remove old SSH CI file
erlingrj Dec 11, 2022
049aa99
Hack more at the windows support
erlingrj Dec 11, 2022
4109b8d
More fixes
erlingrj Dec 11, 2022
8ca3d0f
More windows
erlingrj Dec 11, 2022
b6d3a0e
Make windows platform API static since it is defined in headers
erlingrj Dec 11, 2022
56d0cbc
Apply suggestions from code review
erlingrj Dec 15, 2022
847b7ce
Address Edwards feedback on the Arduino support
erlingrj Dec 15, 2022
8361765
Add code-review feedback
erlingrj Dec 15, 2022
e0ea9a6
Merge branch 'lock-time' of https://github.com/lf-lang/reactor-c into…
erlingrj Dec 15, 2022
a91f605
Update include/core/platform.h
erlingrj Dec 15, 2022
ea29aad
Apply suggestions from Marten
erlingrj Dec 19, 2022
70a8f77
Rename nested critical section variable
erlingrj Dec 19, 2022
af73a48
Merge branch 'main' into lock-time
lhstrh Dec 21, 2022
6369aa9
Update pointer to lf
erlingrj Dec 21, 2022
becb567
Apply suggestions from code review
erlingrj Dec 21, 2022
8962371
Add comment on empty critical section impl in os unthreaded
erlingrj Dec 21, 2022
c58b354
Update trace macro
erlingrj Dec 21, 2022
073f175
Update lf-ref
erlingrj Dec 21, 2022
965e9b2
update lf ref
erlingrj Dec 21, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,24 @@ jobs:
unit-tests-single:
uses: lf-lang/reactor-c/.github/workflows/unit-tests.yml@main
with:
cmake-args: '-UNUMBER_OF_WORKERS'
cmake-args: '-UNUMBER_OF_WORKERS -DLF_UNTHREADED=1'

unit-tests-multi:
uses: lf-lang/reactor-c/.github/workflows/unit-tests.yml@main
with:
cmake-args: '-DNUMBER_OF_WORKERS=4'
cmake-args: '-DNUMBER_OF_WORKERS=4 -DLF_THREADED=1'

fetch-lf:
uses: lf-lang/lingua-franca/.github/workflows/extract-ref.yml@master
with:
file: 'lingua-franca-ref.txt'

# lf-ssh:
# needs: fetch-lf
# uses: lf-lang/reactor-c/.github/workflows/ssh.yml@main
# with:
# runtime-ref: ${{ github.ref }}
# compiler-ref: ${{ needs.fetch-lf.outputs.ref }}

lf-default:
needs: fetch-lf
Expand Down
4 changes: 3 additions & 1 deletion core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ define(FEDERATED_DECENTRALIZED)
define(FEDERATED)
define(LF_REACTION_GRAPH_BREADTH)
define(LINGUA_FRANCA_TRACE)
define(LF_THREADED)
define(LF_UNTHREADED)
define(LOG_LEVEL)
define(MODAL_REACTORS)
define(NUMBER_OF_FEDERATES)
Expand Down Expand Up @@ -89,7 +91,7 @@ target_include_directories(core PUBLIC ../include/core/modal_models)
target_include_directories(core PUBLIC ../include/core/threaded)
target_include_directories(core PUBLIC ../include/core/utils)

if(DEFINED NUMBER_OF_WORKERS OR DEFINED LINGUA_FRANCA_TRACE)
if(DEFINED LF_THREADED OR DEFINED LINGUA_FRANCA_TRACE)
find_package(Threads REQUIRED)
target_link_libraries(core PUBLIC Threads::Threads)
endif()
5 changes: 3 additions & 2 deletions core/federated/RTI/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ include_directories(${IncludeDir}/modal_models)
include_directories(${IncludeDir}/platform)
include_directories(${IncludeDir}/utils)


# Declare a new executable target and list all its sources
add_executable(
RTI
Expand All @@ -67,8 +68,8 @@ IF(CMAKE_BUILD_TYPE MATCHES DEBUG)
target_compile_definitions(RTI PUBLIC LOG_LEVEL=4)
ENDIF(CMAKE_BUILD_TYPE MATCHES DEBUG)

# Set the number of workers to enable threading
target_compile_definitions(RTI PUBLIC NUMBER_OF_WORKERS)
# Set LF_THREADING to get the threaded support
target_compile_definitions(RTI PUBLIC LF_THREADED=1)

# Find threads and link to it
find_package(Threads REQUIRED)
Expand Down
11 changes: 6 additions & 5 deletions core/federated/net_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,7 @@ void encode_tag(
* Checks if str matches regex.
* @return true if there is a match, false otherwise.
*/
bool match_regex(char* str, char* regex) {
bool match_regex(const char* str, char* regex) {
regex_t regex_compiled;
regmatch_t group;
bool valid = false;
Expand Down Expand Up @@ -617,7 +617,7 @@ bool validate_port(char* port) {
* Checks if host is valid.
* @return true if valid, false otherwise.
*/
bool validate_host(char* host) {
bool validate_host(const char* host) {
// regex taken from LFValidator.xtend
char* ipv4_regex = "((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])";
char* host_or_FQN_regex = "^([a-z0-9]+(-[a-z0-9]+)*)|(([a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,})$";
Expand All @@ -629,7 +629,7 @@ bool validate_host(char* host) {
* Checks if user is valid.
* @return true if valid, false otherwise.
*/
bool validate_user(char* user) {
bool validate_user(const char* user) {
// regex taken from LFValidator.xtend
char* username_regex = "^[a-z_]([a-z0-9_-]{0,31}|[a-z0-9_-]{0,30}\\$)$";
return match_regex(user, username_regex);
Expand All @@ -639,7 +639,8 @@ bool validate_user(char* user) {
* Extract one match group from the rti_addr regex .
* @return true if SUCCESS, else false.
*/
bool extract_match_group(const char* rti_addr, char* dest, regmatch_t group, int max_len, int min_len, const char* err_msg) {
bool extract_match_group(const char* rti_addr, char* dest, regmatch_t group,
int max_len, int min_len, const char* err_msg) {
size_t size = group.rm_eo - group.rm_so;
if (size > max_len || size < min_len) {
lf_print_error("%s", err_msg);
Expand All @@ -655,7 +656,7 @@ bool extract_match_group(const char* rti_addr, char* dest, regmatch_t group, int
* @return true if success, else false.
*/
bool extract_match_groups(const char* rti_addr, char** rti_addr_strs, bool** rti_addr_flags, regmatch_t* group_array,
int* gids, int* max_lens, int* min_lens, const char** err_msgs) {
int* gids, int* max_lens, int* min_lens, const char** err_msgs) {
for (int i = 0; i < 3; i++) {
if (group_array[gids[i]].rm_so != -1) {
if (!extract_match_group(rti_addr, rti_addr_strs[i], group_array[gids[i]], max_lens[i], min_lens[i], err_msgs[i])) {
Expand Down
6 changes: 5 additions & 1 deletion core/platform/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@ elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
message("Using Windows SDK version ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}")
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Arduino")
set(LF_PLATFORM_FILES lf_arduino_support.c)
add_compile_definitions(PUBLIC PLATFORM_ARDUINO)
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Nrf52")
set(LF_PLATFORM_FILES lf_nrf52_support.c)
add_compile_definitions(PUBLIC PLATFORM_NRF52)
else()
message(FATAL_ERROR "Your platform is not supported! The C target supports Linux, MacOS, Windows, and Arduino.")
message(FATAL_ERROR "Your platform is not supported! The C target supports Linux, MacOS, Windows, Arduino and Nrf52.")
endif()

set(GENERAL_SOURCES ${LF_PLATFORM_FILES})
Expand Down
3 changes: 0 additions & 3 deletions core/platform/Platform.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
set(LF_PLATFORM_FILE lf_windows_support.c)
set(CMAKE_SYSTEM_VERSION 10.0)
message("Using Windows SDK version ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}")
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Arduino")
set(LF_PLATFORM_FILE lf_arduino_support.c)
message("Using Arduino CMake")
else()
message(FATAL_ERROR "Your platform is not supported! The C target supports Linux, MacOS and Windows.")
endif()
249 changes: 167 additions & 82 deletions core/platform/lf_arduino_support.c
Original file line number Diff line number Diff line change
@@ -1,82 +1,167 @@
/* Arduino Platform API support for the C target of Lingua Franca. */

/*************
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.
***************/

/** Arduino API support for the C target of Lingua Franca.
*
* @author{Anirudh Rengarajan <arengarajan@berkeley.edu>}
*/


#include <time.h>
#include <errno.h>

#include "lf_arduino_support.h"
#include "platform.h"
#include "Arduino.h"

/**
* Pause execution for a number of microseconds.
*
* This function works very accurately in the range from 3 to 16383 microseconds.
* We cannot assure that delayMicroseconds will perform precisely for smaller delay-times.
* Larger delay times may actually delay for an extremely brief time.
*
* @return 0 always.
*/
int lf_nanosleep(instant_t requested_time) {
unsigned int microsec = (unsigned int) requested_time;
if(microsec < 3) {
return 0;
}
else if(microsec <= 16383) {
delayMicroseconds(microsec);
}
else {
delay(microsec / 1000);
}
return 0;
}

/**
* Initialize the LF clock. Arduino auto-initializes its clock, so we don't do anything.
*/
void lf_initialize_clock() {}

/**
* Fetch the value of _LF_CLOCK (see lf_arduino_support.h) and store it in t. The
* timestamp value in 't' will be physical Arduino time in microseconds,
* which starts once Arduino boots up.
*
* @return 0 for success, or -1 for failure. In case of failure, errno will be
* set appropriately.
*/
int lf_clock_gettime(instant_t* t) {

if (t == NULL) {
// The t argument address references invalid memory
errno = EFAULT;
return -1;
}

*t = micros();
return 0;
}
/* Arduino Platform API support for the C target of Lingua Franca. */

/*************
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.
***************/

/** Arduino API support for the C target of Lingua Franca.
lhstrh marked this conversation as resolved.
Show resolved Hide resolved
*
* @author{Anirudh Rengarajan <arengarajan@berkeley.edu>}
* @author{Erling Rennemo Jellum <erling.r.jellum@ntnu.no>}
*/


#include <time.h>
#include <errno.h>

#include "lf_arduino_support.h"
#include "../platform.h"
#include "Arduino.h"

// Combine 2 32bit values into a 64bit
#define COMBINE_HI_LO(hi,lo) ((((uint64_t) hi) << 32) | ((uint64_t) lo))

// Keep track of physical actions being entered into the system
static volatile bool _lf_async_event = false;
// Keep track of whether we are in a critical section or not
static volatile int _lf_in_critical_section = 0;
erlingrj marked this conversation as resolved.
Show resolved Hide resolved

/**
* Global timing variables:
* Since Arduino is 32bit, we need to also maintain the 32 higher bits.

* _lf_time_us_high is incremented at each overflow of 32bit Arduino timer.
* _lf_time_us_low_last is the last value we read from the 32 bit Arduino timer.
* We can detect overflow by reading a value that is lower than this.
* This does require us to read the timer and update this variable at least once per 35 minutes.
* This is not an issue when we do a busy-sleep. If we go to HW timer sleep we would want to register an interrupt
* capturing the overflow.

*/
static volatile uint32_t _lf_time_us_high = 0;
static volatile uint32_t _lf_time_us_low_last = 0;

/**
* @brief Sleep until an absolute time.
* TODO: For improved power consumption this should be implemented with a HW timer and interrupts.
*
* @param wakeup int64_t time of wakeup
* @return int 0 if successful sleep, -1 if awoken by async event
*/
int lf_sleep_until(instant_t wakeup) {
instant_t now;
_lf_async_event = false;
lf_critical_section_exit();

// Do busy sleep
do {
lf_clock_gettime(&now);
} while ((now < wakeup) && !_lf_async_event);

lf_critical_section_enter();

if (_lf_async_event) {
lf_ack_events();
return -1;
} else {
return 0;
}

}

/**
* @brief Sleep for a specified duration.

erlingrj marked this conversation as resolved.
Show resolved Hide resolved
*
* @param sleep_duration int64_t nanoseconds representing the desired sleep duration
* @return int 0 if success. -1 if interrupted by async event.
*/
int lf_sleep(interval_t sleep_duration) {
instant_t now;
lf_clock_gettime(&now);
instant_t wakeup = now + sleep_duration;

return lf_sleep_until(wakeup);

}

/**
* Initialize the LF clock. Arduino auto-initializes its clock, so we don't do anything.
*/
void lf_initialize_clock() {}

/**
* Write the current time in nanoseconds into the location given by the argument.
* This returns 0 (it never fails, assuming the argument gives a valid memory location).
* This has to be called at least once per 35 minutes to properly handle overflows of the 32-bit clock.
* TODO: This is only addressable by setting up interrupts on a timer peripheral to occur at wrap.
*/
int lf_clock_gettime(instant_t* t) {

assert(t != NULL);

uint32_t now_us_low = micros();

// Detect whether overflow has occured since last read
// TODO: This assumes that we lf_clock_gettime is called at least once per overflow
if (now_us_low < _lf_time_us_low_last) {
_lf_time_us_high++;
}

*t = COMBINE_HI_LO(_lf_time_us_high, now_us_low) * 1000ULL;
return 0;
}

/**
* Enter a critical section by disabling interrupts, supports
* nested critical sections.
*/
int lf_critical_section_enter() {
if (_lf_in_critical_section++ == 0) {
// First nested entry into a critical section.
// If interrupts are not initially enabled, then increment again to prevent
// TODO: Do we need to check whether the interrupts were enabled to
// begin with? AFAIK there is no Arduino API for that
noInterrupts();
}
return 0;
}

/**
* @brief Exit a critical section.
* If interrupts were enabled when the matching call to
* lf_critical_section_enter()
* occurred, then they will be re-enabled here.
*/
int lf_critical_section_exit() {
erlingrj marked this conversation as resolved.
Show resolved Hide resolved
_lf_in_critical_section--;
if (_lf_in_critical_section == 0) {
interrupts();
}
return 0;
}

/**
* Handle notifications from the runtime of changes to the event queue.
* If a sleep is in progress, it should be interrupted.
*/
int lf_notify_of_event() {
_lf_async_event = true;
return 0;
}
Loading