master/fsm_slave.c
changeset 1831 1875b9fea0ba
parent 1804 742607c464c4
child 1878 8f37abf260cf
equal deleted inserted replaced
1830:ef09f0ea0c4c 1831:1875b9fea0ba
    42 /*****************************************************************************/
    42 /*****************************************************************************/
    43 
    43 
    44 void ec_fsm_slave_state_idle(ec_fsm_slave_t *);
    44 void ec_fsm_slave_state_idle(ec_fsm_slave_t *);
    45 void ec_fsm_slave_state_ready(ec_fsm_slave_t *);
    45 void ec_fsm_slave_state_ready(ec_fsm_slave_t *);
    46 int ec_fsm_slave_action_process_sdo(ec_fsm_slave_t *);
    46 int ec_fsm_slave_action_process_sdo(ec_fsm_slave_t *);
       
    47 void ec_fsm_slave_state_sdo_request(ec_fsm_slave_t *);
    47 int ec_fsm_slave_action_process_foe(ec_fsm_slave_t *);
    48 int ec_fsm_slave_action_process_foe(ec_fsm_slave_t *);
    48 void ec_fsm_slave_state_sdo_request(ec_fsm_slave_t *);
       
    49 void ec_fsm_slave_state_foe_request(ec_fsm_slave_t *);
    49 void ec_fsm_slave_state_foe_request(ec_fsm_slave_t *);
    50 
    50 int ec_fsm_slave_action_process_soe(ec_fsm_slave_t *);
       
    51 void ec_fsm_slave_state_soe_request(ec_fsm_slave_t *);
    51 
    52 
    52 /*****************************************************************************/
    53 /*****************************************************************************/
    53 
    54 
    54 /** Constructor.
    55 /** Constructor.
    55  */
    56  */
    69     fsm->state = ec_fsm_slave_state_idle;
    70     fsm->state = ec_fsm_slave_state_idle;
    70 
    71 
    71     // init sub-state-machines
    72     // init sub-state-machines
    72     ec_fsm_coe_init(&fsm->fsm_coe, fsm->datagram);
    73     ec_fsm_coe_init(&fsm->fsm_coe, fsm->datagram);
    73     ec_fsm_foe_init(&fsm->fsm_foe, fsm->datagram);
    74     ec_fsm_foe_init(&fsm->fsm_foe, fsm->datagram);
       
    75     ec_fsm_soe_init(&fsm->fsm_soe, fsm->datagram);
    74 }
    76 }
    75 
    77 
    76 /*****************************************************************************/
    78 /*****************************************************************************/
    77 
    79 
    78 /** Destructor.
    80 /** Destructor.
    82         )
    84         )
    83 {
    85 {
    84     // clear sub-state machines
    86     // clear sub-state machines
    85     ec_fsm_coe_clear(&fsm->fsm_coe);
    87     ec_fsm_coe_clear(&fsm->fsm_coe);
    86     ec_fsm_foe_clear(&fsm->fsm_foe);
    88     ec_fsm_foe_clear(&fsm->fsm_foe);
       
    89     ec_fsm_soe_clear(&fsm->fsm_soe);
    87 }
    90 }
    88 
    91 
    89 /*****************************************************************************/
    92 /*****************************************************************************/
    90 
    93 
    91 /** Executes the current state of the state machine.
    94 /** Executes the current state of the state machine.
   105 
   108 
   106     fsm->state(fsm);
   109     fsm->state(fsm);
   107     return;
   110     return;
   108 }
   111 }
   109 
   112 
   110 
       
   111 /*****************************************************************************/
   113 /*****************************************************************************/
   112 
   114 
   113 /** Sets the current state of the state machine to READY
   115 /** Sets the current state of the state machine to READY
   114  *
       
   115  */
   116  */
   116 void ec_fsm_slave_ready(
   117 void ec_fsm_slave_ready(
   117         ec_fsm_slave_t *fsm /**< Slave state machine. */
   118         ec_fsm_slave_t *fsm /**< Slave state machine. */
   118         )
   119         )
   119 {
   120 {
   120     if (fsm->state == ec_fsm_slave_state_idle) {
   121     if (fsm->state == ec_fsm_slave_state_idle) {
   121         if (fsm->slave->master->debug_level) {
   122         if (fsm->slave->master->debug_level) {
   122             EC_DBG("Slave %u ready for SDO/FOE.\n",
   123             EC_DBG("Slave %u ready for requests.\n",
   123                     fsm->slave->ring_position);
   124                     fsm->slave->ring_position);
   124         }
   125         }
   125         fsm->state = ec_fsm_slave_state_ready;
   126         fsm->state = ec_fsm_slave_state_ready;
   126     }
   127     }
   127     return;
       
   128 }
   128 }
   129 
   129 
   130 /******************************************************************************
   130 /******************************************************************************
   131  * Slave state machine
   131  * Slave state machine
   132  *****************************************************************************/
   132  *****************************************************************************/
   133 
   133 
   134 /*****************************************************************************/
       
   135 
       
   136 /** Slave state: IDLE.
   134 /** Slave state: IDLE.
   137  *
       
   138  *
       
   139  */
   135  */
   140 void ec_fsm_slave_state_idle(
   136 void ec_fsm_slave_state_idle(
   141         ec_fsm_slave_t *fsm /**< Slave state machine. */
   137         ec_fsm_slave_t *fsm /**< Slave state machine. */
   142         )
   138         )
   143 {
   139 {
   146 
   142 
   147 
   143 
   148 /*****************************************************************************/
   144 /*****************************************************************************/
   149 
   145 
   150 /** Slave state: READY.
   146 /** Slave state: READY.
   151  *
       
   152  *
       
   153  */
   147  */
   154 void ec_fsm_slave_state_ready(
   148 void ec_fsm_slave_state_ready(
   155         ec_fsm_slave_t *fsm /**< Slave state machine. */
   149         ec_fsm_slave_t *fsm /**< Slave state machine. */
   156         )
   150         )
   157 {
   151 {
   158     // Check for pending external SDO requests
   152     // Check for pending external SDO requests
   159     if (ec_fsm_slave_action_process_sdo(fsm))
   153     if (ec_fsm_slave_action_process_sdo(fsm))
   160         return;
   154         return;
   161 
   155 
   162     // Check for pending FOE requests
   156     // Check for pending FoE requests
   163     if (ec_fsm_slave_action_process_foe(fsm))
   157     if (ec_fsm_slave_action_process_foe(fsm))
       
   158         return;
       
   159 
       
   160     // Check for pending SoE requests
       
   161     if (ec_fsm_slave_action_process_soe(fsm))
   164         return;
   162         return;
   165 }
   163 }
   166 
   164 
   167 /*****************************************************************************/
   165 /*****************************************************************************/
   168 
   166 
   218         return 1;
   216         return 1;
   219     }
   217     }
   220     return 0;
   218     return 0;
   221 }
   219 }
   222 
   220 
   223 
       
   224 /*****************************************************************************/
       
   225 
       
   226 /** Check for pending FOE requests and process one.
       
   227  *
       
   228  * \return non-zero, if an FOE request is processed.
       
   229  */
       
   230 int ec_fsm_slave_action_process_foe(
       
   231         ec_fsm_slave_t *fsm /**< Slave state machine. */
       
   232         )
       
   233 {
       
   234     ec_slave_t *slave = fsm->slave;
       
   235     ec_master_t *master = slave->master;
       
   236     ec_master_foe_request_t *request, *next;
       
   237 
       
   238     // search the first request to be processed
       
   239     list_for_each_entry_safe(request, next, &slave->foe_requests, list) {
       
   240         if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
       
   241             EC_WARN("Aborting FOE request, slave %u has ERROR.\n",
       
   242                     slave->ring_position);
       
   243             request->req.state = EC_INT_REQUEST_FAILURE;
       
   244             wake_up(&slave->sdo_queue);
       
   245             fsm->sdo_request = NULL;
       
   246             fsm->state = ec_fsm_slave_state_idle;
       
   247             return 0;
       
   248         }
       
   249         list_del_init(&request->list); // dequeue
       
   250         request->req.state = EC_INT_REQUEST_BUSY;
       
   251 
       
   252         if (master->debug_level)
       
   253             EC_DBG("Processing FOE request for slave %u.\n",
       
   254                     slave->ring_position);
       
   255 
       
   256         fsm->foe_request = &request->req;
       
   257         fsm->state = ec_fsm_slave_state_foe_request;
       
   258         ec_fsm_foe_transfer(&fsm->fsm_foe, slave, &request->req);
       
   259         ec_fsm_foe_exec(&fsm->fsm_foe);
       
   260         ec_master_queue_external_datagram(fsm->slave->master,fsm->datagram);
       
   261         return 1;
       
   262     }
       
   263     return 0;
       
   264 }
       
   265 
       
   266 
       
   267 
       
   268 /*****************************************************************************/
   221 /*****************************************************************************/
   269 
   222 
   270 /** Slave state: SDO_REQUEST.
   223 /** Slave state: SDO_REQUEST.
   271  */
   224  */
   272 void ec_fsm_slave_state_sdo_request(
   225 void ec_fsm_slave_state_sdo_request(
   304     fsm->state = ec_fsm_slave_state_ready;
   257     fsm->state = ec_fsm_slave_state_ready;
   305 }
   258 }
   306 
   259 
   307 /*****************************************************************************/
   260 /*****************************************************************************/
   308 
   261 
       
   262 /** Check for pending FOE requests and process one.
       
   263  *
       
   264  * \return non-zero, if an FOE request is processed.
       
   265  */
       
   266 int ec_fsm_slave_action_process_foe(
       
   267         ec_fsm_slave_t *fsm /**< Slave state machine. */
       
   268         )
       
   269 {
       
   270     ec_slave_t *slave = fsm->slave;
       
   271     ec_master_t *master = slave->master;
       
   272     ec_master_foe_request_t *request, *next;
       
   273 
       
   274     // search the first request to be processed
       
   275     list_for_each_entry_safe(request, next, &slave->foe_requests, list) {
       
   276         if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
       
   277             EC_WARN("Aborting FOE request, slave %u has ERROR.\n",
       
   278                     slave->ring_position);
       
   279             request->req.state = EC_INT_REQUEST_FAILURE;
       
   280             wake_up(&slave->sdo_queue);
       
   281             fsm->sdo_request = NULL;
       
   282             fsm->state = ec_fsm_slave_state_idle;
       
   283             return 0;
       
   284         }
       
   285         list_del_init(&request->list); // dequeue
       
   286         request->req.state = EC_INT_REQUEST_BUSY;
       
   287 
       
   288         if (master->debug_level)
       
   289             EC_DBG("Processing FOE request for slave %u.\n",
       
   290                     slave->ring_position);
       
   291 
       
   292         fsm->foe_request = &request->req;
       
   293         fsm->state = ec_fsm_slave_state_foe_request;
       
   294         ec_fsm_foe_transfer(&fsm->fsm_foe, slave, &request->req);
       
   295         ec_fsm_foe_exec(&fsm->fsm_foe);
       
   296         ec_master_queue_external_datagram(fsm->slave->master,fsm->datagram);
       
   297         return 1;
       
   298     }
       
   299     return 0;
       
   300 }
       
   301 
       
   302 /*****************************************************************************/
       
   303 
   309 /** Slave state: FOE REQUEST.
   304 /** Slave state: FOE REQUEST.
   310  */
   305  */
   311 void ec_fsm_slave_state_foe_request(
   306 void ec_fsm_slave_state_foe_request(
   312         ec_fsm_slave_t *fsm /**< Slave state machine. */
   307         ec_fsm_slave_t *fsm /**< Slave state machine. */
   313         )
   308         )
   343     fsm->foe_request = NULL;
   338     fsm->foe_request = NULL;
   344     fsm->state = ec_fsm_slave_state_ready;
   339     fsm->state = ec_fsm_slave_state_ready;
   345 }
   340 }
   346 
   341 
   347 /*****************************************************************************/
   342 /*****************************************************************************/
       
   343 
       
   344 /** Check for pending SoE requests and process one.
       
   345  *
       
   346  * \return non-zero, if a request is processed.
       
   347  */
       
   348 int ec_fsm_slave_action_process_soe(
       
   349         ec_fsm_slave_t *fsm /**< Slave state machine. */
       
   350         )
       
   351 {
       
   352     ec_slave_t *slave = fsm->slave;
       
   353     ec_master_t *master = slave->master;
       
   354     ec_master_soe_request_t *req, *next;
       
   355 
       
   356     // search the first request to be processed
       
   357     list_for_each_entry_safe(req, next, &slave->soe_requests, list) {
       
   358 
       
   359         list_del_init(&req->list); // dequeue
       
   360         if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
       
   361             EC_WARN("Aborting SoE request, slave %u has ERROR.\n",
       
   362                     slave->ring_position);
       
   363             req->req.state = EC_INT_REQUEST_FAILURE;
       
   364             wake_up(&slave->soe_queue);
       
   365             fsm->state = ec_fsm_slave_state_idle;
       
   366             return 0;
       
   367         }
       
   368 
       
   369         if (slave->current_state == EC_SLAVE_STATE_INIT) {
       
   370             EC_WARN("Aborting SoE request, slave %u is in INIT.\n",
       
   371                     slave->ring_position);
       
   372             req->req.state = EC_INT_REQUEST_FAILURE;
       
   373             wake_up(&slave->soe_queue);
       
   374             fsm->state = ec_fsm_slave_state_idle;
       
   375             return 0;
       
   376         }
       
   377 
       
   378         req->req.state = EC_INT_REQUEST_BUSY;
       
   379 
       
   380         // Found pending request. Execute it!
       
   381         if (master->debug_level)
       
   382             EC_DBG("Processing SoE request for slave %u...\n",
       
   383                     slave->ring_position);
       
   384 
       
   385         // Start SoE transfer
       
   386         fsm->soe_request = &req->req;
       
   387         fsm->state = ec_fsm_slave_state_soe_request;
       
   388         ec_fsm_soe_transfer(&fsm->fsm_soe, slave, &req->req);
       
   389         ec_fsm_soe_exec(&fsm->fsm_soe); // execute immediately
       
   390         ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram);
       
   391         return 1;
       
   392     }
       
   393     return 0;
       
   394 }
       
   395 
       
   396 /*****************************************************************************/
       
   397 
       
   398 /** Slave state: SOE_REQUEST.
       
   399  */
       
   400 void ec_fsm_slave_state_soe_request(
       
   401         ec_fsm_slave_t *fsm /**< Slave state machine. */
       
   402         )
       
   403 {
       
   404     ec_slave_t *slave = fsm->slave;
       
   405     ec_master_t *master = slave->master;
       
   406     ec_soe_request_t *request = fsm->soe_request;
       
   407 
       
   408     if (ec_fsm_soe_exec(&fsm->fsm_soe)) {
       
   409         ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram);
       
   410         return;
       
   411     }
       
   412 
       
   413     if (!ec_fsm_soe_success(&fsm->fsm_soe)) {
       
   414         EC_DBG("Failed to process SoE request for slave %u.\n",
       
   415                 fsm->slave->ring_position);
       
   416         request->state = EC_INT_REQUEST_FAILURE;
       
   417         wake_up(&slave->soe_queue);
       
   418         fsm->soe_request = NULL;
       
   419         fsm->state = ec_fsm_slave_state_idle;
       
   420         return;
       
   421     }
       
   422 
       
   423     if (master->debug_level)
       
   424         EC_DBG("Finished SoE request for slave %u.\n",
       
   425                 fsm->slave->ring_position);
       
   426 
       
   427     // SoE request finished
       
   428     request->state = EC_INT_REQUEST_SUCCESS;
       
   429     wake_up(&slave->soe_queue);
       
   430 
       
   431     fsm->soe_request = NULL;
       
   432     fsm->state = ec_fsm_slave_state_ready;
       
   433 }
       
   434 
       
   435 /*****************************************************************************/