master/fsm_sii.c
changeset 755 178353fc47e5
parent 754 0b47b49c5976
child 758 8fa6f825eb7d
equal deleted inserted replaced
754:0b47b49c5976 755:178353fc47e5
    41 #include "globals.h"
    41 #include "globals.h"
    42 #include "mailbox.h"
    42 #include "mailbox.h"
    43 #include "master.h"
    43 #include "master.h"
    44 #include "fsm_sii.h"
    44 #include "fsm_sii.h"
    45 
    45 
       
    46 #define EEPROM_TIMEOUT 10 // read/write timeout [ms]
       
    47 #define EEPROM_INHIBIT  5 // time before evaluating answer at writing [ms]
       
    48 
       
    49 //#define SII_DEBUG
       
    50 
    46 /*****************************************************************************/
    51 /*****************************************************************************/
    47 
    52 
    48 void ec_fsm_sii_state_start_reading(ec_fsm_sii_t *);
    53 void ec_fsm_sii_state_start_reading(ec_fsm_sii_t *);
    49 void ec_fsm_sii_state_read_check(ec_fsm_sii_t *);
    54 void ec_fsm_sii_state_read_check(ec_fsm_sii_t *);
    50 void ec_fsm_sii_state_read_fetch(ec_fsm_sii_t *);
    55 void ec_fsm_sii_state_read_fetch(ec_fsm_sii_t *);
    84    Initializes the SII read state machine.
    89    Initializes the SII read state machine.
    85 */
    90 */
    86 
    91 
    87 void ec_fsm_sii_read(ec_fsm_sii_t *fsm, /**< finite state machine */
    92 void ec_fsm_sii_read(ec_fsm_sii_t *fsm, /**< finite state machine */
    88                      ec_slave_t *slave, /**< slave to read from */
    93                      ec_slave_t *slave, /**< slave to read from */
    89                      uint16_t offset, /**< offset to read from */
    94                      uint16_t word_offset, /**< offset to read from */
    90                      ec_fsm_sii_addressing_t mode /**< addressing scheme */
    95                      ec_fsm_sii_addressing_t mode /**< addressing scheme */
    91                      )
    96                      )
    92 {
    97 {
    93     fsm->state = ec_fsm_sii_state_start_reading;
    98     fsm->state = ec_fsm_sii_state_start_reading;
    94     fsm->slave = slave;
    99     fsm->slave = slave;
    95     fsm->offset = offset;
   100     fsm->word_offset = word_offset;
    96     fsm->mode = mode;
   101     fsm->mode = mode;
    97 }
   102 }
    98 
   103 
    99 /*****************************************************************************/
   104 /*****************************************************************************/
   100 
   105 
   102    Initializes the SII write state machine.
   107    Initializes the SII write state machine.
   103 */
   108 */
   104 
   109 
   105 void ec_fsm_sii_write(ec_fsm_sii_t *fsm, /**< finite state machine */
   110 void ec_fsm_sii_write(ec_fsm_sii_t *fsm, /**< finite state machine */
   106                       ec_slave_t *slave, /**< slave to read from */
   111                       ec_slave_t *slave, /**< slave to read from */
   107                       uint16_t offset, /**< offset to read from */
   112                       uint16_t word_offset, /**< offset to read from */
   108                       const uint8_t *value, /**< pointer to 2 bytes of data */
   113                       const uint8_t *value, /**< pointer to 2 bytes of data */
   109                       ec_fsm_sii_addressing_t mode /**< addressing scheme */
   114                       ec_fsm_sii_addressing_t mode /**< addressing scheme */
   110                       )
   115                       )
   111 {
   116 {
   112     fsm->state = ec_fsm_sii_state_start_writing;
   117     fsm->state = ec_fsm_sii_state_start_writing;
   113     fsm->slave = slave;
   118     fsm->slave = slave;
   114     fsm->offset = offset;
   119     fsm->word_offset = word_offset;
   115     fsm->mode = mode;
   120     fsm->mode = mode;
   116     memcpy(fsm->value, value, 2);
   121     memcpy(fsm->value, value, 2);
   117 }
   122 }
   118 
   123 
   119 /*****************************************************************************/
   124 /*****************************************************************************/
   166         case EC_FSM_SII_NODE:
   171         case EC_FSM_SII_NODE:
   167             ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 4);
   172             ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 4);
   168             break;
   173             break;
   169     }
   174     }
   170 
   175 
   171     EC_WRITE_U8 (datagram->data,     0x00); // read-only access
   176     EC_WRITE_U8 (datagram->data,     0x80); // two address octets
   172     EC_WRITE_U8 (datagram->data + 1, 0x01); // request read operation
   177     EC_WRITE_U8 (datagram->data + 1, 0x01); // request read operation
   173     EC_WRITE_U16(datagram->data + 2, fsm->offset);
   178     EC_WRITE_U16(datagram->data + 2, fsm->word_offset);
       
   179 
       
   180 #ifdef SII_DEBUG
       
   181 	EC_DBG("reading SII data:\n");
       
   182 	ec_print_data(datagram->data, 4);
       
   183 #endif
       
   184 
   174     fsm->retries = EC_FSM_RETRIES;
   185     fsm->retries = EC_FSM_RETRIES;
   175     fsm->state = ec_fsm_sii_state_read_check;
   186     fsm->state = ec_fsm_sii_state_read_check;
   176 }
   187 }
   177 
   188 
   178 /*****************************************************************************/
   189 /*****************************************************************************/
   254                 fsm->slave->ring_position);
   265                 fsm->slave->ring_position);
   255         ec_datagram_print_wc_error(datagram);
   266         ec_datagram_print_wc_error(datagram);
   256         return;
   267         return;
   257     }
   268     }
   258 
   269 
       
   270 #ifdef SII_DEBUG
       
   271 	EC_DBG("checking SII read state:\n");
       
   272 	ec_print_data(datagram->data, 10);
       
   273 #endif
       
   274 
       
   275     if (EC_READ_U8(datagram->data + 1) & 0x20) {
       
   276         EC_ERR("SII: Error on last SII command!\n");
       
   277         fsm->state = ec_fsm_sii_state_error;
       
   278         return;
       
   279     }
       
   280 
   259     // check "busy bit"
   281     // check "busy bit"
   260     if (EC_READ_U8(datagram->data + 1) & 0x81) {
   282     if (EC_READ_U8(datagram->data + 1) & 0x81) { // busy bit or
       
   283 												 // read operation busy
   261         // still busy... timeout?
   284         // still busy... timeout?
   262         if (datagram->cycles_received
   285         if (datagram->cycles_received
   263             - fsm->cycles_start >= (cycles_t) 10 * cpu_khz) {
   286             - fsm->cycles_start >= (cycles_t) EEPROM_TIMEOUT * cpu_khz) {
   264             if (!fsm->check_once_more) {
   287             if (fsm->check_once_more) {
       
   288 				fsm->check_once_more = 0;
       
   289 			} else {
   265                 EC_ERR("SII: Read timeout.\n");
   290                 EC_ERR("SII: Read timeout.\n");
   266                 fsm->state = ec_fsm_sii_state_error;
   291                 fsm->state = ec_fsm_sii_state_error;
   267 #if 0
       
   268                 EC_DBG("SII busy: %02X %02X %02X %02X\n",
       
   269                        EC_READ_U8(datagram->data + 0),
       
   270                        EC_READ_U8(datagram->data + 1),
       
   271                        EC_READ_U8(datagram->data + 2),
       
   272                        EC_READ_U8(datagram->data + 3));
       
   273 #endif
       
   274                 return;
   292                 return;
   275             }
   293             }
   276             fsm->check_once_more = 0;
       
   277         }
   294         }
   278 
   295 
   279         // issue check/fetch datagram again
   296         // issue check/fetch datagram again
   280         switch (fsm->mode) {
       
   281             case EC_FSM_SII_POSITION:
       
   282                 ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10);
       
   283                 break;
       
   284             case EC_FSM_SII_NODE:
       
   285                 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10);
       
   286                 break;
       
   287         }
       
   288         fsm->retries = EC_FSM_RETRIES;
   297         fsm->retries = EC_FSM_RETRIES;
   289         return;
   298         return;
   290     }
   299     }
   291 
       
   292 #if 0
       
   293     EC_DBG("SII rec: %02X %02X %02X %02X - %02X %02X %02X %02X\n",
       
   294            EC_READ_U8(datagram->data + 0), EC_READ_U8(datagram->data + 1),
       
   295            EC_READ_U8(datagram->data + 2), EC_READ_U8(datagram->data + 3),
       
   296            EC_READ_U8(datagram->data + 6), EC_READ_U8(datagram->data + 7),
       
   297            EC_READ_U8(datagram->data + 8), EC_READ_U8(datagram->data + 9));
       
   298 #endif
       
   299 
   300 
   300     // SII value received.
   301     // SII value received.
   301     memcpy(fsm->value, datagram->data + 6, 4);
   302     memcpy(fsm->value, datagram->data + 6, 4);
   302     fsm->state = ec_fsm_sii_state_end;
   303     fsm->state = ec_fsm_sii_state_end;
   303 }
   304 }
   304 
   305 
   305 /*****************************************************************************/
   306 /*****************************************************************************/
   306 
   307 
   307 /**
   308 /**
   308    SII state: START WRITING.
   309    SII state: START WRITING.
   309    Starts reading the slave information interface.
   310    Starts writing a word through the slave information interface.
   310 */
   311 */
   311 
   312 
   312 void ec_fsm_sii_state_start_writing(
   313 void ec_fsm_sii_state_start_writing(
   313 		ec_fsm_sii_t *fsm /**< finite state machine */
   314 		ec_fsm_sii_t *fsm /**< finite state machine */
   314 		)
   315 		)
   315 {
   316 {
   316     ec_datagram_t *datagram = fsm->datagram;
   317     ec_datagram_t *datagram = fsm->datagram;
   317 
   318 
   318     // initiate write operation
   319     // initiate write operation
   319     ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 8);
   320     ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 8);
   320     EC_WRITE_U8 (datagram->data,     0x01); // enable write access
   321     EC_WRITE_U8 (datagram->data,     0x81); // two address octets
       
   322 											// + enable write access
   321     EC_WRITE_U8 (datagram->data + 1, 0x02); // request write operation
   323     EC_WRITE_U8 (datagram->data + 1, 0x02); // request write operation
   322     EC_WRITE_U32(datagram->data + 2, fsm->offset);
   324     EC_WRITE_U16(datagram->data + 2, fsm->word_offset);
       
   325 	memset(datagram->data + 4, 0x00, 2);
   323     memcpy(datagram->data + 6, fsm->value, 2);
   326     memcpy(datagram->data + 6, fsm->value, 2);
       
   327 
       
   328 #ifdef SII_DEBUG
       
   329 	EC_DBG("writing SII data:\n");
       
   330 	ec_print_data(datagram->data, 8);
       
   331 #endif
   324 
   332 
   325     fsm->retries = EC_FSM_RETRIES;
   333     fsm->retries = EC_FSM_RETRIES;
   326     fsm->state = ec_fsm_sii_state_write_check;
   334     fsm->state = ec_fsm_sii_state_write_check;
   327 }
   335 }
   328 
   336 
   358     }
   366     }
   359 
   367 
   360     fsm->cycles_start = datagram->cycles_sent;
   368     fsm->cycles_start = datagram->cycles_sent;
   361     fsm->check_once_more = 1;
   369     fsm->check_once_more = 1;
   362 
   370 
   363     // issue check/fetch datagram
   371     // issue check datagram
   364     ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 2);
   372     ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 2);
   365     fsm->retries = EC_FSM_RETRIES;
   373     fsm->retries = EC_FSM_RETRIES;
   366     fsm->state = ec_fsm_sii_state_write_check2;
   374     fsm->state = ec_fsm_sii_state_write_check2;
   367 }
   375 }
   368 
   376 
   395                 fsm->slave->ring_position);
   403                 fsm->slave->ring_position);
   396         ec_datagram_print_wc_error(datagram);
   404         ec_datagram_print_wc_error(datagram);
   397         return;
   405         return;
   398     }
   406     }
   399 
   407 
   400     if (EC_READ_U8(datagram->data + 1) & 0x82) {
   408 #ifdef SII_DEBUG
       
   409 	EC_DBG("checking SII write state:\n");
       
   410 	ec_print_data(datagram->data, 2);
       
   411 #endif
       
   412 
       
   413     if (EC_READ_U8(datagram->data + 1) & 0x20) {
       
   414         EC_ERR("SII: Error on last SII command!\n");
       
   415         fsm->state = ec_fsm_sii_state_error;
       
   416         return;
       
   417     }
       
   418 
       
   419 	/* FIXME: some slaves never answer with the busy flag set...
       
   420 	 * wait a few ms for the write operation to complete. */
       
   421 	if (datagram->cycles_received - fsm->cycles_start
       
   422 			< (cycles_t) EEPROM_INHIBIT * cpu_khz) {
       
   423 #ifdef SII_DEBUG
       
   424 		EC_DBG("too early.\n");
       
   425 #endif
       
   426         // issue check datagram again
       
   427         fsm->retries = EC_FSM_RETRIES;
       
   428         return;
       
   429 	}
       
   430 
       
   431     if (EC_READ_U8(datagram->data + 1) & 0x82) { // busy bit or
       
   432 												 // write operation busy bit
   401         // still busy... timeout?
   433         // still busy... timeout?
   402         if (datagram->cycles_received
   434         if (datagram->cycles_received
   403             - fsm->cycles_start >= (cycles_t) 10 * cpu_khz) {
   435             - fsm->cycles_start >= (cycles_t) EEPROM_TIMEOUT * cpu_khz) {
   404             if (!fsm->check_once_more) {
   436             if (fsm->check_once_more) {
       
   437 				fsm->check_once_more = 0;
       
   438 			} else {
   405                 EC_ERR("SII: Write timeout.\n");
   439                 EC_ERR("SII: Write timeout.\n");
   406                 fsm->state = ec_fsm_sii_state_error;
   440                 fsm->state = ec_fsm_sii_state_error;
   407                 return;
   441                 return;
   408             }
   442             }
   409             fsm->check_once_more = 0;
       
   410         }
   443         }
   411 
   444 
   412         // issue check/fetch datagram again
   445         // issue check datagram again
   413         fsm->retries = EC_FSM_RETRIES;
   446         fsm->retries = EC_FSM_RETRIES;
   414         return;
   447         return;
   415     }
   448     }
   416 
   449 
   417     if (EC_READ_U8(datagram->data + 1) & 0x40) {
   450     if (EC_READ_U8(datagram->data + 1) & 0x40) {