master/fsm_mapping.c
changeset 792 3778920f61e4
parent 758 8fa6f825eb7d
child 801 6b1e2b0ed8bc
equal deleted inserted replaced
791:3b81d074735c 792:3778920f61e4
    29  *  standard) as the (only) precondition to have the right to use EtherCAT
    29  *  standard) as the (only) precondition to have the right to use EtherCAT
    30  *  Technology, IP and trade marks.
    30  *  Technology, IP and trade marks.
    31  *
    31  *
    32  *****************************************************************************/
    32  *****************************************************************************/
    33 
    33 
    34 /**
    34 /** \file
    35    \file
    35  * EtherCAT PDO mapping state machine.
    36    EtherCAT PDO mapping state machine.
    36  */
    37 */
       
    38 
    37 
    39 /*****************************************************************************/
    38 /*****************************************************************************/
    40 
    39 
    41 #include "globals.h"
    40 #include "globals.h"
    42 #include "master.h"
    41 #include "master.h"
    43 #include "mailbox.h"
    42 #include "mailbox.h"
       
    43 #include "slave_config.h"
       
    44 
    44 #include "fsm_mapping.h"
    45 #include "fsm_mapping.h"
    45 
    46 
    46 /*****************************************************************************/
    47 /*****************************************************************************/
    47 
    48 
    48 void ec_fsm_mapping_state_start(ec_fsm_mapping_t *);
    49 void ec_fsm_mapping_state_start(ec_fsm_mapping_t *);
    54 
    55 
    55 void ec_fsm_mapping_next_sync(ec_fsm_mapping_t *);
    56 void ec_fsm_mapping_next_sync(ec_fsm_mapping_t *);
    56 
    57 
    57 /*****************************************************************************/
    58 /*****************************************************************************/
    58 
    59 
    59 /**
    60 /** Constructor.
    60  * Constructor.
    61  */
    61  */
    62 void ec_fsm_mapping_init(
    62 
    63         ec_fsm_mapping_t *fsm, /**< mapping state machine */
    63 void ec_fsm_mapping_init(ec_fsm_mapping_t *fsm, /**< mapping state machine */
       
    64         ec_fsm_coe_t *fsm_coe /**< CoE state machine to use */
    64         ec_fsm_coe_t *fsm_coe /**< CoE state machine to use */
    65         )
    65         )
    66 {
    66 {
    67     fsm->fsm_coe = fsm_coe;
    67     fsm->fsm_coe = fsm_coe;
    68     fsm->sdodata.data = (uint8_t *) &fsm->sdo_value;
    68     fsm->sdodata.data = (uint8_t *) &fsm->sdo_value;
    69 }
    69 }
    70 
    70 
    71 /*****************************************************************************/
    71 /*****************************************************************************/
    72 
    72 
    73 /**
    73 /** Destructor.
    74  * Destructor.
    74  */
    75  */
    75 void ec_fsm_mapping_clear(
    76 
    76         ec_fsm_mapping_t *fsm /**< mapping state machine */
    77 void ec_fsm_mapping_clear(ec_fsm_mapping_t *fsm /**< mapping state machine */)
    77         )
    78 {
    78 {
    79 }
    79 }
    80 
    80 
    81 /*****************************************************************************/
    81 /*****************************************************************************/
    82 
    82 
    83 /**
    83 /** Start PDO mapping configuration state machine.
    84  * Start PDO mapping configuration state machine.
    84  */
    85  */
       
    86 
       
    87 void ec_fsm_mapping_start(
    85 void ec_fsm_mapping_start(
    88         ec_fsm_mapping_t *fsm, /**< mapping state machine */
    86         ec_fsm_mapping_t *fsm, /**< mapping state machine */
    89         ec_slave_t *slave /**< slave to configure */
    87         ec_slave_t *slave /**< slave to configure */
    90         )
    88         )
    91 {
    89 {
    93     fsm->state = ec_fsm_mapping_state_start;
    91     fsm->state = ec_fsm_mapping_state_start;
    94 }
    92 }
    95 
    93 
    96 /*****************************************************************************/
    94 /*****************************************************************************/
    97 
    95 
    98 /**
    96 /** Get running state.
       
    97  *
    99  * \return false, if state machine has terminated
    98  * \return false, if state machine has terminated
   100  */
    99  */
   101 
       
   102 int ec_fsm_mapping_running(
   100 int ec_fsm_mapping_running(
   103         const ec_fsm_mapping_t *fsm /**< mapping state machine */
   101         const ec_fsm_mapping_t *fsm /**< mapping state machine */
   104         )
   102         )
   105 {
   103 {
   106     return fsm->state != ec_fsm_mapping_state_end
   104     return fsm->state != ec_fsm_mapping_state_end
   107         && fsm->state != ec_fsm_mapping_state_error;
   105         && fsm->state != ec_fsm_mapping_state_error;
   108 }
   106 }
   109 
   107 
   110 /*****************************************************************************/
   108 /*****************************************************************************/
   111 
   109 
   112 /**
   110 /** Executes the current state of the state machine.
   113  * Executes the current state of the state machine.
   111  *
   114  * If the state machine's datagram is not sent or received yet, the execution
   112  * If the state machine's datagram is not sent or received yet, the execution
   115  * of the state machine is delayed to the next cycle.
   113  * of the state machine is delayed to the next cycle.
       
   114  *
   116  * \return false, if state machine has terminated
   115  * \return false, if state machine has terminated
   117  */
   116  */
   118 
       
   119 int ec_fsm_mapping_exec(
   117 int ec_fsm_mapping_exec(
   120         ec_fsm_mapping_t *fsm /**< mapping state machine */
   118         ec_fsm_mapping_t *fsm /**< mapping state machine */
   121         )
   119         )
   122 {
   120 {
   123     fsm->state(fsm);
   121     fsm->state(fsm);
   124     return ec_fsm_mapping_running(fsm);
   122     return ec_fsm_mapping_running(fsm);
   125 }
   123 }
   126 
   124 
   127 /*****************************************************************************/
   125 /*****************************************************************************/
   128 
   126 
   129 /**
   127 /** Get execution result.
       
   128  *
   130  * \return true, if the state machine terminated gracefully
   129  * \return true, if the state machine terminated gracefully
   131  */
   130  */
   132 
       
   133 int ec_fsm_mapping_success(
   131 int ec_fsm_mapping_success(
   134         const ec_fsm_mapping_t *fsm /**< mapping state machine */
   132         const ec_fsm_mapping_t *fsm /**< mapping state machine */
   135         )
   133         )
   136 {
   134 {
   137     return fsm->state == ec_fsm_mapping_state_end;
   135     return fsm->state == ec_fsm_mapping_state_end;
   138 }
   136 }
   139 
   137 
   140 /******************************************************************************
   138 /******************************************************************************
   141  * state functions
   139  * State functions.
   142  *****************************************************************************/
   140  *****************************************************************************/
   143 
   141 
   144 /**
   142 /** Start mapping configuration.
   145  * Start mapping configuration.
   143  */
   146  */
       
   147 
       
   148 void ec_fsm_mapping_state_start(
   144 void ec_fsm_mapping_state_start(
   149         ec_fsm_mapping_t *fsm /**< mapping state machine */
   145         ec_fsm_mapping_t *fsm /**< mapping state machine */
   150         )
   146         )
   151 {
   147 {
       
   148     if (!fsm->slave->config) {
       
   149         fsm->state = ec_fsm_mapping_state_end;
       
   150         return;
       
   151     }
       
   152 
   152     fsm->dir = EC_DIR_OUTPUT;
   153     fsm->dir = EC_DIR_OUTPUT;
   153     ec_fsm_mapping_next_sync(fsm);
   154     ec_fsm_mapping_next_sync(fsm);
   154 }
   155 }
   155 
   156 
   156 /*****************************************************************************/
   157 /*****************************************************************************/
   157 
   158 
   158 /**
   159 /** Process mapping of next sync manager.
   159  * Process mapping of next sync manager.
   160  */
   160  */
       
   161 
       
   162 void ec_fsm_mapping_next_sync(
   161 void ec_fsm_mapping_next_sync(
   163         ec_fsm_mapping_t *fsm /**< mapping state machine */
   162         ec_fsm_mapping_t *fsm /**< mapping state machine */
   164         )
   163         )
   165 {
   164 {
   166     while (1) {
   165     while (1) {
   169             fsm->state = ec_fsm_mapping_state_end;
   168             fsm->state = ec_fsm_mapping_state_end;
   170             return;
   169             return;
   171         }
   170         }
   172 
   171 
   173         if (!(fsm->sync = ec_slave_get_pdo_sync(fsm->slave, fsm->dir))) {
   172         if (!(fsm->sync = ec_slave_get_pdo_sync(fsm->slave, fsm->dir))) {
   174             // no sync manager found for this direction
   173             EC_WARN("next_sync(): No sync manager!\n");
   175             fsm->dir++;
   174             fsm->dir++;
   176             continue;
   175             continue;
   177         }
   176         }
   178 
   177 
   179         fsm->dir++;
   178         fsm->mapping = &fsm->slave->config->mapping[fsm->dir];
   180         if (fsm->sync->alt_mapping)
   179 
       
   180         if (ec_pdo_mapping_equal(&fsm->sync->mapping, fsm->mapping)) {
       
   181             // the mapping for this direction does not have to be altered
       
   182             fsm->dir++;
       
   183             continue;
       
   184         } else {
       
   185             fsm->dir++;
   181             break;
   186             break;
       
   187         }
   182     }
   188     }
   183 
   189 
   184     if (fsm->slave->master->debug_level) {
   190     if (fsm->slave->master->debug_level) {
   185         EC_DBG("Configuring PDO mapping for SM%u of slave %i.\n",
   191         EC_DBG("Configuring PDO mapping for SM%u of slave %u.\n",
   186                 fsm->sync->index, fsm->slave->ring_position);
   192                 fsm->sync->index, fsm->slave->ring_position);
   187     }
   193     }
   188 
   194 
   189     // set mapped PDO count to zero
   195     // set mapped PDO count to zero
   190     fsm->sdodata.index = 0x1C10 + fsm->sync->index;
   196     fsm->sdodata.index = 0x1C10 + fsm->sync->index;
   199     ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
   205     ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
   200 }
   206 }
   201 
   207 
   202 /*****************************************************************************/
   208 /*****************************************************************************/
   203 
   209 
   204 /**
   210 /** Process mapping of next PDO.
   205  * Process mapping of next PDO.
   211  */
   206  */
       
   207 
       
   208 ec_pdo_t *ec_fsm_mapping_next_pdo(
   212 ec_pdo_t *ec_fsm_mapping_next_pdo(
   209         ec_fsm_mapping_t *fsm, /**< mapping state machine */
   213         const ec_fsm_mapping_t *fsm, /**< mapping state machine */
   210         struct list_head *list /**< current PDO list item */
   214         const struct list_head *list /**< current PDO list item */
   211         )
   215         )
   212 {
   216 {
   213     ec_pdo_t *pdo;
   217     list = list->next; 
   214 
   218     if (list == &fsm->mapping->pdos)
   215     do {
   219         return NULL; // no next PDO
   216         list = list->next; 
   220     return list_entry(list, ec_pdo_t, list);
   217         if (list == &fsm->sync->pdos)
   221 }
   218             return NULL; // no next PDO
   222 
   219         pdo = list_entry(list, ec_pdo_t, list);
   223 /*****************************************************************************/
   220     }
   224 
   221     while (pdo->sync_index != fsm->sync->index);
   225 /** Set the number of mapped PDOs to zero.
   222     
   226  */
   223     return pdo;
       
   224 }
       
   225 
       
   226 /*****************************************************************************/
       
   227 
       
   228 /**
       
   229  * Set the number of mapped PDOs to zero.
       
   230  */
       
   231 
       
   232 void ec_fsm_mapping_state_zero_count(
   227 void ec_fsm_mapping_state_zero_count(
   233         ec_fsm_mapping_t *fsm /**< mapping state machine */
   228         ec_fsm_mapping_t *fsm /**< mapping state machine */
   234         )
   229         )
   235 {
   230 {
   236     if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
   231     if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
   243     }
   238     }
   244 
   239 
   245     // map all PDOs belonging to the current sync manager
   240     // map all PDOs belonging to the current sync manager
   246     
   241     
   247     // find first PDO
   242     // find first PDO
   248     if (!(fsm->pdo = ec_fsm_mapping_next_pdo(
   243     if (!(fsm->pdo = ec_fsm_mapping_next_pdo(fsm, &fsm->mapping->pdos))) {
   249                     fsm, &fsm->sync->pdos))) {
       
   250         if (fsm->slave->master->debug_level)
   244         if (fsm->slave->master->debug_level)
   251             EC_DBG("No PDOs to map for SM%u of slave %u.\n",
   245             EC_DBG("No PDOs to map for SM%u of slave %u.\n",
   252                     fsm->sync->index, fsm->slave->ring_position);
   246                     fsm->sync->index, fsm->slave->ring_position);
   253         ec_fsm_mapping_next_sync(fsm);
   247         ec_fsm_mapping_next_sync(fsm);
   254         return;
   248         return;
   269     ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
   263     ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
   270 }
   264 }
   271 
   265 
   272 /*****************************************************************************/
   266 /*****************************************************************************/
   273 
   267 
   274 /**
   268 /** Add a PDO to the sync managers mapping.
   275  * Add a PDO to the sync managers mapping.
   269  */
   276  */
       
   277 
       
   278 void ec_fsm_mapping_state_add_pdo(
   270 void ec_fsm_mapping_state_add_pdo(
   279         ec_fsm_mapping_t *fsm /**< mapping state machine */
   271         ec_fsm_mapping_t *fsm /**< mapping state machine */
   280         )
   272         )
   281 {
   273 {
   282     if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
   274     if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
   287         fsm->state = ec_fsm_mapping_state_error;
   279         fsm->state = ec_fsm_mapping_state_error;
   288         return;
   280         return;
   289     }
   281     }
   290 
   282 
   291     // find next PDO
   283     // find next PDO
   292     if (!(fsm->pdo = ec_fsm_mapping_next_pdo(
   284     if (!(fsm->pdo = ec_fsm_mapping_next_pdo(fsm, &fsm->pdo->list))) {
   293                     fsm, &fsm->pdo->list))) {
       
   294         // no more PDOs to map. write PDO count
   285         // no more PDOs to map. write PDO count
   295         fsm->sdodata.subindex = 0;
   286         fsm->sdodata.subindex = 0;
   296         EC_WRITE_U8(&fsm->sdo_value, fsm->pdo_count);
   287         EC_WRITE_U8(&fsm->sdo_value, fsm->pdo_count);
   297         fsm->sdodata.size = 1;
   288         fsm->sdodata.size = 1;
   298 
   289 
   320     ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
   311     ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
   321 }
   312 }
   322 
   313 
   323 /*****************************************************************************/
   314 /*****************************************************************************/
   324 
   315 
   325 /**
   316 /** Set the number of mapped PDOs.
   326  * Set the number of mapped PDOs.
   317  */
   327  */
       
   328 
       
   329 void ec_fsm_mapping_state_pdo_count(
   318 void ec_fsm_mapping_state_pdo_count(
   330         ec_fsm_mapping_t *fsm /**< mapping state machine */
   319         ec_fsm_mapping_t *fsm /**< mapping state machine */
   331         )
   320         )
   332 {
   321 {
   333     if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
   322     if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
   349 
   338 
   350 /******************************************************************************
   339 /******************************************************************************
   351  * Common state functions
   340  * Common state functions
   352  *****************************************************************************/
   341  *****************************************************************************/
   353 
   342 
   354 /**
   343 /** State: ERROR.
   355    State: ERROR.
   344  */
   356 */
       
   357 
       
   358 void ec_fsm_mapping_state_error(
   345 void ec_fsm_mapping_state_error(
   359         ec_fsm_mapping_t *fsm /**< mapping state machine */
   346         ec_fsm_mapping_t *fsm /**< mapping state machine */
   360         )
   347         )
   361 {
   348 {
   362 }
   349 }
   363 
   350 
   364 /*****************************************************************************/
   351 /*****************************************************************************/
   365 
   352 
   366 /**
   353 /** State: END.
   367    State: END.
   354  */
   368 */
       
   369 
       
   370 void ec_fsm_mapping_state_end(
   355 void ec_fsm_mapping_state_end(
   371         ec_fsm_mapping_t *fsm /**< mapping state machine */
   356         ec_fsm_mapping_t *fsm /**< mapping state machine */
   372         )
   357         )
   373 {
   358 {
   374 }
   359 }