Etherlab原始碼解析----同步管理器SM配置(過程資料)
阿新 • • 發佈:2019-01-29
在進行過程資料通訊之前,EtherCAT主站需要配置從站的同步管理器,通常為SM2和SM3,本文介紹IGH Etherlab配置從站SM2和SM3的過程。
1、SM暫存器
SM配置暫存器從0x800開始,每個通道使用8個位元組。
2、執行配置
當應用程式呼叫ecrt_master_activate(master)啟用master以後,Etherlab狀態機就會執行Fsm_slave_config.c中的
ec_fsm_slave_config_enter_pdo_sync()函式,完成SM2/SM3各暫存器的配置。
/** Check for PDO sync managers to be configured.
*/
void ec_fsm_slave_config_enter_pdo_sync(
ec_fsm_slave_config_t *fsm /**< slave state machine */
)
{
......
// configure sync managers for process data
ec_datagram_fpwr(datagram, slave->station_address,
0x0800 + EC_SYNC_PAGE_SIZE * offset, //準備報文
EC_SYNC_PAGE_SIZE * num_pdo_syncs);
ec_datagram_zero(datagram);
for (i = 0; i < num_pdo_syncs; i++) {
const ec_sync_config_t *sync_config;
uint8_t pdo_xfer = 0;
sync_index = i + offset;
sync = &slave->sii.syncs[sync_index];
if (slave->config) {
const ec_slave_config_t *sc = slave->config;
sync_config = &sc->sync_configs[sync_index];
size = ec_pdo_list_total_size(&sync_config->pdos); //計算已對映的PDO物件的總長度
......
} else {
sync_config = NULL;
size = sync->default_length;
}
ec_sync_page(sync, sync_index, size, sync_config, pdo_xfer, //將SM暫存器寫入報文對應位置
datagram->data + EC_SYNC_PAGE_SIZE * i);
}
fsm->retries = EC_FSM_RETRIES;
fsm->state = ec_fsm_slave_config_state_pdo_sync;
}
在ec_sync_page()中將SM暫存器的值填入報文對應位置:
void ec_sync_page(
const ec_sync_t *sync, /**< Sync manager. */
uint8_t sync_index, /**< Index of the sync manager. */
uint16_t data_size, /**< Data size. */
const ec_sync_config_t *sync_config, /**< Configuration. */
uint8_t pdo_xfer, /**< Non-zero, if PDOs will be transferred via this
sync manager. */
uint8_t *data /**> Configuration memory. */
)
{
......
EC_WRITE_U16(data, sync->physical_start_address);
EC_WRITE_U16(data + 2, data_size);
EC_WRITE_U8 (data + 4, control);
EC_WRITE_U8 (data + 5, 0x00); // status byte (read only)
EC_WRITE_U16(data + 6, enable);
}
3、起始地址和控制字
SM暫存器的物理起始地址和控制字,來源於從站的EEPROM,Etherlab在掃描從站時獲取對應的值。
//Fsm_slave_scan.c
ec_fsm_slave_scan_state_sii_data()
{
......
case 0x0029:
if (ec_slave_fetch_sii_syncs(slave, (uint8_t *) cat_word,cat_size * 2))
goto end;
break;
......
}
//slave.c
int ec_slave_fetch_sii_syncs(
ec_slave_t *slave, /**< EtherCAT slave. */
const uint8_t *data, /**< Category data. */
size_t data_size /**< Number of bytes. */
)
{
......
{
// initialize new sync managers
for (i = 0; i < count; i++, data += 8) {
index = i + slave->sii.sync_count;
sync = &syncs[index];
ec_sync_init(sync, slave);
sync->physical_start_address = EC_READ_U16(data); //物理起始地址
sync->default_length = EC_READ_U16(data + 2); //預設長度,命令列ethercat pdos列印的defaultsize
sync->control_register = EC_READ_U8(data + 4);//控制字
sync->enable = EC_READ_U8(data + 6);//使能
}
if (slave->sii.syncs)
kfree(slave->sii.syncs);
slave->sii.syncs = syncs;
slave->sii.sync_count = total_count;
}
return 0;
}
4、資料長度
SM2暫存器的資料長度等於主站傳送到從站的過程資料的長度,SM3暫存器的長度等於從站傳送到主站的過程資料的長度。
SM資料長度為已對映的PDO物件的總長度,在ec_pdo_list_total_size()中計算。
uint16_t ec_pdo_list_total_size(
const ec_pdo_list_t *pl /**< PDO list. */
)
{
unsigned int bit_size;
const ec_pdo_t *pdo;
const ec_pdo_entry_t *pdo_entry;
uint16_t byte_size;
bit_size = 0;
list_for_each_entry(pdo, &pl->list, list) {
list_for_each_entry(pdo_entry, &pdo->entries, list) {
bit_size += pdo_entry->bit_length;
}
}
if (bit_size % 8) // round up to full bytes
byte_size = bit_size / 8 + 1;
else
byte_size = bit_size / 8;
return byte_size;
}