examples/rtai/rtai_sample.c
changeset 1080 088a61306930
parent 814 a51f857b1b2d
child 1082 ff06c58e269c
equal deleted inserted replaced
1079:ef1266652c4d 1080:088a61306930
    35 
    35 
    36 // Linux
    36 // Linux
    37 #include <linux/module.h>
    37 #include <linux/module.h>
    38 
    38 
    39 // RTAI
    39 // RTAI
    40 #include "rtai_sched.h"
    40 #include <rtai_sched.h>
    41 #include "rtai_sem.h"
    41 #include <rtai_sem.h>
    42 
    42 
    43 // EtherCAT
    43 // EtherCAT
    44 #include "../../include/ecrt.h"
    44 #include "../../include/ecrt.h"
    45 #include "../../include/ecdb.h"
    45 
    46 
    46 /*****************************************************************************/
    47 /*****************************************************************************/
    47 
    48 
    48 // Module parameters
    49 // RTAI task frequency in Hz
    49 
    50 #define FREQUENCY 2000
    50 #define FREQUENCY 2000 // task frequency in Hz
    51 #define INHIBIT_TIME 20
    51 #define INHIBIT_TIME 20
    52 
    52 
    53 #define TIMERTICKS (1000000000 / FREQUENCY)
    53 #define TIMERTICKS (1000000000 / FREQUENCY)
    54 
    54 
       
    55 // Optional features (comment to disable)
       
    56 #define CONFIGURE_PDOS
       
    57 
    55 #define PFX "ec_rtai_sample: "
    58 #define PFX "ec_rtai_sample: "
    56 
    59 
    57 /*****************************************************************************/
    60 /*****************************************************************************/
       
    61 
       
    62 // EtherCAT
       
    63 static ec_master_t *master = NULL;
       
    64 static ec_master_state_t master_state = {};
       
    65 spinlock_t master_lock = SPIN_LOCK_UNLOCKED;
       
    66 
       
    67 static ec_domain_t *domain1 = NULL;
       
    68 static ec_domain_state_t domain1_state = {};
       
    69 
       
    70 static ec_slave_config_t *sc_ana_in = NULL;
       
    71 static ec_slave_config_state_t sc_ana_in_state = {};
    58 
    72 
    59 // RTAI
    73 // RTAI
    60 static RT_TASK task;
    74 static RT_TASK task;
    61 static SEM master_sem;
    75 static SEM master_sem;
    62 static cycles_t t_last_cycle = 0, t_critical;
    76 static cycles_t t_last_cycle = 0, t_critical;
    63 
    77 
    64 // EtherCAT
    78 /*****************************************************************************/
    65 static ec_master_t *master = NULL;
    79 
    66 static ec_domain_t *domain1 = NULL;
    80 // process data
    67 static ec_master_status_t master_status, old_status = {};
    81 static uint8_t *domain1_pd; // process data memory
    68 
    82 
    69 // data fields
    83 #define AnaInSlavePos  0, 1
    70 static void *r_dig_out;
    84 #define DigOutSlavePos 0, 3
    71 static void *r_ana_out;
    85 
    72 static void *r_count;
    86 #define Beckhoff_EL2004 0x00000002, 0x07D43052
    73 //static void *r_freq;
    87 #define Beckhoff_EL3162 0x00000002, 0x0C5A3052
    74 
    88 
    75 const static ec_pdo_reg_t domain1_pdo_regs[] = {
    89 static unsigned int off_ana_in; // offsets for Pdo entries
    76     {"2",      Beckhoff_EL2004_Outputs,   &r_dig_out},
    90 static unsigned int off_dig_out;
    77     {"3",      Beckhoff_EL4132_Output1,   &r_ana_out},
    91 
    78     {"#888:1", Beckhoff_EL5101_Value,     &r_count},
    92 const static ec_pdo_entry_reg_t domain1_regs[] = {
    79     //{"4",      Beckhoff_EL5101_Frequency, &r_freq},
    93     {AnaInSlavePos,  Beckhoff_EL3162, 0x3101, 2, &off_ana_in},
       
    94     {DigOutSlavePos, Beckhoff_EL2004, 0x3001, 1, &off_dig_out},
    80     {}
    95     {}
    81 };
    96 };
    82 
    97 
       
    98 static unsigned int counter = 0;
       
    99 static unsigned int blink = 0;
       
   100 
       
   101 /*****************************************************************************/
       
   102 
       
   103 #ifdef CONFIGURE_PDOS
       
   104 static ec_pdo_entry_info_t el3162_channel1[] = {
       
   105     {0x3101, 1,  8}, // status
       
   106     {0x3101, 2, 16}  // value
       
   107 };
       
   108 
       
   109 static ec_pdo_entry_info_t el3162_channel2[] = {
       
   110     {0x3102, 1,  8}, // status
       
   111     {0x3102, 2, 16}  // value
       
   112 };
       
   113 
       
   114 static ec_pdo_info_t el3162_pdos[] = {
       
   115     {0x1A00, 2, el3162_channel1},
       
   116     {0x1A01, 2, el3162_channel2}
       
   117 };
       
   118 
       
   119 static ec_sync_info_t el3162_syncs[] = {
       
   120     {2, EC_DIR_OUTPUT},
       
   121     {3, EC_DIR_INPUT, 2, el3162_pdos},
       
   122     {0xff}
       
   123 };
       
   124 
       
   125 static ec_pdo_entry_info_t el2004_channels[] = {
       
   126     {0x3001, 1, 1}, // Value 1
       
   127     {0x3001, 2, 1}, // Value 2
       
   128     {0x3001, 3, 1}, // Value 3
       
   129     {0x3001, 4, 1}  // Value 4
       
   130 };
       
   131 
       
   132 static ec_pdo_info_t el2004_pdos[] = {
       
   133     {0x1600, 1, &el2004_channels[0]},
       
   134     {0x1601, 1, &el2004_channels[1]},
       
   135     {0x1602, 1, &el2004_channels[2]},
       
   136     {0x1603, 1, &el2004_channels[3]}
       
   137 };
       
   138 
       
   139 static ec_sync_info_t el2004_syncs[] = {
       
   140     {0, EC_DIR_OUTPUT, 4, el2004_pdos},
       
   141     {1, EC_DIR_INPUT},
       
   142     {0xff}
       
   143 };
       
   144 #endif
       
   145 
       
   146 /*****************************************************************************/
       
   147 
       
   148 void check_domain1_state(void)
       
   149 {
       
   150     ec_domain_state_t ds;
       
   151 
       
   152     spin_lock(&master_lock);
       
   153     ecrt_domain_state(domain1, &ds);
       
   154     spin_unlock(&master_lock);
       
   155 
       
   156     if (ds.working_counter != domain1_state.working_counter)
       
   157         printk(KERN_INFO PFX "Domain1: WC %u.\n", ds.working_counter);
       
   158     if (ds.wc_state != domain1_state.wc_state)
       
   159         printk(KERN_INFO PFX "Domain1: State %u.\n", ds.wc_state);
       
   160 
       
   161     domain1_state = ds;
       
   162 }
       
   163 
       
   164 /*****************************************************************************/
       
   165 
       
   166 void check_master_state(void)
       
   167 {
       
   168     ec_master_state_t ms;
       
   169 
       
   170     spin_lock(&master_lock);
       
   171     ecrt_master_state(master, &ms);
       
   172     spin_unlock(&master_lock);
       
   173 
       
   174     if (ms.slaves_responding != master_state.slaves_responding)
       
   175         printk(KERN_INFO PFX "%u slave(s).\n", ms.slaves_responding);
       
   176     if (ms.al_states != master_state.al_states)
       
   177         printk(KERN_INFO PFX "AL states: 0x%02X.\n", ms.al_states);
       
   178     if (ms.link_up != master_state.link_up)
       
   179         printk(KERN_INFO PFX "Link is %s.\n", ms.link_up ? "up" : "down");
       
   180 
       
   181     master_state = ms;
       
   182 }
       
   183 
       
   184 /*****************************************************************************/
       
   185 
       
   186 void check_slave_config_states(void)
       
   187 {
       
   188     ec_slave_config_state_t s;
       
   189 
       
   190     spin_lock(&master_lock);
       
   191     ecrt_slave_config_state(sc_ana_in, &s);
       
   192     spin_unlock(&master_lock);
       
   193 
       
   194     if (s.al_state != sc_ana_in_state.al_state)
       
   195         printk(KERN_INFO PFX "AnaIn: State 0x%02X.\n", s.al_state);
       
   196     if (s.online != sc_ana_in_state.online)
       
   197         printk(KERN_INFO PFX "AnaIn: %s.\n", s.online ? "online" : "offline");
       
   198     if (s.operational != sc_ana_in_state.operational)
       
   199         printk(KERN_INFO PFX "AnaIn: %soperational.\n",
       
   200                 s.operational ? "" : "Not ");
       
   201 
       
   202     sc_ana_in_state = s;
       
   203 }
       
   204 
    83 /*****************************************************************************/
   205 /*****************************************************************************/
    84 
   206 
    85 void run(long data)
   207 void run(long data)
    86 {
   208 {
    87     static unsigned int blink = 0;
       
    88     static unsigned int counter = 0;
       
    89 
       
    90     while (1) {
   209     while (1) {
    91         t_last_cycle = get_cycles();
   210         t_last_cycle = get_cycles();
    92 
   211 
       
   212         // receive process data
    93         rt_sem_wait(&master_sem);
   213         rt_sem_wait(&master_sem);
    94         ecrt_master_receive(master);
   214         ecrt_master_receive(master);
    95         ecrt_domain_process(domain1);
   215         ecrt_domain_process(domain1);
    96         rt_sem_signal(&master_sem);
   216         rt_sem_signal(&master_sem);
    97 
   217 
    98         // process data
   218         // check process data state (optional)
    99         EC_WRITE_U8(r_dig_out, blink ? 0x0F : 0x00);
   219         check_domain1_state();
       
   220 
       
   221         if (counter) {
       
   222             counter--;
       
   223         } else { // do this at 1 Hz
       
   224             counter = FREQUENCY;
       
   225 
       
   226             // calculate new process data
       
   227             blink = !blink;
       
   228 
       
   229             // check for master state (optional)
       
   230             check_master_state();
       
   231 
       
   232             // check for islave configuration state(s) (optional)
       
   233             check_slave_config_states();
       
   234         }
       
   235 
       
   236         // write process data
       
   237         EC_WRITE_U8(domain1_pd + off_dig_out, blink ? 0x06 : 0x09);
   100 
   238 
   101         rt_sem_wait(&master_sem);
   239         rt_sem_wait(&master_sem);
   102         ecrt_domain_queue(domain1);
   240         ecrt_domain_queue(domain1);
   103         ecrt_master_send(master);
   241         ecrt_master_send(master);
   104         rt_sem_signal(&master_sem);
   242         rt_sem_signal(&master_sem);
   105 		
   243 		
   106         if (counter) {
       
   107             counter--;
       
   108         }
       
   109         else {
       
   110             counter = FREQUENCY;
       
   111             blink = !blink;
       
   112 
       
   113             rt_sem_wait(&master_sem);
       
   114             ecrt_master_get_status(master, &master_status);
       
   115             rt_sem_signal(&master_sem);
       
   116 
       
   117             if (master_status.bus_status != old_status.bus_status) {
       
   118                 printk(KERN_INFO PFX "bus status changed to %i.\n",
       
   119                         master_status.bus_status);
       
   120             }
       
   121             if (master_status.bus_tainted != old_status.bus_tainted) {
       
   122                 printk(KERN_INFO PFX "tainted flag changed to %u.\n",
       
   123                         master_status.bus_tainted);
       
   124             }
       
   125             if (master_status.slaves_responding !=
       
   126                     old_status.slaves_responding) {
       
   127                 printk(KERN_INFO PFX "slaves_responding changed to %u.\n",
       
   128                         master_status.slaves_responding);
       
   129             }
       
   130 
       
   131             old_status = master_status;
       
   132         }
       
   133 
       
   134         rt_task_wait_period();
   244         rt_task_wait_period();
   135     }
   245     }
   136 }
   246 }
   137 
   247 
   138 /*****************************************************************************/
   248 /*****************************************************************************/
   157 /*****************************************************************************/
   267 /*****************************************************************************/
   158 
   268 
   159 int __init init_mod(void)
   269 int __init init_mod(void)
   160 {
   270 {
   161     RTIME tick_period, requested_ticks, now;
   271     RTIME tick_period, requested_ticks, now;
       
   272 #ifdef CONFIGURE_PDOS
       
   273     ec_slave_config_t *sc;
       
   274 #endif
   162 
   275 
   163     printk(KERN_INFO PFX "Starting...\n");
   276     printk(KERN_INFO PFX "Starting...\n");
   164 
   277 
   165     rt_sem_init(&master_sem, 1);
   278     rt_sem_init(&master_sem, 1);
   166 
   279 
   171         goto out_return;
   284         goto out_return;
   172     }
   285     }
   173 
   286 
   174     ecrt_master_callbacks(master, request_lock, release_lock, NULL);
   287     ecrt_master_callbacks(master, request_lock, release_lock, NULL);
   175 
   288 
   176     printk(KERN_INFO PFX "Creating domain...\n");
   289     printk(KERN_INFO PFX "Registering domain...\n");
   177     if (!(domain1 = ecrt_master_create_domain(master))) {
   290     if (!(domain1 = ecrt_master_create_domain(master))) {
   178         printk(KERN_ERR PFX "Domain creation failed!\n");
   291         printk(KERN_ERR PFX "Domain creation failed!\n");
   179         goto out_release_master;
   292         goto out_release_master;
   180     }
   293     }
   181 
   294 
   182     printk(KERN_INFO PFX "Registering Pdos...\n");
   295     if (!(sc_ana_in = ecrt_master_slave_config(
   183     if (ecrt_domain_register_pdo_list(domain1, domain1_pdo_regs)) {
   296                     master, AnaInSlavePos, Beckhoff_EL3162))) {
   184         printk(KERN_ERR PFX "Pdo registration failed!\n");
   297         printk(KERN_ERR PFX "Failed to get slave configuration.\n");
       
   298         goto out_release_master;
       
   299     }
       
   300 
       
   301 #ifdef CONFIGURE_PDOS
       
   302     printk(KERN_INFO PFX "Configuring Pdos...\n");
       
   303     if (ecrt_slave_config_sync_managers(sc_ana_in, EC_END, el3162_syncs)) {
       
   304         printk(KERN_ERR PFX "Failed to configure Pdos.\n");
       
   305         goto out_release_master;
       
   306     }
       
   307 
       
   308     if (!(sc = ecrt_master_slave_config(master, DigOutSlavePos, Beckhoff_EL2004))) {
       
   309         printk(KERN_ERR PFX "Failed to get slave configuration.\n");
       
   310         goto out_release_master;
       
   311     }
       
   312 
       
   313     if (ecrt_slave_config_sync_managers(sc, EC_END, el2004_syncs)) {
       
   314         printk(KERN_ERR PFX "Failed to configure Pdos.\n");
       
   315         goto out_release_master;
       
   316     }
       
   317 #endif
       
   318 
       
   319     printk(KERN_INFO PFX "Registering Pdo entries...\n");
       
   320     if (ecrt_domain_reg_pdo_entry_list(domain1, domain1_regs)) {
       
   321         printk(KERN_ERR PFX "Pdo entry registration failed!\n");
   185         goto out_release_master;
   322         goto out_release_master;
   186     }
   323     }
   187 
   324 
   188     printk(KERN_INFO PFX "Activating master...\n");
   325     printk(KERN_INFO PFX "Activating master...\n");
   189     if (ecrt_master_activate(master)) {
   326     if (ecrt_master_activate(master)) {
   190         printk(KERN_ERR PFX "Failed to activate master!\n");
   327         printk(KERN_ERR PFX "Failed to activate master!\n");
   191         goto out_release_master;
   328         goto out_release_master;
   192     }
   329     }
       
   330 
       
   331     // Get internal process data for domain
       
   332     domain1_pd = ecrt_domain_data(domain1);
   193 
   333 
   194     printk(KERN_INFO PFX "Starting cyclic sample thread...\n");
   334     printk(KERN_INFO PFX "Starting cyclic sample thread...\n");
   195     requested_ticks = nano2count(TIMERTICKS);
   335     requested_ticks = nano2count(TIMERTICKS);
   196     tick_period = start_rt_timer(requested_ticks);
   336     tick_period = start_rt_timer(requested_ticks);
   197     printk(KERN_INFO PFX "RT timer started with %i/%i ticks.\n",
   337     printk(KERN_INFO PFX "RT timer started with %i/%i ticks.\n",