|
1 /************************************************************************************************** |
|
2 * |
|
3 * msr_module.c |
|
4 * |
|
5 * Kernelmodul für 2.6 Kernel zur Meßdatenerfassung, Steuerung und Regelung |
|
6 * Zeitgeber ist der Timerinterrupt (tq) |
|
7 * |
|
8 * Autor: Wilhelm Hagemeister |
|
9 * |
|
10 * (C) Copyright IgH 2002 |
|
11 * Ingenieurgemeinschaft IgH |
|
12 * Heinz-Bäcker Str. 34 |
|
13 * D-45356 Essen |
|
14 * Tel.: +49 201/61 99 31 |
|
15 * Fax.: +49 201/61 98 36 |
|
16 * E-mail: hm@igh-essen.com |
|
17 * |
|
18 * |
|
19 * $RCSfile: msr_module.c,v $ |
|
20 * $Revision: 1.1 $ |
|
21 * $Author: hm $ |
|
22 * $Date: 2005/11/14 20:32:57 $ |
|
23 * $State: Exp $ |
|
24 * |
|
25 * |
|
26 * $Log: msr_module.c,v $ |
|
27 * Revision 1.1 2005/11/14 20:32:57 hm |
|
28 * Initial revision |
|
29 * |
|
30 * Revision 1.13 2005/06/17 11:35:13 hm |
|
31 * *** empty log message *** |
|
32 * |
|
33 * |
|
34 * |
|
35 * |
|
36 **************************************************************************************************/ |
|
37 |
|
38 |
|
39 /*--includes-------------------------------------------------------------------------------------*/ |
|
40 |
|
41 |
|
42 #ifndef __KERNEL__ |
|
43 # define __KERNEL__ |
|
44 #endif |
|
45 #ifndef MODULE |
|
46 # define MODULE |
|
47 #endif |
|
48 |
|
49 #include <linux/config.h> |
|
50 #include <linux/module.h> |
|
51 |
|
52 #include <linux/sched.h> |
|
53 #include <linux/kernel.h> |
|
54 #include <linux/vmalloc.h> |
|
55 #include <linux/fs.h> /* everything... */ |
|
56 #include <linux/proc_fs.h> |
|
57 #include <linux/time.h> |
|
58 #include <linux/timer.h> |
|
59 #include <linux/timex.h> /* fuer get_cycles */ |
|
60 #include <linux/errno.h> /* error codes */ |
|
61 #include <asm/msr.h> /* maschine-specific registers */ |
|
62 #include <linux/param.h> /* fuer HZ */ |
|
63 #include <linux/ipipe.h> |
|
64 |
|
65 #include "msr_param.h" //wird im Projektverzeichnis erwartet |
|
66 |
|
67 //#include <msr_control.h> |
|
68 #include <msr_lists.h> |
|
69 #include <msr_charbuf.h> |
|
70 #include <msr_reg.h> |
|
71 #include <msr_error_reg.h> |
|
72 #include <msr_messages.h> |
|
73 #include <msr_proc.h> |
|
74 #include <msr_utils.h> |
|
75 #include <msr_main.h> |
|
76 |
|
77 |
|
78 #include <msr_float.h> |
|
79 |
|
80 #include "../drivers/ec_master.h" |
|
81 #include "../drivers/ec_device.h" |
|
82 #include "../drivers/ec_types.h" |
|
83 #include "../drivers/ec_module.h" |
|
84 |
|
85 #include "msr_jitter.h" |
|
86 |
|
87 MODULE_AUTHOR("Wilhelm Hagemeister, Ingenieurgemeinschaft IgH"); |
|
88 MODULE_LICENSE("GPL"); |
|
89 |
|
90 /*--external functions---------------------------------------------------------------------------*/ |
|
91 |
|
92 /*--external data--------------------------------------------------------------------------------*/ |
|
93 |
|
94 #define HZREDUCTION (MSR_ABTASTFREQUENZ/HZ) |
|
95 |
|
96 extern wait_queue_head_t msr_read_waitqueue; |
|
97 |
|
98 extern struct msr_char_buf *msr_kanal_puffer; |
|
99 |
|
100 extern int proc_abtastfrequenz; |
|
101 |
|
102 /*--public data----------------------------------------------------------------------------------*/ |
|
103 /*--local data-----------------------------------------------------------------------------------*/ |
|
104 //struct timer_list timer; |
|
105 |
|
106 extern struct timeval process_time; |
|
107 struct timeval msr_time_increment; // Increment per Interrupt |
|
108 |
|
109 //adeos |
|
110 |
|
111 static struct ipipe_domain this_domain; |
|
112 |
|
113 static struct ipipe_sysinfo sys_info; |
|
114 |
|
115 static EtherCAT_master_t *ecat_master = NULL; |
|
116 |
|
117 static EtherCAT_slave_t ecat_slaves[] = |
|
118 { |
|
119 |
|
120 |
|
121 #if 1 |
|
122 // Block 1 |
|
123 ECAT_INIT_SLAVE(Beckhoff_EK1100), |
|
124 ECAT_INIT_SLAVE(Beckhoff_EL4102), |
|
125 ECAT_INIT_SLAVE(Beckhoff_EL1014), |
|
126 ECAT_INIT_SLAVE(Beckhoff_EL3162), |
|
127 ECAT_INIT_SLAVE(Beckhoff_EL2004), |
|
128 ECAT_INIT_SLAVE(Beckhoff_EL3102), |
|
129 ECAT_INIT_SLAVE(Beckhoff_EL2004), |
|
130 ECAT_INIT_SLAVE(Beckhoff_EL2004), |
|
131 ECAT_INIT_SLAVE(Beckhoff_EL2004), |
|
132 ECAT_INIT_SLAVE(Beckhoff_EL2004), |
|
133 ECAT_INIT_SLAVE(Beckhoff_EL2004), |
|
134 |
|
135 // Block 2 |
|
136 ECAT_INIT_SLAVE(Beckhoff_EK1100), |
|
137 ECAT_INIT_SLAVE(Beckhoff_EL1014), |
|
138 ECAT_INIT_SLAVE(Beckhoff_EL1014), |
|
139 ECAT_INIT_SLAVE(Beckhoff_EL1014), |
|
140 ECAT_INIT_SLAVE(Beckhoff_EL1014), |
|
141 ECAT_INIT_SLAVE(Beckhoff_EL1014), |
|
142 ECAT_INIT_SLAVE(Beckhoff_EL2004), |
|
143 ECAT_INIT_SLAVE(Beckhoff_EL2004), |
|
144 ECAT_INIT_SLAVE(Beckhoff_EL2004), |
|
145 ECAT_INIT_SLAVE(Beckhoff_EL2004), |
|
146 ECAT_INIT_SLAVE(Beckhoff_EL1014), |
|
147 ECAT_INIT_SLAVE(Beckhoff_EL1014), |
|
148 ECAT_INIT_SLAVE(Beckhoff_EL1014) |
|
149 #endif |
|
150 |
|
151 #if 1 |
|
152 // Block 3 |
|
153 ,ECAT_INIT_SLAVE(Beckhoff_EK1100), |
|
154 ECAT_INIT_SLAVE(Beckhoff_EL3162), |
|
155 ECAT_INIT_SLAVE(Beckhoff_EL3162), |
|
156 ECAT_INIT_SLAVE(Beckhoff_EL3162), |
|
157 ECAT_INIT_SLAVE(Beckhoff_EL3162), |
|
158 ECAT_INIT_SLAVE(Beckhoff_EL3102), |
|
159 ECAT_INIT_SLAVE(Beckhoff_EL3102), |
|
160 ECAT_INIT_SLAVE(Beckhoff_EL3102), |
|
161 ECAT_INIT_SLAVE(Beckhoff_EL3102), |
|
162 |
|
163 ECAT_INIT_SLAVE(Beckhoff_EL4102), |
|
164 ECAT_INIT_SLAVE(Beckhoff_EL4102), |
|
165 ECAT_INIT_SLAVE(Beckhoff_EL4102), |
|
166 ECAT_INIT_SLAVE(Beckhoff_EL4102) |
|
167 |
|
168 |
|
169 #endif |
|
170 }; |
|
171 |
|
172 #define ECAT_SLAVES_COUNT (sizeof(ecat_slaves) / sizeof(EtherCAT_slave_t)) |
|
173 |
|
174 #define USE_MSR_LIB |
|
175 |
|
176 #ifdef USE_MSR_LIB |
|
177 double value; |
|
178 int dig1; |
|
179 #endif |
|
180 |
|
181 /****************************************************************************** |
|
182 * |
|
183 * Function: next2004 |
|
184 * |
|
185 *****************************************************************************/ |
|
186 |
|
187 |
|
188 |
|
189 static int next2004(int *wrap) |
|
190 { |
|
191 static int i = 0; |
|
192 unsigned int j = 0; |
|
193 |
|
194 *wrap = 0; |
|
195 |
|
196 for (j = 0; j < ECAT_SLAVES_COUNT; j++) |
|
197 { |
|
198 i++; |
|
199 |
|
200 i %= ECAT_SLAVES_COUNT; |
|
201 |
|
202 if (i == 0) *wrap = 1; |
|
203 |
|
204 if (ecat_slaves[i].desc == Beckhoff_EL2004) |
|
205 { |
|
206 return i; |
|
207 } |
|
208 } |
|
209 |
|
210 return -1; |
|
211 } |
|
212 |
|
213 |
|
214 /****************************************************************************** |
|
215 * |
|
216 * Function: msr_controller_run() |
|
217 * |
|
218 *****************************************************************************/ |
|
219 |
|
220 static void msr_controller_run(void) |
|
221 { |
|
222 static int ms = 0; |
|
223 static int cnt = 0; |
|
224 static unsigned long int k = 0; |
|
225 static int firstrun = 1; |
|
226 |
|
227 static int klemme = 0; |
|
228 static int kanal = 0; |
|
229 static int up_down = 0; |
|
230 int wrap = 0; |
|
231 |
|
232 |
|
233 // Prozessdaten lesen |
|
234 msr_jitter_run(MSR_ABTASTFREQUENZ); |
|
235 |
|
236 if (!firstrun) |
|
237 { |
|
238 EtherCAT_read_process_data(ecat_master); |
|
239 |
|
240 // Daten lesen und skalieren |
|
241 #ifdef USE_MSR_LIB |
|
242 value = EtherCAT_read_value(&ecat_master->slaves[5], 0) / 3276.0; |
|
243 dig1 = EtherCAT_read_value(&ecat_master->slaves[2], 0); |
|
244 #endif |
|
245 } |
|
246 else |
|
247 klemme = next2004(&wrap); |
|
248 |
|
249 |
|
250 ms++; |
|
251 ms %= 1000; |
|
252 if (cnt++ > 20) |
|
253 { |
|
254 cnt = 0; |
|
255 |
|
256 if (++kanal > 3) |
|
257 { |
|
258 kanal = 0; |
|
259 klemme = next2004(&wrap); |
|
260 |
|
261 if (wrap == 1) |
|
262 { |
|
263 if (up_down == 1) up_down = 0; |
|
264 else up_down = 1; |
|
265 } |
|
266 } |
|
267 } |
|
268 |
|
269 if (klemme >= 0) { |
|
270 EtherCAT_write_value(&ecat_master->slaves[klemme], kanal,up_down); |
|
271 //printk("ECAT write: Klemme: %d, Kanal: %d, Wert: %d\n",klemme,kanal,up_down); |
|
272 } |
|
273 |
|
274 #if 0 |
|
275 EtherCAT_write_value(&ecat_master->slaves[13], 1, ms > 500 ? 0 : 1); |
|
276 EtherCAT_write_value(&ecat_master->slaves[14], 2, ms > 500 ? 0 : 1); |
|
277 EtherCAT_write_value(&ecat_master->slaves[15], 3, ms > 500 ? 1 : 0); |
|
278 #endif |
|
279 |
|
280 // Prozessdaten schreiben |
|
281 rdtscl(k); |
|
282 EtherCAT_write_process_data(ecat_master); |
|
283 firstrun = 0; |
|
284 |
|
285 } |
|
286 |
|
287 /* |
|
288 *************************************************************************************************** |
|
289 * |
|
290 * Function: msr_run(_interrupt) |
|
291 * |
|
292 * Beschreibung: Routine wird zyklisch im Timerinterrupt ausgeführt |
|
293 * (hier muß alles rein, was Echtzeit ist ...) |
|
294 * |
|
295 * Parameter: Zeiger auf msr_data |
|
296 * |
|
297 * Rückgabe: |
|
298 * |
|
299 * Status: exp |
|
300 * |
|
301 *************************************************************************************************** |
|
302 */ |
|
303 |
|
304 |
|
305 void msr_run(unsigned irq) |
|
306 { |
|
307 |
|
308 static int counter = 0; |
|
309 #ifdef USE_MSR_LIB |
|
310 |
|
311 timeval_add(&process_time,&process_time,&msr_time_increment); |
|
312 |
|
313 MSR_ADEOS_INTERRUPT_CODE( |
|
314 msr_controller_run(); |
|
315 msr_write_kanal_list(); |
|
316 ); |
|
317 #else |
|
318 msr_controller_run(); |
|
319 #endif |
|
320 /* und wieder in die Timerliste eintragen */ |
|
321 /* und neu in die Taskqueue eintragen */ |
|
322 // timer.expires += 1; |
|
323 // add_timer(&timer); |
|
324 |
|
325 ipipe_control_irq(irq,0,IPIPE_ENABLE_MASK); //nicht weiterreichen |
|
326 if(counter++ > HZREDUCTION) { |
|
327 ipipe_propagate_irq(irq); //wie lange braucht der Rest der Pipeline ?? |
|
328 counter = 0; |
|
329 } |
|
330 |
|
331 |
|
332 } |
|
333 |
|
334 void domain_entry (int iflag) { |
|
335 printk("Domain %s started.\n", ipipe_current_domain->name); |
|
336 |
|
337 |
|
338 ipipe_get_sysinfo(&sys_info); |
|
339 ipipe_virtualize_irq(ipipe_current_domain,sys_info.archdep.tmirq, |
|
340 &msr_run, NULL, IPIPE_HANDLE_MASK); |
|
341 |
|
342 ipipe_tune_timer(1000000000UL/MSR_ABTASTFREQUENZ,0); |
|
343 |
|
344 } |
|
345 |
|
346 /* |
|
347 ******************************************************************************* |
|
348 * |
|
349 * Function: msr_register_channels |
|
350 * |
|
351 * Beschreibung: KanŽäle registrieren |
|
352 * |
|
353 * Parameter: |
|
354 * |
|
355 * RŽückgabe: |
|
356 * |
|
357 * Status: exp |
|
358 * |
|
359 ******************************************************************************* |
|
360 */ |
|
361 |
|
362 int msr_globals_register(void) |
|
363 { |
|
364 #ifdef USE_MSR_LIB |
|
365 msr_reg_kanal("/value", "V", &value, TDBL); |
|
366 msr_reg_kanal("/dig1", "", &dig1, TINT); |
|
367 #endif |
|
368 /* msr_reg_kanal("/Taskinfo/Ecat/TX-Delay","us",&ecat_tx_delay,TUINT); |
|
369 msr_reg_kanal("/Taskinfo/Ecat/RX-Delay","us",&ecat_rx_delay,TUINT); |
|
370 msr_reg_kanal("/Taskinfo/Ecat/TX-Cnt","",&tx_intr,TUINT); |
|
371 msr_reg_kanal("/Taskinfo/Ecat/RX-Cnt","",&rx_intr,TUINT); |
|
372 msr_reg_kanal("/Taskinfo/Ecat/Total-Cnt","",&total_intr,TUINT); |
|
373 */ |
|
374 return 0; |
|
375 } |
|
376 |
|
377 |
|
378 /**************************************************************************************************** |
|
379 * the init/clean material |
|
380 ****************************************************************************************************/ |
|
381 |
|
382 |
|
383 int __init init_module() |
|
384 { |
|
385 int result = 0; |
|
386 |
|
387 struct ipipe_domain_attr attr; //ipipe |
|
388 |
|
389 //als allererstes die RT-lib initialisieren |
|
390 #ifdef USE_MSR_LIB |
|
391 result = msr_rtlib_init(1,MSR_ABTASTFREQUENZ,10,&msr_globals_register); |
|
392 |
|
393 if (result < 0) { |
|
394 msr_print_warn("msr_modul: can't initialize rtlib!"); |
|
395 return result; |
|
396 } |
|
397 #endif |
|
398 |
|
399 msr_jitter_init(); |
|
400 printk(KERN_INFO "=== Starting EtherCAT environment... ===\n"); |
|
401 |
|
402 if ((ecat_master = EtherCAT_master(0)) == NULL) |
|
403 { |
|
404 printk(KERN_ERR "No EtherCAT master available!\n"); |
|
405 msr_rtlib_cleanup(); |
|
406 return -1; |
|
407 } |
|
408 |
|
409 printk("Checking EtherCAT slaves.\n"); |
|
410 |
|
411 if (EtherCAT_check_slaves(ecat_master, ecat_slaves, ECAT_SLAVES_COUNT) != 0) |
|
412 { |
|
413 printk(KERN_ERR "EtherCAT: Could not init slaves!\n"); |
|
414 msr_rtlib_cleanup(); |
|
415 return -1; |
|
416 } |
|
417 |
|
418 printk("Activating all EtherCAT slaves.\n"); |
|
419 |
|
420 if (EtherCAT_activate_all_slaves(ecat_master) != 0) |
|
421 { |
|
422 printk(KERN_ERR "EtherCAT: Could not activate slaves!\n"); |
|
423 msr_rtlib_cleanup(); |
|
424 return -1; |
|
425 } |
|
426 |
|
427 |
|
428 do_gettimeofday(&process_time); |
|
429 msr_time_increment.tv_sec=0; |
|
430 msr_time_increment.tv_usec=(unsigned int)(1000000/MSR_ABTASTFREQUENZ); |
|
431 |
|
432 ipipe_init_attr (&attr); |
|
433 attr.name = "IPIPE-MSR-MODULE"; |
|
434 attr.priority = IPIPE_ROOT_PRIO + 1; |
|
435 attr.entry = &domain_entry; |
|
436 ipipe_register_domain(&this_domain,&attr); |
|
437 |
|
438 //den Timertakt |
|
439 /* |
|
440 init_timer(&timer); |
|
441 |
|
442 timer.function = msr_run; |
|
443 timer.data = 0; |
|
444 timer.expires = jiffies+10; // Das erste Mal sofort feuern |
|
445 add_timer(&timer); |
|
446 */ |
|
447 return 0; /* succeed */ |
|
448 } |
|
449 |
|
450 |
|
451 //**************************************************************************** |
|
452 void __exit cleanup_module() |
|
453 |
|
454 { |
|
455 msr_print_info("msk_modul: unloading..."); |
|
456 |
|
457 |
|
458 // del_timer_sync(&timer); |
|
459 ipipe_tune_timer(1000000000UL/HZ,0); //alten Timertakt wieder herstellen |
|
460 |
|
461 ipipe_unregister_domain(&this_domain); |
|
462 |
|
463 |
|
464 |
|
465 printk(KERN_INFO "=== Stopping EtherCAT environment... ===\n"); |
|
466 |
|
467 if (ecat_master) |
|
468 { |
|
469 EtherCAT_clear_process_data(ecat_master); |
|
470 printk(KERN_INFO "Deactivating slaves.\n"); |
|
471 EtherCAT_deactivate_all_slaves(ecat_master); |
|
472 } |
|
473 |
|
474 printk(KERN_INFO "=== EtherCAT environment stopped. ===\n"); |
|
475 |
|
476 // msr_controller_cleanup(); |
|
477 #ifdef USE_MSR_LIB |
|
478 msr_rtlib_cleanup(); |
|
479 #endif |
|
480 } |
|
481 |
|
482 MODULE_LICENSE("GPL"); |
|
483 MODULE_AUTHOR ("Wilhelm Hagemeister <hm@igh-essen.com>"); |
|
484 MODULE_DESCRIPTION ("EtherCAT test environment"); |
|
485 |
|
486 module_init(init_module); |
|
487 module_exit(cleanup_module); |
|
488 |
|
489 |
|
490 |
|
491 |
|
492 |
|
493 |
|
494 |
|
495 |
|
496 |
|
497 |
|
498 |
|
499 |
|
500 |
|
501 |
|
502 |
|
503 |