Commit f9e39035 authored by Thomas Schöpping's avatar Thomas Schöpping
Browse files

Introduced a new app and configuration: µRT-Benchmark.

Note: RPC benchmarks are not yet implemented.
parent dee247c8
################################################################################
# AMiRo-Apps is a collection of applications for the Autonomous Mini Robot #
# (AMiRo) platform. #
# Copyright (C) 2018..2021 Thomas Schöpping et al. #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# This research/work was supported by the Cluster of Excellence Cognitive #
# Interaction Technology 'CITEC' (EXC 277) at Bielefeld University, which is #
# funded by the German Research Foundation (DFG). #
################################################################################
# absolue path to this directory
uRTBenchmark_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
# middleware selection
ifeq ($(CONFIG_MIDDLEWARE),)
CONFIG_MIDDLEWARE := "µRT"
else ifneq ($(CONFIG_MIDDLEWARE),"µRT")
$(error incompatible middleware selected: $(CONFIG_MIDDLEWARE))
endif
# include path
uRTBenchmark_INC = $(uRTBenchmark_DIR)
# C source files
uRTBenchmark_CSRC = $(uRTBenchmark_DIR)/uRT_benchmark.c
# C++ source files
uRTBenchmark_CPPSRC =
/*
AMiRo-Apps is a collection of applications for the Autonomous Mini Robot (AMiRo) platform.
Copyright (C) 2018..2021 Thomas Schöpping et al.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file uRT_benchmark.c
* @brief A µRT benchmark application.
*
* @addtogroup uRT_Benchmark
* @{
*/
#include "uRT_benchmark.h"
/******************************************************************************/
/* LOCAL DEFINITIONS */
/******************************************************************************/
#define TRIGGEREVENT (urtCoreGetEventMask() << 1)
#define TOPICEVENT (urtCoreGetEventMask() << 2)
/******************************************************************************/
/* EXPORTED VARIABLES */
/******************************************************************************/
/******************************************************************************/
/* LOCAL TYPES */
/******************************************************************************/
/******************************************************************************/
/* LOCAL VARIABLES */
/******************************************************************************/
/******************************************************************************/
/* LOCAL FUNCTIONS */
/******************************************************************************/
#if (URT_CFG_PUBSUB_ENABLED == true)
#endif /* (URT_CFG_PUBSUB_ENABLED == true) */
urt_osEventMask_t _ubnSetup(urt_node_t* node, void* bn)
{
urtDebugAssert(bn != NULL);
(void)node;
// local variables
urtbenchmark_node_t* const benchmark = (urtbenchmark_node_t*)bn;
urt_osEventMask_t waitevents = 0;
// initialize node data
#if (CH_CFG_USE_REGISTRY == TRUE)
// set thread name
chRegSetThreadName(benchmark->config->node.name);
#endif /* (CH_CFG_USE_REGISTRY == TRUE) */
if (benchmark->config->node.trigger != NULL) {
urtEventListenerInit(&benchmark->config->node.listener);
urtEventRegister(benchmark->config->node.trigger, &benchmark->config->node.listener, TRIGGEREVENT, 0);
waitevents |= TRIGGEREVENT;
}
#if (URT_CFG_PUBSUB_ENABLED == true)
// initialize publisher data
for (size_t p = 0; p < benchmark->config->publishers.size; ++p) {
urtPublisherInit(&benchmark->config->publishers.buffer[p].publisher,
urtCoreGetTopic(benchmark->config->publishers.buffer[p].topic),
NULL);
}
// initialize subscriber data
for (size_t s = 0; s < benchmark->config->subscribers.size; ++s) {
switch (benchmark->config->subscribers.buffer[s].rtclass) {
case URT_NRT:
urtNrtSubscriberInit(&benchmark->config->subscribers.buffer[s].nrtsubscriber.subscriber);
urtNrtSubscriberSubscribe(&benchmark->config->subscribers.buffer[s].nrtsubscriber.subscriber,
urtCoreGetTopic(benchmark->config->subscribers.buffer[s].topic),
TOPICEVENT,
NULL);
break;
case URT_SRT:
urtSrtSubscriberInit(&benchmark->config->subscribers.buffer[s].srtsubscriber.subscriber);
urtSrtSubscriberSubscribe(&benchmark->config->subscribers.buffer[s].srtsubscriber.subscriber,
urtCoreGetTopic(benchmark->config->subscribers.buffer[s].topic),
TOPICEVENT,
NULL,
benchmark->config->subscribers.buffer[s].srtsubscriber.usefulnesscb,
&benchmark->config->subscribers.buffer[s].srtsubscriber.params);
break;
case URT_FRT:
urtFrtSubscriberInit(&benchmark->config->subscribers.buffer[s].frtsubscriber.subscriber);
urtFrtSubscriberSubscribe(&benchmark->config->subscribers.buffer[s].frtsubscriber.subscriber,
urtCoreGetTopic(benchmark->config->subscribers.buffer[s].topic),
TOPICEVENT,
NULL,
benchmark->config->subscribers.buffer[s].frtsubscriber.deadline,
benchmark->config->subscribers.buffer[s].frtsubscriber.jitter);
break;
case URT_HRT:
urtHrtSubscriberInit(&benchmark->config->subscribers.buffer[s].hrtsubscriber.subscriber);
urtHrtSubscriberSubscribe(&benchmark->config->subscribers.buffer[s].hrtsubscriber.subscriber,
urtCoreGetTopic(benchmark->config->subscribers.buffer[s].topic),
TOPICEVENT,
NULL,
benchmark->config->subscribers.buffer[s].hrtsubscriber.deadline,
benchmark->config->subscribers.buffer[s].hrtsubscriber.jitter,
benchmark->config->subscribers.buffer[s].hrtsubscriber.rate);
break;
}
waitevents |= TOPICEVENT;
}
#endif /* (URT_CFG_PUBSUB_ENABLED == true) */
#if (URT_CFG_RPC_ENABLED == true)
//TODO
#endif /* (URT_CFG_RPC_ENABLED == true) */
return waitevents;
}
urt_osEventMask_t _ubnLoop(urt_node_t* node, urt_osEventMask_t events, void* bn)
{
urtDebugAssert(bn != NULL);
(void)node;
// local variables
urtbenchmark_node_t* const benchmark = (urtbenchmark_node_t*)bn;
urt_osEventMask_t waitevents = 0;
// handle node benchmark
if (events & TRIGGEREVENT && benchmark->config->node.time != NULL) {
*benchmark->config->node.delays = urtTimeNow() - *benchmark->config->node.time;
++benchmark->config->node.delays;
waitevents |= TRIGGEREVENT;
}
#if (URT_CFG_PUBSUB_ENABLED == true)
// handle publisher benchmark
if (events & TRIGGEREVENT) {
for (size_t p = 0; p < benchmark->config->publishers.size; ++p) {
urtPublisherPublish(&benchmark->config->publishers.buffer[p].publisher,
benchmark->config->publishers.buffer[p].payload.buffer,
benchmark->config->publishers.buffer[p].payload.size,
(benchmark->config->publishers.buffer[p].time != NULL) ? *benchmark->config->publishers.buffer[p].time : urtTimeNow(),
benchmark->config->publishers.buffer[p].policy);
waitevents |= TRIGGEREVENT;
}
}
// handle subscriber benchmark
if (events & TOPICEVENT) {
for (size_t s = 0; s < benchmark->config->subscribers.size; ++s) {
switch (benchmark->config->subscribers.buffer[s].rtclass) {
case URT_NRT:
while (urtNrtSubscriberFetchNextMessage(&benchmark->config->subscribers.buffer[s].nrtsubscriber.subscriber,
benchmark->config->subscribers.buffer[s].payload.buffer,
benchmark->config->subscribers.buffer[s].payload.size,
NULL,
benchmark->config->subscribers.buffer[s].delays)
== URT_STATUS_OK) {
++benchmark->config->subscribers.buffer[s].delays;
}
break;
case URT_SRT:
while (urtSrtSubscriberFetchNextMessage(&benchmark->config->subscribers.buffer[s].srtsubscriber.subscriber,
benchmark->config->subscribers.buffer[s].payload.buffer,
benchmark->config->subscribers.buffer[s].payload.size,
NULL,
benchmark->config->subscribers.buffer[s].delays)
== URT_STATUS_OK) {
++benchmark->config->subscribers.buffer[s].delays;
}
break;
case URT_FRT:
while (urtFrtSubscriberFetchNextMessage(&benchmark->config->subscribers.buffer[s].frtsubscriber.subscriber,
benchmark->config->subscribers.buffer[s].payload.buffer,
benchmark->config->subscribers.buffer[s].payload.size,
NULL,
benchmark->config->subscribers.buffer[s].delays)
== URT_STATUS_OK) {
++benchmark->config->subscribers.buffer[s].delays;
}
break;
case URT_HRT:
while (urtHrtSubscriberFetchNextMessage(&benchmark->config->subscribers.buffer[s].hrtsubscriber.subscriber,
benchmark->config->subscribers.buffer[s].payload.buffer,
benchmark->config->subscribers.buffer[s].payload.size,
NULL,
benchmark->config->subscribers.buffer[s].delays)
== URT_STATUS_OK) {
++benchmark->config->subscribers.buffer[s].delays;
}
break;
}
waitevents |= TOPICEVENT;
}
}
#endif /* (URT_CFG_PUBSUB_ENABLED == true) */
#if (URT_CFG_RPC_ENABLED == true)
//TODO
#endif /* (URT_CFG_RPC_ENABLED == true) */
return waitevents;
}
void _ubnShutdown(urt_node_t* node, urt_status_t reason, void* bn)
{
urtDebugAssert(bn != NULL);
(void)node;
(void)reason;
// local variables
urtbenchmark_node_t* const benchmark = (urtbenchmark_node_t*)bn;
// shutdown node
if (benchmark->config->node.trigger != NULL) {
urtEventUnregister(benchmark->config->node.trigger, &benchmark->config->node.listener);
}
#if (URT_CFG_PUBSUB_ENABLED == true)
// shutdown publishers: nothing to do
// shutdown subscribers
for (size_t s = 0; s < benchmark->config->subscribers.size; ++s) {
switch (benchmark->config->subscribers.buffer[s].rtclass) {
case URT_NRT:
urtNrtSubscriberUnsubscribe(&benchmark->config->subscribers.buffer[s].nrtsubscriber.subscriber);
break;
case URT_SRT:
urtSrtSubscriberUnsubscribe(&benchmark->config->subscribers.buffer[s].srtsubscriber.subscriber);
break;
case URT_FRT:
urtFrtSubscriberUnsubscribe(&benchmark->config->subscribers.buffer[s].frtsubscriber.subscriber);
break;
case URT_HRT:
urtHrtSubscriberUnsubscribe(&benchmark->config->subscribers.buffer[s].hrtsubscriber.subscriber);
break;
}
}
#endif /* (URT_CFG_PUBSUB_ENABLED == true) */
#if (URT_CFG_RPC_ENABLED == true)
//TODO
#endif /* (URT_CFG_RPC_ENABLED == true) */
return;
}
/******************************************************************************/
/* EXPORTED FUNCTIONS */
/******************************************************************************/
void ubnInit(urtbenchmark_node_t* bn, urt_osThreadPrio_t prio, urtbenchmark_config_t* config)
{
urtDebugAssert(bn != NULL);
urtDebugAssert(config != NULL);
// initialize the node
urtNodeInit(&bn->node, (urt_osThread_t*)bn->thread, sizeof(bn->thread), prio,
_ubnSetup, bn,
_ubnLoop, bn,
_ubnShutdown, bn);
// set the configuration
bn->config = config;
return;
}
/*
AMiRo-Apps is a collection of applications for the Autonomous Mini Robot (AMiRo) platform.
Copyright (C) 2018..2021 Thomas Schöpping et al.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file uRT_benchmark.h
* @brief A µRT benchmark application.
*
* @addtogroup uRT_Benchmark
* @{
*/
#ifndef URT_BENCHMARK_H
#define URT_BENCHMARK_H
#include <urtbenchmarkconf.h>
#include <urt.h>
/******************************************************************************/
/* CONSTANTS */
/******************************************************************************/
#if !defined(URTBENCHMARK_STACKSIZE) || defined(__DOXYGEN__)
/**
* @brief Stack size of threads.
*/
#define URTBENCHMARK_CFG_STACKSIZE 256
#endif /* !defined(URTBENCHMARK_STACKSIZE) */
#if ((CH_CFG_USE_REGISTRY == TRUE) && !defined(URTBENCHMARK_NODENAMESIZE)) || defined(__DOXYGEN__)
/**
* @brief Maximum length of thread names.
*/
#define URTBENCHMARK_CFG_THREADNAMELENGTH 16
#endif /* ((CH_CFG_USE_REGISTRY == TRUE) && !defined(URTBENCHMARK_NODENAMESIZE)) */
/******************************************************************************/
/* SETTINGS */
/******************************************************************************/
/******************************************************************************/
/* CHECKS */
/******************************************************************************/
/******************************************************************************/
/* DATA STRUCTURES AND TYPES */
/******************************************************************************/
typedef struct urtbenchmark_configdata_payload {
uint8_t* buffer;
size_t size;
} urtbenchmark_configdata_payload_t;
#if (URT_CFG_PUBSUB_ENABLED == true) || defined(__DOXYGEN__)
typedef struct urtbenchmark_configdata_publisher {
urt_publisher_t publisher;
urt_osTime_t* time;
urt_publisher_publishpolicy_t policy;
urtbenchmark_configdata_payload_t payload;
urt_topicid_t topic;
} urtbenchmark_configdata_publisher_t;
typedef struct urtbenchmark_configdata_subscriber {
union {
struct {
urt_nrtsubscriber_t subscriber;
} nrtsubscriber;
struct {
urt_srtsubscriber_t subscriber;
urt_usefulness_f usefulnesscb;
void* params;
} srtsubscriber;
struct {
urt_frtsubscriber_t subscriber;
urt_delay_t deadline;
urt_delay_t jitter;
} frtsubscriber;
struct {
urt_hrtsubscriber_t subscriber;
urt_delay_t deadline;
urt_delay_t jitter;
urt_delay_t rate;
} hrtsubscriber;
};
urt_delay_t* delays;
urtbenchmark_configdata_payload_t payload;
urt_topicid_t topic;
urt_rtclass_t rtclass;
} urtbenchmark_configdata_subscriber_t;
#endif /* (URT_CFG_PUBSUB_ENABLED == true) */
typedef struct urtbenchmark_config {
struct {
#if (CH_CFG_USE_REGISTRY == TRUE)
char name[URTBENCHMARK_CFG_THREADNAMELENGTH];
#endif /* (CH_CFG_USE_REGISTRY == TRUE) */
urt_osEventSource_t* trigger;
urt_osEventListener_t listener;
urt_osTime_t* time;
urt_delay_t* delays;
} node;
#if (URT_CFG_PUBSUB_ENABLED == true) || defined(__DOXYGEN__)
struct {
urtbenchmark_configdata_publisher_t* buffer;
size_t size;
} publishers;
struct {
urtbenchmark_configdata_subscriber_t* buffer;
size_t size;
} subscribers;
#endif /* (URT_CFG_PUBSUB_ENABLED == true) */
#if (URT_CFG_RPC_ENABLED == true) || defined(__DOXYGEN__)
//TODO
#endif /* (URT_CFG_RPC_ENABLED == true) */
} urtbenchmark_config_t;
typedef struct urtbenchmark_node {
URT_THREAD_MEMORY(thread, URTBENCHMARK_CFG_STACKSIZE);
urt_node_t node;
urtbenchmark_config_t* config;
} urtbenchmark_node_t;
/******************************************************************************/
/* MACROS */
/******************************************************************************/
/******************************************************************************/
/* EXTERN DECLARATIONS */
/******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* defined(__cplusplus) */
void ubnInit(urtbenchmark_node_t* bn, urt_osThreadPrio_t prio, urtbenchmark_config_t* config);
#if defined(__cplusplus)
}
#endif /* defined(__cplusplus) */
/******************************************************************************/
/* INLINE FUNCTIONS */
/******************************************************************************/
#endif /* URT_BENCHMARK_H */
/** @} */
################################################################################
# AMiRo-Apps is a collection of applications for the Autonomous Mini Robot #
# (AMiRo) platform. #
# Copyright (C) 2018..2021 Thomas Schöpping et al. #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# This research/work was supported by the Cluster of Excellence Cognitive #
# Interaction Technology 'CITEC' (EXC 277) at Bielefeld University, which is #
# funded by the German Research Foundation (DFG). #
################################################################################
# absolue path to this directory
uRTBenchmarkCONF_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
# list of available/supported modules
uRTBenchmarkCONF_MODULES_DIR = $(uRTBenchmarkCONF_DIR)/modules/
uRTBenchmarkCONF_MODULES = $(patsubst $(uRTBenchmarkCONF_MODULES_DIR)%/,%,$(sort $(dir $(wildcard $(uRTBenchmarkCONF_MODULES_DIR)*/*))))
uRTBenchmarkCONF_CLEANTRGS = $(uRTBenchmarkCONF_MODULES:%=clean_%)
uRTBenchmarkCONF_FLASHTRGS = $(uRTBenchmarkCONF_MODULES:%=flash_%)
.PHONY: all clean $(uRTBenchmarkCONF_MODULES) $(uRTBenchmarkCONF_FLASHTRGS) $(uRTBenchmarkCONF_CLEANTRGS)
all:
$(MAKE) -j$(words $(uRTBenchmarkCONF_MODULES)) $(uRTBenchmarkCONF_MODULES)
clean: $(uRTBenchmarkCONF_CLEANTRGS)
$(uRTBenchmarkCONF_MODULES):
$(MAKE) -C $(uRTBenchmarkCONF_MODULES_DIR)/$@
$(uRTBenchmarkCONF_FLASHTRGS):
$(MAKE) -C $(uRTBenchmarkCONF_MODULES_DIR)/$(@:flash_%=%) flash
$(uRTBenchmarkCONF_CLEANTRGS):
$(MAKE) -C $(uRTBenchmarkCONF_MODULES_DIR)/$(@:clean_%=%) clean
################################################################################
# AMiRo-Apps is a collection of applications for the Autonomous Mini Robot #
# (AMiRo) platform. #
# Copyright (C) 2018..2021 Thomas Schöpping et al. #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# This research/work was supported by the Cluster of Excellence Cognitive #
# Interaction Technology 'CITEC' (EXC 277) at Bielefeld University, which is #
# funded by the German Research Foundation (DFG). #
################################################################################
################################################################################
# Build global options #
# NOTE: Can be overridden externally. #
# #
# Compiler options here.
ifeq ($(USE_OPT),)
USE_OPT = -O2 -fstack-usage
export USE_OPT
endif
# C specific options here (added to USE_OPT).
ifeq ($(USE_COPT),)
USE_COPT = -std=c99 -fshort-enums
export USE_COPT
endif
# C++ specific options here (added to USE_OPT).
ifeq ($(USE_CPPOPT),)
USE_CPPOPT = -fno-rtti -std=c++17
export USE_CPPOPT
endif
# Enable this if you want the linker to remove unused code and data.
ifeq ($(USE_LINK_GC),)
USE_LINK_GC = yes
export USE_LINK_GC
endif
# Linker extra options here.
ifeq ($(USE_LDOPT),)
USE_LDOPT = -lm