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

UARTChannel #191

Open
wants to merge 24 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion examples/riot/coap_federated/receiver/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ DEVELHELP ?= 1
QUIET ?= 1

# Enable reactor-uc features
CFLAGS += -DNETWORK_CHANNEL_COAP_RIOT
CFLAGS += -DNETWORK_CHANNEL_COAP
REACTION_QUEUE_SIZE = 32
EVENT_QUEUE_SIZE = 32

Expand Down
2 changes: 1 addition & 1 deletion examples/riot/coap_federated/sender/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ DEVELHELP ?= 1
QUIET ?= 1

# Enable reactor-uc features
CFLAGS += -DNETWORK_CHANNEL_COAP_RIOT
CFLAGS += -DNETWORK_CHANNEL_COAP
REACTION_QUEUE_SIZE = 32
EVENT_QUEUE_SIZE = 32

Expand Down
3 changes: 0 additions & 3 deletions examples/riot/coap_federated_lf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ DEVELHELP ?= 1
# Change this to 0 show compiler invocation lines by default:
QUIET ?= 1

# Enable reactor-uc features
CFLAGS += -DNETWORK_CHANNEL_COAP_RIOT

# Configure CoAP retransmission timeout
CFLAGS += -DCONFIG_GCOAP_NO_RETRANS_BACKOFF=1
CFLAGS += -DCONFIG_COAP_ACK_TIMEOUT_MS=400
Expand Down
2 changes: 1 addition & 1 deletion examples/riot/hello_lf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LF_MAIN ?= HelloLF

# Enable reactor-uc features
# CFLAGS += -DNETWORK_CHANNEL_TCP_POSIX
# CFLAGS += -DNETWORK_CHANNEL_COAP_RIOT
# CFLAGS += -DNETWORK_CHANNEL_COAP

# Execute the LF compiler if build target is "all"
ifeq ($(firstword $(MAKECMDGOALS)),all)
Expand Down
2 changes: 1 addition & 1 deletion include/reactor-uc/federated.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,4 @@ void FederatedInputConnection_ctor(FederatedInputConnection *self, Reactor *pare
bool *payload_used_buf, size_t payload_size, size_t payload_buf_capacity);

void Federated_distribute_start_tag(Environment *env, instant_t start_time);
#endif
#endif
31 changes: 30 additions & 1 deletion include/reactor-uc/network_channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,26 @@ typedef enum {
typedef enum {
NETWORK_CHANNEL_TYPE_TCP_IP,
NETWORK_CHANNEL_TYPE_COAP_UDP_IP,
NETWORK_CHANNEL_TYPE_UART
} NetworkChannelType;

typedef enum {
NETWORK_CHANNEL_MODE_ASYNC,
NETWORK_CHANNEL_MODE_POLL,
} NetworkChannelMode;

char *NetworkChannel_state_to_string(NetworkChannelState state);

typedef struct FederatedConnectionBundle FederatedConnectionBundle;
typedef struct NetworkChannel NetworkChannel;
typedef struct SyncNetworkChannel SyncNetworkChannel;

struct NetworkChannel {
/**
* @brief Specifies if this NetworkChannel is a aync or async channel
*/
NetworkChannelMode mode;

/**
* @brief Expected time until a connection is established after calling @p open_connection.
*/
Expand Down Expand Up @@ -95,6 +107,19 @@ struct NetworkChannel {
void (*free)(NetworkChannel *self);
};

struct SyncNetworkChannel {
NetworkChannel super;

/**
* @brief Polls for new data and calls the callback handler if a message is successfully decoded
tanneberger marked this conversation as resolved.
Show resolved Hide resolved
*/
void (*poll)(NetworkChannel *self);
};

struct AsyncNetworkChannel {
NetworkChannel super;
};

#if defined(PLATFORM_POSIX)
#ifdef NETWORK_CHANNEL_TCP_POSIX
#include "platform/posix/tcp_ip_channel.h"
Expand All @@ -109,9 +134,12 @@ struct NetworkChannel {
#ifdef NETWORK_CHANNEL_TCP_POSIX
#include "platform/posix/tcp_ip_channel.h"
#endif
#ifdef NETWORK_CHANNEL_COAP_RIOT
#ifdef NETWORK_CHANNEL_COAP
#include "platform/riot/coap_udp_ip_channel.h"
#endif
#ifdef NETWORK_CHANNEL_UART
#include "platform/riot/uart_channel.h"
#endif

#elif defined(PLATFORM_PICO)
#ifdef NETWORK_CHANNEL_TCP_POSIX
Expand All @@ -126,4 +154,5 @@ struct NetworkChannel {
#else
#error "Platform not supported"
#endif

#endif // REACTOR_UC_NETWORK_CHANNEL_H
20 changes: 20 additions & 0 deletions include/reactor-uc/network_channel/uart_channel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef REACTOR_UC_UART_CHANNEL_H
#define REACTOR_UC_UART_CHANNEL_H

typedef enum UARTDataBits UARTDataBits;
typedef enum UARTParityBits UARTParityBits;
typedef enum UARTStopBits UARTStopBits;

enum UARTDataBits { UC_UART_DATA_BITS_5, UC_UART_DATA_BITS_6, UC_UART_DATA_BITS_7, UC_UART_DATA_BITS_8 };

enum UARTParityBits {
UC_UART_PARITY_NONE,
UC_UART_PARITY_EVEN,
UC_UART_PARITY_ODD,
UC_UART_PARITY_MARK,
UC_UART_PARITY_SPACE
};

enum UARTStopBits { UC_UART_STOP_BITS_1, UC_UART_STOP_BITS_2 };

#endif
48 changes: 48 additions & 0 deletions include/reactor-uc/platform/riot/uart_channel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#ifndef REACTOR_UC_RIOT_UART_CHANNEL_H
#define REACTOR_UC_RIOT_UART_CHANNEL_H

#include "reactor-uc/network_channel/uart_channel.h"
#include "reactor-uc/network_channel.h"
#include "reactor-uc/environment.h"

#include "periph/uart.h"
#include "cond.h"

typedef struct FederatedConnectionBundle FederatedConnectionBundle;
typedef struct UARTPollChannel UARTPollChannel;
typedef struct UARTAsyncChannel UARTAsyncChannel;

#define UART_CHANNEL_BUFFERSIZE 1024
// The UartChannel is not connection-oriented and will always appear as connected, so no need to wait.
#define UART_CHANNEL_EXPECTED_CONNECT_DURATION MSEC(0)

struct UARTPollChannel {
SyncNetworkChannel super;
NetworkChannelState state;

FederateMessage output;
unsigned char write_buffer[UART_CHANNEL_BUFFERSIZE];
unsigned char receive_buffer[UART_CHANNEL_BUFFERSIZE];
unsigned int receive_buffer_index;
uart_t uart_dev;

FederatedConnectionBundle *federated_connection;
void (*receive_callback)(FederatedConnectionBundle *conn, const FederateMessage *message);
};

struct UARTAsyncChannel {
UARTPollChannel super;

char decode_thread_stack[THREAD_STACKSIZE_MAIN];
int decode_thread_pid;
mutex_t receive_lock;
cond_t receive_cv;
};

void UARTPollChannel_ctor(UARTPollChannel *self, uint32_t uart_device, uint32_t baud, UARTDataBits data_bits,
UARTParityBits parity, UARTStopBits stop_bits);

void UARTAsyncChannel_ctor(UARTAsyncChannel *self, uint32_t uart_device, uint32_t baud, UARTDataBits data_bits,
UARTParityBits parity, UARTStopBits stop_bits);

#endif
13 changes: 13 additions & 0 deletions lfc/core/src/main/java/org/lflang/validation/AttributeSpec.java
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,19 @@ enum AttrParamType {
new AttributeSpec(List.of(new AttrParamSpec(VALUE_ATTR, AttrParamType.INT, false))));
// @interface:tcp(name="string", address="string") e.g. @interface:tcp(name="if1",
// address="127.0.0.1")

ATTRIBUTE_SPECS_BY_NAME.put(
"interface_uart",
new AttributeSpec(
List.of(
new AttrParamSpec("name", AttrParamType.STRING, true),
new AttrParamSpec("uart_device", AttrParamType.INT, true),
new AttrParamSpec("baud_rate", AttrParamType.INT, true),
new AttrParamSpec("data_bits", AttrParamType.STRING, true),
tanneberger marked this conversation as resolved.
Show resolved Hide resolved
new AttrParamSpec("parity", AttrParamType.STRING, true),
new AttrParamSpec("stop_bits", AttrParamType.STRING, true),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this also be INT?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, STRING is also in caps.

new AttrParamSpec("async", AttrParamType.BOOLEAN, true))));

ATTRIBUTE_SPECS_BY_NAME.put(
"interface_tcp",
new AttributeSpec(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ package org.lflang.generator.uc
import org.lflang.*
import org.lflang.generator.PrependOperator
import org.lflang.generator.orZero
import org.lflang.generator.uc.UcReactorGenerator.Companion.hasStartup
import org.lflang.generator.uc.UcReactorGenerator.Companion.hasShutdown
import org.lflang.generator.uc.UcReactorGenerator.Companion.codeType
import org.lflang.generator.uc.UcReactorGenerator.Companion.getEffects
import org.lflang.generator.uc.UcReactorGenerator.Companion.getObservers
import org.lflang.generator.uc.UcReactorGenerator.Companion.getSources
import org.lflang.AttributeUtils.getMaxNumberOfPendingEvents
import org.lflang.generator.uc.UcReactorGenerator.Companion.hasShutdown
import org.lflang.generator.uc.UcReactorGenerator.Companion.hasStartup
import org.lflang.lf.*

class UcActionGenerator(private val reactor: Reactor) {
Expand All @@ -22,61 +22,72 @@ class UcActionGenerator(private val reactor: Reactor) {
}
}

/** Returns the C Enum representing the type of action.*/
private val Action.actionType
get(): String = if (isPhysical) "PHYSICAL_ACTION" else "LOGICAL_ACTION"
/** Returns the C Enum representing the type of action. */
private val Action.actionType
get(): String = if (isPhysical) "PHYSICAL_ACTION" else "LOGICAL_ACTION"

private fun generateSelfStruct(action: Action) = with(PrependOperator) {
private fun generateSelfStruct(action: Action) =
with(PrependOperator) {
"""
|LF_DEFINE_ACTION_STRUCT${if (action.type == null) "_VOID" else ""}(${reactor.codeType}, ${action.name}, ${action.actionType}, ${reactor.getEffects(action).size}, ${reactor.getSources(action).size}, ${reactor.getObservers(action).size}, ${action.maxNumPendingEvents} ${if (action.type != null) ", ${action.type.toText()}" else ""});
|
""".trimMargin()
}
"""
.trimMargin()
}

private fun generateCtor(action: Action) = with(PrependOperator) {
private fun generateCtor(action: Action) =
with(PrependOperator) {
"""
|LF_DEFINE_ACTION_CTOR${if (action.type == null) "_VOID" else ""}(${reactor.codeType}, ${action.name}, ${action.actionType}, ${reactor.getEffects(action).size}, ${reactor.getSources(action).size}, ${reactor.getObservers(action).size}, ${action.maxNumPendingEvents} ${if (action.type != null) ", ${action.type.toText()}" else ""});
|
""".trimMargin()
}
"""
.trimMargin()
}

private fun generateCtor(builtin: BuiltinTrigger) =
(if (builtin == BuiltinTrigger.STARTUP) "LF_DEFINE_STARTUP_CTOR" else "LF_DEFINE_SHUTDOWN_CTOR") +
"(${reactor.codeType});\n"
private fun generateCtor(builtin: BuiltinTrigger) =
(if (builtin == BuiltinTrigger.STARTUP) "LF_DEFINE_STARTUP_CTOR"
else "LF_DEFINE_SHUTDOWN_CTOR") + "(${reactor.codeType});\n"

fun generateCtors(): String {
var code = reactor.allActions.joinToString(separator = "\n") { generateCtor(it) }
if (reactor.hasStartup) code += generateCtor(BuiltinTrigger.STARTUP)
if (reactor.hasShutdown) code += generateCtor(BuiltinTrigger.SHUTDOWN)
return code
}

fun generateCtors(): String {
var code = reactor.allActions.joinToString(separator = "\n") { generateCtor(it) }
if (reactor.hasStartup) code += generateCtor(BuiltinTrigger.STARTUP);
if (reactor.hasShutdown) code += generateCtor(BuiltinTrigger.SHUTDOWN);
return code;
private fun generateSelfStruct(builtin: BuiltinTrigger) =
(if (builtin == BuiltinTrigger.STARTUP) "LF_DEFINE_STARTUP_STRUCT"
else "LF_DEFINE_SHUTDOWN_STRUCT") +
"(${reactor.codeType}, ${reactor.getEffects(builtin).size}, ${reactor.getObservers(builtin).size});\n"

fun generateSelfStructs(): String {
var code = reactor.allActions.joinToString(separator = "\n") { generateSelfStruct(it) }
if (reactor.hasStartup) {
code += generateSelfStruct(BuiltinTrigger.STARTUP)
}
if (reactor.hasShutdown) {
code += generateSelfStruct(BuiltinTrigger.SHUTDOWN)
}
return code
}

private fun generateSelfStruct(builtin: BuiltinTrigger) =
(if (builtin == BuiltinTrigger.STARTUP) "LF_DEFINE_STARTUP_STRUCT" else "LF_DEFINE_SHUTDOWN_STRUCT") +
"(${reactor.codeType}, ${reactor.getEffects(builtin).size}, ${reactor.getObservers(builtin).size});\n"
fun generateReactorStructFields(): String {
var code =
reactor.allActions.joinToString(
prefix = "// Actions and builtin triggers\n", separator = "\n", postfix = "\n") {
"LF_ACTION_INSTANCE(${reactor.codeType}, ${it.name});"
}
if (reactor.hasStartup) code += "LF_STARTUP_INSTANCE(${reactor.codeType});"
if (reactor.hasShutdown) code += "LF_SHUTDOWN_INSTANCE(${reactor.codeType});"
return code
}

fun generateSelfStructs(): String {
var code = reactor.allActions.joinToString(separator = "\n") { generateSelfStruct(it) }
if (reactor.hasStartup) {
code += generateSelfStruct(BuiltinTrigger.STARTUP) ;
}
if (reactor.hasShutdown) {
code += generateSelfStruct(BuiltinTrigger.SHUTDOWN) ;
}
return code;
}
private fun generateReactorCtorCode(action: Action) =
"LF_INITIALIZE_ACTION(${reactor.codeType}, ${action.name}, ${action.minDelay.orZero().toCCode()}, ${action.minSpacing.orZero().toCCode()});"

fun generateReactorStructFields(): String {
var code = reactor.allActions.joinToString(prefix = "// Actions and builtin triggers\n", separator = "\n", postfix = "\n") { "LF_ACTION_INSTANCE(${reactor.codeType}, ${it.name});" }
if (reactor.hasStartup) code += "LF_STARTUP_INSTANCE(${reactor.codeType});"
if (reactor.hasShutdown) code += "LF_SHUTDOWN_INSTANCE(${reactor.codeType});"
return code;
}
private fun generateReactorCtorCodeStartup() = "LF_INITIALIZE_STARTUP(${reactor.codeType});"

private fun generateReactorCtorCode(action: Action) = "LF_INITIALIZE_ACTION(${reactor.codeType}, ${action.name}, ${action.minDelay.orZero().toCCode()}, ${action.minSpacing.orZero().toCCode()});"
private fun generateReactorCtorCodeStartup() = "LF_INITIALIZE_STARTUP(${reactor.codeType});"
private fun generateReactorCtorCodeShutdown() = "LF_INITIALIZE_SHUTDOWN(${reactor.codeType});"
private fun generateReactorCtorCodeShutdown() = "LF_INITIALIZE_SHUTDOWN(${reactor.codeType});"

fun generateReactorCtorCodes(): String {
var code = reactor.allActions.joinToString(prefix = "// Initialize actions and builtin triggers\n", separator = "\n", postfix = "\n") { generateReactorCtorCode(it)}
Expand Down
Loading
Loading