igh 主站学习记录 ecrt_master_send 函数分析

一:在主站时会有三个线程 介绍

1.1:idle 线程  :用来周期性的发送消息,通过调用ecrt_master_send 函数。

1.2:operation 线程:实时性比较好,不直接调用ecrt_master_send 函数进行发送,而是通过 设置injection_seq_fsm 值,进行发送报文。

1.3:rt 线程:通过定时器周期性调用 ecrt_master_send函数,在ecrt_master_send 函数总不停地检测,

    if (master->injection_seq_rt != master->injection_seq_fsm) {
        // inject datagram produced by master FSM
        ec_master_queue_datagram(master, &master->fsm_datagram);
        master->injection_seq_rt = master->injection_seq_fsm;
    }
rt 线程是在用户程序中调用的,以ethcat 的example 的为例子,在mini.c 文件中有创建定时器timer_setup(&timer, cyclic_task, 0);,周期性执行cyclic_task 函数,在cyclic_task 函数中会调用 ecrt_master_send 函数。

二:函数分析

/*1:生产者只需“提交任务”,消费者(发送线程)按固定节奏“批量处理任务”,这种模式在实时系统中广泛 
 *应用
 *2:通过将数据报注入队列,系统自动在周期性发送流程中处理所有报文,无需模块各自调用发送函数
 */

int ecrt_master_send(ec_master_t *master)
{
    ec_datagram_t *datagram, *n;
    ec_device_index_t dev_idx;
    /*需要发生那个报文是把injection_seq_fsm ++ 然后走到这里就让报文放到队里里面。然后接着周期性发送报文,注意本地发送的报文不一定是这次注入的报文。*/
    if (master->injection_seq_rt != master->injection_seq_fsm) {
        // inject datagram produced by master FSM
        ec_master_queue_datagram(master, &master->fsm_datagram);
        master->injection_seq_rt = master->injection_seq_fsm;
    }

    ec_master_inject_external_datagrams(master);

    for (dev_idx = EC_DEVICE_MAIN; dev_idx < ec_master_num_devices(master);
            dev_idx++) {
        if (unlikely(!master->devices[dev_idx].link_state)) {
            // link is down, no datagram can be sent
            list_for_each_entry_safe(datagram, n,
                    &master->datagram_queue, queue) {
                if (datagram->device_index == dev_idx) {
                    datagram->state = EC_DATAGRAM_ERROR;
                    list_del_init(&datagram->queue);
                }
            }

            if (!master->devices[dev_idx].dev) {
                continue;
            }

            // query link state
            ec_device_poll(&master->devices[dev_idx]);

            // clear frame statistics
            ec_device_clear_stats(&master->devices[dev_idx]);
            continue;
        }

        // send frames  报文发送
        ec_master_send_datagrams(master, dev_idx);
    }
    return 0;
}

三:举例说明:
1:rt 线程:

void rt_thread_entry() {
    while (1) {
        // 1. 执行主站状态机逻辑(可能生成新数据报)
        ec_master_fsm_run(master);

        // 2. 调用发送函数(周期性触发)
        ecrt_master_send(master);

        // 3. 等待下一个周期(如 1ms)
        rt_sleep_until_next_cycle();
    }
}

2:FSM 数据报注入示例

// FSM 生成配置命令后注入队列
void fsm_configure_slave(...) {
    ec_datagram_init(&fsm_datagram, SLAVE_CONFIG_ADDR, sizeof(config_data));
    memcpy(fsm_datagram.data, &config_data, sizeof(config_data));
    ec_master_queue_datagram(master, &fsm_datagram);
    master->injection_seq_fsm++; // 触发 RT 线程发送
}

3:用户程序注入:

// 用户应用程序注入异步读命令
void user_read_slave(...) {
    ec_datagram_init(&user_datagram, SLAVE_READ_ADDR, sizeof(read_cmd));
    memcpy(user_datagram.data, &read_cmd, sizeof(read_cmd));
    ec_master_queue_datagram(master, &user_datagram);
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值