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 |
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) { |