feat(motor): 自适应 PDO 窗口与通道活动指示,新增原生 SOEM 时序诊断
后端 PDO 循环改为按在线槽收缩状态窗口,稀疏总线下单槽每周期都能刷新, 并补上尾部槽的发现扫描游标;新增自旋节拍源(阈值/显式覆盖)、P 核识别 与线程级钉核,自旋期间释放 GIL 以免 HTTP 线程被饿死;启动时先关停旧实例, 避免两个进程争用 Npcap 适配器。 记录每拍完整时间线、GC stop-the-world 事件与网格跳拍数,经 /api/motor/dbg 导出用于归因固定频率的超时;配
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
/** \file
|
||||
* \brief Example code for Simple Open EtherCAT master
|
||||
*
|
||||
* Usage: firm_update ifname1 slave fname
|
||||
* ifname is NIC interface, f.e. eth0
|
||||
* slave = slave number in EtherCAT order 1..n
|
||||
* fname = binary file to store in slave
|
||||
* CAUTION! Using the wrong file can result in a bricked slave!
|
||||
*
|
||||
* This is a slave firmware update test.
|
||||
*
|
||||
* (c)Arthur Ketels 2011
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ethercat.h"
|
||||
|
||||
#define FWBUFSIZE (8 * 1024 * 1024)
|
||||
|
||||
uint8 ob;
|
||||
uint16 ow;
|
||||
uint32 data;
|
||||
char filename[256];
|
||||
char filebuffer[FWBUFSIZE]; // 8MB buffer
|
||||
int filesize;
|
||||
int j;
|
||||
uint16 argslave;
|
||||
|
||||
int input_bin(char *fname, int *length)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
int cc = 0, c;
|
||||
|
||||
fp = fopen(fname, "rb");
|
||||
if(fp == NULL)
|
||||
return 0;
|
||||
while (((c = fgetc(fp)) != EOF) && (cc < FWBUFSIZE))
|
||||
filebuffer[cc++] = (uint8)c;
|
||||
*length = cc;
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void boottest(char *ifname, uint16 slave, char *filename)
|
||||
{
|
||||
printf("Starting firmware update example\n");
|
||||
|
||||
/* initialise SOEM, bind socket to ifname */
|
||||
if (ec_init(ifname))
|
||||
{
|
||||
printf("ec_init on %s succeeded.\n",ifname);
|
||||
/* find and auto-config slaves */
|
||||
|
||||
|
||||
if ( ec_config_init(FALSE) > 0 )
|
||||
{
|
||||
printf("%d slaves found and configured.\n",ec_slavecount);
|
||||
|
||||
printf("Request init state for slave %d\n", slave);
|
||||
ec_slave[slave].state = EC_STATE_INIT;
|
||||
ec_writestate(slave);
|
||||
|
||||
/* wait for slave to reach INIT state */
|
||||
ec_statecheck(slave, EC_STATE_INIT, EC_TIMEOUTSTATE * 4);
|
||||
printf("Slave %d state to INIT.\n", slave);
|
||||
|
||||
/* read BOOT mailbox data, master -> slave */
|
||||
data = ec_readeeprom(slave, ECT_SII_BOOTRXMBX, EC_TIMEOUTEEP);
|
||||
ec_slave[slave].SM[0].StartAddr = (uint16)LO_WORD(data);
|
||||
ec_slave[slave].SM[0].SMlength = (uint16)HI_WORD(data);
|
||||
/* store boot write mailbox address */
|
||||
ec_slave[slave].mbx_wo = (uint16)LO_WORD(data);
|
||||
/* store boot write mailbox size */
|
||||
ec_slave[slave].mbx_l = (uint16)HI_WORD(data);
|
||||
|
||||
/* read BOOT mailbox data, slave -> master */
|
||||
data = ec_readeeprom(slave, ECT_SII_BOOTTXMBX, EC_TIMEOUTEEP);
|
||||
ec_slave[slave].SM[1].StartAddr = (uint16)LO_WORD(data);
|
||||
ec_slave[slave].SM[1].SMlength = (uint16)HI_WORD(data);
|
||||
/* store boot read mailbox address */
|
||||
ec_slave[slave].mbx_ro = (uint16)LO_WORD(data);
|
||||
/* store boot read mailbox size */
|
||||
ec_slave[slave].mbx_rl = (uint16)HI_WORD(data);
|
||||
|
||||
printf(" SM0 A:%4.4x L:%4d F:%8.8x\n", ec_slave[slave].SM[0].StartAddr, ec_slave[slave].SM[0].SMlength,
|
||||
(int)ec_slave[slave].SM[0].SMflags);
|
||||
printf(" SM1 A:%4.4x L:%4d F:%8.8x\n", ec_slave[slave].SM[1].StartAddr, ec_slave[slave].SM[1].SMlength,
|
||||
(int)ec_slave[slave].SM[1].SMflags);
|
||||
/* program SM0 mailbox in for slave */
|
||||
ec_FPWR (ec_slave[slave].configadr, ECT_REG_SM0, sizeof(ec_smt), &ec_slave[slave].SM[0], EC_TIMEOUTRET);
|
||||
/* program SM1 mailbox out for slave */
|
||||
ec_FPWR (ec_slave[slave].configadr, ECT_REG_SM1, sizeof(ec_smt), &ec_slave[slave].SM[1], EC_TIMEOUTRET);
|
||||
|
||||
printf("Request BOOT state for slave %d\n", slave);
|
||||
ec_slave[slave].state = EC_STATE_BOOT;
|
||||
ec_writestate(slave);
|
||||
|
||||
/* wait for slave to reach BOOT state */
|
||||
if (ec_statecheck(slave, EC_STATE_BOOT, EC_TIMEOUTSTATE * 10) == EC_STATE_BOOT)
|
||||
{
|
||||
printf("Slave %d state to BOOT.\n", slave);
|
||||
|
||||
if (input_bin(filename, &filesize))
|
||||
{
|
||||
printf("File read OK, %d bytes.\n",filesize);
|
||||
printf("FoE write....");
|
||||
j = ec_FOEwrite(slave, filename, 0, filesize , &filebuffer, EC_TIMEOUTSTATE);
|
||||
printf("result %d.\n",j);
|
||||
printf("Request init state for slave %d\n", slave);
|
||||
ec_slave[slave].state = EC_STATE_INIT;
|
||||
ec_writestate(slave);
|
||||
}
|
||||
else
|
||||
printf("File not read OK.\n");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("No slaves found!\n");
|
||||
}
|
||||
printf("End firmware update example, close socket\n");
|
||||
/* stop SOEM, close socket */
|
||||
ec_close();
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("No socket connection on %s\nExcecute as root\n",ifname);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
printf("SOEM (Simple Open EtherCAT Master)\nFirmware update example\n");
|
||||
|
||||
if (argc > 3)
|
||||
{
|
||||
argslave = atoi(argv[2]);
|
||||
boottest(argv[1], argslave, argv[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Usage: firm_update ifname1 slave fname\n");
|
||||
printf("ifname = eth0 for example\n");
|
||||
printf("slave = slave number in EtherCAT order 1..n\n");
|
||||
printf("fname = binary file to store in slave\n");
|
||||
printf("CAUTION! Using the wrong file can result in a bricked slave!\n");
|
||||
}
|
||||
|
||||
printf("End program\n");
|
||||
return (0);
|
||||
}
|
||||
Reference in New Issue
Block a user