Enable Epics for RTEMS5 (posix)

This commit is contained in:
Heinz Junkes
2020-09-05 20:17:30 +02:00
committed by Brendan Chandler
parent 1b6b32e9ca
commit 8ef4d29c48
11 changed files with 489 additions and 11 deletions

View File

@ -307,7 +307,7 @@ LDLIBS = $(POSIX_LDLIBS) $(ARCH_DEP_LDLIBS) $(DEBUG_LDLIBS) $(OP_SYS_LDLIBS)\
CPPFLAGS = $($(BUILD_CLASS)_CPPFLAGS) $(POSIX_CPPFLAGS) $(OPT_CPPFLAGS)\
$(DEBUG_CPPFLAGS) $(WARN_CPPFLAGS) $(BASE_CPPFLAGS) $(TARGET_CPPFLAGS)\
$(USR_CPPFLAGS) $(CMD_CPPFLAGS) $(ARCH_DEP_CPPFLAGS) $(OP_SYS_CPPFLAGS)\
$(OP_SYS_INCLUDE_CPPFLAGS) $(CODE_CPPFLAGS) $(API_CPPFLAGS)
$(OP_SYS_INCLUDE_CPPFLAGS) $(CODE_CPPFLAGS)
#--------------------------------------------------
# ar definition default

View File

@ -104,12 +104,14 @@ OP_SYS_CFLAGS_NET_yes = -DRTEMS_LEGACY_STACK
OP_SYS_CFLAGS_NET_no = -DHAVE_SOCKADDR_SA_LEN=1
OP_SYS_CFLAGS += $(OP_SYS_CFLAGS_NET_$(RTEMS_HAS_NETWORKING))
OP_SYS_LDLIBS_posix = -ltftpfs -lbsd -lz
OP_SYS_LDLIBS_kernel = -lCom -lnfs
OP_SYS_LDLIBS += -lrtemsCom -lCom -lc -lrtemscpu $(OP_SYS_LDLIBS_$(OS_API)) -lm
OP_SYS_LDLIBS_posix_NET_yes = -ltftpfs -lbsd -lz
OP_SYS_LDLIBS_posix_NET_no = -ltftpfs -lbsd -lz
OP_SYS_LDLIBS_kernel_NET_yes = -lCom -lnfs
OP_SYS_LDLIBS_kernel_NET_no = -lCom -lnfs
OP_SYS_LDLIBS += -lrtemsCom -lCom -lc -lrtemscpu $(OP_SYS_LDLIBS_$(OS_API)_NET_$(RTEMS_HAS_NETWORKING)) -lm
OP_SYS_LDFLAGS_posix = -u POSIX_Init
OP_SYS_LDFLAGS_kernel = -u Init \
OP_SYS_LDFLAGS_kernel = $(CPU_FLAGS) -u Init \
$(PROJECT_RELEASE)/lib/no-dpmem.rel \
$(PROJECT_RELEASE)/lib/no-mp.rel \
$(PROJECT_RELEASE)/lib/no-part.rel \

View File

@ -6,6 +6,7 @@
#-------------------------------------------------------
# Include definitions from RTEMS-pc386
include $(CONFIG)/os/CONFIG.Common.RTEMS-pc386
# For Tests overwrite it with pc686
include $(CONFIG)/os/CONFIG.Common.RTEMS-pc686
RTEMS_QEMU_FIXUPS = YES

View File

@ -4,7 +4,13 @@
# Site-specific overrides go in CONFIG_SITE.Common.RTEMS-pc686
#
#-------------------------------------------------------
#
# Author: W. Eric Norum
# Canadian Light Source
# eric@cls.usask.ca
#
# All RTEMS targets use the same Makefile fragment
#
RTEMS_BSP = pc686
RTEMS_TARGET_CPU = i386
GNU_TARGET = i386-rtems
@ -24,6 +30,7 @@ include $(CONFIG)/os/CONFIG.Common.RTEMS
#
OP_SYS_LDFLAGS += -Wl,-Ttext,0x100000
# This check must appear after the above include
ifneq ($(RTEMS_VERSION),5)
$(info *** This target is not compatible with the configured RTEMS version.)

View File

@ -3,6 +3,7 @@
# Definitions for darwin-x86 host builds
# Sites may override these definitions in CONFIG_SITE.darwin-x86.Common
#-------------------------------------------------------
#support for IPv6 etc.
OP_SYS_CFLAGS += -DHAVE_SOCKADDR_SA_LEN=1
#Include definitions common to unix hosts
include $(CONFIG)/os/CONFIG.UnixCommon.Common

View File

@ -11,9 +11,6 @@
# installation. For RTEMS 5 only the major version number is
# used, but for RTEMS 4.10.2 say all 3 components are required.
#
# TRAVIS-CI:
RTEMS_VERSION = 5
RTEMS_BASE = /home/travis/.rtems
# FHI:
#RTEMS_VERSION = 5

View File

@ -47,6 +47,7 @@ int epicsNtpGetTime(char *ntpIp, struct timespec *now)
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(ntpIp);
serv_addr.sin_port = htons( portno );
// Call up the server using its IP address and port number.

View File

@ -0,0 +1,251 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author W. Eric Norum
* norume@aps.anl.gov
* 630 252 4793
*/
/*
* We want to access information which is
* normally hidden from application programs.
*/
#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ 1
#define epicsExportSharedSymbols
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rtems.h>
#include <rtems/error.h>
#include "epicsMessageQueue.h"
#include "errlog.h"
LIBCOM_API epicsMessageQueueId epicsStdCall
epicsMessageQueueCreate(unsigned int capacity, unsigned int maximumMessageSize)
{
rtems_status_code sc;
epicsMessageQueueId id = calloc(1, sizeof(*id));
rtems_interrupt_level level;
static char c1 = 'a';
static char c2 = 'a';
static char c3 = 'a';
if(!id)
return NULL;
sc = rtems_message_queue_create (rtems_build_name ('Q', c3, c2, c1),
capacity,
maximumMessageSize,
RTEMS_FIFO|RTEMS_LOCAL,
&id->id);
if (sc != RTEMS_SUCCESSFUL) {
free(id);
errlogPrintf ("Can't create message queue: %s\n", rtems_status_text (sc));
return NULL;
}
id->maxSize = maximumMessageSize;
id->localBuf = NULL;
rtems_interrupt_disable (level);
if (c1 == 'z') {
if (c2 == 'z') {
if (c3 == 'z') {
c3 = 'a';
}
else {
c3++;
}
c2 = 'a';
}
else {
c2++;
}
c1 = 'a';
}
else {
c1++;
}
rtems_interrupt_enable (level);
return id;
}
static rtems_status_code rtems_message_queue_send_timeout(
rtems_id id,
void *buffer,
uint32_t size,
rtems_interval timeout)
{
Message_queue_Control *the_message_queue;
Objects_Locations location;
CORE_message_queue_Status msg_status;
the_message_queue = _Message_queue_Get( id, &location );
switch ( location )
{
case OBJECTS_ERROR:
return RTEMS_INVALID_ID;
case OBJECTS_LOCAL:
msg_status = _CORE_message_queue_Send(
&the_message_queue->message_queue,
buffer,
size,
id,
NULL,
1,
timeout
);
_Thread_Enable_dispatch();
/*
* If we had to block, then this is where the task returns
* after it wakes up. The returned status is correct for
* non-blocking operations but if we blocked, then we need
* to look at the status in our TCB.
*/
if ( msg_status == CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT )
msg_status = _Thread_Executing->Wait.return_code;
return _Message_queue_Translate_core_message_queue_return_code( msg_status );
}
return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
}
LIBCOM_API int epicsStdCall epicsMessageQueueSend(
epicsMessageQueueId id,
void *message,
unsigned int messageSize)
{
if (rtems_message_queue_send_timeout(id->id, message, messageSize, RTEMS_NO_TIMEOUT) == RTEMS_SUCCESSFUL)
return 0;
else
return -1;
}
LIBCOM_API int epicsStdCall epicsMessageQueueSendWithTimeout(
epicsMessageQueueId id,
void *message,
unsigned int messageSize,
double timeout)
{
rtems_interval delay;
extern double rtemsTicksPerSecond_double;
/*
* Convert time to ticks
*/
if (timeout <= 0.0)
return epicsMessageQueueTrySend(id, message, messageSize);
delay = (int)(timeout * rtemsTicksPerSecond_double);
if (delay == 0)
delay++;
if (rtems_message_queue_send_timeout(id->id, message, messageSize, delay) == RTEMS_SUCCESSFUL)
return 0;
else
return -1;
}
static int receiveMessage(
epicsMessageQueueId id,
void *buffer,
uint32_t size,
uint32_t wait,
rtems_interval delay)
{
size_t rsize;
rtems_status_code sc;
if (size < id->maxSize) {
if (id->localBuf == NULL) {
id->localBuf = malloc(id->maxSize);
if (id->localBuf == NULL)
return -1;
}
rsize = receiveMessage(id, id->localBuf, id->maxSize, wait, delay);
if (rsize > size)
return -1;
memcpy(buffer, id->localBuf, rsize);
}
else {
sc = rtems_message_queue_receive(id->id, buffer, &rsize, wait, delay);
if (sc != RTEMS_SUCCESSFUL)
return -1;
}
return rsize;
}
LIBCOM_API int epicsStdCall epicsMessageQueueTryReceive(
epicsMessageQueueId id,
void *message,
unsigned int size)
{
return receiveMessage(id, message, size, RTEMS_NO_WAIT, 0);
}
LIBCOM_API int epicsStdCall epicsMessageQueueReceive(
epicsMessageQueueId id,
void *message,
unsigned int size)
{
return receiveMessage(id, message, size, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
}
LIBCOM_API int epicsStdCall epicsMessageQueueReceiveWithTimeout(
epicsMessageQueueId id,
void *message,
unsigned int size,
double timeout)
{
rtems_interval delay;
uint32_t wait;
extern double rtemsTicksPerSecond_double;
/*
* Convert time to ticks
*/
if (timeout <= 0.0) {
wait = RTEMS_NO_WAIT;
delay = 0;
}
else {
wait = RTEMS_WAIT;
delay = (int)(timeout * rtemsTicksPerSecond_double);
if (delay == 0)
delay++;
}
return receiveMessage(id, message, size, wait, delay);
}
LIBCOM_API int epicsStdCall epicsMessageQueuePending(
epicsMessageQueueId id)
{
uint32_t count;
rtems_status_code sc;
sc = rtems_message_queue_get_number_pending(id->id, &count);
if (sc != RTEMS_SUCCESSFUL) {
errlogPrintf("Message queue %x get number pending failed: %s\n",
(unsigned int)id,
rtems_status_text(sc));
return -1;
}
return count;
}
LIBCOM_API void epicsStdCall epicsMessageQueueShow(
epicsMessageQueueId id,
int level)
{
int pending = epicsMessageQueuePending(id);
if (pending >= 0)
printf ("Message queue %lx -- Pending: %d\n", (unsigned long)id, pending);
}

View File

@ -0,0 +1,29 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author W. Eric Norum
* norume@aps.anl.gov
* 630 252 4793
*/
/*
* Very thin shims around RTEMS routines
*/
#include <rtems.h>
struct epicsMessageQueueOSD {
rtems_id id;
unsigned int maxSize;
void *localBuf;
};
#define epicsMessageQueueDestroy(q) (rtems_message_queue_delete((q)->id))
#define epicsMessageQueueTrySend(q,m,l) (rtems_message_queue_send((q)->id, (m), (l)) == RTEMS_SUCCESSFUL ? 0 : -1)

View File

@ -0,0 +1,160 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author W. Eric Norum
* norume@aps.anl.gov
* 630 252 4793
*/
/*
* We want to access information which is
* normally hidden from application programs.
*/
#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ 1
#define epicsExportSharedSymbols
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rtems.h>
#include <rtems/error.h>
#include "epicsMessageQueue.h"
#include "errlog.h"
#include <epicsAtomic.h>
#include <errno.h>
#include <mqueue.h>
#include <fcntl.h>
LIBCOM_API epicsMessageQueueId epicsStdCall
epicsMessageQueueCreate(unsigned int capacity, unsigned int maximumMessageSize)
{
struct mq_attr the_attr;
epicsMessageQueueId id = (epicsMessageQueueId)calloc(1, sizeof(*id));
epicsAtomicIncrIntT(&id->idCnt);
sprintf(id->name, "MQ_%01d", epicsAtomicGetIntT(&id->idCnt));
the_attr.mq_maxmsg = capacity;
the_attr.mq_msgsize = maximumMessageSize;
id->id = mq_open(id->name, O_RDWR | O_CREAT | O_EXCL, 0644, &the_attr);
if (id->id <0) {
fprintf (stderr, "Can't create message queue: %s\n", strerror (errno));
return NULL;
}
return id;
}
LIBCOM_API void epicsStdCall epicsMessageQueueDestroy(
epicsMessageQueueId id)
{
int rv;
rv = mq_close(id->id);
if( rv ) {
fprintf(stderr, "epicsMessageQueueDestroy mq_close failed: %s\n",
strerror(rv));
}
rv = mq_unlink(id->name);
if( rv ) {
fprintf(stderr,"epicsMessageQueueDestroy mq_unlink %s failed: %s\n",
id->name, strerror(rv));
}
free(id);
}
LIBCOM_API int epicsStdCall epicsMessageQueueTrySend(
epicsMessageQueueId id,
void *message,
unsigned int messageSize)
{
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return mq_timedsend(id->id, (char const *)message, messageSize, 0, &ts);
}
LIBCOM_API int epicsStdCall epicsMessageQueueSendWithTimeout(
epicsMessageQueueId id,
void *message,
unsigned int messageSize,
double timeout)
{
struct timespec ts;
unsigned long micros;
// assume timeout in sec
micros = (unsigned long)(timeout * 1000000.0);
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += micros / 1000000L;
ts.tv_nsec += (micros % 1000000L) * 1000L;
return mq_timedsend (id->id, (const char *)message, messageSize, 0, &ts);
}
LIBCOM_API int epicsStdCall epicsMessageQueueTryReceive(
epicsMessageQueueId id,
void *message,
unsigned int size)
{
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return mq_timedreceive(id->id, (char *)message, size, NULL, &ts);
}
LIBCOM_API int epicsStdCall epicsMessageQueueReceiveWithTimeout(
epicsMessageQueueId id,
void *message,
unsigned int size,
double timeout)
{
unsigned long micros;
struct timespec ts;
micros = (unsigned long)(timeout * 1000000.0);
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += micros / 1000000L;
ts.tv_nsec += (micros % 1000000L) * 1000L;
return mq_timedreceive(id->id, (char *)message, size, NULL, &ts);
}
LIBCOM_API int epicsStdCall epicsMessageQueuePending(
epicsMessageQueueId id)
{
int rv;
struct mq_attr the_attr;
rv = mq_getattr(id->id, &the_attr);
if (rv) {
fprintf(stderr, "Epics Message queue %x (%s) get attr failed: %s\n",
(unsigned int)id->id, id->name, strerror(rv));
return -1;
}
return the_attr.mq_curmsgs;
}
LIBCOM_API void epicsStdCall epicsMessageQueueShow(
epicsMessageQueueId id,
int level)
{
int rv;
struct mq_attr the_attr;
rv = mq_getattr(id->id, &the_attr);
if (rv) {
fprintf(stderr, "Epics Message queue %x (%s) get attr failed: %s\n",
(unsigned int)id->id, id->name, strerror(rv));
}
printf("Message Queue Used:%ld Max Msg:%lu", the_attr.mq_curmsgs, the_attr.mq_maxmsg);
if (level >= 1)
printf(" Maximum size:%lu", the_attr.mq_msgsize);
printf("\n");
}

View File

@ -0,0 +1,29 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author W. Eric Norum
* norume@aps.anl.gov
* 630 252 4793
*/
/*
* Very thin shims around RTEMS routines
*/
#include <rtems.h>
#include <mqueue.h>
struct epicsMessageQueueOSD {
mqd_t id;
char name[24];
int idCnt;
};
#define epicsMessageQueueSend(q,m,l) (mq_send((q)->id, (const char*)(m), (l), 0))
#define epicsMessageQueueReceive(q,m,s) (mq_receive((q)->id, (char*)(m), (s), NULL))