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

Add very basic support for FlexPRET platform #29

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
5 changes: 4 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ set(BUILD_LF_TESTS OFF CACHE BOOL "Build lf tests")
set(BUILD_UNIT_TESTS OFF CACHE BOOL "Build unit tests")
set(TEST_COVERAGE OFF CACHE BOOL "Compute test coverage")
set(ASAN OFF CACHE BOOL "Compile with AddressSanitizer")
set(PLATFORM "POSIX" CACHE STRING "Platform to target")

set(EVENT_QUEUE_SIZE 10 CACHE STRING "Static size of the event queue")
set(REACTION_QUEUE_SIZE 10 CACHE STRING "Static size of the reaction queue")
Expand Down Expand Up @@ -52,6 +51,10 @@ if (PLATFORM STREQUAL "POSIX")
if(BUILD_EXAMPLES)
add_subdirectory(examples/posix)
endif ()
elseif (PLATFORM STREQUAL "FLEXPRET")
add_library(reactor-uc STATIC ${SOURCES})
add_subdirectory($ENV{FP_SDK_PATH} BINARY_DIR)
target_link_libraries(reactor-uc PUBLIC fp-sdk)
elseif (PLATFORM STREQUAL "ZEPHYR")
zephyr_library_named(reactor-uc)
zephyr_library_sources(${SOURCES})
Expand Down
58 changes: 58 additions & 0 deletions examples/flexpret/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
cmake_minimum_required(VERSION 3.22)

if(DEFINED ENV{FP_SDK_PATH})
# Set toolchain to RISC-V; must be done before call to project()
include($ENV{FP_SDK_PATH}/cmake/riscv-toolchain.cmake)
else()
message(FATAL_ERROR "FP_SDK_PATH environment variable not set!")
endif()

project(fp-timer
LANGUAGES C
DESCRIPTION "LF on FlexPRET using uC runtime running a simple timer"
VERSION 1.0.0
)

set(DEBUG true)
set(SUPPORT_LONG_LONG true) # printf

add_executable(fp-timer timer.c)

set(PLATFORM "FLEXPRET" CACHE STRING "Platform to target")
set(BUILD_EXAMPLES OFF CAHCHE BOOL)

add_subdirectory(../.. reactor-uc)
#add_subdirectory($ENV{FP_SDK_PATH} BINARY_DIR)
#target_link_libraries(fp-lf-uc PRIVATE
# ${CMAKE_CURRENT_LIST_DIR}/../src-gen/FlexPRET_uC/build/libFlexPRET_uC.a
# ${CMAKE_CURRENT_LIST_DIR}/../src-gen/FlexPRET_uC/build/reactor-uc/libreactor-uc.a
#)


target_link_libraries(fp-timer PRIVATE fp-sdk reactor-uc)

include($ENV{FP_SDK_PATH}/cmake/fp-app.cmake)

fp_add_outputs(fp-timer)



# cmake_minimum_required(VERSION 3.20.0)
# set(PLATFORM "PICO" CACHE STRING "Platform to target")
# set(BUILD_EXAMPLES OFF CAHCHE BOOL)

# if (DEFINED ENV{PICO_SDK_PATH})
# include("$ENV{PICO_SDK_PATH}/pico_sdk_init.cmake")
# else()
# message(FATAL_ERROR "PICO_SDK_PATH environment variable not set")
# endif()

# project(reactor-uc-pico)
# pico_sdk_init()
# add_subdirectory(../../ reactor-uc)

# add_executable(hello_world
# timer_ex.c
# )

# target_link_libraries(hello_world PRIVATE reactor-uc)
47 changes: 47 additions & 0 deletions examples/flexpret/timer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include "reactor-uc/reactor-uc.h"

typedef struct {
Timer super;
Reaction *effects[0];
} MyTimer;

typedef struct {
Reaction super;
} MyReaction;

struct MyReactor {
Reactor super;
MyReaction my_reaction;
MyTimer timer;
Reaction *_reactions[1];
Trigger *_triggers[1];
};

void timer_handler(Reaction *_self) {
struct MyReactor *self = (struct MyReactor *)_self->parent;
printf("Hello World @ %lld\n", self->super.env->get_logical_time(self->super.env));
}

void MyReaction_ctor(MyReaction *self, Reactor *parent) {
Reaction_ctor(&self->super, parent, timer_handler, NULL, 0, 0);
}

void MyReactor_ctor(struct MyReactor *self, Environment *env) {
self->_reactions[0] = (Reaction *)&self->my_reaction;
self->_triggers[0] = (Trigger *)&self->timer;
Reactor_ctor(&self->super, "MyReactor", env, NULL, NULL, 0, self->_reactions, 1, self->_triggers, 1);
MyReaction_ctor(&self->my_reaction, &self->super);
Timer_ctor(&self->timer.super, &self->super, MSEC(0), USEC(100), self->timer.effects, 1);
TIMER_REGISTER_EFFECT(self->timer, self->my_reaction);
}

struct MyReactor my_reactor;
Environment env;
int main() {
Environment_ctor(&env, (Reactor *)&my_reactor);
env.scheduler.set_timeout(&env.scheduler, SEC(1));
MyReactor_ctor(&my_reactor, &env);
env.assemble(&env);
env.start(&env);
return 0;
}
15 changes: 15 additions & 0 deletions include/reactor-uc/platform/flexpret/flexpret.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef REACTOR_UC_PLATFORM_FLEXPRET_H
#define REACTOR_UC_PLATFORM_FLEXPRET_H

#include "reactor-uc/platform.h"
#include <flexpret/flexpret.h>

typedef struct {
Platform super;
volatile bool async_event_occurred;
bool in_critical_section;
fp_lock_t lock;
} PlatformFlexpret;

void PlatformFlexpret_ctor(Platform *self);
#endif
2 changes: 2 additions & 0 deletions src/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "platform/riot/riot.c"
#elif defined(PLATFORM_ZEPHYR)
#include "platform/zephyr/zephyr.c"
#elif defined(PLATFORM_FLEXPRET)
#include "platform/flexpret/flexpret.c"
#elif defined(PLATFORM_PICO)
#include "platform/pico/pico.c"
#else
Expand Down
96 changes: 96 additions & 0 deletions src/platform/flexpret/flexpret.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include "reactor-uc/platform/flexpret/flexpret.h"
#include "reactor-uc/error.h"

static PlatformFlexpret platform;

lf_ret_t PlatformFlexpret_initialize(Platform *self) {
PlatformFlexpret *p = (PlatformFlexpret *) self;
p->async_event_occurred = false;
p->in_critical_section = false;
p->lock = (fp_lock_t) FP_LOCK_INITIALIZER;
return LF_OK;
}

instant_t PlatformFlexpret_get_physical_time(Platform *self) {
(void)self;
return (instant_t) rdtime64();
}

lf_ret_t PlatformFlexpret_wait_until_interruptible(Platform *self, instant_t wakeup_time) {
PlatformFlexpret *p = (PlatformFlexpret *) self;

p->async_event_occurred = false;
self->leave_critical_section(self);
// For FlexPRET specifically this functionality is directly available as
// an instruction
// It cannot fail - if it does, there is a bug in the processor and not much
// software can do about it
fp_wait_until(wakeup_time);
self->enter_critical_section(self);

if (p->async_event_occurred) {
return LF_SLEEP_INTERRUPTED;
} else {
return LF_OK;
}
}

lf_ret_t PlatformFlexpret_wait_until(Platform *self, instant_t wakeup_time) {
(void)self;

// Interrupts should be disabled here so it does not matter whether we
// use wait until or delay until, but delay until is more accurate here
fp_delay_until(wakeup_time);
return LF_OK;
}

// Note: Code is directly copied from FlexPRET's reactor-c implementation;
// beware of code duplication
void PlatformFlexpret_leave_critical_section(Platform *self) {
PlatformFlexpret *p = (PlatformFlexpret *) self;

// In the special case where this function is called during an interrupt
// subroutine (isr) it should have no effect
if ((read_csr(CSR_STATUS) & 0x04) == 0x04)
return;

validate(p->in_critical_section == true);

fp_interrupt_enable();
fp_lock_release(&p->lock);
p->in_critical_section = false;
}

// Note: Code is directly copied from FlexPRET's reactor-c implementation;
// beware of code duplication
void PlatformFlexpret_enter_critical_section(Platform *self) {
PlatformFlexpret *p = (PlatformFlexpret *) self;

// In the special case where this function is called during an interrupt
// subroutine (isr) it should have no effect
if ((read_csr(CSR_STATUS) & 0x04) == 0x04)
return;

validate(p->in_critical_section == false);

fp_interrupt_disable();
fp_lock_acquire(&p->lock);
p->in_critical_section = true;
}

void PlatformFlexpret_new_async_event(Platform *self) {
PlatformFlexpret *p = (PlatformFlexpret *) self;
p->async_event_occurred = true;
}

void Platform_ctor(Platform *self) {
self->enter_critical_section = PlatformFlexpret_enter_critical_section;
self->leave_critical_section = PlatformFlexpret_leave_critical_section;
self->get_physical_time = PlatformFlexpret_get_physical_time;
self->wait_until = PlatformFlexpret_wait_until;
self->initialize = PlatformFlexpret_initialize;
self->wait_until_interruptible = PlatformFlexpret_wait_until_interruptible;
self->new_async_event = PlatformFlexpret_new_async_event;
}

Platform *Platform_new(void) { return (Platform *)&platform; }
Loading