feat!: 1.6.0 DWT 剖分探针 + 1.6.1 输入 PDO 瘦身 640→496(待重烧验收)
1.6.0 剖分探针(上一轮真机已验证, 随本轮一并入库): - ecatappl.c: 0x2000 sub5..12 DWT 周期累加器(PDI_Isr/输入映射/640B 写细分) - ethercat_pdo.cpp: 输出按需全量读(12B 探针判 seq 沿, 省每周期 ~190µs 全量读) - 段5 诊断区(负载率+seq)随 PDO 上报, 主站 /api/app/load 轮询 1.6.1 输入 PDO 瘦身 640→496(62×64bit; 0..359 与 1.5.61 逐字节兼容): - 依据: DWT 实测 640B 写恒 296µs/拍且与 SYNC0 相位无关(主站 dc_bench 五形态 对拍极差 0.04%), PRAM ≈0.463µs/B 线性; 真机 6086 帧 DLC 仅 24/32 - 批量接收条目 8B 头+64B 数据 → 8B+32B(DLC 真值保留, 截断打 flags bit1, 环形队列仍存全量 64B); 段5 诊断区 632→484 - 预期写侧 −67µs/拍(→~230µs, 占空 29.7%→23%); LRW 帧 1024→880B - 五处一致: ethercat_pdo_size.h(真源) / dc_app.c(62 条目+映射初始化器) / gen_eeprom.py(PD_IN_SIZE, nEntry 自动推导) / DCU_ESI.xml(SM3 496+62 条目) / bridge.h(kEcatRxBatchDataMax=32, 断言更新) - 主站 tools/ecat decode_input 按 Ibytes 双布局自适应, 固件/EEPROM 与主站可 任意先后升级; 混烧(只烧一侧)会被 SM 长度校验拦下(AL 0x001A) - AC6 编译 0 警告; 真机验收待: 烧 axf + ecat.bat flash + 断电冷启动 (流程与复验判据见 tools/ecat/MIGRATION.md 1.6.1 节)
This commit is contained in:
@@ -25,7 +25,7 @@
|
||||
<!-- SM2: Process Data Output (RxPDO, Master -> Slave) -->
|
||||
<Sm DefaultSize="384" StartAddress="#x1400" ControlByte="#x64" Enable="1">Outputs</Sm>
|
||||
<!-- SM3: Process Data Input (TxPDO, Slave -> Master) -->
|
||||
<Sm DefaultSize="640" StartAddress="#x1880" ControlByte="#x20" Enable="1">Inputs</Sm>
|
||||
<Sm DefaultSize="496" StartAddress="#x1880" ControlByte="#x20" Enable="1">Inputs</Sm>
|
||||
<!-- RxPDO (Output, Master -> Slave): 索引 0x1600-0x17FF,映射 0x7000:01..48
|
||||
1.5.56 扩到 48 条目(384B):兼容单帧区 48B + CANFD 批量发送区 336B。
|
||||
与 dc_app.c 的 PDO_OUT_ENTRIES / gen_eeprom.py 的 PD_OUT_SIZE 必须一致,
|
||||
@@ -374,6 +374,8 @@
|
||||
1.5.56 扩到 80 条目(640B):电机状态窗口 + CANFD 批量接收区 280B。
|
||||
SM3 起址随之挪到 #x1880 —— SM2 是 3-buffer 模式,384B×3 占到 #x187F。
|
||||
(384+640)×3 = 3072 = 过程数据区 0x1400-0x1FFF 全长,恰好用满。
|
||||
1.6.1 输入瘦身 640→496: 批量接收条目数据 64→32B(截断见 bridge.h),
|
||||
条目 80→62, SM3 实占 3×496=1488B (0x1880-0x1E4F), DPRAM 留 432B。
|
||||
撞址会被 SSC ecatslv.c 重叠检查拦下,报 INVALIDSMOUTCFG。 -->
|
||||
<TxPdo Fixed="1" Mandatory="1" Sm="3">
|
||||
<Index>#x1A00</Index>
|
||||
@@ -812,132 +814,24 @@
|
||||
<Name>Status Data 62</Name>
|
||||
<DataType>ULINT</DataType>
|
||||
</Entry>
|
||||
<Entry>
|
||||
<Index>#x6000</Index>
|
||||
<SubIndex>63</SubIndex>
|
||||
<BitLen>64</BitLen>
|
||||
<Name>Status Data 63</Name>
|
||||
<DataType>ULINT</DataType>
|
||||
</Entry>
|
||||
<Entry>
|
||||
<Index>#x6000</Index>
|
||||
<SubIndex>64</SubIndex>
|
||||
<BitLen>64</BitLen>
|
||||
<Name>Status Data 64</Name>
|
||||
<DataType>ULINT</DataType>
|
||||
</Entry>
|
||||
<Entry>
|
||||
<Index>#x6000</Index>
|
||||
<SubIndex>65</SubIndex>
|
||||
<BitLen>64</BitLen>
|
||||
<Name>Status Data 65</Name>
|
||||
<DataType>ULINT</DataType>
|
||||
</Entry>
|
||||
<Entry>
|
||||
<Index>#x6000</Index>
|
||||
<SubIndex>66</SubIndex>
|
||||
<BitLen>64</BitLen>
|
||||
<Name>Status Data 66</Name>
|
||||
<DataType>ULINT</DataType>
|
||||
</Entry>
|
||||
<Entry>
|
||||
<Index>#x6000</Index>
|
||||
<SubIndex>67</SubIndex>
|
||||
<BitLen>64</BitLen>
|
||||
<Name>Status Data 67</Name>
|
||||
<DataType>ULINT</DataType>
|
||||
</Entry>
|
||||
<Entry>
|
||||
<Index>#x6000</Index>
|
||||
<SubIndex>68</SubIndex>
|
||||
<BitLen>64</BitLen>
|
||||
<Name>Status Data 68</Name>
|
||||
<DataType>ULINT</DataType>
|
||||
</Entry>
|
||||
<Entry>
|
||||
<Index>#x6000</Index>
|
||||
<SubIndex>69</SubIndex>
|
||||
<BitLen>64</BitLen>
|
||||
<Name>Status Data 69</Name>
|
||||
<DataType>ULINT</DataType>
|
||||
</Entry>
|
||||
<Entry>
|
||||
<Index>#x6000</Index>
|
||||
<SubIndex>70</SubIndex>
|
||||
<BitLen>64</BitLen>
|
||||
<Name>Status Data 70</Name>
|
||||
<DataType>ULINT</DataType>
|
||||
</Entry>
|
||||
<Entry>
|
||||
<Index>#x6000</Index>
|
||||
<SubIndex>71</SubIndex>
|
||||
<BitLen>64</BitLen>
|
||||
<Name>Status Data 71</Name>
|
||||
<DataType>ULINT</DataType>
|
||||
</Entry>
|
||||
<Entry>
|
||||
<Index>#x6000</Index>
|
||||
<SubIndex>72</SubIndex>
|
||||
<BitLen>64</BitLen>
|
||||
<Name>Status Data 72</Name>
|
||||
<DataType>ULINT</DataType>
|
||||
</Entry>
|
||||
<Entry>
|
||||
<Index>#x6000</Index>
|
||||
<SubIndex>73</SubIndex>
|
||||
<BitLen>64</BitLen>
|
||||
<Name>Status Data 73</Name>
|
||||
<DataType>ULINT</DataType>
|
||||
</Entry>
|
||||
<Entry>
|
||||
<Index>#x6000</Index>
|
||||
<SubIndex>74</SubIndex>
|
||||
<BitLen>64</BitLen>
|
||||
<Name>Status Data 74</Name>
|
||||
<DataType>ULINT</DataType>
|
||||
</Entry>
|
||||
<Entry>
|
||||
<Index>#x6000</Index>
|
||||
<SubIndex>75</SubIndex>
|
||||
<BitLen>64</BitLen>
|
||||
<Name>Status Data 75</Name>
|
||||
<DataType>ULINT</DataType>
|
||||
</Entry>
|
||||
<Entry>
|
||||
<Index>#x6000</Index>
|
||||
<SubIndex>76</SubIndex>
|
||||
<BitLen>64</BitLen>
|
||||
<Name>Status Data 76</Name>
|
||||
<DataType>ULINT</DataType>
|
||||
</Entry>
|
||||
<Entry>
|
||||
<Index>#x6000</Index>
|
||||
<SubIndex>77</SubIndex>
|
||||
<BitLen>64</BitLen>
|
||||
<Name>Status Data 77</Name>
|
||||
<DataType>ULINT</DataType>
|
||||
</Entry>
|
||||
<Entry>
|
||||
<Index>#x6000</Index>
|
||||
<SubIndex>78</SubIndex>
|
||||
<BitLen>64</BitLen>
|
||||
<Name>Status Data 78</Name>
|
||||
<DataType>ULINT</DataType>
|
||||
</Entry>
|
||||
<Entry>
|
||||
<Index>#x6000</Index>
|
||||
<SubIndex>79</SubIndex>
|
||||
<BitLen>64</BitLen>
|
||||
<Name>Status Data 79</Name>
|
||||
<DataType>ULINT</DataType>
|
||||
</Entry>
|
||||
<Entry>
|
||||
<Index>#x6000</Index>
|
||||
<SubIndex>80</SubIndex>
|
||||
<BitLen>64</BitLen>
|
||||
<Name>Status Data 80</Name>
|
||||
<DataType>ULINT</DataType>
|
||||
</Entry>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</TxPdo>
|
||||
<Mailbox DataLinkLayer="true">
|
||||
<CoE SdoInfo="true" CompleteAccess="true" SegmentedSdo="true"/>
|
||||
|
||||
@@ -40,13 +40,15 @@
|
||||
* PDO 数据缓冲
|
||||
*
|
||||
* 1.5.56 扩到 DPRAM 硬上限:输出 48×64bit=384B,输入 80×64bit=640B(非对称)。
|
||||
* 1.6.1 输入瘦身 640→496(62×64bit):批量接收条目数据 64→32B + 诊断区前移,
|
||||
* 依据与推导见 comm/ethercat_pdo_size.h 的 1.6.1 注。
|
||||
* 长度的唯一真源是 comm/ethercat_pdo_size.h;本文件用 _Static_assert 与之绑定,
|
||||
* 改一处漏一处会编译失败。为何硬上限是 out+in≤1024B 见该头文件的推导。
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/** 输出/输入 PDO 的 64bit 条目数。 */
|
||||
#define PDO_OUT_ENTRIES 48u /* 48×8 = 384 B */
|
||||
#define PDO_IN_ENTRIES 80u /* 80×8 = 640 B */
|
||||
#define PDO_IN_ENTRIES 62u /* 62×8 = 496 B (1.6.1 瘦身,原 80×8=640) */
|
||||
|
||||
/** 输出数据对象 0x7000 (主站→从站, RxPDO) */
|
||||
typedef struct OBJ_STRUCT_PACKED_START {
|
||||
@@ -71,7 +73,7 @@ static TOBJ6000 s_inputObj = {PDO_IN_ENTRIES, {0}};
|
||||
_Static_assert(offsetof(TOBJ7000, u64Data) == 2, "TOBJ7000 未紧排:检查 OBJ_STRUCT_PACKED_START");
|
||||
_Static_assert(offsetof(TOBJ6000, u64Data) == 2, "TOBJ6000 未紧排:检查 OBJ_STRUCT_PACKED_START");
|
||||
_Static_assert(sizeof(TOBJ7000) == 2 + 8 * PDO_OUT_ENTRIES, "TOBJ7000 尺寸应为 2+384");
|
||||
_Static_assert(sizeof(TOBJ6000) == 2 + 8 * PDO_IN_ENTRIES, "TOBJ6000 尺寸应为 2+640");
|
||||
_Static_assert(sizeof(TOBJ6000) == 2 + 8 * PDO_IN_ENTRIES, "TOBJ6000 尺寸应为 2+496");
|
||||
|
||||
/* 与 C++ 侧桥接层的长度约定绑定:任一处改了尺寸而忘了另一处,这里直接编译失败,
|
||||
* 而不是等到运行期 SAFEOP 报 AL 0x001A/0x0011 再回头查。 */
|
||||
@@ -94,10 +96,19 @@ typedef struct OBJ_STRUCT_PACKED_START {
|
||||
UINT32 u32Sync1; /* sub2 */
|
||||
UINT32 u32EscIrq; /* sub3 */
|
||||
UINT32 u32UptimeS; /* sub4 */
|
||||
/* 1.6.0 剖分埋点(sub5..12,DWT 周期/计数累加,主站 1s 差分;定位完即移除) */
|
||||
UINT32 u32PdiCyc; /* sub5: PDI_Isr 全函数累计 */
|
||||
UINT32 u32OutCyc; /* sub6: PDO_OutputMapping(输出探针/全量读) */
|
||||
UINT32 u32FreeRunCyc; /* sub7: MainLoop free-run 块(SM 同步下恒 0) */
|
||||
UINT32 u32PdiCnt; /* sub8: PDI_Isr 触发次数 */
|
||||
UINT32 u32InCyc; /* sub9: PDO_InputMapping 全程(APPL+输入PDO写) */
|
||||
UINT32 u32InWriteCyc; /* sub10: 其中 HW_EscWriteIsr 输入PDO 过程数据写 */
|
||||
UINT32 u32AlCyc; /* sub11: PDI_Isr 内 AL 事件读×2+超限应答 */
|
||||
UINT32 u32AppCyc; /* sub12: ECAT_Application(桥 processOutput) */
|
||||
} OBJ_STRUCT_PACKED_END
|
||||
TOBJ2000;
|
||||
|
||||
static TOBJ2000 s_syncDiag = {4, 0, 0, 0, 0};
|
||||
static TOBJ2000 s_syncDiag = {12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
/* 同上:UINT32 首条目必须落在字节 2(未紧排时为 4)。 */
|
||||
_Static_assert(offsetof(TOBJ2000, u32Sync0) == 2, "TOBJ2000 未紧排:检查 OBJ_STRUCT_PACKED_START");
|
||||
@@ -107,6 +118,16 @@ extern UINT32 EcatDbg_GetSync0(void);
|
||||
extern UINT32 EcatDbg_GetSync1(void);
|
||||
extern UINT32 EcatDbg_GetEscIrq(void);
|
||||
extern UINT32 EcatDbg_GetUptimeSec(void);
|
||||
/* 1.6.0 剖分埋点:ecatappl.c 累加器 + ethercat_sync.cpp 的 DWT 读 */
|
||||
extern UINT32 EcatDbg_Dwt(void);
|
||||
extern volatile UINT32 g_dbg_pdiCyc;
|
||||
extern volatile UINT32 g_dbg_outCyc;
|
||||
extern volatile UINT32 g_dbg_freerunCyc;
|
||||
extern volatile UINT32 g_dbg_pdiCnt;
|
||||
extern volatile UINT32 g_dbg_inCyc;
|
||||
extern volatile UINT32 g_dbg_inWriteCyc;
|
||||
extern volatile UINT32 g_dbg_alCyc;
|
||||
extern volatile UINT32 g_dbg_appCyc;
|
||||
|
||||
/* 过程数据收发模块 (comm/ethercat_pdo.cpp 的 extern "C" shim, 1.5.54)。
|
||||
* 1.5.53 时这里直接调 EcatCan_* 转发桥;1.5.54 把"一个 EtherCAT 周期怎么收发"
|
||||
@@ -161,12 +182,13 @@ static TOBJ_RXPDO_MAPPING sRxPDOMap = {PDO_OUT_ENTRIES, {
|
||||
PDO_MAP_8(0x7000, 24), PDO_MAP_8(0x7000, 32), PDO_MAP_8(0x7000, 40)
|
||||
}};
|
||||
|
||||
/* 0x1A00: 映射 0x6000:01..80, 每个 64 bits */
|
||||
/* 0x1A00: 映射 0x6000:01..62, 每个 64 bits(1.6.1 瘦身 80→62:7×8 + 6) */
|
||||
static TOBJ_TXPDO_MAPPING sTxPDOMap = {PDO_IN_ENTRIES, {
|
||||
PDO_MAP_8(0x6000, 0), PDO_MAP_8(0x6000, 8), PDO_MAP_8(0x6000, 16),
|
||||
PDO_MAP_8(0x6000, 24), PDO_MAP_8(0x6000, 32), PDO_MAP_8(0x6000, 40),
|
||||
PDO_MAP_8(0x6000, 48), PDO_MAP_8(0x6000, 56), PDO_MAP_8(0x6000, 64),
|
||||
PDO_MAP_8(0x6000, 72)
|
||||
PDO_MAP_8(0x6000, 48),
|
||||
PDO_MAP_ENTRY(0x6000, 57), PDO_MAP_ENTRY(0x6000, 58), PDO_MAP_ENTRY(0x6000, 59),
|
||||
PDO_MAP_ENTRY(0x6000, 60), PDO_MAP_ENTRY(0x6000, 61), PDO_MAP_ENTRY(0x6000, 62)
|
||||
}};
|
||||
|
||||
_Static_assert(sizeof(sRxPDOMap.aEntries) / 4 == PDO_OUT_ENTRIES, "0x1600 条目数不符");
|
||||
@@ -215,12 +237,21 @@ OBJCONST TSDOINFOENTRYDESC OBJMEM asInputEntryDesc[] = {
|
||||
{DEFTYPE_UNSIGNED64, 0x40, ACCESS_READ | OBJACCESS_TXPDOMAPPING}
|
||||
};
|
||||
|
||||
/* SYNC 诊断 0x2000: REC, Sub0..Sub4 共 5 项, 纯只读不参与 PDO 映射。 */
|
||||
/* SYNC 诊断 0x2000: REC, Sub0..Sub12 共 13 项, 纯只读不参与 PDO 映射。
|
||||
* sub5..12 为 1.6.0 剖分埋点(DWT 周期/计数累加), 定位负载构成后移除。 */
|
||||
OBJCONST TSDOINFOENTRYDESC OBJMEM asSyncDiagEntryDesc[] = {
|
||||
{DEFTYPE_UNSIGNED8, 0x08, ACCESS_READ},
|
||||
{DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
|
||||
{DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
|
||||
{DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
|
||||
{DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
|
||||
{DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
|
||||
{DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
|
||||
{DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
|
||||
{DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
|
||||
{DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
|
||||
{DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
|
||||
{DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
|
||||
{DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ}
|
||||
};
|
||||
|
||||
@@ -265,8 +296,8 @@ TOBJECT OBJMEM ApplicationObjDicList[] = {
|
||||
{NULL, NULL, 0x6000, {DEFTYPE_UNSIGNED64, PDO_IN_ENTRIES | (OBJCODE_ARR << 8)},
|
||||
asInputEntryDesc, aName0x6000, &s_inputObj, NULL, NULL, 0x0000},
|
||||
|
||||
/* 0x2000: SYNC 诊断 (只读, 主站 SDO 轮询验证 DC 通路) */
|
||||
{NULL, NULL, 0x2000, {DEFTYPE_RECORD, 4 | (OBJCODE_REC << 8)},
|
||||
/* 0x2000: SYNC 诊断 (只读, 主站 SDO 轮询验证 DC 通路; sub5..8 为 1.6.0 剖分埋点) */
|
||||
{NULL, NULL, 0x2000, {DEFTYPE_RECORD, 12 | (OBJCODE_REC << 8)},
|
||||
asSyncDiagEntryDesc, aName0x2000, &s_syncDiag, NULL, NULL, 0x0000},
|
||||
|
||||
/* 终止条目 */
|
||||
@@ -280,7 +311,7 @@ TOBJECT OBJMEM * VARMEM ApplicationObjDic = ApplicationObjDicList;
|
||||
*---------------------------------------------------------------------------*/
|
||||
UINT16 APPL_GenerateMapping(UINT16 *pInputSize, UINT16 *pOutputSize)
|
||||
{
|
||||
*pInputSize = ECAT_PDO_IN_BYTES; /* 80×UINT64 = 640 bytes */
|
||||
*pInputSize = ECAT_PDO_IN_BYTES; /* 62×UINT64 = 496 bytes (1.6.1) */
|
||||
*pOutputSize = ECAT_PDO_OUT_BYTES; /* 48×UINT64 = 384 bytes */
|
||||
return 0;
|
||||
}
|
||||
@@ -340,6 +371,15 @@ void APPL_InputMapping(UINT16 *pInputData)
|
||||
s_syncDiag.u32Sync1 = EcatDbg_GetSync1();
|
||||
s_syncDiag.u32EscIrq = EcatDbg_GetEscIrq();
|
||||
s_syncDiag.u32UptimeS = EcatDbg_GetUptimeSec();
|
||||
/* 1.6.0 剖分埋点快照(sub5..12) */
|
||||
s_syncDiag.u32PdiCyc = g_dbg_pdiCyc;
|
||||
s_syncDiag.u32OutCyc = g_dbg_outCyc;
|
||||
s_syncDiag.u32FreeRunCyc = g_dbg_freerunCyc;
|
||||
s_syncDiag.u32PdiCnt = g_dbg_pdiCnt;
|
||||
s_syncDiag.u32InCyc = g_dbg_inCyc;
|
||||
s_syncDiag.u32InWriteCyc = g_dbg_inWriteCyc;
|
||||
s_syncDiag.u32AlCyc = g_dbg_alCyc;
|
||||
s_syncDiag.u32AppCyc = g_dbg_appCyc;
|
||||
|
||||
/* 1.5.54:先让 EthercatPdo 把本周期的输入数据写进 0x6000 的对象存储,
|
||||
* 再交给 ESC。经由对象存储中转(而非直接写 pInputData)是为了让主站
|
||||
|
||||
@@ -79,7 +79,10 @@ MBX_TX_SIZE = 256
|
||||
PD_OUT_OFFSET = 0x1400 # SM2: RxPDO (Master -> Slave outputs)
|
||||
PD_OUT_SIZE = 384 # 48×64bit
|
||||
PD_IN_OFFSET = 0x1880 # SM3: TxPDO (Slave -> Master inputs)
|
||||
PD_IN_SIZE = 640 # 80×64bit
|
||||
PD_IN_SIZE = 496 # 62×64bit (1.6.1 瘦身,原 80×64bit=640)
|
||||
# 1.6.1 瘦身 640→496:批量接收条目数据 64→32B + 段5诊断区前移到 484。
|
||||
# SM3 实占 3×496=1488B (0x1880-0x1E4F),DPRAM 留 432B 余量;
|
||||
# 依据见 comm/ethercat_pdo_size.h 的 1.6.1 注。改后必须重烧 EEPROM 并断电冷启动。
|
||||
|
||||
# 3-buffer 占用与 DPRAM 上限自检:改尺寸/偏移时立刻在生成阶段拦住,
|
||||
# 而不是等烧进 EEPROM、冷启动后再看 AL 错误码。
|
||||
|
||||
Reference in New Issue
Block a user