master/canopen.c
changeset 138 7e743a61a991
parent 137 3fb18812871a
child 139 998215ab9b92
equal deleted inserted replaced
137:3fb18812871a 138:7e743a61a991
    14 
    14 
    15 #include "master.h"
    15 #include "master.h"
    16 
    16 
    17 /*****************************************************************************/
    17 /*****************************************************************************/
    18 
    18 
       
    19 void ec_canopen_abort_msg(uint32_t);
       
    20 int ec_slave_fetch_sdo_descriptions(ec_slave_t *);
       
    21 
       
    22 /*****************************************************************************/
       
    23 
    19 /**
    24 /**
    20    SDO Abort Code Messages
    25    SDO Abort Code Messages
    21 */
    26 */
    22 
    27 
    23 typedef struct
    28 typedef struct
    27 }
    32 }
    28 ec_sdo_abort_message_t;
    33 ec_sdo_abort_message_t;
    29 
    34 
    30 const ec_sdo_abort_message_t sdo_abort_messages[];
    35 const ec_sdo_abort_message_t sdo_abort_messages[];
    31 
    36 
    32 void ec_canopen_abort_msg(uint32_t);
    37 /*****************************************************************************/
    33 int ec_slave_fetch_sdo_descriptions(ec_slave_t *);
    38 
    34 
    39 /**
    35 /*****************************************************************************/
    40    Beschreibt ein CANopen-SDO eines Slaves im Expedited-Modus.
    36 
    41    \return 0 wenn alles ok, < 0 bei Fehler
    37 /**
    42  */
    38    Schreibt ein CANopen-SDO (service data object), expedited.
    43 
    39  */
    44 int ec_slave_sdo_write_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
    40 
    45                            uint16_t sdo_index, /**< SDO-Index */
    41 int ecrt_slave_sdo_exp_write(ec_slave_t *slave, /**< EtherCAT-Slave */
    46                            uint8_t sdo_subindex, /**< SDO-Subindex */
    42                              uint16_t sdo_index, /**< SDO-Index */
    47                            const uint8_t *sdo_data, /**< Neuer Wert */
    43                              uint8_t sdo_subindex, /**< SDO-Subindex */
    48                            size_t size
    44                              uint32_t value, /**< Neuer Wert */
    49                            )
    45                              size_t size /**< Größe des Datenfeldes */
       
    46                              )
       
    47 {
    50 {
    48     uint8_t data[0x0A];
    51     uint8_t data[0x0A];
    49     unsigned int i;
       
    50     size_t rec_size;
    52     size_t rec_size;
    51 
    53 
    52     if (size == 0 || size > 4) {
    54     if (size == 0 || size > 4) {
    53         EC_ERR("Invalid SDO data size: %i!\n", size);
    55         EC_ERR("Invalid data size!\n");
    54         return -1;
    56         return -1;
    55     }
    57     }
    56 
    58 
    57     EC_WRITE_U16(data,     0x02 << 12); // Number (0), Service (SDO request)
    59     EC_WRITE_U16(data,     0x2000); // SDO request
    58     EC_WRITE_U8 (data + 2, 0x23 | ((4 - size) << 2)); // Spec., exp., init.
    60     EC_WRITE_U8 (data + 2, 0x23 | (4 - size) << 2); // expedited, size specif.
    59     EC_WRITE_U16(data + 3, sdo_index);
    61     EC_WRITE_U16(data + 3, sdo_index);
    60     EC_WRITE_U8 (data + 5, sdo_subindex);
    62     EC_WRITE_U8 (data + 5, sdo_subindex);
    61 
    63 
    62     for (i = 0; i < size; i++) {
    64     memcpy(data + 6, sdo_data, size);
    63         EC_WRITE_U8(data + 6 + i, value & 0xFF);
    65     if (size < 4) memset(data + 6 + size, 0x00, 4 - size);
    64         value >>= 8;
       
    65     }
       
    66 
    66 
    67     // Mailox senden und empfangen
    67     // Mailox senden und empfangen
    68     if (ec_slave_mailbox_send(slave, 0x03, data, 0x0A)) return -1;
    68     if (ec_slave_mailbox_send(slave, 0x03, data, 0x0A)) return -1;
    69 
    69 
    70     rec_size = 0x0A;
    70     rec_size = 0x0A;
    71     if (ec_slave_mailbox_receive(slave, 0x03, data, &rec_size)) return -1;
    71     if (ec_slave_mailbox_receive(slave, 0x03, data, &rec_size)) return -1;
    72 
    72 
    73     if (EC_READ_U16(data) >> 12 == 0x02 && // SDO request
    73     if (EC_READ_U16(data) >> 12 == 0x02 && // SDO request
    74         EC_READ_U8 (data + 2) >> 5 == 0x04) { // Abort SDO transf. req.
    74         EC_READ_U8 (data + 2) >> 5 == 0x04) { // Abort SDO transfer request
    75         EC_ERR("SDO download of 0x%04X:%X (value %X, size %X) aborted on slave"
    75         EC_ERR("SDO download of 0x%04X:%X (%i bytes) aborted on!"
    76                " %i.\n", sdo_index, sdo_subindex, value, size,
    76                " slave %i.\n", sdo_index, sdo_subindex, size,
    77                slave->ring_position);
    77                slave->ring_position);
    78         ec_canopen_abort_msg(EC_READ_U32(data + 6));
    78         ec_canopen_abort_msg(EC_READ_U32(data + 6));
    79         return -1;
    79         return -1;
    80     }
    80     }
    81 
    81 
    93 }
    93 }
    94 
    94 
    95 /*****************************************************************************/
    95 /*****************************************************************************/
    96 
    96 
    97 /**
    97 /**
    98    Liest ein CANopen-SDO (service data object), expedited.
    98    Liest 32-Bit eines CANopen-SDOs im Expedited-Modus aus einem Slave.
    99  */
    99    \return 0 wenn alles ok, < 0 bei Fehler
   100 
   100  */
   101 int ecrt_slave_sdo_exp_read(ec_slave_t *slave, /**< EtherCAT-Slave */
   101 
   102                             uint16_t sdo_index, /**< SDO-Index */
   102 int ec_slave_sdo_read_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
   103                             uint8_t sdo_subindex, /**< SDO-Subindex */
   103                           uint16_t sdo_index, /**< SDO-Index */
   104                             uint32_t *value /**< Speicher für gel. Wert */
   104                           uint8_t sdo_subindex, /**< SDO-Subindex */
   105                             )
   105                           uint8_t *target /**< Speicher für 4 Bytes */
       
   106                           )
   106 {
   107 {
   107     uint8_t data[0x20];
   108     uint8_t data[0x20];
   108     size_t rec_size;
   109     size_t rec_size;
   109 
   110 
   110     EC_WRITE_U16(data,     0x2000); // Number (0), Service = SDO request
   111     EC_WRITE_U16(data,     0x2000); // SDO request
   111     EC_WRITE_U8 (data + 2, 0x1 << 1 | 0x2 << 5); // Expedited upload request
   112     EC_WRITE_U8 (data + 2, 0x42); // Upload request, expedited
   112     EC_WRITE_U16(data + 3, sdo_index);
   113     EC_WRITE_U16(data + 3, sdo_index);
   113     EC_WRITE_U8 (data + 5, sdo_subindex);
   114     EC_WRITE_U8 (data + 5, sdo_subindex);
   114 
   115 
   115     if (ec_slave_mailbox_send(slave, 0x03, data, 6)) return -1;
   116     if (ec_slave_mailbox_send(slave, 0x03, data, 6)) return -1;
   116 
   117 
   132         EC_ERR("Invalid SDO upload response at slave %i!\n",
   133         EC_ERR("Invalid SDO upload response at slave %i!\n",
   133                slave->ring_position);
   134                slave->ring_position);
   134         return -1;
   135         return -1;
   135     }
   136     }
   136 
   137 
   137     *value = EC_READ_U32(data + 6);
   138     memcpy(target, data + 6, 4);
   138     return 0;
   139     return 0;
   139 }
   140 }
   140 
   141 
   141 /*****************************************************************************/
   142 /*****************************************************************************/
   142 
   143 
   143 /**
   144 /**
   144    Liest ein CANopen-SDO (service data object).
   145    Liest ein CANopen-SDO aus einem Slave.
       
   146    \return 0 wenn alles ok, < 0 bei Fehler
   145  */
   147  */
   146 
   148 
   147 int ecrt_slave_sdo_read(ec_slave_t *slave, /**< EtherCAT-Slave */
   149 int ecrt_slave_sdo_read(ec_slave_t *slave, /**< EtherCAT-Slave */
   148                         uint16_t sdo_index, /**< SDO-Index */
   150                         uint16_t sdo_index, /**< SDO-Index */
   149                         uint8_t sdo_subindex, /**< SDO-Subindex */
   151                         uint8_t sdo_subindex, /**< SDO-Subindex */
   153 {
   155 {
   154     uint8_t data[0x20];
   156     uint8_t data[0x20];
   155     size_t rec_size, data_size;
   157     size_t rec_size, data_size;
   156     uint32_t complete_size;
   158     uint32_t complete_size;
   157 
   159 
   158     EC_WRITE_U16(data,     0x2000); // Number (0), Service = SDO request
   160     EC_WRITE_U16(data,     0x2000); // SDO request
   159     EC_WRITE_U8 (data + 2, 0x2 << 5); // Initiate upload request
   161     EC_WRITE_U8 (data + 2, 0x2 << 5); // Initiate upload request
   160     EC_WRITE_U16(data + 3, sdo_index);
   162     EC_WRITE_U16(data + 3, sdo_index);
   161     EC_WRITE_U8 (data + 5, sdo_subindex);
   163     EC_WRITE_U8 (data + 5, sdo_subindex);
   162 
   164 
   163     if (ec_slave_mailbox_send(slave, 0x03, data, 6)) return -1;
   165     if (ec_slave_mailbox_send(slave, 0x03, data, 6)) return -1;
   207 }
   209 }
   208 
   210 
   209 /*****************************************************************************/
   211 /*****************************************************************************/
   210 
   212 
   211 /**
   213 /**
   212    Schreibt ein CANopen-SDO (Angabe des Masters und der Adresse), expedited.
       
   213 
       
   214    Siehe ecrt_slave_sdo_exp_write()
       
   215 
       
   216    \return 0 wenn alles ok, < 0 bei Fehler
       
   217  */
       
   218 
       
   219 int ecrt_master_sdo_exp_write(ec_master_t *master,
       
   220                               /**< EtherCAT-Master */
       
   221                               const char *addr,
       
   222                               /**< Addresse, siehe ec_master_slave_address() */
       
   223                               uint16_t index,
       
   224                               /**< SDO-Index */
       
   225                               uint8_t subindex,
       
   226                               /**< SDO-Subindex */
       
   227                               uint32_t value,
       
   228                               /**< Neuer Wert */
       
   229                               size_t size
       
   230                               /**< Größe des Datenfeldes */
       
   231                               )
       
   232 {
       
   233     ec_slave_t *slave;
       
   234     if (!(slave = ec_master_slave_address(master, addr))) return -1;
       
   235     return ecrt_slave_sdo_exp_write(slave, index, subindex, value, size);
       
   236 }
       
   237 
       
   238 /*****************************************************************************/
       
   239 
       
   240 /**
       
   241    Liest ein CANopen-SDO (Angabe des Masters und der Adresse), expedited.
       
   242 
       
   243    Siehe ecrt_slave_sdo_exp_read()
       
   244 
       
   245    \return 0 wenn alles ok, < 0 bei Fehler
       
   246  */
       
   247 
       
   248 int ecrt_master_sdo_exp_read(ec_master_t *master,
       
   249                              /**< EtherCAT-Slave */
       
   250                              const char *addr,
       
   251                              /**< Addresse, siehe ec_master_slave_address() */
       
   252                              uint16_t index,
       
   253                              /**< SDO-Index */
       
   254                              uint8_t subindex,
       
   255                              /**< SDO-Subindex */
       
   256                              uint32_t *value
       
   257                              /**< Speicher für gel. Wert */
       
   258                              )
       
   259 {
       
   260     ec_slave_t *slave;
       
   261     if (!(slave = ec_master_slave_address(master, addr))) return -1;
       
   262     return ecrt_slave_sdo_exp_read(slave, index, subindex, value);
       
   263 }
       
   264 
       
   265 /*****************************************************************************/
       
   266 
       
   267 /**
       
   268    Liest ein CANopen-SDO (Angabe des Masters und der Adresse), expedited.
       
   269 
       
   270    Siehe ecrt_slave_sdo_exp_read()
       
   271 
       
   272    \return 0 wenn alles ok, < 0 bei Fehler
       
   273  */
       
   274 
       
   275 int ecrt_master_sdo_read(ec_master_t *master, /**< EtherCAT-Master */
       
   276                          const char *addr, /**< Addresse, siehe
       
   277                                               ec_master_slave_address() */
       
   278                          uint16_t sdo_index, /**< SDO-Index */
       
   279                          uint8_t sdo_subindex, /**< SDO-Subindex */
       
   280                          uint8_t *target, /**< Speicher für gel. Wert */
       
   281                          size_t *size /**< Größe des Speichers */
       
   282                          )
       
   283 {
       
   284     ec_slave_t *slave;
       
   285     if (!(slave = ec_master_slave_address(master, addr))) return -1;
       
   286     return ecrt_slave_sdo_read(slave, sdo_index, sdo_subindex, target, size);
       
   287 }
       
   288 
       
   289 /*****************************************************************************/
       
   290 
       
   291 /**
       
   292    Holt das Object-Dictionary aus dem Slave.
   214    Holt das Object-Dictionary aus dem Slave.
   293 
       
   294    \return 0, wenn alles ok, sonst < 0
   215    \return 0, wenn alles ok, sonst < 0
   295 */
   216 */
   296 
   217 
   297 int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT-Slave */)
   218 int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT-Slave */)
   298 {
   219 {
   300     size_t rec_size;
   221     size_t rec_size;
   301     unsigned int i, sdo_count;
   222     unsigned int i, sdo_count;
   302     ec_sdo_t *sdo;
   223     ec_sdo_t *sdo;
   303     uint16_t sdo_index;
   224     uint16_t sdo_index;
   304 
   225 
   305     EC_WRITE_U16(data,     0x8000); // Number (0), Service = SDO information
   226     EC_WRITE_U16(data,     0x8000); // SDO information
   306     EC_WRITE_U8 (data + 2,   0x01); // Get OD List Request
   227     EC_WRITE_U8 (data + 2,   0x01); // Get OD List Request
   307     EC_WRITE_U8 (data + 3,   0x00); // res.
   228     EC_WRITE_U8 (data + 3,   0x00);
   308     EC_WRITE_U16(data + 4, 0x0000); // fragments left
   229     EC_WRITE_U16(data + 4, 0x0000);
   309     EC_WRITE_U16(data + 6, 0x0001); // Deliver all SDOs!
   230     EC_WRITE_U16(data + 6, 0x0001); // Deliver all SDOs!
   310 
   231 
   311     if (ec_slave_mailbox_send(slave, 0x03, data, 8)) return -1;
   232     if (ec_slave_mailbox_send(slave, 0x03, data, 8)) return -1;
   312 
   233 
   313     do {
   234     do {
   368     uint8_t data[0xF0];
   289     uint8_t data[0xF0];
   369     size_t rec_size, name_size;
   290     size_t rec_size, name_size;
   370     ec_sdo_t *sdo;
   291     ec_sdo_t *sdo;
   371 
   292 
   372     list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
   293     list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
   373         EC_WRITE_U16(data,     0x8000); // Number (0), Service = SDO inform.
   294         EC_WRITE_U16(data,     0x8000); // SDO information
   374         EC_WRITE_U8 (data + 2,   0x03); // Get object description request
   295         EC_WRITE_U8 (data + 2,   0x03); // Get object description request
   375         EC_WRITE_U8 (data + 3,   0x00); // res.
   296         EC_WRITE_U8 (data + 3,   0x00);
   376         EC_WRITE_U16(data + 4, 0x0000); // fragments left
   297         EC_WRITE_U16(data + 4, 0x0000);
   377         EC_WRITE_U16(data + 6, sdo->index); // SDO index
   298         EC_WRITE_U16(data + 6, sdo->index); // SDO index
       
   299 
   378         if (ec_slave_mailbox_send(slave, 0x03, data, 8)) return -1;
   300         if (ec_slave_mailbox_send(slave, 0x03, data, 8)) return -1;
   379 
   301 
   380         rec_size = 0xF0;
   302         rec_size = 0xF0;
   381         if (ec_slave_mailbox_receive(slave, 0x03, data, &rec_size))
   303         if (ec_slave_mailbox_receive(slave, 0x03, data, &rec_size))
   382             return -1;
   304             return -1;
   487      " dictionary is present"},
   409      " dictionary is present"},
   488     {}
   410     {}
   489 };
   411 };
   490 
   412 
   491 /*****************************************************************************/
   413 /*****************************************************************************/
   492 
   414 // Echtzeitschnittstelle
   493 EXPORT_SYMBOL(ecrt_slave_sdo_exp_write);
   415 
   494 EXPORT_SYMBOL(ecrt_slave_sdo_exp_read);
   416 /*****************************************************************************/
       
   417 
       
   418 /**
       
   419    Liest ein 8-Bit CANopen-SDO im Expedited-Modus aus einem Slave.
       
   420    Siehe ec_slave_sdo_read_exp()
       
   421    \return 0 wenn alles ok, < 0 bei Fehler
       
   422  */
       
   423 
       
   424 int ecrt_slave_sdo_read_exp8(ec_slave_t *slave, /**< EtherCAT-Slave */
       
   425                              uint16_t sdo_index, /**< SDO-Index */
       
   426                              uint8_t sdo_subindex, /**< SDO-Subindex */
       
   427                              uint8_t *target /**< Speicher für gel. Wert */
       
   428                              )
       
   429 {
       
   430     uint8_t data[4];
       
   431     if (ec_slave_sdo_read_exp(slave, sdo_index, sdo_subindex, data)) return -1;
       
   432     *target = EC_READ_U8(data);
       
   433     return 0;
       
   434 }
       
   435 
       
   436 /*****************************************************************************/
       
   437 
       
   438 /**
       
   439    Liest ein 16-Bit CANopen-SDO im Expedited-Modus aus einem Slave.
       
   440    Siehe ec_slave_sdo_read_exp()
       
   441    \return 0 wenn alles ok, < 0 bei Fehler
       
   442  */
       
   443 
       
   444 int ecrt_slave_sdo_read_exp16(ec_slave_t *slave, /**< EtherCAT-Slave */
       
   445                               uint16_t sdo_index, /**< SDO-Index */
       
   446                               uint8_t sdo_subindex, /**< SDO-Subindex */
       
   447                               uint16_t *target /**< Speicher für gel. Wert */
       
   448                               )
       
   449 {
       
   450     uint8_t data[4];
       
   451     if (ec_slave_sdo_read_exp(slave, sdo_index, sdo_subindex, data)) return -1;
       
   452     *target = EC_READ_U16(data);
       
   453     return 0;
       
   454 }
       
   455 
       
   456 /*****************************************************************************/
       
   457 
       
   458 /**
       
   459    Liest ein 32-Bit CANopen-SDO im Expedited-Modus aus einem Slave.
       
   460    Siehe ec_slave_sdo_read_exp()
       
   461    \return 0 wenn alles ok, < 0 bei Fehler
       
   462  */
       
   463 
       
   464 int ecrt_slave_sdo_read_exp32(ec_slave_t *slave, /**< EtherCAT-Slave */
       
   465                               uint16_t sdo_index, /**< SDO-Index */
       
   466                               uint8_t sdo_subindex, /**< SDO-Subindex */
       
   467                               uint32_t *target /**< Speicher für gel. Wert */
       
   468                               )
       
   469 {
       
   470     uint8_t data[4];
       
   471     if (ec_slave_sdo_read_exp(slave, sdo_index, sdo_subindex, data)) return -1;
       
   472     *target = EC_READ_U32(data);
       
   473     return 0;
       
   474 }
       
   475 
       
   476 /*****************************************************************************/
       
   477 
       
   478 /**
       
   479    Beschreibt ein 8-Bit CANopen-SDO eines Slaves im Expedited-Modus.
       
   480    \return 0 wenn alles ok, < 0 bei Fehler
       
   481  */
       
   482 
       
   483 int ecrt_slave_sdo_write_exp8(ec_slave_t *slave, /**< EtherCAT-Slave */
       
   484                               uint16_t sdo_index, /**< SDO-Index */
       
   485                               uint8_t sdo_subindex, /**< SDO-Subindex */
       
   486                               uint8_t value /**< Neuer Wert */
       
   487                               )
       
   488 {
       
   489     return ec_slave_sdo_write_exp(slave, sdo_index, sdo_subindex, &value, 1);
       
   490 }
       
   491 
       
   492 /*****************************************************************************/
       
   493 
       
   494 /**
       
   495    Beschreibt ein 16-Bit CANopen-SDO eines Slaves im Expedited-Modus.
       
   496    \return 0 wenn alles ok, < 0 bei Fehler
       
   497  */
       
   498 
       
   499 int ecrt_slave_sdo_write_exp16(ec_slave_t *slave, /**< EtherCAT-Slave */
       
   500                                uint16_t sdo_index, /**< SDO-Index */
       
   501                                uint8_t sdo_subindex, /**< SDO-Subindex */
       
   502                                uint16_t value /**< Neuer Wert */
       
   503                                )
       
   504 {
       
   505     uint8_t data[2];
       
   506     EC_WRITE_U16(data, value);
       
   507     return ec_slave_sdo_write_exp(slave, sdo_index, sdo_subindex, data, 2);
       
   508 }
       
   509 
       
   510 /*****************************************************************************/
       
   511 
       
   512 /**
       
   513    Beschreibt ein 32-Bit CANopen-SDO eines Slaves im Expedited-Modus.
       
   514    \return 0 wenn alles ok, < 0 bei Fehler
       
   515  */
       
   516 
       
   517 int ecrt_slave_sdo_write_exp32(ec_slave_t *slave, /**< EtherCAT-Slave */
       
   518                                uint16_t sdo_index, /**< SDO-Index */
       
   519                                uint8_t sdo_subindex, /**< SDO-Subindex */
       
   520                                uint32_t value /**< Neuer Wert */
       
   521                                )
       
   522 {
       
   523     uint8_t data[4];
       
   524     EC_WRITE_U32(data, value);
       
   525     return ec_slave_sdo_write_exp(slave, sdo_index, sdo_subindex, data, 4);
       
   526 }
       
   527 
       
   528 /*****************************************************************************/
       
   529 
       
   530 EXPORT_SYMBOL(ecrt_slave_sdo_read_exp8);
       
   531 EXPORT_SYMBOL(ecrt_slave_sdo_read_exp16);
       
   532 EXPORT_SYMBOL(ecrt_slave_sdo_read_exp32);
       
   533 EXPORT_SYMBOL(ecrt_slave_sdo_write_exp8);
       
   534 EXPORT_SYMBOL(ecrt_slave_sdo_write_exp16);
       
   535 EXPORT_SYMBOL(ecrt_slave_sdo_write_exp32);
   495 EXPORT_SYMBOL(ecrt_slave_sdo_read);
   536 EXPORT_SYMBOL(ecrt_slave_sdo_read);
   496 EXPORT_SYMBOL(ecrt_master_sdo_exp_write);
       
   497 EXPORT_SYMBOL(ecrt_master_sdo_exp_read);
       
   498 EXPORT_SYMBOL(ecrt_master_sdo_read);
       
   499 
   537 
   500 /*****************************************************************************/
   538 /*****************************************************************************/
   501 
   539 
   502 /* Emacs-Konfiguration
   540 /* Emacs-Konfiguration
   503 ;;; Local Variables: ***
   541 ;;; Local Variables: ***