自建极简Ethercat主站-第4章 FMMU内存管理单元

第4章 FMMU内存管理单元

源码地址

4.1 FMMU简介

​ Fieldbus Memory Management Units(FMMU),通过内部的映射将逻辑地址转换为ESC内部实际的物理地址。我在使用逻辑寻址的时候需要用到FMMU,我们在数据包头填写的地址就是这一包数据逻辑地址的起始地址。逻辑寻址时,如果本报数据中有逻辑地址与FMMU所配置的逻辑地址匹配,那么就会对FMMU逻辑地址所对应的物理地址进行操作。

4.2 映射举例

​ FMMU的配置寄存器从0x0600开始,每个FMMU通道有16个字节的配置寄存器。现在将物理地址0x0F01:10x0F02:0映射至逻辑地址0x00001234:30x00001235:2,映射结果如下表所示。逻辑地址长度2是因为在映射的时候横跨了两个字节的长度。

FMMU配置寄存器寄存器偏移
逻辑地址起始地址0x0:0x30x00001234
逻辑地址长度0x4:0x52
逻辑地址起始位0x63
逻辑地址终止位0x72
物理地址起始地址0x8:0x90x0F01
物理地址起始位0xA1
类型0xB
激活0xC1(使能)

在这里插入图片描述

4.3 FMMU与SM的区别

  1. FMMU是用于地址的映射,用于数据的寻址,SM是用于内存访问的管理,保证数据的一致性与安全
  2. 一个FMMU可以配置为双向的(读或写或读写),SM只能配置为单向(读或写)。一般在过程数据传输的时候两个会配合使用,FMMU用来寻址,SM用来数据交换。

4.4 FMMU其他特性

  1. 同一个ESC中同方向(读或写)的两个FMMU,如果其中一个使用的是按位映射(逻辑映射的起始位不是0或者终止位不是7或者物理地址的起始位不是0),那么逻辑地址范围之间必须间隔至少3个逻辑字节,且间隔的逻辑地址没有被任何相同类型的FMMU配置。如上面举例的图中所示,逻辑地址映射的最后一个字节的地址是0x00001235,那么与其相邻的FMMU的逻辑起始地址最小是0x00001239。如果不是采用的位映射,那么逻辑地址可以相邻。
  2. 位映射一般只用于数字输出寄存器(0x0F00:0x0F03),其他寄存器和内存总是按照字节来映射。
  3. 每个逻辑地址最多能只能由一个FMMU读加一个FMMU写或者一个FMMU读写。如果同一个逻辑地址被两个或这两个以上的FMMU配置,且方向相同,则使用编号较低的FMMU,其他的FMMU被忽略。
  4. 一个物理地址可以被多个FMMU配置,它们的访问不冲突。
  5. 对于同一个逻辑地址,使用一个读加一个写FMMU的效果与使用一个读写FMMU的效果是一样的。
  6. 配置为读写的FMMU不可以和SM共同使用。
  7. 任何地址都支持按位读取,例如一个字节的逻辑地址,在ESC1中映射了bit0bit2,在ESC2中映射了bit3bit7,那么在读取ESC2的数据的时候,只会改变bit3bit7,bit0bit2不会被改变。

4.5 FMMU配置实现

  1. 配置Ethercat地址空间的逻辑地址、逻辑地址长度、逻辑起始位、终止位。
  2. 配置物理地址的起始地址、物理起始位。
  3. 配置FMMU的传输方向,激活FMMU。

​ FMMU常用于COE中的PDO通信,FMMU与SM配合使用,FMMU映射的内存就是SM缓存模式所管理的内存。所以获取FMMU的配置参数取通常取决于SM的配置参数。

4.5.1 代码示例
/**
 * @******************************************************************************: 
 * @func: [mecm_fmmu_config]
 * @description: SM 配置,配置信息应该事先由EEPROM中读取出来或者手动填充
 * @note: 
 * @author: gxf
 * @param [uint16_t] slave 从站编号1,2,3,4,5...
 * @param [uint8_t] sm_cnt SM编号,0,1,2,3...
 * @return [*] ret<=0:配置失败
 * @==============================================================================: 
 */
int mecm_fmmu_config(uint16_t slave,uint8_t fmmu_cnt)
{
    int ret = 0;
    uint8_t buf[13];
    uint16_t i = 0;
    uint16_t tmp = 0;
    uint16_t configaddr = mecm_slave[slave].configaddr;
    /* 获取逻辑地址起始地址 */
    tmp = mecm_slave[slave].rFMMU[fmmu_cnt].fmmu_logi_start_addr;
    /* 大小端转换,然后将配置保存在临时数组中,之后一起配置 */
    buf[0] = htoel(tmp)&0xFF;
    buf[1] = (htoel(tmp)>>8)&0xFF;
    buf[2] = (htoel(tmp)>>16)&0xFF;
    buf[3] = (htoel(tmp)>>24)&0xFF;
    /* 获取逻辑地址映射长度 */
    tmp = mecm_slave[slave].rFMMU[fmmu_cnt].fmmu_length;
    /* 大小端转换,然后将配置保存在临时数组中,之后一起配置 */
    buf[4] = htoes(tmp)&0xFF;
    buf[5] = (htoes(tmp)>>8)&0xFF;
    buf[6] = mecm_slave[slave].rFMMU[fmmu_cnt].fmmu_logo_start_bit;
    buf[7] = mecm_slave[slave].rFMMU[fmmu_cnt].fmmu_logo_stop_bit;
    tmp = mecm_slave[slave].rFMMU[fmmu_cnt].fmmu_phys_start_addr;
    /* 大小端转换,然后将配置保存在临时数组中,之后一起配置 */
    buf[8] = htoes(tmp)&0xFF;
    buf[9] = (htoes(tmp)>>8)&0xFF;
    buf[10] = mecm_slave[slave].rFMMU[fmmu_cnt].fmmu_phys_start_bit;
    buf[11] = mecm_slave[slave].rFMMU[fmmu_cnt].fmmu_type;
    buf[12] = mecm_slave[slave].rFMMU[fmmu_cnt].fmmu_activate;
    /* 配置FMMU */
    ret = mecm_FPWR(configaddr,ESC_SM0_REG_STRART_ADDR+sm_cnt*8,buf,13,50000);
    return ret;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值