diff --git a/configure/CONFIG_COMMON b/configure/CONFIG_COMMON index d56802968..9ccdf2804 100644 --- a/configure/CONFIG_COMMON +++ b/configure/CONFIG_COMMON @@ -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 diff --git a/configure/os/CONFIG.Common.RTEMS b/configure/os/CONFIG.Common.RTEMS index 610057d53..2d9243a60 100644 --- a/configure/os/CONFIG.Common.RTEMS +++ b/configure/os/CONFIG.Common.RTEMS @@ -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 \ diff --git a/configure/os/CONFIG.Common.RTEMS-pc386-qemu b/configure/os/CONFIG.Common.RTEMS-pc386-qemu index 684f01a19..29196ff65 100644 --- a/configure/os/CONFIG.Common.RTEMS-pc386-qemu +++ b/configure/os/CONFIG.Common.RTEMS-pc386-qemu @@ -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 diff --git a/configure/os/CONFIG.Common.RTEMS-pc686 b/configure/os/CONFIG.Common.RTEMS-pc686 index 7f9446e1e..882a2f3cb 100644 --- a/configure/os/CONFIG.Common.RTEMS-pc686 +++ b/configure/os/CONFIG.Common.RTEMS-pc686 @@ -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.) diff --git a/configure/os/CONFIG.darwin-x86.Common b/configure/os/CONFIG.darwin-x86.Common index e779f7dc1..960c74b8a 100644 --- a/configure/os/CONFIG.darwin-x86.Common +++ b/configure/os/CONFIG.darwin-x86.Common @@ -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 diff --git a/configure/os/CONFIG_SITE.Common.RTEMS b/configure/os/CONFIG_SITE.Common.RTEMS index 9b44101eb..18d62ddca 100644 --- a/configure/os/CONFIG_SITE.Common.RTEMS +++ b/configure/os/CONFIG_SITE.Common.RTEMS @@ -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 diff --git a/modules/libcom/RTEMS/epicsNtp.c b/modules/libcom/RTEMS/epicsNtp.c index 8f4e70ada..9dcd6cd69 100644 --- a/modules/libcom/RTEMS/epicsNtp.c +++ b/modules/libcom/RTEMS/epicsNtp.c @@ -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. diff --git a/modules/libcom/src/osi/os/RTEMS-kernel/osdMessageQueue.c b/modules/libcom/src/osi/os/RTEMS-kernel/osdMessageQueue.c new file mode 100644 index 000000000..c7a05fcc5 --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-kernel/osdMessageQueue.c @@ -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 +#include +#include +#include +#include +#include +#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); +} diff --git a/modules/libcom/src/osi/os/RTEMS-kernel/osdMessageQueue.h b/modules/libcom/src/osi/os/RTEMS-kernel/osdMessageQueue.h new file mode 100644 index 000000000..0244a1f0b --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-kernel/osdMessageQueue.h @@ -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 + +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) diff --git a/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.c b/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.c new file mode 100644 index 000000000..3774ef2d8 --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.c @@ -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 +#include +#include +#include +#include +#include +#include "epicsMessageQueue.h" +#include "errlog.h" +#include + +#include +#include +#include + +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"); +} diff --git a/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.h b/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.h new file mode 100644 index 000000000..0311ee486 --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.h @@ -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 +#include + +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)) \ No newline at end of file