master/datagram.c
changeset 815 002fe9ec778f
parent 809 ec4ef8911824
child 816 d02761e14eb0
equal deleted inserted replaced
814:a51f857b1b2d 815:002fe9ec778f
    63 
    63 
    64 /*****************************************************************************/
    64 /*****************************************************************************/
    65 
    65 
    66 /** Constructor.
    66 /** Constructor.
    67  */
    67  */
    68 void ec_datagram_init(ec_datagram_t *datagram /**< EtherCAT datagram */)
    68 void ec_datagram_init(ec_datagram_t *datagram /**< EtherCAT datagram. */)
    69 {
    69 {
    70     INIT_LIST_HEAD(&datagram->queue); // mark as unqueued
    70     INIT_LIST_HEAD(&datagram->queue); // mark as unqueued
    71     datagram->type = EC_DATAGRAM_NONE;
    71     datagram->type = EC_DATAGRAM_NONE;
    72     memset(datagram->address, 0x00, EC_ADDR_LEN);
    72     memset(datagram->address, 0x00, EC_ADDR_LEN);
    73     datagram->data = NULL;
    73     datagram->data = NULL;
    88 
    88 
    89 /*****************************************************************************/
    89 /*****************************************************************************/
    90 
    90 
    91 /** Destructor.
    91 /** Destructor.
    92  */
    92  */
    93 void ec_datagram_clear(ec_datagram_t *datagram /**< EtherCAT datagram */)
    93 void ec_datagram_clear(ec_datagram_t *datagram /**< EtherCAT datagram. */)
    94 {
    94 {
    95     if (datagram->data_origin == EC_ORIG_INTERNAL && datagram->data)
    95     if (datagram->data_origin == EC_ORIG_INTERNAL && datagram->data)
    96         kfree(datagram->data);
    96         kfree(datagram->data);
    97 }
    97 }
    98 
    98 
   105  * \attention If external payload memory has been provided, no range checking
   105  * \attention If external payload memory has been provided, no range checking
   106  *            is done!
   106  *            is done!
   107  *
   107  *
   108  * \return 0 in case of success, else < 0
   108  * \return 0 in case of success, else < 0
   109  */
   109  */
   110 int ec_datagram_prealloc(ec_datagram_t *datagram, /**< EtherCAT datagram */
   110 int ec_datagram_prealloc(
   111         size_t size /**< New size in bytes */
   111         ec_datagram_t *datagram, /**< EtherCAT datagram. */
       
   112         size_t size /**< New payload size in bytes. */
   112         )
   113         )
   113 {
   114 {
   114     if (datagram->data_origin == EC_ORIG_EXTERNAL
   115     if (datagram->data_origin == EC_ORIG_EXTERNAL
   115             || size <= datagram->mem_size)
   116             || size <= datagram->mem_size)
   116         return 0;
   117         return 0;
   130     return 0;
   131     return 0;
   131 }
   132 }
   132 
   133 
   133 /*****************************************************************************/
   134 /*****************************************************************************/
   134 
   135 
   135 /** Initializes an EtherCAT NPRD datagram.
       
   136  *
       
   137  * Node-adressed physical read.
       
   138  *
       
   139  * \return 0 in case of success, else < 0
       
   140  */
       
   141 int ec_datagram_nprd(ec_datagram_t *datagram,
       
   142                      /**< EtherCAT datagram */
       
   143                      uint16_t node_address,
       
   144                      /**< configured station address */
       
   145                      uint16_t offset,
       
   146                      /**< physical memory address */
       
   147                      size_t data_size
       
   148                      /**< number of bytes to read */
       
   149                      )
       
   150 {
       
   151     if (unlikely(node_address == 0x0000))
       
   152         EC_WARN("Using node address 0x0000!\n");
       
   153 
       
   154     EC_FUNC_HEADER;
       
   155     datagram->type = EC_DATAGRAM_NPRD;
       
   156     EC_WRITE_U16(datagram->address, node_address);
       
   157     EC_WRITE_U16(datagram->address + 2, offset);
       
   158     EC_FUNC_FOOTER;
       
   159 }
       
   160 
       
   161 /*****************************************************************************/
       
   162 
       
   163 /** Initializes an EtherCAT NPWR datagram.
       
   164  *
       
   165  * Node-adressed physical write.
       
   166  *
       
   167  * \return 0 in case of success, else < 0
       
   168  */
       
   169 int ec_datagram_npwr(ec_datagram_t *datagram,
       
   170                      /**< EtherCAT datagram */
       
   171                      uint16_t node_address,
       
   172                      /**< configured station address */
       
   173                      uint16_t offset,
       
   174                      /**< physical memory address */
       
   175                      size_t data_size
       
   176                      /**< number of bytes to write */
       
   177                      )
       
   178 {
       
   179     if (unlikely(node_address == 0x0000))
       
   180         EC_WARN("Using node address 0x0000!\n");
       
   181 
       
   182     EC_FUNC_HEADER;
       
   183     datagram->type = EC_DATAGRAM_NPWR;
       
   184     EC_WRITE_U16(datagram->address, node_address);
       
   185     EC_WRITE_U16(datagram->address + 2, offset);
       
   186     EC_FUNC_FOOTER;
       
   187 }
       
   188 
       
   189 /*****************************************************************************/
       
   190 
       
   191 /** Initializes an EtherCAT APRD datagram.
   136 /** Initializes an EtherCAT APRD datagram.
   192  *
   137  *
   193  * Autoincrement physical read.
   138  * \return 0 in case of success, else < 0
   194  *
   139  */
   195  * \return 0 in case of success, else < 0
   140 int ec_datagram_aprd(
   196  */
   141         ec_datagram_t *datagram, /**< EtherCAT datagram. */
   197 int ec_datagram_aprd(ec_datagram_t *datagram,
   142         uint16_t ring_position, /**< Auto-increment address. */
   198                      /**< EtherCAT datagram */
   143         uint16_t mem_address, /**< Physical memory address. */
   199                      uint16_t ring_position,
   144         size_t data_size /**< Number of bytes to read. */
   200                      /**< auto-increment position */
   145         )
   201                      uint16_t offset,
       
   202                      /**< physical memory address */
       
   203                      size_t data_size
       
   204                      /**< number of bytes to read */
       
   205                      )
       
   206 {
   146 {
   207     EC_FUNC_HEADER;
   147     EC_FUNC_HEADER;
   208     datagram->type = EC_DATAGRAM_APRD;
   148     datagram->type = EC_DATAGRAM_APRD;
   209     EC_WRITE_S16(datagram->address, (int16_t) ring_position * (-1));
   149     EC_WRITE_S16(datagram->address, (int16_t) ring_position * (-1));
   210     EC_WRITE_U16(datagram->address + 2, offset);
   150     EC_WRITE_U16(datagram->address + 2, mem_address);
   211     EC_FUNC_FOOTER;
   151     EC_FUNC_FOOTER;
   212 }
   152 }
   213 
   153 
   214 /*****************************************************************************/
   154 /*****************************************************************************/
   215 
   155 
   216 /** Initializes an EtherCAT APWR datagram.
   156 /** Initializes an EtherCAT APWR datagram.
   217  *
   157  *
   218  * Autoincrement physical write.
   158  * \return 0 in case of success, else < 0
   219  *
   159  */
   220  * \return 0 in case of success, else < 0
   160 int ec_datagram_apwr(
   221  */
   161         ec_datagram_t *datagram, /**< EtherCAT datagram. */
   222 int ec_datagram_apwr(ec_datagram_t *datagram,
   162         uint16_t ring_position, /**< Auto-increment address. */
   223                      /**< EtherCAT datagram */
   163         uint16_t mem_address, /**< Physical memory address. */
   224                      uint16_t ring_position,
   164         size_t data_size /**< Number of bytes to write. */
   225                      /**< auto-increment position */
   165         )
   226                      uint16_t offset,
       
   227                      /**< physical memory address */
       
   228                      size_t data_size
       
   229                      /**< number of bytes to write */
       
   230                      )
       
   231 {
   166 {
   232     EC_FUNC_HEADER;
   167     EC_FUNC_HEADER;
   233     datagram->type = EC_DATAGRAM_APWR;
   168     datagram->type = EC_DATAGRAM_APWR;
   234     EC_WRITE_S16(datagram->address, (int16_t) ring_position * (-1));
   169     EC_WRITE_S16(datagram->address, (int16_t) ring_position * (-1));
   235     EC_WRITE_U16(datagram->address + 2, offset);
   170     EC_WRITE_U16(datagram->address + 2, mem_address);
       
   171     EC_FUNC_FOOTER;
       
   172 }
       
   173 
       
   174 /*****************************************************************************/
       
   175 
       
   176 /** Initializes an EtherCAT APRW datagram.
       
   177  *
       
   178  * \return 0 in case of success, else < 0
       
   179  */
       
   180 int ec_datagram_aprw(
       
   181         ec_datagram_t *datagram, /**< EtherCAT datagram. */
       
   182         uint16_t ring_position, /**< Auto-increment address. */
       
   183         uint16_t mem_address, /**< Physical memory address. */
       
   184         size_t data_size /**< Number of bytes to write. */
       
   185         )
       
   186 {
       
   187     EC_FUNC_HEADER;
       
   188     datagram->type = EC_DATAGRAM_APRW;
       
   189     EC_WRITE_S16(datagram->address, (int16_t) ring_position * (-1));
       
   190     EC_WRITE_U16(datagram->address + 2, mem_address);
       
   191     EC_FUNC_FOOTER;
       
   192 }
       
   193 
       
   194 /*****************************************************************************/
       
   195 
       
   196 /** Initializes an EtherCAT ARMW datagram.
       
   197  *
       
   198  * \return 0 in case of success, else < 0
       
   199  */
       
   200 int ec_datagram_armw(
       
   201         ec_datagram_t *datagram, /**< EtherCAT datagram. */
       
   202         uint16_t ring_position, /**< Auto-increment address. */
       
   203         uint16_t mem_address, /**< Physical memory address. */
       
   204         size_t data_size /**< Number of bytes to read. */
       
   205         )
       
   206 {
       
   207     EC_FUNC_HEADER;
       
   208     datagram->type = EC_DATAGRAM_ARMW;
       
   209     EC_WRITE_S16(datagram->address, (int16_t) ring_position * (-1));
       
   210     EC_WRITE_U16(datagram->address + 2, mem_address);
       
   211     EC_FUNC_FOOTER;
       
   212 }
       
   213 
       
   214 /*****************************************************************************/
       
   215 
       
   216 /** Initializes an EtherCAT FPRD datagram.
       
   217  *
       
   218  * \return 0 in case of success, else < 0
       
   219  */
       
   220 int ec_datagram_fprd(
       
   221         ec_datagram_t *datagram, /**< EtherCAT datagram. */
       
   222         uint16_t configured_address, /**< Configured station address. */
       
   223         uint16_t mem_address, /**< Physical memory address. */
       
   224         size_t data_size /**< Number of bytes to read. */
       
   225         )
       
   226 {
       
   227     if (unlikely(configured_address == 0x0000))
       
   228         EC_WARN("Using configured station address 0x0000!\n");
       
   229 
       
   230     EC_FUNC_HEADER;
       
   231     datagram->type = EC_DATAGRAM_FPRD;
       
   232     EC_WRITE_U16(datagram->address, configured_address);
       
   233     EC_WRITE_U16(datagram->address + 2, mem_address);
       
   234     EC_FUNC_FOOTER;
       
   235 }
       
   236 
       
   237 /*****************************************************************************/
       
   238 
       
   239 /** Initializes an EtherCAT FPWR datagram.
       
   240  *
       
   241  * \return 0 in case of success, else < 0
       
   242  */
       
   243 int ec_datagram_fpwr(
       
   244         ec_datagram_t *datagram, /**< EtherCAT datagram. */
       
   245         uint16_t configured_address, /**< Configured station address. */
       
   246         uint16_t mem_address, /**< Physical memory address. */
       
   247         size_t data_size /**< Number of bytes to write. */
       
   248         )
       
   249 {
       
   250     if (unlikely(configured_address == 0x0000))
       
   251         EC_WARN("Using configured station address 0x0000!\n");
       
   252 
       
   253     EC_FUNC_HEADER;
       
   254     datagram->type = EC_DATAGRAM_FPWR;
       
   255     EC_WRITE_U16(datagram->address, configured_address);
       
   256     EC_WRITE_U16(datagram->address + 2, mem_address);
       
   257     EC_FUNC_FOOTER;
       
   258 }
       
   259 
       
   260 /*****************************************************************************/
       
   261 
       
   262 /** Initializes an EtherCAT FPRW datagram.
       
   263  *
       
   264  * \return 0 in case of success, else < 0
       
   265  */
       
   266 int ec_datagram_fprw(
       
   267         ec_datagram_t *datagram, /**< EtherCAT datagram. */
       
   268         uint16_t configured_address, /**< Configured station address. */
       
   269         uint16_t mem_address, /**< Physical memory address. */
       
   270         size_t data_size /**< Number of bytes to write. */
       
   271         )
       
   272 {
       
   273     if (unlikely(configured_address == 0x0000))
       
   274         EC_WARN("Using configured station address 0x0000!\n");
       
   275 
       
   276     EC_FUNC_HEADER;
       
   277     datagram->type = EC_DATAGRAM_FPRW;
       
   278     EC_WRITE_U16(datagram->address, configured_address);
       
   279     EC_WRITE_U16(datagram->address + 2, mem_address);
       
   280     EC_FUNC_FOOTER;
       
   281 }
       
   282 
       
   283 /*****************************************************************************/
       
   284 
       
   285 /** Initializes an EtherCAT FRMW datagram.
       
   286  *
       
   287  * \return 0 in case of success, else < 0
       
   288  */
       
   289 int ec_datagram_frmw(
       
   290         ec_datagram_t *datagram, /**< EtherCAT datagram. */
       
   291         uint16_t configured_address, /**< Configured station address. */
       
   292         uint16_t mem_address, /**< Physical memory address. */
       
   293         size_t data_size /**< Number of bytes to write. */
       
   294         )
       
   295 {
       
   296     if (unlikely(configured_address == 0x0000))
       
   297         EC_WARN("Using configured station address 0x0000!\n");
       
   298 
       
   299     EC_FUNC_HEADER;
       
   300     datagram->type = EC_DATAGRAM_FRMW;
       
   301     EC_WRITE_U16(datagram->address, configured_address);
       
   302     EC_WRITE_U16(datagram->address + 2, mem_address);
   236     EC_FUNC_FOOTER;
   303     EC_FUNC_FOOTER;
   237 }
   304 }
   238 
   305 
   239 /*****************************************************************************/
   306 /*****************************************************************************/
   240 
   307 
   241 /** Initializes an EtherCAT BRD datagram.
   308 /** Initializes an EtherCAT BRD datagram.
   242  *
   309  *
   243  * Broadcast read.
   310  * \return 0 in case of success, else < 0
   244  *
   311  */
   245  * \return 0 in case of success, else < 0
   312 int ec_datagram_brd(
   246  */
   313         ec_datagram_t *datagram, /**< EtherCAT datagram. */
   247 int ec_datagram_brd(ec_datagram_t *datagram,
   314         uint16_t mem_address, /**< Physical memory address. */
   248                     /**< EtherCAT datagram */
   315         size_t data_size /**< Number of bytes to read. */
   249                     uint16_t offset,
   316         )
   250                     /**< physical memory address */
       
   251                     size_t data_size
       
   252                     /**< number of bytes to read */
       
   253                     )
       
   254 {
   317 {
   255     EC_FUNC_HEADER;
   318     EC_FUNC_HEADER;
   256     datagram->type = EC_DATAGRAM_BRD;
   319     datagram->type = EC_DATAGRAM_BRD;
   257     EC_WRITE_U16(datagram->address, 0x0000);
   320     EC_WRITE_U16(datagram->address, 0x0000);
   258     EC_WRITE_U16(datagram->address + 2, offset);
   321     EC_WRITE_U16(datagram->address + 2, mem_address);
   259     EC_FUNC_FOOTER;
   322     EC_FUNC_FOOTER;
   260 }
   323 }
   261 
   324 
   262 /*****************************************************************************/
   325 /*****************************************************************************/
   263 
   326 
   264 /** Initializes an EtherCAT BWR datagram.
   327 /** Initializes an EtherCAT BWR datagram.
   265  *
   328  *
   266  * Broadcast write.
   329  * \return 0 in case of success, else < 0
   267  *
   330  */
   268  * \return 0 in case of success, else < 0
   331 int ec_datagram_bwr(
   269  */
   332         ec_datagram_t *datagram, /**< EtherCAT datagram. */
   270 int ec_datagram_bwr(ec_datagram_t *datagram,
   333         uint16_t mem_address, /**< Physical memory address. */
   271                     /**< EtherCAT datagram */
   334         size_t data_size /**< Number of bytes to write. */
   272                     uint16_t offset,
   335         )
   273                     /**< physical memory address */
       
   274                     size_t data_size
       
   275                     /**< number of bytes to write */
       
   276                     )
       
   277 {
   336 {
   278     EC_FUNC_HEADER;
   337     EC_FUNC_HEADER;
   279     datagram->type = EC_DATAGRAM_BWR;
   338     datagram->type = EC_DATAGRAM_BWR;
   280     EC_WRITE_U16(datagram->address, 0x0000);
   339     EC_WRITE_U16(datagram->address, 0x0000);
   281     EC_WRITE_U16(datagram->address + 2, offset);
   340     EC_WRITE_U16(datagram->address + 2, mem_address);
   282     EC_FUNC_FOOTER;
   341     EC_FUNC_FOOTER;
   283 }
   342 }
   284 
   343 
   285 /*****************************************************************************/
   344 /*****************************************************************************/
   286 
   345 
   287 /** Initializes an EtherCAT LRW datagram.
   346 /** Initializes an EtherCAT BRW datagram.
   288  *
   347  *
   289  * Logical read write.
   348  * \return 0 in case of success, else < 0
       
   349  */
       
   350 int ec_datagram_brw(
       
   351         ec_datagram_t *datagram, /**< EtherCAT datagram. */
       
   352         uint16_t mem_address, /**< Physical memory address. */
       
   353         size_t data_size /**< Number of bytes to write. */
       
   354         )
       
   355 {
       
   356     EC_FUNC_HEADER;
       
   357     datagram->type = EC_DATAGRAM_BRW;
       
   358     EC_WRITE_U16(datagram->address, 0x0000);
       
   359     EC_WRITE_U16(datagram->address + 2, mem_address);
       
   360     EC_FUNC_FOOTER;
       
   361 }
       
   362 
       
   363 /*****************************************************************************/
       
   364 
       
   365 /** Initializes an EtherCAT LRD datagram.
   290  *
   366  *
   291  * \attention It is assumed, that the external memory is at least \a data_size
   367  * \attention It is assumed, that the external memory is at least \a data_size
   292  *            bytes large.
   368  *            bytes large.
   293  *
   369  *
   294  * \return 0 in case of success, else < 0
   370  * \return 0 in case of success, else < 0
   295  */
   371  */
       
   372 int ec_datagram_lrd(
       
   373         ec_datagram_t *datagram, /**< EtherCAT datagram. */
       
   374         uint32_t offset, /**< Logical address. */
       
   375         size_t data_size, /**< Number of bytes to read/write. */
       
   376         uint8_t *external_memory /**< Pointer to the memory to use. */
       
   377         )
       
   378 {
       
   379     datagram->data = external_memory;
       
   380     datagram->data_origin = EC_ORIG_EXTERNAL;
       
   381     EC_FUNC_HEADER;
       
   382     datagram->type = EC_DATAGRAM_LRD;
       
   383     EC_WRITE_U32(datagram->address, offset);
       
   384     EC_FUNC_FOOTER;
       
   385 }
       
   386 
       
   387 /*****************************************************************************/
       
   388 
       
   389 /** Initializes an EtherCAT LWR datagram.
       
   390  *
       
   391  * \attention It is assumed, that the external memory is at least \a data_size
       
   392  *            bytes large.
       
   393  *
       
   394  * \return 0 in case of success, else < 0
       
   395  */
       
   396 int ec_datagram_lwr(
       
   397         ec_datagram_t *datagram, /**< EtherCAT datagram. */
       
   398         uint32_t offset, /**< Logical address. */
       
   399         size_t data_size, /**< Number of bytes to read/write. */
       
   400         uint8_t *external_memory /**< Pointer to the memory to use. */
       
   401         )
       
   402 {
       
   403     datagram->data = external_memory;
       
   404     datagram->data_origin = EC_ORIG_EXTERNAL;
       
   405     EC_FUNC_HEADER;
       
   406     datagram->type = EC_DATAGRAM_LWR;
       
   407     EC_WRITE_U32(datagram->address, offset);
       
   408     EC_FUNC_FOOTER;
       
   409 }
       
   410 
       
   411 /*****************************************************************************/
       
   412 
       
   413 /** Initializes an EtherCAT LRW datagram.
       
   414  *
       
   415  * \attention It is assumed, that the external memory is at least \a data_size
       
   416  *            bytes large.
       
   417  *
       
   418  * \return 0 in case of success, else < 0
       
   419  */
   296 int ec_datagram_lrw(
   420 int ec_datagram_lrw(
   297         ec_datagram_t *datagram, /**< EtherCAT datagram */
   421         ec_datagram_t *datagram, /**< EtherCAT datagram. */
   298         uint32_t offset, /**< Logical address. */
   422         uint32_t offset, /**< Logical address. */
   299         size_t data_size, /**< Number of bytes to read/write. */
   423         size_t data_size, /**< Number of bytes to read/write. */
   300         uint8_t *external_memory /**< Pointer to the memory to use. */
   424         uint8_t *external_memory /**< Pointer to the memory to use. */
   301         )
   425         )
   302 {
   426 {