809 |
802 |
810 void ec_fsm_master_validate_vendor(ec_fsm_t *fsm /**< finite state machine */) |
803 void ec_fsm_master_validate_vendor(ec_fsm_t *fsm /**< finite state machine */) |
811 { |
804 { |
812 ec_slave_t *slave = fsm->slave; |
805 ec_slave_t *slave = fsm->slave; |
813 |
806 |
814 fsm->sii_state(fsm); // execute SII state machine |
807 ec_fsm_sii_exec(&fsm->fsm_sii); // execute SII state machine |
815 |
808 |
816 if (fsm->sii_state == ec_fsm_error) { |
809 if (ec_fsm_sii_running(&fsm->fsm_sii)) return; |
|
810 |
|
811 if (!ec_fsm_sii_success(&fsm->fsm_sii)) { |
817 fsm->slave->error_flag = 1; |
812 fsm->slave->error_flag = 1; |
818 EC_ERR("Failed to validate vendor ID of slave %i.\n", |
813 EC_ERR("Failed to validate vendor ID of slave %i.\n", |
819 slave->ring_position); |
814 slave->ring_position); |
820 fsm->master_state = ec_fsm_master_start; |
815 fsm->master_state = ec_fsm_master_start; |
821 fsm->master_state(fsm); // execute immediately |
816 fsm->master_state(fsm); // execute immediately |
822 return; |
817 return; |
823 } |
818 } |
824 |
819 |
825 if (fsm->sii_state != ec_fsm_end) return; |
820 if (EC_READ_U32(fsm->fsm_sii.value) != slave->sii_vendor_id) { |
826 |
|
827 if (EC_READ_U32(fsm->sii_value) != slave->sii_vendor_id) { |
|
828 EC_ERR("Slave %i: invalid vendor ID!\n", slave->ring_position); |
821 EC_ERR("Slave %i: invalid vendor ID!\n", slave->ring_position); |
829 fsm->master_state = ec_fsm_master_start; |
822 fsm->master_state = ec_fsm_master_start; |
830 fsm->master_state(fsm); // execute immediately |
823 fsm->master_state(fsm); // execute immediately |
831 return; |
824 return; |
832 } |
825 } |
833 |
826 |
834 // vendor ID is ok. check product code. |
827 // vendor ID is ok. check product code. |
835 fsm->master_state = ec_fsm_master_validate_product; |
828 fsm->master_state = ec_fsm_master_validate_product; |
836 fsm->sii_offset = 0x000A; // product code |
829 ec_fsm_sii_read(&fsm->fsm_sii, slave, 0x000A, EC_FSM_SII_POSITION); |
837 fsm->sii_mode = 0; |
830 ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately |
838 fsm->sii_state = ec_fsm_sii_start_reading; |
|
839 fsm->sii_state(fsm); // execute immediately |
|
840 } |
831 } |
841 |
832 |
842 /*****************************************************************************/ |
833 /*****************************************************************************/ |
843 |
834 |
844 /** |
835 /** |
879 |
870 |
880 void ec_fsm_master_validate_product(ec_fsm_t *fsm /**< finite state machine */) |
871 void ec_fsm_master_validate_product(ec_fsm_t *fsm /**< finite state machine */) |
881 { |
872 { |
882 ec_slave_t *slave = fsm->slave; |
873 ec_slave_t *slave = fsm->slave; |
883 |
874 |
884 fsm->sii_state(fsm); // execute SII state machine |
875 ec_fsm_sii_exec(&fsm->fsm_sii); // execute SII state machine |
885 |
876 |
886 if (fsm->sii_state == ec_fsm_error) { |
877 if (ec_fsm_sii_running(&fsm->fsm_sii)) return; |
|
878 |
|
879 if (!ec_fsm_sii_success(&fsm->fsm_sii)) { |
887 fsm->slave->error_flag = 1; |
880 fsm->slave->error_flag = 1; |
888 EC_ERR("Failed to validate product code of slave %i.\n", |
881 EC_ERR("Failed to validate product code of slave %i.\n", |
889 slave->ring_position); |
882 slave->ring_position); |
890 fsm->master_state = ec_fsm_master_start; |
883 fsm->master_state = ec_fsm_master_start; |
891 fsm->master_state(fsm); // execute immediately |
884 fsm->master_state(fsm); // execute immediately |
892 return; |
885 return; |
893 } |
886 } |
894 |
887 |
895 if (fsm->sii_state != ec_fsm_end) return; |
888 if (EC_READ_U32(fsm->fsm_sii.value) != slave->sii_product_code) { |
896 |
|
897 if (EC_READ_U32(fsm->sii_value) != slave->sii_product_code) { |
|
898 EC_ERR("Slave %i: invalid product code!\n", slave->ring_position); |
889 EC_ERR("Slave %i: invalid product code!\n", slave->ring_position); |
899 EC_ERR("expected 0x%08X, got 0x%08X.\n", slave->sii_product_code, |
890 EC_ERR("expected 0x%08X, got 0x%08X.\n", slave->sii_product_code, |
900 EC_READ_U32(fsm->sii_value)); |
891 EC_READ_U32(fsm->fsm_sii.value)); |
901 fsm->master_state = ec_fsm_master_start; |
892 fsm->master_state = ec_fsm_master_start; |
902 fsm->master_state(fsm); // execute immediately |
893 fsm->master_state(fsm); // execute immediately |
903 return; |
894 return; |
904 } |
895 } |
905 |
896 |
1018 |
1007 |
1019 void ec_fsm_master_write_eeprom(ec_fsm_t *fsm /**< finite state machine */) |
1008 void ec_fsm_master_write_eeprom(ec_fsm_t *fsm /**< finite state machine */) |
1020 { |
1009 { |
1021 ec_slave_t *slave = fsm->slave; |
1010 ec_slave_t *slave = fsm->slave; |
1022 |
1011 |
1023 fsm->sii_state(fsm); // execute SII state machine |
1012 ec_fsm_sii_exec(&fsm->fsm_sii); // execute SII state machine |
1024 |
1013 |
1025 if (fsm->sii_state == ec_fsm_error) { |
1014 if (ec_fsm_sii_running(&fsm->fsm_sii)) return; |
|
1015 |
|
1016 if (!ec_fsm_sii_success(&fsm->fsm_sii)) { |
1026 fsm->slave->error_flag = 1; |
1017 fsm->slave->error_flag = 1; |
1027 EC_ERR("Failed to write EEPROM contents to slave %i.\n", |
1018 EC_ERR("Failed to write EEPROM contents to slave %i.\n", |
1028 slave->ring_position); |
1019 slave->ring_position); |
1029 kfree(slave->new_eeprom_data); |
1020 kfree(slave->new_eeprom_data); |
1030 slave->new_eeprom_data = NULL; |
1021 slave->new_eeprom_data = NULL; |
1031 fsm->master_state = ec_fsm_master_start; |
1022 fsm->master_state = ec_fsm_master_start; |
1032 fsm->master_state(fsm); // execute immediately |
1023 fsm->master_state(fsm); // execute immediately |
1033 return; |
1024 return; |
1034 } |
1025 } |
1035 |
1026 |
1036 if (fsm->sii_state != ec_fsm_end) return; |
|
1037 |
|
1038 fsm->sii_offset++; |
1027 fsm->sii_offset++; |
1039 if (fsm->sii_offset < slave->new_eeprom_size) { |
1028 if (fsm->sii_offset < slave->new_eeprom_size) { |
1040 memcpy(fsm->sii_value, slave->new_eeprom_data + fsm->sii_offset, 2); |
1029 ec_fsm_sii_write(&fsm->fsm_sii, slave, fsm->sii_offset, |
1041 fsm->sii_state = ec_fsm_sii_start_writing; |
1030 slave->new_eeprom_data + fsm->sii_offset, |
1042 fsm->sii_state(fsm); // execute immediately |
1031 EC_FSM_SII_NODE); |
|
1032 ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately |
1043 return; |
1033 return; |
1044 } |
1034 } |
1045 |
1035 |
1046 // finished writing EEPROM |
1036 // finished writing EEPROM |
1047 EC_INFO("Finished writing EEPROM of slave %i.\n", slave->ring_position); |
1037 EC_INFO("Finished writing EEPROM of slave %i.\n", slave->ring_position); |
1284 { |
1273 { |
1285 ec_slave_t *slave = fsm->slave; |
1274 ec_slave_t *slave = fsm->slave; |
1286 uint16_t cat_type, cat_size; |
1275 uint16_t cat_type, cat_size; |
1287 |
1276 |
1288 // execute SII state machine |
1277 // execute SII state machine |
1289 fsm->sii_state(fsm); |
1278 ec_fsm_sii_exec(&fsm->fsm_sii); |
1290 |
1279 |
1291 if (fsm->sii_state == ec_fsm_error) { |
1280 if (ec_fsm_sii_running(&fsm->fsm_sii)) return; |
|
1281 |
|
1282 if (!ec_fsm_sii_success(&fsm->fsm_sii)) { |
1292 fsm->slave->error_flag = 1; |
1283 fsm->slave->error_flag = 1; |
1293 fsm->slave_state = ec_fsm_error; |
1284 fsm->slave_state = ec_fsm_error; |
1294 EC_ERR("Failed to read EEPROM size of slave %i.\n", |
1285 EC_ERR("Failed to read EEPROM size of slave %i.\n", |
1295 slave->ring_position); |
1286 slave->ring_position); |
1296 return; |
1287 return; |
1297 } |
1288 } |
1298 |
1289 |
1299 if (fsm->sii_state != ec_fsm_end) return; |
1290 cat_type = EC_READ_U16(fsm->fsm_sii.value); |
1300 |
1291 cat_size = EC_READ_U16(fsm->fsm_sii.value + 2); |
1301 cat_type = EC_READ_U16(fsm->sii_value); |
|
1302 cat_size = EC_READ_U16(fsm->sii_value + 2); |
|
1303 |
1292 |
1304 if (cat_type != 0xFFFF) { // not the last category |
1293 if (cat_type != 0xFFFF) { // not the last category |
1305 fsm->sii_offset += cat_size + 2; |
1294 fsm->sii_offset += cat_size + 2; |
1306 fsm->sii_state = ec_fsm_sii_start_reading; |
1295 ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset, |
1307 fsm->sii_state(fsm); // execute state immediately |
1296 EC_FSM_SII_NODE); |
|
1297 ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately |
1308 return; |
1298 return; |
1309 } |
1299 } |
1310 |
1300 |
1311 slave->eeprom_size = (fsm->sii_offset + 1) * 2; |
1301 slave->eeprom_size = (fsm->sii_offset + 1) * 2; |
1312 |
1302 |
1344 { |
1333 { |
1345 ec_slave_t *slave = fsm->slave; |
1334 ec_slave_t *slave = fsm->slave; |
1346 uint16_t *cat_word, cat_type, cat_size; |
1335 uint16_t *cat_word, cat_type, cat_size; |
1347 |
1336 |
1348 // execute SII state machine |
1337 // execute SII state machine |
1349 fsm->sii_state(fsm); |
1338 ec_fsm_sii_exec(&fsm->fsm_sii); |
1350 |
1339 |
1351 if (fsm->sii_state == ec_fsm_error) { |
1340 if (ec_fsm_sii_running(&fsm->fsm_sii)) return; |
|
1341 |
|
1342 if (!ec_fsm_sii_success(&fsm->fsm_sii)) { |
1352 fsm->slave->error_flag = 1; |
1343 fsm->slave->error_flag = 1; |
1353 fsm->slave_state = ec_fsm_error; |
1344 fsm->slave_state = ec_fsm_error; |
1354 EC_ERR("Failed to fetch EEPROM contents of slave %i.\n", |
1345 EC_ERR("Failed to fetch EEPROM contents of slave %i.\n", |
1355 slave->ring_position); |
1346 slave->ring_position); |
1356 return; |
1347 return; |
1357 } |
1348 } |
1358 |
1349 |
1359 if (fsm->sii_state != ec_fsm_end) return; |
|
1360 |
|
1361 // 2 words fetched |
1350 // 2 words fetched |
1362 |
1351 |
1363 if (fsm->sii_offset + 2 <= slave->eeprom_size / 2) { // 2 words fit |
1352 if (fsm->sii_offset + 2 <= slave->eeprom_size / 2) { // 2 words fit |
1364 memcpy(slave->eeprom_data + fsm->sii_offset * 2, fsm->sii_value, 4); |
1353 memcpy(slave->eeprom_data + fsm->sii_offset * 2, |
|
1354 fsm->fsm_sii.value, 4); |
1365 } |
1355 } |
1366 else { // copy the last word |
1356 else { // copy the last word |
1367 memcpy(slave->eeprom_data + fsm->sii_offset * 2, fsm->sii_value, 2); |
1357 memcpy(slave->eeprom_data + fsm->sii_offset * 2, |
|
1358 fsm->fsm_sii.value, 2); |
1368 } |
1359 } |
1369 |
1360 |
1370 if (fsm->sii_offset + 2 < slave->eeprom_size / 2) { |
1361 if (fsm->sii_offset + 2 < slave->eeprom_size / 2) { |
1371 // fetch the next 2 words |
1362 // fetch the next 2 words |
1372 fsm->sii_offset += 2; |
1363 fsm->sii_offset += 2; |
1373 fsm->sii_state = ec_fsm_sii_start_reading; |
1364 ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset, |
1374 fsm->sii_state(fsm); // execute state immediately |
1365 EC_FSM_SII_NODE); |
|
1366 ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately |
1375 return; |
1367 return; |
1376 } |
1368 } |
1377 |
1369 |
1378 // Evaluate EEPROM contents |
1370 // Evaluate EEPROM contents |
1379 |
1371 |
1788 EC_DBG("Slave %i is now in OP.\n", slave->ring_position); |
1780 EC_DBG("Slave %i is now in OP.\n", slave->ring_position); |
1789 EC_DBG("Finished configuration of slave %i.\n", slave->ring_position); |
1781 EC_DBG("Finished configuration of slave %i.\n", slave->ring_position); |
1790 } |
1782 } |
1791 |
1783 |
1792 fsm->slave_state = ec_fsm_end; // successful |
1784 fsm->slave_state = ec_fsm_end; // successful |
1793 } |
|
1794 |
|
1795 /****************************************************************************** |
|
1796 * SII state machine |
|
1797 *****************************************************************************/ |
|
1798 |
|
1799 /** |
|
1800 SII state: START READING. |
|
1801 Starts reading the slave information interface. |
|
1802 */ |
|
1803 |
|
1804 void ec_fsm_sii_start_reading(ec_fsm_t *fsm /**< finite state machine */) |
|
1805 { |
|
1806 ec_datagram_t *datagram = &fsm->datagram; |
|
1807 |
|
1808 // initiate read operation |
|
1809 if (fsm->sii_mode) { |
|
1810 ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 4); |
|
1811 } |
|
1812 else { |
|
1813 ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x502, 4); |
|
1814 } |
|
1815 |
|
1816 EC_WRITE_U8 (datagram->data, 0x00); // read-only access |
|
1817 EC_WRITE_U8 (datagram->data + 1, 0x01); // request read operation |
|
1818 EC_WRITE_U16(datagram->data + 2, fsm->sii_offset); |
|
1819 ec_master_queue_datagram(fsm->master, datagram); |
|
1820 fsm->sii_state = ec_fsm_sii_read_check; |
|
1821 } |
|
1822 |
|
1823 /*****************************************************************************/ |
|
1824 |
|
1825 /** |
|
1826 SII state: READ CHECK. |
|
1827 Checks, if the SII-read-datagram has been sent and issues a fetch datagram. |
|
1828 */ |
|
1829 |
|
1830 void ec_fsm_sii_read_check(ec_fsm_t *fsm /**< finite state machine */) |
|
1831 { |
|
1832 ec_datagram_t *datagram = &fsm->datagram; |
|
1833 |
|
1834 if (datagram->state != EC_DATAGRAM_RECEIVED |
|
1835 || datagram->working_counter != 1) { |
|
1836 EC_ERR("SII: Reception of read datagram failed.\n"); |
|
1837 fsm->sii_state = ec_fsm_error; |
|
1838 return; |
|
1839 } |
|
1840 |
|
1841 fsm->sii_start = datagram->cycles_sent; |
|
1842 fsm->sii_check_once_more = 1; |
|
1843 |
|
1844 // issue check/fetch datagram |
|
1845 if (fsm->sii_mode) { |
|
1846 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10); |
|
1847 } |
|
1848 else { |
|
1849 ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10); |
|
1850 } |
|
1851 |
|
1852 ec_master_queue_datagram(fsm->master, datagram); |
|
1853 fsm->sii_state = ec_fsm_sii_read_fetch; |
|
1854 } |
|
1855 |
|
1856 /*****************************************************************************/ |
|
1857 |
|
1858 /** |
|
1859 SII state: READ FETCH. |
|
1860 Fetches the result of an SII-read datagram. |
|
1861 */ |
|
1862 |
|
1863 void ec_fsm_sii_read_fetch(ec_fsm_t *fsm /**< finite state machine */) |
|
1864 { |
|
1865 ec_datagram_t *datagram = &fsm->datagram; |
|
1866 |
|
1867 if (datagram->state != EC_DATAGRAM_RECEIVED |
|
1868 || datagram->working_counter != 1) { |
|
1869 EC_ERR("SII: Reception of check/fetch datagram failed.\n"); |
|
1870 fsm->sii_state = ec_fsm_error; |
|
1871 return; |
|
1872 } |
|
1873 |
|
1874 // check "busy bit" |
|
1875 if (EC_READ_U8(datagram->data + 1) & 0x81) { |
|
1876 // still busy... timeout? |
|
1877 if (datagram->cycles_received |
|
1878 - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { |
|
1879 if (!fsm->sii_check_once_more) { |
|
1880 EC_ERR("SII: Read timeout.\n"); |
|
1881 fsm->sii_state = ec_fsm_error; |
|
1882 #if 0 |
|
1883 EC_DBG("SII busy: %02X %02X %02X %02X\n", |
|
1884 EC_READ_U8(datagram->data + 0), |
|
1885 EC_READ_U8(datagram->data + 1), |
|
1886 EC_READ_U8(datagram->data + 2), |
|
1887 EC_READ_U8(datagram->data + 3)); |
|
1888 #endif |
|
1889 return; |
|
1890 } |
|
1891 fsm->sii_check_once_more = 0; |
|
1892 } |
|
1893 |
|
1894 // issue check/fetch datagram again |
|
1895 if (fsm->sii_mode) { |
|
1896 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10); |
|
1897 } |
|
1898 else { |
|
1899 ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10); |
|
1900 } |
|
1901 ec_master_queue_datagram(fsm->master, datagram); |
|
1902 return; |
|
1903 } |
|
1904 |
|
1905 #if 0 |
|
1906 EC_DBG("SII rec: %02X %02X %02X %02X - %02X %02X %02X %02X\n", |
|
1907 EC_READ_U8(datagram->data + 0), EC_READ_U8(datagram->data + 1), |
|
1908 EC_READ_U8(datagram->data + 2), EC_READ_U8(datagram->data + 3), |
|
1909 EC_READ_U8(datagram->data + 6), EC_READ_U8(datagram->data + 7), |
|
1910 EC_READ_U8(datagram->data + 8), EC_READ_U8(datagram->data + 9)); |
|
1911 #endif |
|
1912 |
|
1913 // SII value received. |
|
1914 memcpy(fsm->sii_value, datagram->data + 6, 4); |
|
1915 fsm->sii_state = ec_fsm_end; |
|
1916 } |
|
1917 |
|
1918 /*****************************************************************************/ |
|
1919 |
|
1920 /** |
|
1921 SII state: START WRITING. |
|
1922 Starts reading the slave information interface. |
|
1923 */ |
|
1924 |
|
1925 void ec_fsm_sii_start_writing(ec_fsm_t *fsm /**< finite state machine */) |
|
1926 { |
|
1927 ec_datagram_t *datagram = &fsm->datagram; |
|
1928 |
|
1929 // initiate write operation |
|
1930 ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 8); |
|
1931 EC_WRITE_U8 (datagram->data, 0x01); // enable write access |
|
1932 EC_WRITE_U8 (datagram->data + 1, 0x02); // request write operation |
|
1933 EC_WRITE_U32(datagram->data + 2, fsm->sii_offset); |
|
1934 memcpy(datagram->data + 6, fsm->sii_value, 2); |
|
1935 ec_master_queue_datagram(fsm->master, datagram); |
|
1936 fsm->sii_state = ec_fsm_sii_write_check; |
|
1937 } |
|
1938 |
|
1939 /*****************************************************************************/ |
|
1940 |
|
1941 /** |
|
1942 SII state: WRITE CHECK. |
|
1943 */ |
|
1944 |
|
1945 void ec_fsm_sii_write_check(ec_fsm_t *fsm /**< finite state machine */) |
|
1946 { |
|
1947 ec_datagram_t *datagram = &fsm->datagram; |
|
1948 |
|
1949 if (datagram->state != EC_DATAGRAM_RECEIVED |
|
1950 || datagram->working_counter != 1) { |
|
1951 EC_ERR("SII: Reception of write datagram failed.\n"); |
|
1952 fsm->sii_state = ec_fsm_error; |
|
1953 return; |
|
1954 } |
|
1955 |
|
1956 fsm->sii_start = datagram->cycles_sent; |
|
1957 fsm->sii_check_once_more = 1; |
|
1958 |
|
1959 // issue check/fetch datagram |
|
1960 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 2); |
|
1961 ec_master_queue_datagram(fsm->master, datagram); |
|
1962 fsm->sii_state = ec_fsm_sii_write_check2; |
|
1963 } |
|
1964 |
|
1965 /*****************************************************************************/ |
|
1966 |
|
1967 /** |
|
1968 SII state: WRITE CHECK 2. |
|
1969 */ |
|
1970 |
|
1971 void ec_fsm_sii_write_check2(ec_fsm_t *fsm /**< finite state machine */) |
|
1972 { |
|
1973 ec_datagram_t *datagram = &fsm->datagram; |
|
1974 |
|
1975 if (datagram->state != EC_DATAGRAM_RECEIVED |
|
1976 || datagram->working_counter != 1) { |
|
1977 EC_ERR("SII: Reception of write check datagram failed.\n"); |
|
1978 fsm->sii_state = ec_fsm_error; |
|
1979 return; |
|
1980 } |
|
1981 |
|
1982 if (EC_READ_U8(datagram->data + 1) & 0x82) { |
|
1983 // still busy... timeout? |
|
1984 if (datagram->cycles_received |
|
1985 - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { |
|
1986 if (!fsm->sii_check_once_more) { |
|
1987 EC_ERR("SII: Write timeout.\n"); |
|
1988 fsm->sii_state = ec_fsm_error; |
|
1989 return; |
|
1990 } |
|
1991 fsm->sii_check_once_more = 0; |
|
1992 } |
|
1993 |
|
1994 // issue check/fetch datagram again |
|
1995 ec_master_queue_datagram(fsm->master, datagram); |
|
1996 return; |
|
1997 } |
|
1998 |
|
1999 if (EC_READ_U8(datagram->data + 1) & 0x40) { |
|
2000 EC_ERR("SII: Write operation failed!\n"); |
|
2001 fsm->sii_state = ec_fsm_error; |
|
2002 return; |
|
2003 } |
|
2004 |
|
2005 // success |
|
2006 fsm->sii_state = ec_fsm_end; |
|
2007 } |
1785 } |
2008 |
1786 |
2009 /****************************************************************************** |
1787 /****************************************************************************** |
2010 * state change state machine |
1788 * state change state machine |
2011 *****************************************************************************/ |
1789 *****************************************************************************/ |