Commit caf1be06 authored by Tommy Olofsson's avatar Tommy Olofsson
Browse files

Merge branch vxworks into master.

parents a49c3d81 62dd9d1f
build/
*build/
doc/gen
lib/
gen/
......@@ -10,3 +10,6 @@ tags
data.enc
sig.enc
.*.swp
*~
\#*
.\#*
......@@ -9,5 +9,9 @@ include(LibFindMacros)
find_path(CUNIT_INCLUDE_DIR NAMES CUnit/CUnit.h PATH_SUFFIXES cunit)
find_library(CUNIT_LIBRARY NAMES cunit libcunit cunitlib)
set(CUNIT_PROCESS_INCLUDES CUNIT_INCLUDE_DIR)
set(CUNIT_PROCESS_LIBS CUNIT_LIBRARY)
libfind_process(CUNIT)
......@@ -7,10 +7,12 @@
include(LibFindMacros)
if(NOT $ENV{LABCOMM_ROOT_DIR} STREQUAL "")
set(LABCOMM_ROOT_DIR $ENV{LABCOMM_ROOT_DIR} CACHE PATH "LabComm base directory location (optional, used for nonstandard installation paths)" FORCE)
else()
set(LABCOMM_ROOT_DIR "${Firefly_PROJECT_DIR}/../labcomm/lib/c/")
if(NOT LABCOMM_ROOT_DIR)
# No toolchain file used.
if("$ENV{LABCOMM}" STREQUAL "")
message(FATAL_ERROR "Set env. variable LABCOMM to labcomm root.")
endif()
set(LABCOMM_ROOT_DIR $ENV{LABCOMM}/lib/c)
endif()
# Header files to find
......@@ -28,4 +30,3 @@ set(LABCOMM_PROCESS_LIBS LABCOMM_LIBRARY)
set(LABCOMM_FIND_REQUIRED true)
libfind_process(LABCOMM)
......@@ -173,6 +173,7 @@ typedef bool (* firefly_connection_error_f)(struct firefly_connection *conn,
* opened.
*
* @param conn The newly opened connection.
* @param context A user specified context.
*/
typedef void (* firefly_connection_opened_f)(struct firefly_connection *conn);
......@@ -211,6 +212,7 @@ struct firefly_connection_actions {
* offered to.
* @param tc A struct containing the transport layer specific
* functions and data.
* @param context An initial value of the connection context.
*
* @return int Indicating error if any.
* @retval 0 if no error, negative error number otherwise.
......@@ -219,7 +221,8 @@ int firefly_connection_open(
struct firefly_connection_actions *actions,
struct firefly_memory_funcs *memory_replacements,
struct firefly_event_queue *event_queue,
struct firefly_transport_connection *tc);
struct firefly_transport_connection *tc,
void *context);
/**
* @brief Spawns an event that will close the connection specified by
......@@ -340,4 +343,62 @@ void firefly_channel_restrict(struct firefly_channel *chan);
*/
void firefly_channel_unrestrict(struct firefly_channel *chan);
/* Stuff for predictable type registration. */
typedef void (*labcomm_handler_function)(void *value, void *context);
typedef int (*labcomm_decoder_register_function)(struct labcomm_decoder *d,
labcomm_handler_function f,
void *context);
typedef int (*labcomm_encoder_register_function)(struct labcomm_encoder *e);
struct firefly_channel_decoder_type {
labcomm_decoder_register_function register_func;
labcomm_handler_function handler;
void *context;
struct firefly_channel_decoder_type *next;
};
struct firefly_channel_encoder_type {
labcomm_encoder_register_function register_func;
struct firefly_channel_encoder_type *next;
};
struct firefly_channel_types {
struct firefly_channel_decoder_type *decoder_types;
struct firefly_channel_encoder_type *encoder_types;
};
#if 0
struct firefly_channel_types *firefly_channel_types_new(void);
void firefly_channel_types_free(struct firefly_channel_types *ct);
#endif
#define FIREFLY_CHANNEL_TYPES_INITIALIZER { NULL, NULL }
void firefly_channel_types_add_decoder_type(
struct firefly_channel_types *types,
labcomm_decoder_register_function register_func,
labcomm_handler_function handler,
void *context);
void firefly_channel_types_add_encoder_type(
struct firefly_channel_types *types,
labcomm_encoder_register_function register_func);
/**
* Used to open with automatic restriction after type registration.
*/
void firefly_channel_open_auto_restrict(struct firefly_connection *conn,
struct firefly_channel_types types);
/**
* Used in accept channel with automatic restriction after type registration.
* Use only in channel-accept-callback.
*/
void firefly_channel_set_types(struct firefly_channel *chan,
struct firefly_channel_types types);
#endif
......@@ -21,7 +21,13 @@
#include <stdlib.h>
#include <stdbool.h>
#ifdef LABCOMM_COMPAT
#include LABCOMM_COMPAT
#else
#include <stdint.h>
#endif
/**
* @brief Defines the maximum number of events an event may depend on.
......
#ifndef FIREFLY_EVENT_QUEUE_VX_H
#define FIREFLY_EVENT_QUEUE_VX_H
#include <utils/firefly_event_queue.h>
/**
* @brief Construct a new struct firefly_event_queue with with a context
* specific for this utility.
*
* @param pool_size The number of preallocated events.
* @return The newly contructed event queue.
*/
struct firefly_event_queue *firefly_event_queue_vx_new(size_t pool_size);
/**
* @brief Free the specified event queue and the posix specific context. Stop
* the event loop if it is running.
*
* @param eq The event queue to free
*/
void firefly_event_queue_vx_free(struct firefly_event_queue **eq);
/**
* @brief Start the event loop.
*
* @param eq The event queue to loop execute events from. It must have been
* constructed with firefly_event_queue_vx_new().
* @param attr The attributes to use when starting the event loop posix thread.
* If NULL the default is used.
* @return Integer indicating result.
* @retval 0 on success.
* @retval <0 on failure.
*/
int firefly_event_queue_vx_run(struct firefly_event_queue *eq);
/**
* @brief Stop the event loop. Will block untill the event loop is stopped.
*
* @param eq The event queue of the event loop to stop. It must have been
* constructed with firefly_event_queue_vx_new().
* @return Integer indicating result.
* @retval 0 on success.
* @retval <0 on failure.
*/
int firefly_event_queue_vx_stop(struct firefly_event_queue *eq);
int64_t firefly_event_queue_vx_add(struct firefly_event_queue *eq,
unsigned char prio, firefly_event_execute_f execute, void *context,
unsigned int nbr_deps, const int64_t *deps);
#endif
......@@ -15,6 +15,7 @@ sample struct {
sample struct {
int dest_chan_id;
int source_chan_id;
boolean auto_restrict;
} channel_request;
sample struct {
......
......@@ -5,7 +5,7 @@
## General {{{
cmake_minimum_required (VERSION 2.8)
project (Firefly)
project (Firefly C)
if(NOT CMAKE_CROSSCOMPILING)
enable_testing()
endif(NOT CMAKE_CROSSCOMPILING)
......@@ -61,27 +61,45 @@ link_directories(${LINK_DIRECTORIES} ${LABCOMM_LIBRARIES})
## FLAGS {{{
set(C_STD "-std=c99")
set(ERR_FLAGS "-Wall -Wextra")
set(MACROS_DEF "-DDEBUG")
if(DEFINED $ENV{DEBUG})
set(MACROS_DEF "-DDEBUG -O0")
else()
set(MACROS_DEF "-DNDEBUG -O3")
endif()
if(CMAKE_CROSSCOMPILING)
# CFLAGS when cross compiling to the ARM-card:
set(CMAKE_C_FLAGS
"${C_STD} "
"${ERR_FLAGS} -Wfloat-equal -Werror-implicit-function-declaration "
"-mthumb -mcpu=cortex-m3 -T../ft-sense/src/adc_freertos_lwip/standalone.ld"
"-ffunction-sections -fdata-sections "
"${MACROS_DEF} -DUART_BUFFERED -Dsprintf=usprintf "
"-Dsnprintf=usnprintf -Dvsnprintf=uvsnprintf -Dprintf=uipprintf "
"-DFIREFLY_MALLOC=pvPortMalloc -Dcalloc=pvPortCalloc -DFIREFLY_FREE=vPortFree "
"-DARM_CORTEXM3_CODESOURCERY -DLABCOMM_NO_STDIO "
"-DLABCOMM_COMPAT=\\\"labcomm_compat_arm_cortexm3.h\\\" "
"-DGCC_ARMCM3=1"
)
# Join the list stuff above to a single string:
JOIN("${CMAKE_C_FLAGS}" CMAKE_C_FLAGS)
if (VXWORKS_COMPILING)
# CFLAGS when cross compiling to the ARM-card:
set(CMAKE_C_FLAGS
"${C_STD} "
"${ERR_FLAGS} "
"${MACROS_DEF} "
"-DLABCOMM_COMPAT=\\\"labcomm_compat_vxworks.h\\\" "
)
# Join the list stuff above to a single string:
JOIN("${CMAKE_C_FLAGS}" CMAKE_C_FLAGS)
else()
# CFLAGS when cross compiling to the ARM-card:
set(CMAKE_C_FLAGS
"${C_STD} "
"${ERR_FLAGS} -Wfloat-equal -Werror-implicit-function-declaration "
"-mthumb -mcpu=cortex-m3 -T../ft-sense/src/adc_freertos_lwip/standalone.ld"
"-ffunction-sections -fdata-sections "
"${MACROS_DEF} -DUART_BUFFERED -Dsprintf=usprintf "
"-Dsnprintf=usnprintf -Dvsnprintf=uvsnprintf -Dprintf=uipprintf "
"-DFIREFLY_MALLOC=pvPortMalloc -Dcalloc=pvPortCalloc -DFIREFLY_FREE=vPortFree "
"-DARM_CORTEXM3_CODESOURCERY -DLABCOMM_NO_STDIO "
"-DLABCOMM_COMPAT=\\\"labcomm_compat_arm_cortexm3.h\\\" "
"-DGCC_ARMCM3=1"
)
# Join the list stuff above to a single string:
JOIN("${CMAKE_C_FLAGS}" CMAKE_C_FLAGS)
endif()
else()
# CFLAGS when compiling normally:
set(CMAKE_C_FLAGS "${C_STD} ${ERR_FLAGS} ${MACROS_DEF} -g")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_STD} ${ERR_FLAGS} ${MACROS_DEF} -g")
endif(CMAKE_CROSSCOMPILING)
## }}}
......@@ -117,6 +135,7 @@ add_library(gen-files
${Firefly_PROJECT_DIR}/gen/firefly_protocol.c
${Firefly_PROJECT_DIR}/gen/pingpong.c
)
# Tell CMake that the files above are generated at compile time,
# otherwise CMake complains about missing files when generating
# build files:
......
......@@ -18,6 +18,11 @@ set(DRIVERLIB_DIR ${FT_SENSE_DIR}/lib/driverlib)
# according to CMake manual:
set(CMAKE_SYSTEM_NAME Generic)
if("$ENV{LABOMM_ARM}" STREQUAL "")
message(FATAL_ERROR "Set env. variable LABCOMM_ARM to labcomm root.")
endif()
set(LABCOMM_ROOT_DIR $ENV{LABCOMM_ARM}/lib/c)
# Specify the cross compiler:
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
set(CROSS_COMPILER_ARM arm-none-eabi-gcc)
......
# Set system name to Generic when compiling for embedded systems
# according to CMake manual:
set(CMAKE_SYSTEM_NAME Generic)
set(VXWORKS_COMPILING TRUE)
if("$ENV{LABCOMM_VX}" STREQUAL "")
message(FATAL_ERROR "Set env. variable LABCOMM_VX to labcomm root.")
endif()
set(LABCOMM_ROOT_DIR $ENV{LABCOMM_VX}/lib/c)
# Specify the cross compiler:
set(CMAKE_C_COMPILER i586-wrs-vxworks-gcc)
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DLABCOMM_COMPAT=\\\"labcomm_compat_vxworks.h\\\" -DLABCOMM_NO_STDIO")
# Add additional includes
include_directories(
/opt/robot/include
/opt/robot/include/vxworks/5.5.1/
/opt/robot/include/vxworks/5.5.1/wrn/coreip/
)
......@@ -22,7 +22,8 @@ set_source_files_properties(${Firefly_PROJECT_DIR}/gen/firefly_protocol.c PROPER
add_library(firefly ${firefly_src_files})
# If not cross compiling, add firefly with error lib target:
if (NOT CMAKE_CROSSCOMPILING)
#if (NOT CMAKE_CROSSCOMPILING)
if (NOT ARM_COMPILING)
add_library(firefly-werr
${firefly_src_files}
${Firefly_SOURCE_DIR}/utils/firefly_errors.c
......@@ -32,7 +33,8 @@ if (NOT CMAKE_CROSSCOMPILING)
set(firefly_install_werr
firefly-werr
)
endif (NOT CMAKE_CROSSCOMPILING)
#endif (NOT CMAKE_CROSSCOMPILING)
endif (NOT ARM_COMPILING)
# Add libs to install target:
install(TARGETS ${firefly_install_werr} firefly
......
......@@ -14,6 +14,15 @@
#include "utils/firefly_event_queue_private.h"
#include "utils/cppmacros.h"
/*
* FIREFLY_PROTO_ACK_*: Used to use the existing ack-functionality
* working with protocol types as well. This may or may not be the
* right way to do this...
*
* Must be negative.
*/
#define FIREFLY_PROTO_ACK_RESTRICT_ACK -1
/*
* Used by reg_proto_sigs() below to "short circuit" the connection during
* the initial registration of protocol types.
......@@ -40,9 +49,12 @@ void reg_proto_sigs(struct labcomm_encoder *enc,
struct labcomm_decoder *dec,
struct firefly_connection *conn)
{
struct firefly_transport_connection *orig_transport = conn->transport;
struct firefly_transport_connection *orig_transport;
orig_transport = conn->transport;
conn->transport = &sig_transport;
init_firefly_protocol__signatures();
labcomm_decoder_register_firefly_protocol_data_sample(dec,
handle_data_sample, conn);
......@@ -67,7 +79,6 @@ void reg_proto_sigs(struct labcomm_encoder *enc,
labcomm_decoder_register_firefly_protocol_channel_restrict_ack(
dec, handle_channel_restrict_ack, conn);
labcomm_encoder_register_firefly_protocol_data_sample(enc);
labcomm_encoder_register_firefly_protocol_channel_request(enc);
labcomm_encoder_register_firefly_protocol_channel_response(enc);
......@@ -80,14 +91,14 @@ void reg_proto_sigs(struct labcomm_encoder *enc,
conn->transport = orig_transport;
}
void firefly_unknown_dest(struct firefly_connection *conn,
int src_id, int dest_id)
static void firefly_unknown_dest(struct firefly_connection *conn,
int src_id, int dest_id, const char *action)
{
UNUSED_VAR(conn);
firefly_protocol_channel_close chan_close;
firefly_error(FIREFLY_ERROR_PROTO_STATE, 1,
"Received open channel on non-existing channel");
firefly_error(FIREFLY_ERROR_PROTO_STATE, 2,
"Received %s on a non-existent channel", action);
chan_close.dest_chan_id = src_id;
chan_close.source_chan_id = dest_id;
......@@ -122,6 +133,7 @@ int firefly_channel_open_event(void *event_arg)
chan_req.source_chan_id = chan->local_id;
chan_req.dest_chan_id = chan->remote_id;
chan_req.auto_restrict = false;
labcomm_encoder_ioctl(conn->transport_encoder,
FIREFLY_LABCOMM_IOCTL_TRANS_SET_IMPORTANT_ID,
......@@ -145,6 +157,65 @@ void firefly_channel_open(struct firefly_connection *conn)
firefly_error(FIREFLY_ERROR_ALLOC, 1, "Could not add event.");
}
int firefly_channel_open_auto_restrict_event(void *event_arg)
{
struct firefly_event_chan_open_auto_restrict *arg;
struct firefly_channel_types types;
struct firefly_connection *conn;
struct firefly_channel *chan;
firefly_protocol_channel_request chan_req;
arg = event_arg;
conn = arg->connection;
types = arg->types;
if (conn->open != FIREFLY_CONNECTION_OPEN) {
firefly_channel_raise(NULL, conn, FIREFLY_ERROR_CONN_STATE,
"Can't open new channel on closed connection.\n");
return -1;
}
chan = firefly_channel_new(conn);
if (!chan) {
firefly_error(FIREFLY_ERROR_ALLOC, 1,
"Could not allocate channel.\n");
return -1;
}
chan->auto_restrict = true;
add_channel_to_connection(chan, conn);
chan_req.source_chan_id = chan->local_id;
chan_req.dest_chan_id = chan->remote_id;
chan_req.auto_restrict = true;
firefly_channel_set_types(chan, types);
labcomm_encoder_ioctl(conn->transport_encoder,
FIREFLY_LABCOMM_IOCTL_TRANS_SET_IMPORTANT_ID,
&chan->important_id);
labcomm_encode_firefly_protocol_channel_request(conn->transport_encoder,
&chan_req);
FIREFLY_FREE(event_arg);
return 0;
}
void firefly_channel_open_auto_restrict(struct firefly_connection *conn,
struct firefly_channel_types types)
{
int64_t ret;
struct firefly_event_chan_open_auto_restrict *ev;
ev = FIREFLY_MALLOC(sizeof(*ev));
if (ev) {
ev->connection = conn;
ev->types = types;
ret = conn->event_queue->offer_event_cb(conn->event_queue,
FIREFLY_PRIORITY_HIGH,
firefly_channel_open_auto_restrict_event,
ev, 0, NULL);
if (ret < 0)
firefly_error(FIREFLY_ERROR_ALLOC, 1, "Could not add event.");
} else {
firefly_error(FIREFLY_ERROR_ALLOC, 1, "Could not add event.");
}
}
static int64_t create_channel_closed_event(struct firefly_channel *chan,
unsigned int nbr_deps, const int64_t *deps)
{
......@@ -266,6 +337,7 @@ int handle_channel_request_event(void *event_arg)
firefly_protocol_channel_response res;
chan->remote_id = fecrr->chan_req.source_chan_id;
chan->auto_restrict = fecrr->chan_req.auto_restrict;
add_channel_to_connection(chan, conn);
res.dest_chan_id = chan->remote_id;
......@@ -277,6 +349,7 @@ int handle_channel_request_event(void *event_arg)
res.source_chan_id = CHANNEL_ID_NOT_SET;
firefly_channel_free(remove_channel_from_connection(chan, conn));
} else {
/* TODO: Decoder registrations. */
labcomm_encoder_ioctl(fecrr->conn->transport_encoder,
FIREFLY_LABCOMM_IOCTL_TRANS_SET_IMPORTANT_ID,
&chan->important_id);
......@@ -325,6 +398,7 @@ static void firefly_channel_send_channel_ack(
int dest_chan_id)
{
firefly_protocol_channel_ack ack;
if (chan != NULL) {
ack.ack = true;
ack.source_chan_id = chan->local_id;
......@@ -349,7 +423,7 @@ int handle_channel_response_event(void *event_arg)
if (chan == NULL) {
firefly_unknown_dest(fecrr->conn, fecrr->chan_res.source_chan_id,
fecrr->chan_res.dest_chan_id);
fecrr->chan_res.dest_chan_id, "channel_response");
} else if (fecrr->chan_res.ack) {
if (chan->remote_id == CHANNEL_ID_NOT_SET) {
chan->remote_id = fecrr->chan_res.source_chan_id;
......@@ -406,10 +480,10 @@ int handle_channel_ack_event(void *event_arg)
fecar->chan_ack.dest_chan_id);
if (chan != NULL) {
firefly_channel_ack(chan);
firefly_channel_internal_opened(chan);
firefly_channel_internal_opened(chan); /* TODO: Why? */
} else {
firefly_unknown_dest(fecar->conn, fecar->chan_ack.source_chan_id,
fecar->chan_ack.dest_chan_id);
fecar->chan_ack.dest_chan_id, "channel_ack");
}
FIREFLY_FREE(event_arg);
......@@ -481,10 +555,21 @@ int handle_data_sample_event(void *event_arg)
if (expected_seqno <= 0) {
expected_seqno = 1;
}
if (fers->data.important) {
firefly_protocol_ack ack_pkt;
ack_pkt.dest_chan_id = chan->remote_id;
ack_pkt.src_chan_id = chan->local_id;
ack_pkt.seqno = fers->data.seqno;
labcomm_encode_firefly_protocol_ack(
chan->conn->transport_encoder,
&ack_pkt);
}
if (!fers->data.important ||
expected_seqno == fers->data.seqno)
{
size_t size;
int id;
size = fers->data.app_enc_data.n_0;
labcomm_decoder_ioctl(chan->proto_decoder,
......@@ -492,24 +577,52 @@ int handle_data_sample_event(void *event_arg)
fers->data.app_enc_data.a,
size);
labcomm_decoder_decode_one(chan->proto_decoder);
id = labcomm_decoder_decode_one(chan->proto_decoder);
if (fers->data.important) {
chan->remote_seqno = fers->data.seqno;
}
}
if (fers->data.important) {
firefly_protocol_ack ack_pkt;
ack_pkt.dest_chan_id = chan->remote_id;
ack_pkt.src_chan_id = chan->local_id;
ack_pkt.seqno = fers->data.seqno;
labcomm_encode_firefly_protocol_ack(
chan->conn->transport_encoder,
&ack_pkt);
if (id == -ENOENT) {
#if 0
if (!chan->auto_restrict) {
firefly_error(FIREFLY_ERROR_LABCOMM, 1,
"Unkn. type. Use autorestr.");
} else {
firefly_error(FIREFLY_ERROR_LABCOMM, 1,
"Wait for restr.");
}
#endif
} else if (!chan->restricted_local &&
chan->auto_restrict)
{
size_t n = 0;
for (; n < chan->n_decoder_types; n++) {
if (chan->seen_decoder_ids[n] == -1 ||
chan->seen_decoder_ids[n] == id)
{
break;
}
}
chan->seen_decoder_ids[n] = id;
if (n == chan->n_decoder_types-1) {
FIREFLY_FREE(chan->seen_decoder_ids);
chan->seen_decoder_ids = NULL;
chan->n_decoder_types = 0; /* State-ish */
channel_auto_restr_send_ack(chan);
}
}
} else if (fers->data.important &&
expected_seqno != fers->data.seqno)
{
#if 0 /* This would probably be a good idea, but it breaks existing tests. */
firefly_error(FIREFLY_ERROR_PROTO_STATE, 1,
"Received data flagged important with "
"unexpected sequence number.");
#endif
}
} else {
firefly_unknown_dest(fers->conn, fers->data.src_chan_id,
fers->data.dest_chan_id);
fers->data.dest_chan_id, "data_sample");
}
FIREFLY_RUNTIME_FREE(fers->conn, fers->data.app_enc_data.a);
......@@ -526,8 +639,11 @@ void handle_ack(firefly_protocol_ack *ack, void *context)
conn = context;
chan = find_channel_by_local_id(conn, ack->dest_chan_id);
if (chan == NULL) {
firefly_unknown_dest(conn, ack->src_chan_id, ack->dest_chan_id);
} else if (chan->current_seqno == ack->seqno && ack->seqno > 0) {
firefly_unknown_dest(conn, ack->src_chan_id, ack->dest_chan_id, "ack");
} else if ((chan->current_seqno == ack->seqno && ack->seqno > 0) ||
(chan->auto_restrict && chan->restricted_local &&
ack->seqno == FIREFLY_PROTO_ACK_RESTRICT_ACK))
{
firefly_channel_ack(chan);
}
}
......@@ -643,7 +759,7 @@ int channel_restrict_request_event(void *context)
chan = find_channel_by_local_id(conn, earg->rreq.dest_chan_id);
if (!chan) {
firefly_unknown_dest(conn, earg->rreq.source_chan_id,
earg->rreq.dest_chan_id);
earg->rreq.dest_chan_id, "channel_restrict_request");
FIREFLY_FREE(earg);
return -1;
}
......@@ -721,26 +837,45 @@ int channel_restrict_ack_event(void *context)