master/slave.c
changeset 735 0773628aabab
parent 730 226fe5065cf2
child 740 68d83b45dfa2
equal deleted inserted replaced
734:8c9d62f7c2cd 735:0773628aabab
   889 }
   889 }
   890 
   890 
   891 /*****************************************************************************/
   891 /*****************************************************************************/
   892 
   892 
   893 /**
   893 /**
       
   894  * Calculates the EEPROM checksum field.
       
   895  *
       
   896  * The checksum is generated with the polynom x^8+x^2+x+1 (0x07) and an
       
   897  * initial value of 0xff (see IEC 61158-6-12 ch. 5.4).
       
   898  *
       
   899  * The below code was originally generated with PYCRC
       
   900  * http://www.tty1.net/pycrc
       
   901  *
       
   902  * ./pycrc.py --width=8 --poly=0x07 --reflect-in=0 --xor-in=0xff
       
   903  *   --reflect-out=0 --xor-out=0 --generate c --algorithm=bit-by-bit
       
   904  *
       
   905  * \return CRC8
       
   906  */
       
   907 
       
   908 uint8_t ec_slave_eeprom_crc(const uint8_t *data, size_t length)
       
   909 {
       
   910     unsigned int i;
       
   911     uint8_t bit, byte, crc = 0x48;
       
   912 
       
   913     while (length--) {
       
   914         byte = *data++;
       
   915         for (i = 0; i < 8; i++) {
       
   916             bit = crc & 0x80;
       
   917             crc = (crc << 1) | ((byte >> (7 - i)) & 0x01);
       
   918             if (bit) crc ^= 0x07;
       
   919         }
       
   920     }
       
   921 
       
   922     for (i = 0; i < 8; i++) {
       
   923         bit = crc & 0x80;
       
   924         crc <<= 1;
       
   925         if (bit) crc ^= 0x07;
       
   926     }
       
   927 
       
   928     return crc;
       
   929 }
       
   930 
       
   931 /*****************************************************************************/
       
   932 
       
   933 /**
   894  * Writes complete EEPROM contents to a slave.
   934  * Writes complete EEPROM contents to a slave.
   895  * \return data size written in case of success, otherwise error code.
   935  * \return data size written in case of success, otherwise error code.
   896  */
   936  */
   897 
   937 
   898 ssize_t ec_slave_write_eeprom(ec_slave_t *slave, /**< EtherCAT slave */
   938 ssize_t ec_slave_write_eeprom(ec_slave_t *slave, /**< EtherCAT slave */
   902 {
   942 {
   903     ec_eeprom_write_request_t request;
   943     ec_eeprom_write_request_t request;
   904     const uint16_t *cat_header;
   944     const uint16_t *cat_header;
   905     uint16_t cat_type, cat_size;
   945     uint16_t cat_type, cat_size;
   906     int ret;
   946     int ret;
       
   947     uint8_t crc;
   907 
   948 
   908     if (slave->master->mode != EC_MASTER_MODE_IDLE) { // FIXME
   949     if (slave->master->mode != EC_MASTER_MODE_IDLE) { // FIXME
   909         EC_ERR("Writing EEPROMs only allowed in idle mode!\n");
   950         EC_ERR("Writing EEPROMs only allowed in idle mode!\n");
   910         return -EBUSY;
   951         return -EBUSY;
   911     }
   952     }
   925     if (request.size < 0x0041) {
   966     if (request.size < 0x0041) {
   926         EC_ERR("EEPROM data too short! Dropping.\n");
   967         EC_ERR("EEPROM data too short! Dropping.\n");
   927         return -EINVAL;
   968         return -EINVAL;
   928     }
   969     }
   929 
   970 
       
   971     // calculate checksum
       
   972     crc = ec_slave_eeprom_crc(data, 14); // CRC over words 0 to 6
       
   973     if (crc != data[14]) {
       
   974         EC_WARN("EEPROM CRC incorrect. Must be 0x%02x.\n", crc);
       
   975     }
       
   976 
   930     cat_header = request.words + EC_FIRST_EEPROM_CATEGORY_OFFSET;
   977     cat_header = request.words + EC_FIRST_EEPROM_CATEGORY_OFFSET;
   931     cat_type = EC_READ_U16(cat_header);
   978     cat_type = EC_READ_U16(cat_header);
   932     while (cat_type != 0xFFFF) { // cycle through categories
   979     while (cat_type != 0xFFFF) { // cycle through categories
   933         if (cat_header + 1 > request.words + request.size) {
   980         if (cat_header + 1 > request.words + request.size) {
   934             EC_ERR("EEPROM data corrupted! Dropping.\n");
   981             EC_ERR("EEPROM data corrupted! Dropping.\n");
   962         size_t size /**< size of data in bytes */
  1009         size_t size /**< size of data in bytes */
   963         )
  1010         )
   964 {
  1011 {
   965     ec_eeprom_write_request_t request;
  1012     ec_eeprom_write_request_t request;
   966     char *remainder;
  1013     char *remainder;
   967     uint16_t alias, word;
  1014     uint16_t alias, words[8];
   968     int ret;
  1015     int ret;
       
  1016     uint8_t crc;
   969 
  1017 
   970     if (slave->master->mode != EC_MASTER_MODE_IDLE) { // FIXME
  1018     if (slave->master->mode != EC_MASTER_MODE_IDLE) { // FIXME
   971         EC_ERR("Writing EEPROMs only allowed in idle mode!\n");
  1019         EC_ERR("Writing to EEPROM is only allowed in idle mode!\n");
   972         return -EBUSY;
  1020         return -EBUSY;
   973     }
  1021     }
   974 
  1022 
   975     alias = simple_strtoul(data, &remainder, 0);
  1023     alias = simple_strtoul(data, &remainder, 0);
   976     if (remainder == (char *) data || (*remainder && *remainder != '\n')) {
  1024     if (remainder == (char *) data || (*remainder && *remainder != '\n')) {
   977         EC_ERR("Invalid alias value! Dropping.\n");
  1025         EC_ERR("Invalid alias value! Dropping.\n");
   978         return -EINVAL;
  1026         return -EINVAL;
   979     }
  1027     }
       
  1028 
       
  1029     if (!slave->eeprom_data || slave->eeprom_size < 16) {
       
  1030         EC_ERR("Failed to read EEPROM contents from slave %u.\n",
       
  1031                 slave->ring_position);
       
  1032         return -EINVAL;
       
  1033     }
       
  1034 
       
  1035     // copy first 7 words of recent EEPROM contents
       
  1036     memcpy(words, slave->eeprom_data, 14);
   980     
  1037     
   981     // correct endianess
  1038     // write new alias address
   982     EC_WRITE_U16(&word, alias);
  1039     EC_WRITE_U16(words + 4, alias);
       
  1040 
       
  1041     // calculate new checksum over words 0 to 6
       
  1042     crc = ec_slave_eeprom_crc((const uint8_t *) words, 14);
       
  1043     EC_WRITE_U16(words + 7, crc);
   983 
  1044 
   984     // init EEPROM write request
  1045     // init EEPROM write request
   985     INIT_LIST_HEAD(&request.list);
  1046     INIT_LIST_HEAD(&request.list);
   986     request.slave = slave;
  1047     request.slave = slave;
   987     request.words = &word;
  1048     request.words = words;
   988     request.offset = 0x0004;
  1049     request.offset = 0x0000;
   989     request.size = 1;
  1050     request.size = 8;
   990 
  1051 
   991     if ((ret = ec_slave_schedule_eeprom_writing(&request)))
  1052     if ((ret = ec_slave_schedule_eeprom_writing(&request)))
   992         return ret; // error code
  1053         return ret; // error code
   993 
  1054 
   994     slave->sii_alias = alias; // FIXME: do this in state machine
  1055     slave->sii_alias = alias; // FIXME: do this in state machine