Etherlab源码解析----FMMU配置

FMMU的全称是Fieldbus Memory Management Unit, 负责将从站本地物理存储地址映射到网段内逻辑地址。

本地物理存储地址可以是ESC的寄存器区域,最典型的应用是邮箱通信中,将SM1的状态位(0x80D.3)映射到逻辑地址,主站周期性地读这一位的状态来判断邮箱的状态。

本地物理存储地址也可以是SM所管理的过程数据所在的地址空间,本文将简述IGH Etherlab在何时,以及如何配置从站过程数据对应的FMMU。

1、 FMMU寄存器

每个FMMU通道使用16个字节的配置寄存器,从0x0600开始。
这里写图片描述

2、执行配置

当应用程序调用ecrt_master_activate(master)激活master以后,Etherlab状态机将配置从站的FMMU寄存器。

//Fsm_slave_config.c

void ec_fsm_slave_config_enter_fmmu(
        ec_fsm_slave_config_t *fsm /**< slave state machine */
        )
{
    ......

    // configure FMMUs
    ec_datagram_fpwr(datagram, slave->station_address,
                     0x0600, EC_FMMU_PAGE_SIZE * slave->base_fmmu_count);
    ec_datagram_zero(datagram);
    for (i = 0; i < slave->config->used_fmmus; i++) {
        fmmu = &slave->config->fmmu_configs[i];
        if (!(sync = ec_slave_get_sync(slave, fmmu->sync_index))) {  //寻找对应的SM
            slave->error_flag = 1;
            fsm->state = ec_fsm_slave_config_state_error;
            EC_SLAVE_ERR(slave, "Failed to determine PDO sync manager"
                    " for FMMU!\n");
            return;
        }
        ec_fmmu_config_page(fmmu, sync,                 //填充FMMU各寄存器
                datagram->data + EC_FMMU_PAGE_SIZE * i);
    }

    fsm->retries = EC_FSM_RETRIES;
    fsm->state = ec_fsm_slave_config_state_fmmu;
}
//Fmmu_config.c
void ec_fmmu_config_page(
        const ec_fmmu_config_t *fmmu, /**< EtherCAT FMMU configuration. */
        const ec_sync_t *sync, /**< Sync manager. */
        uint8_t *data /**> Configuration page memory. */
        )
{
    EC_CONFIG_DBG(fmmu->sc, 1, "FMMU: LogAddr 0x%08X, Size %3u,"
            " PhysAddr 0x%04X, SM%u, Dir %s\n",
            fmmu->logical_start_address, fmmu->data_size,
            sync->physical_start_address, fmmu->sync_index,
            fmmu->dir == EC_DIR_INPUT ? "in" : "out");

    EC_WRITE_U32(data,      fmmu->logical_start_address);
    EC_WRITE_U16(data + 4,  fmmu->data_size); // size of fmmu
    EC_WRITE_U8 (data + 6,  0x00); // logical start bit
    EC_WRITE_U8 (data + 7,  0x07); // logical end bit
    EC_WRITE_U16(data + 8,  sync->physical_start_address);
    EC_WRITE_U8 (data + 10, 0x00); // physical start bit
    EC_WRITE_U8 (data + 11, fmmu->dir == EC_DIR_INPUT ? 0x01 : 0x02);
    EC_WRITE_U16(data + 12, 0x0001); // enable
    EC_WRITE_U16(data + 14, 0x0000); // reserved
}

3、逻辑地址和数据长度

在ec_fmmu_config_page()函数中,FMMU配置寄存器中最重要的两个值fmmu->logical_start_address和fmmu->data_size是如何确定的呢?
在应用程序注册PDO对象时,IGH Etherlab将分配相应的FMMU,并与domain关联起来。

int ecrt_slave_config_reg_pdo_entry()
{
    ......

    //根据index和subindex查找PDO所在的SM通道
    for (sync_index = 0; sync_index < EC_MAX_SYNC_MANAGERS; sync_index++) {
        sync_config = &sc->sync_configs[sync_index];
        bit_offset = 0;

        list_for_each_entry(pdo, &sync_config->pdos.list, list) {
            list_for_each_entry(entry, &pdo->entries, list) {
                if (entry->index != index || entry->subindex != subindex) {
                    bit_offset += entry->bit_length;
                } else {
                    bit_pos = bit_offset % 8;
                    if (bit_position) {
                        *bit_position = bit_pos;
                    } else if (bit_pos) {
                        EC_CONFIG_ERR(sc, "PDO entry 0x%04X:%02X does"
                                " not byte-align.\n", index, subindex);
                        return -EFAULT;
                    }

                    sync_offset = ec_slave_config_prepare_fmmu(        //分配FMMU
                            sc, domain, sync_index, sync_config->dir);
                    if (sync_offset < 0)
                        return sync_offset;

                    return sync_offset + bit_offset / 8;
                }
            }
        }
    }

    EC_CONFIG_ERR(sc, "PDO entry 0x%04X:%02X is not mapped.\n",
           index, subindex);
    return -ENOENT;
}

而ec_slave_config_prepare_fmmu()将调用ec_fmmu_config_init(),为logical_start_address和data_size赋值:

//Fmmu_config.c
void ec_fmmu_config_init(
        ec_fmmu_config_t *fmmu, /**< EtherCAT FMMU configuration. */
        ec_slave_config_t *sc, /**< EtherCAT slave configuration. */
        ec_domain_t *domain, /**< EtherCAT domain. */
        uint8_t sync_index, /**< Sync manager index to use. */
        ec_direction_t dir /**< PDO direction. */
        )
{
    INIT_LIST_HEAD(&fmmu->list);
    fmmu->sc = sc;
    fmmu->sync_index = sync_index;
    fmmu->dir = dir;

    fmmu->logical_start_address = domain->data_size;//domain中的偏移地址
    fmmu->data_size = ec_pdo_list_total_size(  //SM中已映射的PDO总长度
            &sc->sync_configs[sync_index].pdos);

    ec_domain_add_fmmu_config(domain, fmmu); //将fmmu与domain关联起来
}

4、配置实例

这里写图片描述

  • 8
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值