1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

fix(opal): Unresolved references

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
This commit is contained in:
Steffen Vogel 2024-10-31 12:49:33 +01:00
parent 1520743f73
commit b4b98287d7
5 changed files with 67 additions and 434 deletions

View file

@ -0,0 +1,66 @@
# Makefile.
#
# Author: Steffen Vogel <post@steffenvogel.de>
# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University
# SPDX-License-Identifier: Apache-2.0
# Specify program name
PROGRAM = AsyncIP
TARGET_RTLAB_ROOT ?= /usr/opalrt
RTLAB_ROOT = $(TARGET_RTLAB_ROOT)
# Intel is the default compiler
RTLAB_INTEL_COMPILER ?= 0
ifeq ($(RTLAB_INTEL_COMPILER),1)
CC = opicc
else
CC = gcc
endif
LIB_TARGET = -lpthread -lrt -lm
# Add Intel C library for compilation with gcc
ifeq ($(RTLAB_INTEL_COMPILER),0)
LIB_TARGET += -lirc -ldl
else
LD_OPTS += -diag-disable remark,warn
endif
LD := $(CC)
CC_OPTS = -std=c99 -D_GNU_SOURCE -MMD
LD_OPTS =
OBJS = main.o msg.o utils.o socket.o
ifeq ($(DEBUG),1)
CC_OPTS += -g -D_DEBUG
LD_OPTS += -g
else
CC_OPTS += -O
endif
ifneq ($(PROTOCOL),)
CC_OPTS += -DPROTOCOL=$(PROTOCOL)
endif
INCPATH = -I. -I$(RTLAB_ROOT)/common/include_target
LIBPATH = -L. $(OPAL_LIBPATH)
# The required libraries are transfered automatically in the model directory before compilation
LIBS := -lOpalAsyncApiCore -lOpalCore -lOpalUtils $(OPAL_LIBS) $(LIB_TARGET)
CFLAGS = $(CC_OPTS) $(INCPATH)
LDFLAGS = $(LD_OPTS) $(LIBPATH)
all: $(PROGRAM)
install:
\mkdir -p $(RTLAB_ROOT)/local
\chmod 755 $(RTLAB_ROOT/local
\cp -f $(PROGRAM) $(RTLAB_ROOT)/local
clean:
\rm -f $(OBJS) $(PROGRAM)
$(PROGRAM): $(OBJS)
$(LD) $(LDFLAGS) -o $@ $(OBJS) -Wl,--start-group $(LIBS) -Wl,--end-group

View file

@ -1,68 +0,0 @@
# Makefile.
#
# Author: Steffen Vogel <post@steffenvogel.de>
# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University
# SPDX-License-Identifier: Apache-2.0
TARGET = AsyncIP
VPATH = src
RTLAB_INTEL_COMPILER ?= 1
# Compiler selection
ifeq ($(RTLAB_INTEL_COMPILER),1)
CC = opicc
LD = opicpc
else
CC = gcc
LD = g++
INTEL_LIBS = -limf -lirc
INTEL_OBJS = compat.o
endif
# Support for debugging symbols
ifeq ($(DEBUG),1)
CC_DEBUG_OPTS = -g -D_DEBUG
LD_DEBUG_OPTS = -g
else
CC_DEBUG_OPTS = -O
LD_DEBUG_OPTS =
endif
TARGET_LIB = -lpthread -lm -ldl -lutil -lrt $(INTEL_LIBS)
LIBPATH = -L. $(OPAL_LIBPATH)
INCLUDES = -I. -Iinclude $(OPAL_INCPATH)
ifneq ($(RTLAB_ROOT),)
INCLUDES += -I$(RTLAB_ROOT)/common/include_target
endif
CC_OPTS = -std=c99 -D_GNU_SOURCE -MMD
LD_OPTS =
OBJS = main.o msg.o utils.o socket.o $(INTEL_OBJS)
ifneq ($(PROTOCOL),)
CC_OPTS += -DPROTOCOL=$(PROTOCOL)
endif
ADDLIB = -lOpalCore -lOpalUtils
LIBS = -lOpalAsyncApiCore $(ADDLIB) $(TARGET_LIB) $(OPAL_LIBS)
CFLAGS = -c $(CC_OPTS) $(CC_DEBUG_OPTS) $(INCLUDES)
LDFLAGS = $(LD_OPTS) $(LD_DEBUG_OPTS) $(LIBPATH)
all: $(TARGET)
install: $(TARGET)
install -m 0755 -D -t $(DESTDIR)$(PREFIX)/bin $(TARGET)
clean:
rm -f $(OBJS) $(OBJS:%.o=%.d) $(TARGET)
$(TARGET): $(OBJS)
$(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
-include $(wildcard *.d)

View file

@ -39,7 +39,7 @@ INTERNAL_IGN_SOURCE_FILE=sfun_gen_async_ctrl.c sfun_recv_async.c sfun_send_async
INTERNAL_LIBRARY2=-lOpalAsyncApiR2014b
INTERNAL_LIBRARY3=-lOpalAsyncApiCore
[ExtraPutFilesComp]
Makefile.mk=Ascii
AsyncIP.mk=Ascii
include\config.h=Ascii
include\msg.h=Ascii
include\msg_format.h=Ascii
@ -112,4 +112,3 @@ sm_send_receive_DEBUG=OFF
sm_send_receive_XHP_ENABLE=FALSE
[UserEnvVars]
PROTOCOL=VILLAS
RTLAB_INTEL_COMPILER=1

View file

@ -1,29 +0,0 @@
/* Compatibility code for GCC.
*
* OPAL-RT's libSystem.a links against some Intel
*
* Author: Steffen Vogel <post@steffenvogel.de>
* SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
size_t __intel_sse2_strlen(const char *s) { return strlen(s); }
void *_intel_fast_memset(void *b, int c, size_t len) {
return memset(b, c, len);
}
void *_intel_fast_memcpy(void *restrict dst, const void *restrict src,
size_t n) {
return memcpy(dst, src, n);
}
int _intel_fast_memcmp(const void *s1, const void *s2, size_t n) {
return memcmp(s1, s2, n);
}
void *_intel_fast_memmove(void *dest, const void *src, size_t num) {
return memmove(dest, src, num);
}

View file

@ -1,335 +0,0 @@
/** Main routine of AsyncIP.
*
* Author: Steffen Vogel <post@steffenvogel.de>
* SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University
* SPDX-License-Identifier: Apache-2.0
*********************************************************************************/
/* Standard ANSI C headers needed for this program */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <pthread.h>
/* Define RTLAB before including OpalPrint.h for messages to be sent
* to the OpalDisplay. Otherwise stdout will be used. */
#define RTLAB
#include "OpalPrint.h"
#include "AsyncApi.h"
/* This is the message format */
#include "config.h"
#include "socket.h"
#include "utils.h"
#if PROTOCOL == VILLAS
#include "msg.h"
#include "msg_format.h"
#endif
/* This is just for initializing the shared memory access to communicate
* with the RT-LAB model. It's easier to remember the arguments like this */
#define ASYNC_SHMEM_NAME argv[1]
#define ASYNC_SHMEM_SIZE atoi(argv[2])
#define PRINT_SHMEM_NAME argv[3]
/* Global Variables */
struct socket skt;
static void * SendToIPPort(void *arg)
{
unsigned int ModelState, SendID = 1, Sequence = 0;
int nbSend = 0, ret, cnt, len;
/* Data from OPAL-RT model */
double mdldata[MAX_VALUES];
int mdldata_size;
#if PROTOCOL == VILLAS
char buf[MSG_LEN(MAX_VALUES)];
struct msg *msg = (struct msg *) buf;
#elif PROTOCOL == GTNET_SKT
char buf[MAX_VALUES * sizeof(float)];
float *msg = (float *) buf;
#endif
OpalPrint("%s: SendToIPPort thread started\n", PROGNAME);
OpalGetNbAsyncSendIcon(&nbSend);
if (nbSend < 1) {
OpalPrint("%s: SendToIPPort: No transimission block for this controller. Stopping thread.\n", PROGNAME);
return NULL;
}
do {
/* This call unblocks when the 'Data Ready' line of a send icon is asserted. */
ret = OpalWaitForAsyncSendRequest(&SendID);
if (ret != EOK) {
ModelState = OpalGetAsyncModelState();
if ((ModelState != STATE_RESET) && (ModelState != STATE_STOP)) {
OpalSetAsyncSendIconError(ret, SendID);
OpalPrint("%s: OpalWaitForAsyncSendRequest(), errno %d\n", PROGNAME, ret);
}
continue;
}
/* No errors encountered yet */
OpalSetAsyncSendIconError(0, SendID);
/* Get the size of the data being sent by the unblocking SendID */
OpalGetAsyncSendIconDataLength(&mdldata_size, SendID);
cnt = mdldata_size / sizeof(double);
if (cnt > MAX_VALUES) {
OpalPrint("%s: Number of signals for SendID=%d exceeds allowed maximum (%d)\n",
PROGNAME, SendID, MAX_VALUES);
return NULL;
}
/* Read data from the model */
OpalGetAsyncSendIconData(mdldata, mdldata_size, SendID);
#if PROTOCOL == VILLAS
/* Get current time */
struct timespec now;
clock_gettime(CLOCK_REALTIME, &now);
msg->length = mdldata_size / sizeof(double);
msg->sequence = Sequence++;
msg->ts.sec = now.tv_sec;
msg->ts.nsec = now.tv_nsec;
for (int i = 0; i < msg->length; i++)
msg->data[i].f = (float) mdldata[i];
msg_hton(msg);
len = MSG_LEN(msg->length);
#elif PROTOCOL == GTNET_SKT
uint32_t *imsg = (uint32_t *) msg;
for (int i = 0; i < cnt; i++) {
msg[i] = (float) mdldata[i];
imsg[i] = htonl(imsg[i]);
}
len = mdldata_size / sizeof(double) * sizeof(float);
#else
#error Unknown protocol
#endif
/* Perform the actual write to the ip port */
ret = socket_send(&skt, (char *) msg, len);
if (ret < 0)
OpalSetAsyncSendIconError(errno, SendID);
else
OpalSetAsyncSendIconError(0, SendID);
/* This next call allows the execution of the "asynchronous" process
* to actually be synchronous with the model. To achieve this, you
* should set the "Sending Mode" in the Async_Send block to
* NEED_REPLY_BEFORE_NEXT_SEND or NEED_REPLY_NOW. This will force
* the model to wait for this process to call this
* OpalAsyncSendRequestDone function before continuing. */
OpalAsyncSendRequestDone(SendID);
/* Before continuing, we make sure that the real-time model
* has not been stopped. If it has, we quit. */
ModelState = OpalGetAsyncModelState();
} while ((ModelState != STATE_RESET) && (ModelState != STATE_STOP));
OpalPrint("%s: SendToIPPort: Finished\n", PROGNAME);
return NULL;
}
static void * RecvFromIPPort(void *arg)
{
unsigned int ModelState, RecvID = 1;
int nbRecv = 0, ret, cnt;
/* Data from OPAL-RT model */
double mdldata[MAX_VALUES];
int mdldata_size;
#if PROTOCOL == VILLAS
char buf[MSG_LEN(MAX_VALUES)];
struct msg *msg = (struct msg *) buf;
#elif PROTOCOL == GTNET_SKT
char buf[MAX_VALUES * sizeof(float)];
float *msg = (float *) buf;
#else
#error Unknown protocol
#endif
OpalPrint("%s: RecvFromIPPort thread started\n", PROGNAME);
OpalGetNbAsyncRecvIcon(&nbRecv);
if (nbRecv < 1) {
OpalPrint("%s: RecvFromIPPort: No reception block for this controller. Stopping thread.\n", PROGNAME);
return NULL;
}
do {
/* Receive message */
ret = socket_recv(&skt, (char *) msg, sizeof(buf), 1.0);
if (ret < 1) {
ModelState = OpalGetAsyncModelState();
if ((ModelState != STATE_RESET) && (ModelState != STATE_STOP)) {
if (ret == 0) /* timeout, so we continue silently */
OpalPrint("%s: Timeout while waiting for data\n", PROGNAME, errno);
if (ret == -1) /* a more serious error, so we print it */
OpalPrint("%s: Error %d while waiting for data\n", PROGNAME, errno);
continue;
}
break;
}
/* Get the number of signals to send back to the model */
OpalGetAsyncRecvIconDataLength(&mdldata_size, RecvID);
cnt = mdldata_size / sizeof(double);
if (cnt > MAX_VALUES) {
OpalPrint("%s: Number of signals for RecvID=%d (%d) exceeds allowed maximum (%d)\n",
PROGNAME, RecvID, cnt, MAX_VALUES);
return NULL;
}
#if PROTOCOL == VILLAS
msg_ntoh(msg);
ret = msg_verify(msg);
if (ret) {
OpalPrint("%s: Skipping invalid packet\n", PROGNAME);
continue;
}
if (cnt > msg->length) {
OpalPrint("%s: Number of signals for RecvID=%d (%d) exceeds what was received (%d)\n",
PROGNAME, RecvID, cnt, msg->length);
}
for (int i = 0; i < msg->length; i++) {
mdldata[i] = (double) msg->data[i].f;
printf("Data rcvd from VILLAS %f\n", mdldata[i]);
}
/* Update OPAL model */
OpalSetAsyncRecvIconStatus(msg->sequence, RecvID); /* Set the Status to the message ID */
#elif PROTOCOL == GTNET_SKT
uint32_t *imsg = (uint32_t *) msg;
for (int i = 0; i < cnt; i++)
imsg[i] = ntohl(imsg[i]);
printf("Protocol GTNET_SKT\n");
for (int i = 0; i < cnt; i++) {
mdldata[i] = (double) msg[i];
printf("Data rcvd from GTNET_SKT %f\n", mdldata[i]);
}
#else
#error Unknown protocol
#endif
OpalSetAsyncRecvIconError(0, RecvID); /* Set the Error to 0 */
OpalSetAsyncRecvIconData(mdldata, mdldata_size, RecvID);
/* Before continuing, we make sure that the real-time model
* has not been stopped. If it has, we quit. */
ModelState = OpalGetAsyncModelState();
} while ((ModelState != STATE_RESET) && (ModelState != STATE_STOP));
OpalPrint("%s: RecvFromIPPort: Finished\n", PROGNAME);
return NULL;
}
int main(int argc, char *argv[])
{
/* @todo remove after testing */
printf("*****************Starting the Application****************\n");
FILE * testfile = fopen ("testfile.txt","w");
if (testfile!=NULL)
{
fputs ("test file to check if main runs", testfile);
fclose (testfile);
}
int ret;
Opal_GenAsyncParam_Ctrl IconCtrlStruct;
pthread_t tid_send, tid_recv;
OpalPrint("%s: This is %s client version %s\n", PROGNAME, PROGNAME, VERSION);
/* Check for the proper arguments to the program */
if (argc < 4) {
printf("Invalid Arguments: 1-AsyncShmemName 2-AsyncShmemSize 3-PrintShmemName\n");
exit(0);
}
/* Enable the OpalPrint function. This prints to the OpalDisplay. */
ret = OpalSystemCtrl_Register(PRINT_SHMEM_NAME);
if (ret != EOK) {
printf("%s: ERROR: OpalPrint() access not available\n", PROGNAME);
exit(EXIT_FAILURE);
}
/* Open Share Memory created by the model. */
ret = OpalOpenAsyncMem(ASYNC_SHMEM_SIZE, ASYNC_SHMEM_NAME);
if (ret != EOK) {
OpalPrint("%s: ERROR: Model shared memory not available\n", PROGNAME);
exit(EXIT_FAILURE);
}
AssignProcToCpu0();
/* Get IP Controler Parameters (ie: ip address, port number...) and
* initialize the device on the QNX node. */
memset(&IconCtrlStruct, 0, sizeof(IconCtrlStruct));
ret = OpalGetAsyncCtrlParameters(&IconCtrlStruct, sizeof(IconCtrlStruct));
if (ret != EOK) {
OpalPrint("%s: ERROR: Could not get controller parameters (%d).\n", PROGNAME, ret);
exit(EXIT_FAILURE);
}
/* Initialize socket */
ret = socket_init(&skt, IconCtrlStruct);
if (ret != EOK) {
OpalPrint("%s: ERROR: Initialization failed.\n", PROGNAME);
exit(EXIT_FAILURE);
}
/* Start send/receive threads */
ret = pthread_create(&tid_send, NULL, SendToIPPort, NULL);
if (ret == -1)
OpalPrint("%s: ERROR: Could not create thread (SendToIPPort), errno %d\n", PROGNAME, errno);
ret = pthread_create(&tid_recv, NULL, RecvFromIPPort, NULL);
if (ret == -1)
OpalPrint("%s: ERROR: Could not create thread (RecvFromIPPort), errno %d\n", PROGNAME, errno);
/* Wait for both threads to finish */
ret = pthread_join(tid_send, NULL);
if (ret != 0)
OpalPrint("%s: ERROR: pthread_join (SendToIPPort), errno %d\n", PROGNAME, ret);
ret = pthread_join(tid_recv, NULL);
if (ret != 0)
OpalPrint("%s: ERROR: pthread_join (RecvFromIPPort), errno %d\n", PROGNAME, ret);
/* Close the ip port and shared memories */
socket_close(&skt, IconCtrlStruct);
OpalCloseAsyncMem (ASYNC_SHMEM_SIZE, ASYNC_SHMEM_NAME);
OpalSystemCtrl_UnRegister(PRINT_SHMEM_NAME);
return 0;
}