Commit cf58207e authored by yoogx's avatar yoogx

* Add minepump example

parent bfd616d9
AADL_SOURCES = $(srcdir)/minepump.aadl
AADL_ROOT = minepump.impl
OTHER_FILES = $(srcdir)/minepump.c $(srcdir)/simu.c $(srcdir)/simu.h
CLEANDIRS = minepump_impl
CLEANFILES = *.lnt demo.svl
include $(srcdir)/../Makefile.common
AVAILABLE_TARGETS= parse-aadl c
package MinePump
public
with Data_Model; -- For data representation (integer, ...)
with Deployment; -- For execution platform
-- Basic integer data type
data Int
-- Definition of an integer type
properties
Data_Model::Data_Representation => Integer;
end Int;
-- WaterLevelMonitorig task
thread WaterLevelMonitoring
features
WaterAlarm : out data port Int;
properties
Dispatch_Protocol => Periodic; -- Concurrency configuration
Period => 250 ms;
Compute_Execution_Time => 1 ms .. 2 ms;
Priority => 2;
Source_Language => (C); -- Link to code source
Compute_Entrypoint_Source_Text => "waterlevelmonitoring_body";
Source_Text => ("minepump.c");
end WaterLevelMonitoring;
-- MethaneMonitoring task
thread MethaneMonitoring
features
MethaneLevel : out data port int;
properties
Dispatch_Protocol => Periodic; -- Concurrency configuration
Period => 100 ms;
Compute_Execution_Time => 1 ms .. 2 ms;
Priority => 2;
Source_Language => (C); -- Link to code source
Compute_Entrypoint_Source_Text => "methanemonitoring_body";
Source_Text => ("minepump.c");
end MethaneMonitoring;
thread PumpCtrl
features
MethaneLevel : in event data port int;
WaterLevel : in event data port int;
WaterAlarm : out data port Int;
properties
Dispatch_Protocol => Sporadic; -- Concurrency configuration
Period => 100 ms;
Compute_Execution_Time => 1 ms .. 2 ms;
Priority => 2;
Source_Language => (C); -- Link to code source
Compute_Entrypoint_Source_Text => "pumpctrl_body";
Source_Text => "minepump.c";
end PumpCtrl;
thread WaterAlarm
features
WaterAlarm : in event data port Int;
properties
Dispatch_Protocol => Sporadic; -- Concurrency configuration
Period => 100 ms;
Compute_Execution_Time => 1 ms .. 2 ms;
Priority => 2;
Source_Language => (C); -- Link to code source
Compute_Entrypoint_Source_Text => "wateralarm_body";
Source_Text => "minepump.c";
end WaterAlarm;
-- MinePump software process
process MinePump_Software
end MinePump_Software;
process implementation MinePump_Software.impl
subcomponents
WaterLevelMonitoring_Thread : thread WaterLevelMonitoring;
MethaneMonitoring_Thread : thread MethaneMonitoring;
PumpCtrl_Thread : thread PumpCtrl;
WaterAlarm_Thread : thread WaterAlarm;
connections
C1 : port MethaneMonitoring_Thread.MethaneLevel
-> PumpCtrl_Thread.MethaneLevel;
C2 : port WaterLevelMonitoring_Thread.WaterAlarm
-> PumpCtrl_Thread.WaterLevel;
C3 : port PumpCtrl_Thread.WaterAlarm
-> WaterAlarm_Thread.WaterAlarm;
end MinePump_Software.impl;
processor CPU
properties
Scheduling_Protocol => (POSIX_1003_HIGHEST_PRIORITY_FIRST_PROTOCOL);
Deployment::Execution_Platform => Native;
end CPU;
system MinePump
end MinePump;
system implementation MinePump.impl
subcomponents
Software : process MinePump_Software.impl;
Hardware : processor CPU;
properties
Actual_Processor_Binding => (reference (Hardware)) applies to Software;
end MinePump.impl;
end MinePump;
\ No newline at end of file
/* Files generated from AADL model */
#include <request.h>
#include <deployment.h>
#include <po_hi_gqueue.h>
#include "simu.h" /* MinePump simulator */
#define MS_L1 70
#define MS_L2 100
#define Normal 0
#define Alarm1 1
#define Alarm2 2
#define LowLevel 0
#define HighLevel 1
/*****************************************************************************/
/* Helper macros to access AADL entities */
#define LOCAL_PORT(THREAD_INSTANCE_NAME, PORT_NAME) THREAD_INSTANCE_NAME ## _local_ ## PORT_NAME
#define REQUEST_PORT(THREAD_INSTANCE_NAME, PORT_NAME) THREAD_INSTANCE_NAME ## _global_ ## PORT_NAME
#define PORT_VARIABLE(THREAD_INSTANCE_NAME, PORT_NAME) vars.REQUEST_PORT(THREAD_INSTANCE_NAME,PORT_NAME).REQUEST_PORT(THREAD_INSTANCE_NAME,PORT_NAME)
/*****************************************************************************/
/* WaterLevelMonitoring_Thread is a periodic task, period = 250 ms.
It has one output port called "WaterAlarm", of integer type
At each dispatch, it reads the HLS and LLS sensors, using the
ReadHLS() and RealLLS() functions.
- If HLS is true, it sends "HighValue" through its out port;
- else, if LLS is false, it sends "LowValue";
- otherwise, it sends the previous value.
*/
void waterlevelmonitoring_body(__po_hi_task_id self) {
/* Logic of the thread */
static int waterlvl = LowLevel;
if (ReadHLS()) {
waterlvl = HighLevel;
} else if (!ReadLLS()) {
waterlvl = LowLevel;
}
/* Send waterlvl through the wateralarm port */
/* NOTE: Sending through an output port requires some discipline in
naming conventions */
__po_hi_request_t request; /* AADL request type */
/* The name of an output port is built from the thread_instance name
and the port name using the REQUEST_PORT macro */
request.port = REQUEST_PORT (waterlevelmonitoring_thread, wateralarm);
/* The name of the corresponding port variable is built from the
port name, following similar pattern. */
request.PORT_VARIABLE (waterlevelmonitoring_thread,wateralarm) = waterlvl;
/* We send the request through the thread *local* port, built from
the instance name and the port name using the LOCAL_PORT macro */
__po_hi_gqueue_store_out
(self,
LOCAL_PORT (waterlevelmonitoring_thread, wateralarm),
&request);
}
/*****************************************************************************/
/* MethaneMonitoring_Thread is a periodic task, period = 100 ms.
It has one output port called "MethaneLevel", of integer type
At each dispatch, it reads the MS sensor. Depending on the methane
level (constant MS_L1 and MS_L2), it sends either normal, Alert1 or
Alert2 through its output port.
*/
void methanemonitoring_body (__po_hi_task_id self) {
/* Logic of the thread */
int level = Normal;
BYTE MS;
MS=ReadMS();
if (MS>MS_L2) {
level=Alarm2;
} else if (MS>MS_L1) {
level=Alarm1;
} else {
level=Normal;
}
/* Port management */
__po_hi_request_t request;
request.port = REQUEST_PORT (methanemonitoring_thread, methanelevel);
request.PORT_VARIABLE (methanemonitoring_thread,methanelevel) = level;
__po_hi_gqueue_store_out
(self,
LOCAL_PORT (methanemonitoring_thread, methanelevel),
&request);
}
/*****************************************************************************/
/* PumpCtrl_Thread is a sporadic task, with a MIAT of 1 ms It is
triggered by incoming events from sensors.
It has two input ports (dispatching)
* MethaneLevel, of integer type
* WaterLevel, of integer type
and one output port
* WaterAlarm, of integer type
This task manages the alarm logic, and the pump.
- if the alarm level is different from Normal, it sends the value 1
through its wateralarm output port, otherwise it sends 0;
- if the alarm level is Alarm2 then the pump is deactivated (cmd =
0 sent to CmdPump); else, if the water level is high, then the
pump is activated (cmd = 1 sent to CmdPump), otherwise the pump
is left off.
*/
void pumpctrl_body(__po_hi_task_id self) {
int niveau_eau, niveau_alarme, alarme;
int cmd=0;
/* Read from the MethaneLevel port */
__po_hi_request_t request;
/* Get the value from the methanelevel port */
__po_hi_gqueue_get_value
(self,
LOCAL_PORT (pumpctrl_thread,methanelevel),
&(request));
/* Extract it from the port variable */
niveau_alarme = request.PORT_VARIABLE (pumpctrl_thread,methanelevel);
/* Dequeue the event */
__po_hi_gqueue_next_value (self, LOCAL_PORT (pumpctrl_thread,methanelevel));
if (niveau_alarme==Normal) {
alarme=0;
} else {
alarme=1;
}
/* Send alarme value through the WaterAlarm port */
request.port = REQUEST_PORT(pumpctrl_thread, wateralarm);
request.PORT_VARIABLE(pumpctrl_thread,wateralarm) = alarme;
__po_hi_gqueue_store_out
(self,
LOCAL_PORT (pumpctrl_thread, wateralarm),
&request);
if (niveau_alarme==Alarm2) {
cmd=0;
} else {
/* Read from the WaterLevel port */
__po_hi_gqueue_get_value(self,LOCAL_PORT (pumpctrl_thread,waterlevel),&(request));
niveau_eau = request.PORT_VARIABLE(pumpctrl_thread,waterlevel);
__po_hi_gqueue_next_value (self, LOCAL_PORT (pumpctrl_thread,waterlevel));
if (niveau_eau==HighLevel) {
cmd=1;
} else if (niveau_eau==LowLevel) {
cmd=0;
}
}
CmdPump(cmd);
}
/*****************************************************************************/
/* WaterAlarm_Thread is a sporadic task, with a MIAT of 1 ms
It has one input port (dispatching)
* WaterAlarm, of integer type
It calls CmdAlarm with the value read.
*/
void wateralarm_body(__po_hi_task_id self) {
int value = 1;
/* Read from the WaterAlarm port */
__po_hi_request_t request;
__po_hi_gqueue_get_value(self,LOCAL_PORT (wateralarm_thread,wateralarm),&(request));
value = request.PORT_VARIABLE(wateralarm_thread,wateralarm);
__po_hi_gqueue_next_value (self, LOCAL_PORT (wateralarm_thread, wateralarm));
CmdAlarm(value);
}
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#ifdef __SIMU_SOCKET__
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#endif /* __SIMU_SOCKET__ */
#include "simu.h"
#ifdef __SIMU_SOCKET__
FILE * sockin;
#endif /* __SIMU_SOCKET__ */
FILE * sockout;
pthread_mutex_t mutex_simu_minepump;
int CmdPump_Value = 0; /* c = 0, pump is off, c = 1, pump is on */
BYTE WaterLevel_Value = 50;
/*****************************************************************************/
void InitSimu(void) {
if (sockout != NULL)
return;
#ifdef __SIMU_SOCKET__
int sock;
struct sockaddr_in address;
if ((sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0)
perror("Can't open socket");
address.sin_family = AF_INET; /* Internet address family */
address.sin_addr.s_addr=inet_addr("127.0.0.1"); /* Server IP address */
address.sin_port =htons(4242); /* Server port */
if (connect(sock, (struct sockaddr*)&address,sizeof(address)) < 0)
perror("Je ne peux me connecter au simulateur. Assurez-vous que minepump.tcl s'execute");
sockin=fdopen(sock,"r");
sockout=fdopen(sock,"w");
#else
sockout=stdout;
#endif /* __SIMU_SOCKET__ */
pthread_mutex_init(&mutex_simu_minepump,0);
}
/*****************************************************************************/
BYTE ReadHLS(void) {
InitSimu();
BYTE b;
pthread_mutex_lock (&mutex_simu_minepump);
#ifdef __SIMU_SOCKET__
fprintf(sockout,"HLS\n");
fflush(sockout);
b=fgetc(sockin);
#else
WaterLevel_Value = WaterLevel_Value - CmdPump_Value*4 + 2;
b = (WaterLevel_Value > 100)?1:0;
#endif /* __SIMU_SOCKET__ */
pthread_mutex_unlock (&mutex_simu_minepump);
return b;
}
/*****************************************************************************/
BYTE ReadLLS(void) {
InitSimu ();
BYTE b;
pthread_mutex_lock (&mutex_simu_minepump);
#ifdef __SIMU_SOCKET__
fprintf(sockout,"LLS\n");
fflush(sockout);
b=fgetc(sockin);
#else
b = (WaterLevel_Value > 80)?1:0;
#endif /* __SIMU_SOCKET__ */
pthread_mutex_unlock (&mutex_simu_minepump);
return b;
}
/*****************************************************************************/
BYTE ReadMS(void) {
InitSimu ();
static BYTE b = 50;
pthread_mutex_lock (&mutex_simu_minepump);
#ifdef __SIMU_SOCKET__
fprintf(sockout,"MS\n");
fflush(sockout);
b=fgetc(sockin);
#else
/* If there is no GUI, we simply emulate the methane sensor. The methane
gets up and down */
static BYTE b_increment = 2;
b += b_increment;
if (b == 100 || b == 40)
b_increment = - b_increment;
#endif /* __SIMU_SOCKET__ */
pthread_mutex_unlock (&mutex_simu_minepump);
return b;
}
/*****************************************************************************/
void CmdPump(BYTE cmd) {
InitSimu ();
pthread_mutex_lock (&mutex_simu_minepump);
CmdPump_Value = cmd ? 1 : 0;
#ifndef __SIMU_SOCKET__
fprintf(sockout,"WL = %3d\t", WaterLevel_Value);
#endif /* __SIMU_SOCKET__ */
fprintf(sockout,"Pump %d\n",CmdPump_Value);
fflush(sockout);
pthread_mutex_unlock (&mutex_simu_minepump);
}
/*****************************************************************************/
void CmdAlarm(BYTE cmd) {
InitSimu ();
int c=cmd?1:0; /* c = 0, alarm is off, c = 1, alarm is on */
pthread_mutex_lock (&mutex_simu_minepump);
fprintf(sockout,"Alarm %d\t",c);
fflush(sockout);
pthread_mutex_unlock (&mutex_simu_minepump);
}
/**
* simu.h: simulator for the mine pump
*/
#ifndef _SIMU_H_
#define _SIMU_H_
#ifndef BYTE
#define BYTE unsigned char
#endif
void InitSimu(void);
/* Initialize simulator, should be called before any other function
* from this unit
*/
BYTE ReadHLS(void); /* Return status byte from HLS sensor */
BYTE ReadLLS(void); /* Return status byte from LLS sensor */
BYTE ReadMS(void); /* Return status byte from MS sensor */
void CmdPump(BYTE cmd); /* Command pump, 1 = on, 0 = off */
void CmdAlarm(BYTE cmd); /* Command alarm, 1 = on, 0 = off */
#endif /* _SIMU_H_ */
USER_OBJS += simu.o
simu.o: ../../simu.c ../../simu.h
$(CC) -c $(INCLUDE) $(CFLAGS) ../../simu.c -o simu.o
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment