master/fsm_slave.c
branchstable-1.3
changeset 1746 72e7507b3f1b
parent 1745 07fd94c5119d
equal deleted inserted replaced
1745:07fd94c5119d 1746:72e7507b3f1b
   401 
   401 
   402     cat_type = EC_READ_U16(fsm->fsm_sii.value);
   402     cat_type = EC_READ_U16(fsm->fsm_sii.value);
   403     cat_size = EC_READ_U16(fsm->fsm_sii.value + 2);
   403     cat_size = EC_READ_U16(fsm->fsm_sii.value + 2);
   404 
   404 
   405     if (cat_type != 0xFFFF) { // not the last category
   405     if (cat_type != 0xFFFF) { // not the last category
   406         fsm->sii_offset += cat_size + 2;
   406         off_t next_offset = 2UL + fsm->sii_offset + cat_size;
   407         if (fsm->sii_offset >= EC_MAX_EEPROM_SIZE) {
   407         if (next_offset >= EC_MAX_EEPROM_SIZE) {
   408             EC_WARN("EEPROM size of slave %i exceeds"
   408             EC_WARN("EEPROM size of slave %i exceeds"
   409                     " %i words (0xffff limiter missing?).\n",
   409                     " %u words (0xffff limiter missing?).\n",
   410                     slave->ring_position, EC_MAX_EEPROM_SIZE);
   410                     slave->ring_position, EC_MAX_EEPROM_SIZE);
   411             slave->eeprom_size = EC_FIRST_EEPROM_CATEGORY_OFFSET * 2;
   411             slave->eeprom_size = EC_FIRST_EEPROM_CATEGORY_OFFSET * 2;
   412             goto alloc_eeprom;
   412             goto alloc_eeprom;
   413         }
   413         }
       
   414         fsm->sii_offset = next_offset;
   414         ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
   415         ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
   415                         EC_FSM_SII_NODE);
   416                         EC_FSM_SII_NODE);
   416         ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately
   417         ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately
   417         return;
   418         return;
   418     }
   419     }
   419 
   420 
   420     slave->eeprom_size = (fsm->sii_offset + 1) * 2;
   421     slave->eeprom_size = (fsm->sii_offset + 1) * 2;
   421 
   422 
   422 alloc_eeprom:
   423 alloc_eeprom:
   423     if (slave->eeprom_data) {
   424     if (slave->eeprom_data) {
   424         EC_INFO("Freeing old EEPROM data on slave %i...\n",
   425         EC_WARN("Freeing old EEPROM data on slave %i...\n",
   425                 slave->ring_position);
   426                 slave->ring_position);
   426         kfree(slave->eeprom_data);
   427         kfree(slave->eeprom_data);
   427     }
   428     }
   428 
   429 
   429     if (!(slave->eeprom_data =
   430     if (!(slave->eeprom_data =
   430           (uint8_t *) kmalloc(slave->eeprom_size, GFP_ATOMIC))) {
   431                 (uint8_t *) kmalloc(slave->eeprom_size, GFP_ATOMIC))) {
   431         fsm->slave->error_flag = 1;
   432         EC_ERR("Failed to allocate %u bytes of EEPROM data for slave %u.\n",
   432         fsm->state = ec_fsm_slave_state_error;
   433                slave->eeprom_size, slave->ring_position);
   433         EC_ERR("Failed to allocate EEPROM data on slave %i.\n",
   434         slave->eeprom_size = 0;
   434                slave->ring_position);
   435         slave->error_flag = 1;
       
   436         fsm->state = ec_fsm_slave_state_error;
   435         return;
   437         return;
   436     }
   438     }
   437 
   439 
   438     // Start fetching EEPROM contents
   440     // Start fetching EEPROM contents
   439 
   441 
   450 */
   452 */
   451 
   453 
   452 void ec_fsm_slave_scan_state_eeprom_data(ec_fsm_slave_t *fsm /**< slave state machine */)
   454 void ec_fsm_slave_scan_state_eeprom_data(ec_fsm_slave_t *fsm /**< slave state machine */)
   453 {
   455 {
   454     ec_slave_t *slave = fsm->slave;
   456     ec_slave_t *slave = fsm->slave;
   455     uint16_t *cat_word, cat_type, cat_size;
   457     uint16_t *cat_word, cat_type, cat_size, eeprom_word_size = slave->eeprom_size / 2;
   456 
   458 
   457     if (ec_fsm_sii_exec(&fsm->fsm_sii)) return;
   459     if (ec_fsm_sii_exec(&fsm->fsm_sii)) return;
   458 
   460 
   459     if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
   461     if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
   460         fsm->slave->error_flag = 1;
   462         fsm->slave->error_flag = 1;
   464         return;
   466         return;
   465     }
   467     }
   466 
   468 
   467     // 2 words fetched
   469     // 2 words fetched
   468 
   470 
   469     if (fsm->sii_offset + 2 <= slave->eeprom_size / 2) { // 2 words fit
   471     if (fsm->sii_offset + 2 <= eeprom_word_size) { // 2 words fit
   470         memcpy(slave->eeprom_data + fsm->sii_offset * 2,
   472         memcpy(slave->eeprom_data + fsm->sii_offset * 2,
   471                fsm->fsm_sii.value, 4);
   473                fsm->fsm_sii.value, 4);
   472     }
   474     }
   473     else { // copy the last word
   475     else { // copy the last word
   474         memcpy(slave->eeprom_data + fsm->sii_offset * 2,
   476         memcpy(slave->eeprom_data + fsm->sii_offset * 2,
   475                fsm->fsm_sii.value, 2);
   477                fsm->fsm_sii.value, 2);
   476     }
   478     }
   477 
   479 
   478     if (fsm->sii_offset + 2 < slave->eeprom_size / 2) {
   480     if (fsm->sii_offset + 2 < eeprom_word_size) {
   479         // fetch the next 2 words
   481         // fetch the next 2 words
   480         fsm->sii_offset += 2;
   482         fsm->sii_offset += 2;
   481         ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
   483         ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
   482                         EC_FSM_SII_NODE);
   484                         EC_FSM_SII_NODE);
   483         ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately
   485         ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately
   505     slave->sii_tx_mailbox_size =
   507     slave->sii_tx_mailbox_size =
   506         EC_READ_U16(slave->eeprom_data + 2 * 0x001B);
   508         EC_READ_U16(slave->eeprom_data + 2 * 0x001B);
   507     slave->sii_mailbox_protocols =
   509     slave->sii_mailbox_protocols =
   508         EC_READ_U16(slave->eeprom_data + 2 * 0x001C);
   510         EC_READ_U16(slave->eeprom_data + 2 * 0x001C);
   509 
   511 
       
   512     if (eeprom_word_size < EC_FIRST_EEPROM_CATEGORY_OFFSET + 1) {
       
   513         EC_ERR("Unexpected end of EEPROM data in slave %u:"
       
   514                 " First category header missing.\n",
       
   515                 slave->ring_position);
       
   516         goto end;
       
   517     }
       
   518 
   510     // evaluate category data
   519     // evaluate category data
   511     cat_word = (uint16_t *) slave->eeprom_data + EC_FIRST_EEPROM_CATEGORY_OFFSET;
   520     cat_word =
       
   521         (uint16_t *) slave->eeprom_data + EC_FIRST_EEPROM_CATEGORY_OFFSET;
   512     while (EC_READ_U16(cat_word) != 0xFFFF) {
   522     while (EC_READ_U16(cat_word) != 0xFFFF) {
       
   523 
       
   524         // type and size words must fit
       
   525         if (cat_word + 2 - (uint16_t *) slave->eeprom_data
       
   526                 > eeprom_word_size) {
       
   527             EC_ERR("Unexpected end of EEPROM data in slave %u:"
       
   528                     " Category header incomplete.\n",
       
   529                     slave->ring_position);
       
   530             goto end;
       
   531         }
       
   532 
   513         cat_type = EC_READ_U16(cat_word) & 0x7FFF;
   533         cat_type = EC_READ_U16(cat_word) & 0x7FFF;
   514         cat_size = EC_READ_U16(cat_word + 1);
   534         cat_size = EC_READ_U16(cat_word + 1);
       
   535         cat_word += 2;
       
   536 
       
   537         if (cat_word + cat_size - (uint16_t *) slave->eeprom_data
       
   538                 > eeprom_word_size) {
       
   539             EC_WARN("Unexpected end of EEPROM data in slave %u:"
       
   540                     " Category data incomplete.\n",
       
   541                     slave->ring_position);
       
   542             goto end;
       
   543         }
   515 
   544 
   516         switch (cat_type) {
   545         switch (cat_type) {
   517             case 0x000A:
   546             case 0x000A:
   518                 if (ec_slave_fetch_sii_strings(
   547                 if (ec_slave_fetch_sii_strings(slave, (uint8_t *) cat_word,
   519                             slave, (uint8_t *) (cat_word + 2)))
   548                             cat_size * 2))
   520                     goto end;
   549                     goto end;
   521                 break;
   550                 break;
   522             case 0x001E:
   551             case 0x001E:
   523                 ec_slave_fetch_sii_general(
   552                 if (ec_slave_fetch_sii_general(slave, (uint8_t *) cat_word,
   524                         slave, (uint8_t *) (cat_word + 2));
   553                             cat_size * 2))
       
   554                     goto end;
   525                 break;
   555                 break;
   526             case 0x0028:
   556             case 0x0028:
   527                 break;
   557                 break;
   528             case 0x0029:
   558             case 0x0029:
   529                 if (ec_slave_fetch_sii_syncs(
   559                 if (ec_slave_fetch_sii_syncs(slave, (uint8_t *) cat_word,
   530                             slave, (uint8_t *) (cat_word + 2), cat_size))
   560                             cat_size * 2))
   531                     goto end;
   561                     goto end;
   532                 break;
   562                 break;
   533             case 0x0032:
   563             case 0x0032:
   534                 if (ec_slave_fetch_sii_pdos(
   564                 if (ec_slave_fetch_sii_pdos( slave, (uint8_t *) cat_word,
   535                             slave, (uint8_t *) (cat_word + 2),
   565                             cat_size * 2, EC_TX_PDO))
   536                             cat_size, EC_TX_PDO))
       
   537                     goto end;
   566                     goto end;
   538                 break;
   567                 break;
   539             case 0x0033:
   568             case 0x0033:
   540                 if (ec_slave_fetch_sii_pdos(
   569                 if (ec_slave_fetch_sii_pdos( slave, (uint8_t *) cat_word,
   541                             slave, (uint8_t *) (cat_word + 2),
   570                             cat_size * 2, EC_RX_PDO))
   542                             cat_size, EC_RX_PDO))
       
   543                     goto end;
   571                     goto end;
   544                 break;
   572                 break;
   545             default:
   573             default:
   546                 if (fsm->slave->master->debug_level)
   574                 if (fsm->slave->master->debug_level)
   547                     EC_WARN("Unknown category type 0x%04X in slave %i.\n",
   575                     EC_WARN("Unknown category type 0x%04X in slave %i.\n",
   548                             cat_type, slave->ring_position);
   576                             cat_type, slave->ring_position);
   549         }
   577         }
   550 
   578 
   551         cat_word += cat_size + 2;
   579         cat_word += cat_size;
       
   580         if (cat_word - (uint16_t *) slave->eeprom_data >= eeprom_word_size) {
       
   581             EC_WARN("Unexpected end of EEPROM data in slave %u:"
       
   582                     " Next category header missing.\n",
       
   583                     slave->ring_position);
       
   584             goto end;
       
   585         }
   552     }
   586     }
   553 
   587 
   554     fsm->state = ec_fsm_slave_state_end;
   588     fsm->state = ec_fsm_slave_state_end;
   555     return;
   589     return;
   556 
   590 
   592     ec_datagram_t *datagram = fsm->datagram;
   626     ec_datagram_t *datagram = fsm->datagram;
   593 
   627 
   594     if (ec_fsm_change_exec(&fsm->fsm_change)) return;
   628     if (ec_fsm_change_exec(&fsm->fsm_change)) return;
   595 
   629 
   596     if (!ec_fsm_change_success(&fsm->fsm_change)) {
   630     if (!ec_fsm_change_success(&fsm->fsm_change)) {
   597         slave->error_flag = 1;
   631         if (!fsm->fsm_change.spontaneous_change)
       
   632             slave->error_flag = 1;
   598         fsm->state = ec_fsm_slave_state_error;
   633         fsm->state = ec_fsm_slave_state_error;
   599         return;
   634         return;
   600     }
   635     }
   601 
   636 
   602     slave->self_configured = 1;
   637     slave->self_configured = 1;
   660 }
   695 }
   661 
   696 
   662 /*****************************************************************************/
   697 /*****************************************************************************/
   663 
   698 
   664 /**
   699 /**
       
   700  * Check for mailbox sync managers to be configured.
   665  */
   701  */
   666 
   702 
   667 void ec_fsm_slave_conf_enter_mbox_sync(
   703 void ec_fsm_slave_conf_enter_mbox_sync(
   668         ec_fsm_slave_t *fsm /**< slave state machine */
   704         ec_fsm_slave_t *fsm /**< slave state machine */
   669         )
   705         )
   681                    slave->ring_position);
   717                    slave->ring_position);
   682         }
   718         }
   683         return;
   719         return;
   684     }
   720     }
   685 
   721 
   686     if (!slave->sii_mailbox_protocols || slave->sii_sync_count < 2) {
   722     if (!slave->sii_mailbox_protocols) {
   687         // no mailbox sync managers to be configured
   723         // no mailbox protocols supported
       
   724         if (master->debug_level)
       
   725             EC_DBG("Slave %i does not support mailbox communication.\n",
       
   726                     slave->ring_position);
   688         ec_fsm_slave_conf_enter_preop(fsm);
   727         ec_fsm_slave_conf_enter_preop(fsm);
   689         return;
   728         return;
   690     }
   729     }
   691 
   730 
   692     if (master->debug_level) {
   731     if (master->debug_level) {
   693         EC_DBG("Configuring mailbox sync managers of slave %i.\n",
   732         EC_DBG("Configuring mailbox sync managers of slave %i.\n",
   694                slave->ring_position);
   733                slave->ring_position);
   695     }
   734     }
   696 
   735 
   697     // configure sync managers
   736     if (slave->sii_sync_count >= 2) {
   698     ec_datagram_npwr(datagram, slave->station_address, 0x0800,
   737         // configure sync managers
   699                      EC_SYNC_SIZE * slave->sii_sync_count);
   738         ec_datagram_npwr(datagram, slave->station_address, 0x0800,
   700     memset(datagram->data, 0x00, EC_SYNC_SIZE * slave->sii_sync_count);
   739                 EC_SYNC_SIZE * slave->sii_sync_count);
   701 
   740         memset(datagram->data, 0x00, EC_SYNC_SIZE * slave->sii_sync_count);
   702     for (i = 0; i < 2; i++) {
   741 
   703         ec_sync_config(&slave->sii_syncs[i],
   742         for (i = 0; i < 2; i++) {
   704                 datagram->data + EC_SYNC_SIZE * i);
   743             ec_sync_config(&slave->sii_syncs[i],
       
   744                     datagram->data + EC_SYNC_SIZE * i);
       
   745         }
       
   746     } else { // no mailbox sync manager configurations provided
       
   747         ec_sync_t sync;
       
   748 
       
   749         if (master->debug_level)
       
   750             EC_DBG("Slave %i does not provide"
       
   751                     " mailbox sync manager configurations.\n",
       
   752                     slave->ring_position);
       
   753 
       
   754         ec_datagram_npwr(datagram, slave->station_address, 0x0800,
       
   755                 EC_SYNC_SIZE * 2);
       
   756         memset(datagram->data, 0x00, EC_SYNC_SIZE * 2);
       
   757 
       
   758         ec_sync_init(&sync, slave, 0);
       
   759         sync.physical_start_address = slave->sii_rx_mailbox_offset;
       
   760         sync.length = slave->sii_rx_mailbox_size;
       
   761         sync.control_register = 0x26;
       
   762         sync.enable = 1;
       
   763         ec_sync_config(&sync, datagram->data + EC_SYNC_SIZE * sync.index);
       
   764 
       
   765         ec_sync_init(&sync, slave, 1);
       
   766         sync.physical_start_address = slave->sii_tx_mailbox_offset;
       
   767         sync.length = slave->sii_tx_mailbox_size;
       
   768         sync.control_register = 0x22;
       
   769         sync.enable = 1;
       
   770         ec_sync_config(&sync, datagram->data + EC_SYNC_SIZE * sync.index);
   705     }
   771     }
   706 
   772 
   707     fsm->retries = EC_FSM_RETRIES;
   773     fsm->retries = EC_FSM_RETRIES;
   708     fsm->state = ec_fsm_slave_conf_state_mbox_sync;
   774     fsm->state = ec_fsm_slave_conf_state_mbox_sync;
   709 }
   775 }
   743 }
   809 }
   744 
   810 
   745 /*****************************************************************************/
   811 /*****************************************************************************/
   746 
   812 
   747 /**
   813 /**
       
   814  * Request PREOP state.
   748  */
   815  */
   749 
   816 
   750 void ec_fsm_slave_conf_enter_preop(ec_fsm_slave_t *fsm /**< slave state machine */)
   817 void ec_fsm_slave_conf_enter_preop(ec_fsm_slave_t *fsm /**< slave state machine */)
   751 {
   818 {
   752     fsm->state = ec_fsm_slave_conf_state_preop;
   819     fsm->state = ec_fsm_slave_conf_state_preop;
   766     ec_master_t *master = fsm->slave->master;
   833     ec_master_t *master = fsm->slave->master;
   767 
   834 
   768     if (ec_fsm_change_exec(&fsm->fsm_change)) return;
   835     if (ec_fsm_change_exec(&fsm->fsm_change)) return;
   769 
   836 
   770     if (!ec_fsm_change_success(&fsm->fsm_change)) {
   837     if (!ec_fsm_change_success(&fsm->fsm_change)) {
   771         slave->error_flag = 1;
   838         if (!fsm->fsm_change.spontaneous_change)
       
   839             slave->error_flag = 1;
   772         fsm->state = ec_fsm_slave_state_error;
   840         fsm->state = ec_fsm_slave_state_error;
   773         return;
   841         return;
   774     }
   842     }
   775 
   843 
   776     // slave is now in PREOP
   844     // slave is now in PREOP
   793 }
   861 }
   794 
   862 
   795 /*****************************************************************************/
   863 /*****************************************************************************/
   796 
   864 
   797 /**
   865 /**
       
   866  * Check for SDO configurations to be applied.
   798  */
   867  */
   799 
   868 
   800 void ec_fsm_slave_conf_enter_sdoconf(ec_fsm_slave_t *fsm /**< slave state machine */)
   869 void ec_fsm_slave_conf_enter_sdoconf(ec_fsm_slave_t *fsm /**< slave state machine */)
   801 {
   870 {
   802     ec_slave_t *slave = fsm->slave;
   871     ec_slave_t *slave = fsm->slave;
   848 }
   917 }
   849 
   918 
   850 /*****************************************************************************/
   919 /*****************************************************************************/
   851 
   920 
   852 /**
   921 /**
       
   922  * Check for alternative PDO mappings to be applied.
   853  */
   923  */
   854 
   924 
   855 void ec_fsm_slave_conf_enter_mapconf(
   925 void ec_fsm_slave_conf_enter_mapconf(
   856         ec_fsm_slave_t *fsm /**< slave state machine */
   926         ec_fsm_slave_t *fsm /**< slave state machine */
   857         )
   927         )
   894 }
   964 }
   895 
   965 
   896 /*****************************************************************************/
   966 /*****************************************************************************/
   897 
   967 
   898 /**
   968 /**
       
   969  * Check for PDO sync managers to be configured.
   899  */
   970  */
   900 
   971 
   901 void ec_fsm_slave_conf_enter_pdo_sync(
   972 void ec_fsm_slave_conf_enter_pdo_sync(
   902         ec_fsm_slave_t *fsm /**< slave state machine */
   973         ec_fsm_slave_t *fsm /**< slave state machine */
   903         )
   974         )
   926 }
   997 }
   927 
   998 
   928 /*****************************************************************************/
   999 /*****************************************************************************/
   929 
  1000 
   930 /**
  1001 /**
       
  1002  * Configure PDO sync managers.
   931  */
  1003  */
   932 
  1004 
   933 void ec_fsm_slave_conf_state_pdo_sync(ec_fsm_slave_t *fsm /**< slave state machine */)
  1005 void ec_fsm_slave_conf_state_pdo_sync(ec_fsm_slave_t *fsm /**< slave state machine */)
   934 {
  1006 {
   935     ec_datagram_t *datagram = fsm->datagram;
  1007     ec_datagram_t *datagram = fsm->datagram;
   959 }
  1031 }
   960 
  1032 
   961 /*****************************************************************************/
  1033 /*****************************************************************************/
   962 
  1034 
   963 /**
  1035 /**
   964 */
  1036  * Check for FMMUs to be configured.
       
  1037  */
   965 
  1038 
   966 void ec_fsm_slave_conf_enter_fmmu(ec_fsm_slave_t *fsm /**< slave state machine */)
  1039 void ec_fsm_slave_conf_enter_fmmu(ec_fsm_slave_t *fsm /**< slave state machine */)
   967 {
  1040 {
   968     ec_slave_t *slave = fsm->slave;
  1041     ec_slave_t *slave = fsm->slave;
   969     ec_datagram_t *datagram = fsm->datagram;
  1042     ec_datagram_t *datagram = fsm->datagram;
  1021 }
  1094 }
  1022 
  1095 
  1023 /*****************************************************************************/
  1096 /*****************************************************************************/
  1024 
  1097 
  1025 /**
  1098 /**
       
  1099  * Request SAVEOP state.
  1026  */
  1100  */
  1027 
  1101 
  1028 void ec_fsm_slave_conf_enter_saveop(ec_fsm_slave_t *fsm /**< slave state machine */)
  1102 void ec_fsm_slave_conf_enter_saveop(ec_fsm_slave_t *fsm /**< slave state machine */)
  1029 {
  1103 {
  1030     fsm->state = ec_fsm_slave_conf_state_saveop;
  1104     fsm->state = ec_fsm_slave_conf_state_saveop;
  1044     ec_slave_t *slave = fsm->slave;
  1118     ec_slave_t *slave = fsm->slave;
  1045 
  1119 
  1046     if (ec_fsm_change_exec(&fsm->fsm_change)) return;
  1120     if (ec_fsm_change_exec(&fsm->fsm_change)) return;
  1047 
  1121 
  1048     if (!ec_fsm_change_success(&fsm->fsm_change)) {
  1122     if (!ec_fsm_change_success(&fsm->fsm_change)) {
  1049         fsm->slave->error_flag = 1;
  1123         if (!fsm->fsm_change.spontaneous_change)
       
  1124             fsm->slave->error_flag = 1;
  1050         fsm->state = ec_fsm_slave_state_error;
  1125         fsm->state = ec_fsm_slave_state_error;
  1051         return;
  1126         return;
  1052     }
  1127     }
  1053 
  1128 
  1054     // slave is now in SAVEOP
  1129     // slave is now in SAVEOP
  1084     ec_slave_t *slave = fsm->slave;
  1159     ec_slave_t *slave = fsm->slave;
  1085 
  1160 
  1086     if (ec_fsm_change_exec(&fsm->fsm_change)) return;
  1161     if (ec_fsm_change_exec(&fsm->fsm_change)) return;
  1087 
  1162 
  1088     if (!ec_fsm_change_success(&fsm->fsm_change)) {
  1163     if (!ec_fsm_change_success(&fsm->fsm_change)) {
  1089         slave->error_flag = 1;
  1164         if (!fsm->fsm_change.spontaneous_change)
       
  1165             slave->error_flag = 1;
  1090         fsm->state = ec_fsm_slave_state_error;
  1166         fsm->state = ec_fsm_slave_state_error;
  1091         return;
  1167         return;
  1092     }
  1168     }
  1093 
  1169 
  1094     // slave is now in OP
  1170     // slave is now in OP