27 #include "mb_master_private.h" |
27 #include "mb_master_private.h" |
28 |
28 |
29 |
29 |
30 |
30 |
31 #define DEF_REQ_SEND_RETRIES 0 |
31 #define DEF_REQ_SEND_RETRIES 0 |
|
32 |
|
33 |
|
34 #define MODBUS_PARAM_STRING_SIZE 64 |
|
35 |
32 |
36 |
33 // Used by the Modbus server node |
37 // Used by the Modbus server node |
34 #define MEM_AREA_SIZE 65536 |
38 #define MEM_AREA_SIZE 65536 |
35 typedef struct{ |
39 typedef struct{ |
36 u16 ro_bits [MEM_AREA_SIZE]; |
40 u16 ro_bits [MEM_AREA_SIZE]; |
37 u16 rw_bits [MEM_AREA_SIZE]; |
41 u16 rw_bits [MEM_AREA_SIZE]; |
38 u16 ro_words[MEM_AREA_SIZE]; |
42 u16 ro_words[MEM_AREA_SIZE]; |
39 u16 rw_words[MEM_AREA_SIZE]; |
43 u16 rw_words[MEM_AREA_SIZE]; |
40 } server_mem_t; |
44 } server_mem_t; |
41 |
45 |
|
46 |
|
47 /* |
|
48 * Beremiz has a program to run on the PLC (Beremiz_service.py) |
|
49 * to handle downloading of compiled programs, start/stop of PLC, etc. |
|
50 * (see runtime/PLCObject.py for start/stop, loading, ...) |
|
51 * |
|
52 * This service also includes a web server to access PLC state (start/stop) |
|
53 * and to change some basic confiuration parameters. |
|
54 * (see runtime/NevowServer.py for the web server) |
|
55 * |
|
56 * The web server allows for extensions, where additional configuration |
|
57 * parameters may be changed on the running/downloaded PLC. |
|
58 * Modbus plugin also comes with an extension to the web server, through |
|
59 * which the basic Modbus plugin configuration parameters may be changed |
|
60 * |
|
61 * This means that most values in the server_node_t and client_node_t |
|
62 * may be changed after the co,piled code (.so file) is loaded into |
|
63 * memory, and before the code starts executing. |
|
64 * Since the we will also want to change the host and port (TCP) and the |
|
65 * serial device (RTU) at this time, it is best if we allocate memory for |
|
66 * these strings that may be overwritten by the web server (i.e., do not use |
|
67 * const strings) in the server_node_t and client_node_t structures. |
|
68 * |
|
69 * The following structure members |
|
70 * - node_addr_t.addr.tcp.host |
|
71 * - node_addr_t.addr.tcp.service (i.e. the port) |
|
72 * - node_addr_t.addr.rtu.device |
|
73 * are all char *, and do not allocate memory for the strings. |
|
74 * |
|
75 * We therefore include two generic char arrays, str1 and str2, |
|
76 * that will store the above strings, and the C code will initiliaze |
|
77 * the node_addre_t.addr string pointers to these strings. |
|
78 * i.e., either addr.rtu.device will point to str1, |
|
79 * or |
|
80 * addr.tcp.host and addr.tcp.service |
|
81 * will point to str1 and str2 respectively |
|
82 */ |
42 typedef struct{ |
83 typedef struct{ |
43 const char *location; |
84 const char *location; |
|
85 const char *config_name; |
|
86 char str1[MODBUS_PARAM_STRING_SIZE]; |
|
87 char str2[MODBUS_PARAM_STRING_SIZE]; |
44 u8 slave_id; |
88 u8 slave_id; |
45 node_addr_t node_address; |
89 node_addr_t node_address; |
46 int mb_nd; // modbus library node used for this server |
90 int mb_nd; // modbus library node used for this server |
47 int init_state; // store how far along the server's initialization has progressed |
91 int init_state; // store how far along the server's initialization has progressed |
48 pthread_t thread_id; // thread handling this server |
92 pthread_t thread_id; // thread handling this server |
51 |
95 |
52 |
96 |
53 // Used by the Modbus client node |
97 // Used by the Modbus client node |
54 typedef struct{ |
98 typedef struct{ |
55 const char *location; |
99 const char *location; |
|
100 const char *config_name; |
|
101 char str1[MODBUS_PARAM_STRING_SIZE]; |
|
102 char str2[MODBUS_PARAM_STRING_SIZE]; |
56 node_addr_t node_address; |
103 node_addr_t node_address; |
57 int mb_nd; |
104 int mb_nd; // modbus library node used for this client |
58 int init_state; // store how far along the client's initialization has progressed |
105 int init_state; // store how far along the client's initialization has progressed |
59 u64 comm_period; |
106 u64 comm_period;// period to use when periodically sending requests to remote server |
60 int prev_error; // error code of the last printed error message (0 when no error) |
107 int prev_error; // error code of the last printed error message (0 when no error) |
61 pthread_t thread_id; // thread handling all communication with this client |
108 pthread_t thread_id; // thread handling all communication for this client node |
|
109 timer_t timer_id; // timer used to periodically activate this client node's thread |
|
110 pthread_mutex_t mutex; // mutex to be used with the following condition variable |
|
111 pthread_cond_t condv; // used to signal the client thread when to start new modbus transactions |
|
112 int execute_req; /* used, in association with condition variable, |
|
113 * to signal when to send the modbus request to the server |
|
114 * Note that we cannot simply rely on the condition variable to signal |
|
115 * when to activate the client thread, as the call to |
|
116 * pthread_cond_wait() may return without having been signaled! |
|
117 * From the manual: |
|
118 * Spurious wakeups from the |
|
119 * pthread_cond_timedwait() or pthread_cond_wait() functions may occur. |
|
120 * Since the return from pthread_cond_timedwait() or pthread_cond_wait() |
|
121 * does not imply anything about the value of this predicate, the predi- |
|
122 * cate should be re-evaluated upon such return. |
|
123 */ |
|
124 int periodic_act; /* (boolen) flag will be set when the client node's thread was activated |
|
125 * (by signaling the above condition variable) by the periodic timer. |
|
126 * Note that this same thread may also be activated (condition variable is signaled) |
|
127 * by other sources, such as when the user program requests that a specific |
|
128 * client MB transation be executed (flag_exec_req in client_request_t) |
|
129 */ |
62 } client_node_t; |
130 } client_node_t; |
63 |
131 |
64 |
132 |
65 // Used by the Modbus client plugin |
133 // Used by the Modbus client plugin |
66 typedef enum { |
134 typedef enum { |
80 u16 count; |
148 u16 count; |
81 int retries; |
149 int retries; |
82 u8 error_code; // modbus error code (if any) of current request |
150 u8 error_code; // modbus error code (if any) of current request |
83 int prev_error; // error code of the last printed error message (0 when no error) |
151 int prev_error; // error code of the last printed error message (0 when no error) |
84 struct timespec resp_timeout; |
152 struct timespec resp_timeout; |
|
153 u8 write_on_change; // boolean flag. If true => execute MB request when data to send changes |
85 // buffer used to store located PLC variables |
154 // buffer used to store located PLC variables |
86 u16 plcv_buffer[REQ_BUF_SIZE]; |
155 u16 plcv_buffer[REQ_BUF_SIZE]; |
87 // buffer used to store data coming from / going to server |
156 // buffer used to store data coming from / going to server |
88 u16 coms_buffer[REQ_BUF_SIZE]; |
157 u16 coms_buffer[REQ_BUF_SIZE]; |
89 pthread_mutex_t coms_buf_mutex; // mutex to access coms_buffer[] |
158 pthread_mutex_t coms_buf_mutex; // mutex to access coms_buffer[] |
|
159 /* boolean flag that will be mapped onto a (BOOL) located variable |
|
160 * (u16 because IEC 61131-3 BOOL are mapped onto u16 in C code! ) |
|
161 * -> allow PLC program to request when to start the MB transaction |
|
162 * -> will be reset once the MB transaction has completed |
|
163 */ |
|
164 u16 flag_exec_req; |
|
165 /* flag that works in conjunction with flag_exec_req |
|
166 * (does not really need to be u16 as it is not mapped onto a located variable. ) |
|
167 * -> used by internal logic to indicate that the client thread |
|
168 * that will be executing the MB transaction |
|
169 * requested by flag exec_req has already been activated. |
|
170 * -> will be reset once the MB transaction has completed |
|
171 */ |
|
172 u16 flag_exec_started; |
|
173 /* flag that will be mapped onto a (WORD) located variable |
|
174 * (u16 because the flag is a word! ) |
|
175 * -> MSByte will store the result of the last executed MB transaction |
|
176 * 1 -> error accessing IP network, or serial interface |
|
177 * 2 -> reply received from server was an invalid frame |
|
178 * 3 -> server did not reply before timeout expired |
|
179 * 4 -> server returned a valid error frame |
|
180 * -> if the MSByte is 4, the LSByte will store the MB error code returned by the server |
|
181 * -> will be reset (set to 0) once this MB transaction has completed sucesfully |
|
182 */ |
|
183 u16 flag_exec_status; |
90 } client_request_t; |
184 } client_request_t; |
91 |
185 |
92 |
186 |
93 /* The total number of nodes, needed to support _all_ instances of the modbus plugin */ |
187 /* The total number of nodes, needed to support _all_ instances of the modbus plugin */ |
94 #define TOTAL_TCPNODE_COUNT %(total_tcpnode_count)s |
188 #define TOTAL_TCPNODE_COUNT %(total_tcpnode_count)s |