beremiz

Parents d2b0c768755d
Children 0375d801fff7
Runtime+SVGHMI: Added a generic way to wakeup non-real-time threads from real-time PLC thread. Replace SVGHMI specific calls in Linux and Xenomai implementations of plc_main.c. Fixed xenomai build, xeno-config making problems with --no-auto-init argument.
--- a/svghmi/svghmi.c Thu Jul 29 11:59:28 2021 +0200
+++ b/svghmi/svghmi.c Mon Aug 16 22:49:08 2021 +0200
@@ -208,8 +208,17 @@
return 0;
}
-void SVGHMI_SuspendFromPythonThread(void);
-void SVGHMI_WakeupFromRTThread(void);
+static void *svghmi_handle;
+
+void SVGHMI_SuspendFromPythonThread(void)
+{
+ wait_RT_to_nRT_signal(svghmi_handle);
+}
+
+void SVGHMI_WakeupFromRTThread(void)
+{
+ unblock_RT_to_nRT_signal(svghmi_handle);
+}
int svghmi_continue_collect;
@@ -220,6 +229,12 @@
svghmi_continue_collect = 1;
+ /* create svghmi_pipe */
+ svghmi_handle = create_RT_to_nRT_signal("SVGHMI_pipe");
+
+ if(!svghmi_handle)
+ return 1;
+
return 0;
}
@@ -227,6 +242,7 @@
{
svghmi_continue_collect = 0;
SVGHMI_WakeupFromRTThread();
+ delete_RT_to_nRT_signal(svghmi_handle);
}
void __retrieve_svghmi()
--- a/targets/Linux/plc_Linux_main.c Thu Jul 29 11:59:28 2021 +0200
+++ b/targets/Linux/plc_Linux_main.c Mon Aug 16 22:49:08 2021 +0200
@@ -239,14 +239,53 @@
static pthread_cond_t svghmi_send_WakeCond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t svghmi_send_WakeCondLock = PTHREAD_MUTEX_INITIALIZER;
-void SVGHMI_SuspendFromPythonThread(void)
-{
- pthread_mutex_lock(&svghmi_send_WakeCondLock);
- pthread_cond_wait(&svghmi_send_WakeCond, &svghmi_send_WakeCondLock);
- pthread_mutex_unlock(&svghmi_send_WakeCondLock);
+struct RT_to_nRT_signal_s {
+ pthread_cond_t WakeCond;
+ pthread_mutex_t WakeCondLock;
+};
+
+typedef struct RT_to_nRT_signal_s RT_to_nRT_signal_t;
+
+#define _LogAndReturnNull(text) \
+ {\
+ char mstr[256] = text " for ";\
+ strncat(mstr, name, 255);\
+ LogMessage(LOG_CRITICAL, mstr, strlen(mstr));\
+ return NULL;\
+ }
+
+void *create_RT_to_nRT_signal(char* name){
+ RT_to_nRT_signal_t *sig = (RT_to_nRT_signal_t*)malloc(sizeof(RT_to_nRT_signal_t));
+
+ if(!sig)
+ _LogAndReturnNull("Failed allocating memory for RT_to_nRT signal");
+
+ pthread_cond_init(&sig->WakeCond, NULL);
+ pthread_mutex_init(&sig->WakeCondLock, NULL);
+
+ return (void*)sig;
}
-void SVGHMI_WakeupFromRTThread(void)
-{
- pthread_cond_signal(&svghmi_send_WakeCond);
+void delete_RT_to_nRT_signal(void* handle){
+ RT_to_nRT_signal_t *sig = (RT_to_nRT_signal_t*)handle;
+
+ pthread_cond_destroy(&sig->WakeCond);
+ pthread_mutex_destroy(&sig->WakeCondLock);
+
+ free(sig);
}
+
+int wait_RT_to_nRT_signal(void* handle){
+ int ret;
+ RT_to_nRT_signal_t *sig = (RT_to_nRT_signal_t*)handle;
+ pthread_mutex_lock(&sig->WakeCondLock);
+ ret = pthread_cond_wait(&sig->WakeCond, &sig->WakeCondLock);
+ pthread_mutex_unlock(&sig->WakeCondLock);
+ return ret;
+}
+
+int unblock_RT_to_nRT_signal(void* handle){
+ RT_to_nRT_signal_t *sig = (RT_to_nRT_signal_t*)handle;
+ return pthread_cond_signal(&sig->WakeCond);
+}
+
--- a/targets/Xenomai/__init__.py Thu Jul 29 11:59:28 2021 +0200
+++ b/targets/Xenomai/__init__.py Mon Aug 16 22:49:08 2021 +0200
@@ -37,7 +37,7 @@
if xeno_config:
from util.ProcessLogger import ProcessLogger
status, result, _err_result = ProcessLogger(self.CTRInstance.logger,
- xeno_config + " --skin=posix --skin=alchemy --no-auto-init --"+flagsname,
+ xeno_config + " --skin=posix --skin=alchemy "+flagsname,
no_stdout=True).spin()
if status:
self.CTRInstance.logger.write_error(_("Unable to get Xenomai's %s \n") % flagsname)
@@ -45,9 +45,9 @@
return []
def getBuilderLDFLAGS(self):
- xeno_ldflags = self.getXenoConfig("ldflags")
+ xeno_ldflags = self.getXenoConfig("--no-auto-init --ldflags")
return toolchain_gcc.getBuilderLDFLAGS(self) + xeno_ldflags + ["-shared"]
def getBuilderCFLAGS(self):
- xeno_cflags = self.getXenoConfig("cflags")
+ xeno_cflags = self.getXenoConfig("--cflags")
return toolchain_gcc.getBuilderCFLAGS(self) + xeno_cflags + ["-fPIC"]
--- a/targets/Xenomai/plc_Xenomai_main.c Thu Jul 29 11:59:28 2021 +0200
+++ b/targets/Xenomai/plc_Xenomai_main.c Mon Aug 16 22:49:08 2021 +0200
@@ -18,27 +18,11 @@
unsigned int PLC_state = 0;
#define PLC_STATE_TASK_CREATED 1
-#define PLC_STATE_DEBUG_FILE_OPENED 2
-#define PLC_STATE_DEBUG_PIPE_CREATED 4
-#define PLC_STATE_PYTHON_FILE_OPENED 8
-#define PLC_STATE_PYTHON_PIPE_CREATED 16
-#define PLC_STATE_WAITDEBUG_FILE_OPENED 32
-#define PLC_STATE_WAITDEBUG_PIPE_CREATED 64
-#define PLC_STATE_WAITPYTHON_FILE_OPENED 128
-#define PLC_STATE_WAITPYTHON_PIPE_CREATED 256
-#define PLC_STATE_SVGHMI_FILE_OPENED 512
-#define PLC_STATE_SVGHMI_PIPE_CREATED 1024
+#define PLC_STATE_DEBUG_PIPE_CREATED 2
+#define PLC_STATE_PYTHON_PIPE_CREATED 8
+#define PLC_STATE_WAITDEBUG_PIPE_CREATED 16
+#define PLC_STATE_WAITPYTHON_PIPE_CREATED 32
-#define WAITDEBUG_PIPE_DEVICE "/dev/rtp0"
-#define WAITDEBUG_PIPE_MINOR 0
-#define DEBUG_PIPE_DEVICE "/dev/rtp1"
-#define DEBUG_PIPE_MINOR 1
-#define WAITPYTHON_PIPE_DEVICE "/dev/rtp2"
-#define WAITPYTHON_PIPE_MINOR 2
-#define PYTHON_PIPE_DEVICE "/dev/rtp3"
-#define PYTHON_PIPE_MINOR 3
-#define SVGHMI_PIPE_DEVICE "/dev/rtp4"
-#define SVGHMI_PIPE_MINOR 4
#define PIPE_SIZE 1
// rt-pipes commands
@@ -68,16 +52,36 @@
}
RT_TASK PLC_task;
-RT_PIPE WaitDebug_pipe;
-RT_PIPE WaitPython_pipe;
-RT_PIPE Debug_pipe;
-RT_PIPE Python_pipe;
-RT_PIPE svghmi_pipe;
-int WaitDebug_pipe_fd;
-int WaitPython_pipe_fd;
-int Debug_pipe_fd;
-int Python_pipe_fd;
-int svghmi_pipe_fd;
+void *WaitDebug_handle;
+void *WaitPython_handle;
+void *Debug_handle;
+void *Python_handle;
+void *svghmi_handle;
+
+struct RT_to_nRT_signal_s {
+ int used;
+ RT_PIPE pipe;
+ int pipe_fd;
+ char *name;
+};
+typedef struct RT_to_nRT_signal_s RT_to_nRT_signal_t;
+
+#define max_RT_to_nRT_signals 16
+
+static RT_to_nRT_signal_t RT_to_nRT_signal_pool[max_RT_to_nRT_signals];
+
+int recv_RT_to_nRT_signal(void* handle, char* payload){
+ RT_to_nRT_signal_t *sig = (RT_to_nRT_signal_t*)handle;
+ if(!sig->used) return -EINVAL;
+ return read(sig->pipe_fd, payload, 1);
+}
+
+int send_RT_to_nRT_signal(void* handle, char payload){
+ RT_to_nRT_signal_t *sig = (RT_to_nRT_signal_t*)handle;
+ if(!sig->used) return -EINVAL;
+ return rt_pipe_write(&sig->pipe, &payload, 1, P_NORMAL);
+}
+
int PLC_shutdown = 0;
@@ -102,17 +106,85 @@
{
/* explicitely finish python thread */
char msg = PYTHON_FINISH;
- rt_pipe_write(&WaitPython_pipe, &msg, sizeof(msg), P_NORMAL);
+ send_RT_to_nRT_signal(WaitPython_handle, msg);
}
{
/* explicitely finish debug thread */
char msg = DEBUG_FINISH;
- rt_pipe_write(&WaitDebug_pipe, &msg, sizeof(msg), P_NORMAL);
+ send_RT_to_nRT_signal(WaitDebug_handle, msg);
}
}
static unsigned long __debug_tick;
+#define _LogAndReturnNull(text) \
+ {\
+ char mstr[256] = text " for ";\
+ strncat(mstr, name, 255);\
+ LogMessage(LOG_CRITICAL, mstr, strlen(mstr));\
+ return NULL;\
+ }
+
+void *create_RT_to_nRT_signal(char* name){
+ int new_index = -1;
+ RT_to_nRT_signal_t *sig;
+ char pipe_dev[64];
+
+ /* find a free slot */
+ for(int i=0; i < max_RT_to_nRT_signals; i++){
+ sig = &RT_to_nRT_signal_pool[i];
+ if(!sig->used){
+ new_index = i;
+ break;
+ }
+ }
+
+ /* fail if none found */
+ if(new_index == -1) {
+ _LogAndReturnNull("Maximum count of RT-PIPE reached while creating pipe");
+ }
+
+ /* create rt pipe */
+ if(rt_pipe_create(&sig->pipe, name, new_index, PIPE_SIZE) < 0){
+ _LogAndReturnNull("Failed opening real-time end of RT-PIPE");
+ }
+
+ /* open pipe's userland */
+ snprintf(pipe_dev, 64, "/dev/rtp%d", new_index);
+ if((sig->pipe_fd = open(pipe_dev, O_RDWR)) == -1){
+ rt_pipe_delete(&sig->pipe);
+ _LogAndReturnNull("Failed opening non-real-time end of RT-PIPE");
+ }
+
+ sig->used = 1;
+ sig->name = name;
+
+ return sig;
+}
+
+void delete_RT_to_nRT_signal(void* handle){
+ RT_to_nRT_signal_t *sig = (RT_to_nRT_signal_t*)handle;
+
+ if(!sig->used) return;
+
+ rt_pipe_delete(&sig->pipe);
+
+ close(sig->pipe_fd);
+
+ sig->used = 0;
+}
+
+int wait_RT_to_nRT_signal(void* handle){
+ char cmd;
+ int ret = recv_RT_to_nRT_signal(handle, &cmd);
+ return (ret == 1) ? 0 : ((ret == 0) ? ENODATA : -ret);
+}
+
+int unblock_RT_to_nRT_signal(void* handle){
+ int ret = send_RT_to_nRT_signal(handle, 0);
+ return (ret == 1) ? 0 : ((ret == 0) ? EINVAL : -ret);
+}
+
void PLC_cleanup_all(void)
{
if (PLC_state & PLC_STATE_TASK_CREATED) {
@@ -120,56 +192,25 @@
PLC_state &= ~PLC_STATE_TASK_CREATED;
}
- if (PLC_state & PLC_STATE_SVGHMI_PIPE_CREATED) {
- rt_pipe_delete(&svghmi_pipe);
- PLC_state &= ~PLC_STATE_SVGHMI_PIPE_CREATED;
- }
-
- if (PLC_state & PLC_STATE_SVGHMI_FILE_OPENED) {
- close(svghmi_pipe_fd);
- PLC_state &= ~PLC_STATE_SVGHMI_FILE_OPENED;
- }
-
if (PLC_state & PLC_STATE_WAITDEBUG_PIPE_CREATED) {
- rt_pipe_delete(&WaitDebug_pipe);
+ delete_RT_to_nRT_signal(WaitDebug_handle);
PLC_state &= ~PLC_STATE_WAITDEBUG_PIPE_CREATED;
}
- if (PLC_state & PLC_STATE_WAITDEBUG_FILE_OPENED) {
- close(WaitDebug_pipe_fd);
- PLC_state &= ~PLC_STATE_WAITDEBUG_FILE_OPENED;
- }
-
if (PLC_state & PLC_STATE_WAITPYTHON_PIPE_CREATED) {
- rt_pipe_delete(&WaitPython_pipe);
+ delete_RT_to_nRT_signal(WaitPython_handle);
PLC_state &= ~PLC_STATE_WAITPYTHON_PIPE_CREATED;
}
- if (PLC_state & PLC_STATE_WAITPYTHON_FILE_OPENED) {
- close(WaitPython_pipe_fd);
- PLC_state &= ~PLC_STATE_WAITPYTHON_FILE_OPENED;
- }
-
if (PLC_state & PLC_STATE_DEBUG_PIPE_CREATED) {
- rt_pipe_delete(&Debug_pipe);
+ delete_RT_to_nRT_signal(Debug_handle);
PLC_state &= ~PLC_STATE_DEBUG_PIPE_CREATED;
}
- if (PLC_state & PLC_STATE_DEBUG_FILE_OPENED) {
- close(Debug_pipe_fd);
- PLC_state &= ~PLC_STATE_DEBUG_FILE_OPENED;
- }
-
if (PLC_state & PLC_STATE_PYTHON_PIPE_CREATED) {
- rt_pipe_delete(&Python_pipe);
+ delete_RT_to_nRT_signal(Python_handle);
PLC_state &= ~PLC_STATE_PYTHON_PIPE_CREATED;
}
-
- if (PLC_state & PLC_STATE_PYTHON_FILE_OPENED) {
- close(Python_pipe_fd);
- PLC_state &= ~PLC_STATE_PYTHON_FILE_OPENED;
- }
-
}
int stopPLC()
@@ -213,59 +254,28 @@
/* no memory swapping for that process */
mlockall(MCL_CURRENT | MCL_FUTURE);
+
+ /* memory initialization */
PLC_shutdown = 0;
-
- /*** RT Pipes creation and opening ***/
- /* create Debug_pipe */
- if(rt_pipe_create(&Debug_pipe, "Debug_pipe", DEBUG_PIPE_MINOR, PIPE_SIZE) < 0)
- _startPLCLog(FO "Debug_pipe real-time end");
- PLC_state |= PLC_STATE_DEBUG_PIPE_CREATED;
+ bzero(RT_to_nRT_signal_pool, sizeof(RT_to_nRT_signal_pool));
- /* open Debug_pipe*/
- if((Debug_pipe_fd = open(DEBUG_PIPE_DEVICE, O_RDWR)) == -1)
- _startPLCLog(FO DEBUG_PIPE_DEVICE);
- PLC_state |= PLC_STATE_DEBUG_FILE_OPENED;
-
+ /*** RT Pipes ***/
+ /* create Debug_pipe */
+ if(Debug_handle = create_RT_to_nRT_signal("Debug_pipe")) goto error;
+ PLC_state |= PLC_STATE_DEBUG_PIPE_CREATED;
+
/* create Python_pipe */
- if(rt_pipe_create(&Python_pipe, "Python_pipe", PYTHON_PIPE_MINOR, PIPE_SIZE) < 0)
- _startPLCLog(FO "Python_pipe real-time end");
+ if(Python_handle = create_RT_to_nRT_signal("Python_pipe")) goto error;
PLC_state |= PLC_STATE_PYTHON_PIPE_CREATED;
- /* open Python_pipe*/
- if((Python_pipe_fd = open(PYTHON_PIPE_DEVICE, O_RDWR)) == -1)
- _startPLCLog(FO PYTHON_PIPE_DEVICE);
- PLC_state |= PLC_STATE_PYTHON_FILE_OPENED;
-
/* create WaitDebug_pipe */
- if(rt_pipe_create(&WaitDebug_pipe, "WaitDebug_pipe", WAITDEBUG_PIPE_MINOR, PIPE_SIZE) < 0)
- _startPLCLog(FO "WaitDebug_pipe real-time end");
+ if(WaitDebug_handle = create_RT_to_nRT_signal("WaitDebug_pipe")) goto error;
PLC_state |= PLC_STATE_WAITDEBUG_PIPE_CREATED;
- /* open WaitDebug_pipe*/
- if((WaitDebug_pipe_fd = open(WAITDEBUG_PIPE_DEVICE, O_RDWR)) == -1)
- _startPLCLog(FO WAITDEBUG_PIPE_DEVICE);
- PLC_state |= PLC_STATE_WAITDEBUG_FILE_OPENED;
-
/* create WaitPython_pipe */
- if(rt_pipe_create(&WaitPython_pipe, "WaitPython_pipe", WAITPYTHON_PIPE_MINOR, PIPE_SIZE) < 0)
- _startPLCLog(FO "WaitPython_pipe real-time end");
+ if(WaitPython_handle = create_RT_to_nRT_signal("WaitPython_pipe")) goto error;
PLC_state |= PLC_STATE_WAITPYTHON_PIPE_CREATED;
- /* open WaitPython_pipe*/
- if((WaitPython_pipe_fd = open(WAITPYTHON_PIPE_DEVICE, O_RDWR)) == -1)
- _startPLCLog(FO WAITPYTHON_PIPE_DEVICE);
- PLC_state |= PLC_STATE_WAITPYTHON_FILE_OPENED;
-
- /* create svghmi_pipe */
- if(rt_pipe_create(&svghmi_pipe, "svghmi_pipe", SVGHMI_PIPE_MINOR, PIPE_SIZE) < 0)
- _startPLCLog(FO "svghmi_pipe real-time end");
- PLC_state |= PLC_STATE_SVGHMI_PIPE_CREATED;
-
- /* open svghmi_pipe*/
- if((svghmi_pipe_fd = open(SVGHMI_PIPE_DEVICE, O_RDWR)) == -1)
- _startPLCLog(FO SVGHMI_PIPE_DEVICE);
- PLC_state |= PLC_STATE_SVGHMI_FILE_OPENED;
-
/*** create PLC task ***/
if(rt_task_create(&PLC_task, "PLC_task", 0, 50, T_JOINABLE))
_startPLCLog("Failed creating PLC task");
@@ -309,7 +319,7 @@
DEBUG_BUSY, DEBUG_FREE) == DEBUG_BUSY){
char msg = DEBUG_UNLOCK;
/* signal to NRT for wakeup */
- rt_pipe_write(&Debug_pipe, &msg, sizeof(msg), P_NORMAL);
+ send_RT_to_nRT_signal(Debug_handle, msg);
}
}
@@ -321,8 +331,8 @@
int res;
if (PLC_shutdown) return -1;
/* Wait signal from PLC thread */
- res = read(WaitDebug_pipe_fd, &cmd, sizeof(cmd));
- if (res == sizeof(cmd) && cmd == DEBUG_PENDING_DATA){
+ recv_RT_to_nRT_signal(WaitDebug_handle, &cmd);
+ if (res == 1 && cmd == DEBUG_PENDING_DATA){
*tick = __debug_tick;
return 0;
}
@@ -337,7 +347,7 @@
/* remember tick */
__debug_tick = __tick;
/* signal debugger thread it can read data */
- rt_pipe_write(&WaitDebug_pipe, &msg, sizeof(msg), P_NORMAL);
+ send_RT_to_nRT_signal(WaitDebug_handle, msg);
}
int suspendDebug(int disable)
@@ -349,7 +359,7 @@
DEBUG_FREE,
DEBUG_BUSY) != DEBUG_FREE &&
cmd == DEBUG_UNLOCK){
- if(read(Debug_pipe_fd, &cmd, sizeof(cmd)) != sizeof(cmd)){
+ if(recv_RT_to_nRT_signal(Debug_handle, &cmd) != 1){
return -1;
}
}
@@ -373,7 +383,7 @@
char cmd;
if (PLC_shutdown) return -1;
/* Wait signal from PLC thread */
- if(read(WaitPython_pipe_fd, &cmd, sizeof(cmd))==sizeof(cmd) && cmd==PYTHON_PENDING_COMMAND){
+ if(recv_RT_to_nRT_signal(WaitPython_handle, &cmd) == 1 && cmd==PYTHON_PENDING_COMMAND){
return 0;
}
return -1;
@@ -383,7 +393,7 @@
void UnBlockPythonCommands(void)
{
char msg = PYTHON_PENDING_COMMAND;
- rt_pipe_write(&WaitPython_pipe, &msg, sizeof(msg), P_NORMAL);
+ send_RT_to_nRT_signal(WaitPython_handle, msg);
}
int TryLockPython(void)
@@ -404,7 +414,7 @@
PYTHON_FREE,
PYTHON_BUSY) != PYTHON_FREE &&
cmd == UNLOCK_PYTHON){
- read(Python_pipe_fd, &cmd, sizeof(cmd));
+ recv_RT_to_nRT_signal(Python_handle, &cmd);
}
}
@@ -416,23 +426,11 @@
PYTHON_FREE) == PYTHON_BUSY){
if(rt_task_self()){/*is that the real time task ?*/
char cmd = UNLOCK_PYTHON;
- rt_pipe_write(&Python_pipe, &cmd, sizeof(cmd), P_NORMAL);
+ send_RT_to_nRT_signal(Python_handle, cmd);
}/* otherwise, no signaling from non real time */
} /* as plc does not wait for lock. */
}
-void SVGHMI_SuspendFromPythonThread(void)
-{
- char cmd = 1; /*whatever*/
- read(svghmi_pipe_fd, &cmd, sizeof(cmd));
-}
-
-void SVGHMI_WakeupFromRTThread(void)
-{
- char cmd;
- rt_pipe_write(&svghmi_pipe, &cmd, sizeof(cmd), P_NORMAL);
-}
-
#ifndef HAVE_RETAIN
int CheckRetainBuffer(void)
{
--- a/targets/beremiz.h Thu Jul 29 11:59:28 2021 +0200
+++ b/targets/beremiz.h Mon Aug 16 22:49:08 2021 +0200
@@ -26,5 +26,9 @@
#endif
long AtomicCompareExchange(long* atomicvar,long compared, long exchange);
+void *create_RT_to_nRT_signal(char* name);
+void delete_RT_to_nRT_signal(void* handle);
+int wait_RT_to_nRT_signal(void* handle);
+int unblock_RT_to_nRT_signal(void* handle);
#endif