#在一块GD32F407VET6+LAN9252的板子上移植了ECAT的io和CIA402协议代码,代码直接用其他人生成的,只改了MCU的驱动
#结果能正常跑起来的是IO代码、CIA402协议代码没法跑起来,TWINCAT只能进入到prOP状态,并且报各个对象字典无法读取的错误
#经排查,是CIA402appl.c里进行PDO映射的函数UINT16 APPL_GenerateMapping(UINT16* pInputSize,UINT16* pOutputSize)出了问题
仿真发现进协议的时候,这个函数的映射失败,CIA402从站结构体的定义没有生效,为此一直很郁闷;请问我该怎么做才能解决这个问题?
在一块GD32F407VET6+LAN9252的板子上移植了ECAT的io和CIA402协议代码,代码直接用其他人生成的,只改了MCU的驱动
#结果能正常跑起来的是IO代码、CIA402协议代码没法跑起来,TWINCAT只能进入到prOP状态,并且报各个对象字典无法读取的错误
经排查,是CIA402appl.c里进行PDO映射的函数UINT16 APPL_GenerateMapping(UINT16* pInputSize,UINT16* pOutputSize)出了问题
仿真发现进协议的时候,这个函数的映射失败,CIA402从站结构体的定义没有生效,为此一直很郁闷;请问我该怎么做才能解决这个问题?
根据提供的信息,这个问题可能是由于以下原因引起的:
没有正确地初始化LAN9252的从站结构体。
没有将LAN9252的从站结构体与GD32F407VET6+LAN9252的主站结构体进行映射。
没有将GD32F407VET6+LAN9252的主站结构体与UINT16 APPL_GenerateMapping(UINT16* pInputSize,UINT16* pOutputSize)函数中的两个参数进行映射。
为了解决这个问题,可以尝试以下步骤:
根据LAN9252的使用手册,正确地初始化从站结构体。
在GD32F407VET6+LAN9252的主站结构体中,将LAN9252的从站结构体与相应的从站结构体进行映射。
对于UINT16 APPL_GenerateMapping(UINT16* pInputSize,UINT16* pOutputSize)函数中的两个参数,分别进行映射。例如,可以使用以下代码将UINT16类型的参数映射为LAN9252的从站结构体类型:
typedef struct {
UINT16 x;
UINT16 y;
} LAN9252_ST;
LAN9252_ST* lan9252_input_mapping;
LAN9252_ST* lan9252_output_mapping;
void Gd32F407VET6_LAN9252_Init(void) {
lan9252_input_mapping = (LAN9252_ST*) malloc(sizeof(LAN9252_ST));
lan9252_output_mapping = (LAN9252_ST*) malloc(sizeof(LAN9252_ST));
if (lan9252_input_mapping == NULL || lan9252_output_mapping == NULL) {
// Handle error
}
/* Add code to initialize the LAN9252 input and output mapping structures */
}
void Gd32F407VET6_LAN9252_Mapping(LAN9252_ST* pInput, LAN9252_ST* pOutput) {
/* Add code to map the input and output structures */
}
在UINT16 APPL_GenerateMapping(UINT16* pInputSize,UINT16* pOutputSize)函数中,将LAN9252的从站结构体类型和GD32F407VET6的主站结构体类型作为参数传递。例如,可以使用以下代码将UINT16类型的参数映射为LAN9252的从站结构体类型:
void APPL_GenerateMapping(UINT16* pInputSize,UINT16* pOutputSize) {
/* Add code to generate the mapping between the input and output structures */
}
希望以上步骤能够解决这个问题,并且使得代码能够正常运行。
来自GPT的回答:
在移植ECAT的IO和CIA402协议代码时遇到问题,其中APPL_GenerateMapping函数无法成功进行PDO映射,导致CIA402从站结构体定义无效的情况。以下是一些可能的解决方案和建议:
检查代码修改:确保在进行MCU驱动修改时没有引入错误,尤其是涉及到CIA402协议代码和结构体定义的地方。检查数据类型、指针传递等方面是否正确。
查看错误报告:详细查看TWINCAT报告的错误信息,尤其是关于对象字典无法读取的错误。这些错误信息可能会提供关键线索,指示哪些部分出现了问题。
检查从站配置:确保CIA402从站的配置正确,并且与主站(TWINCAT)的配置相匹配。检查对象字典的定义和映射是否正确。
调试APPL_GenerateMapping函数:通过调试APPL_GenerateMapping函数,检查其中的映射过程和相关的变量。确保输入和输出大小参数的正确性,并确保函数内部的逻辑正确执行。
参考示例代码和文档:查看官方文档和示例代码,了解APPL_GenerateMapping函数的正确使用方法和示例。比较您的代码和示例代码之间的差异,确认是否有遗漏或错误的地方。
咨询开发者社区:将您的问题和代码细节提交给相关的开发者社区或论坛,以获得更多的帮助和反馈。其他有经验的开发者可能会提供更具体的解决方案或指导。
请注意,由于无法直接查看和调试您的具体代码,以上建议仅供参考。对于特定问题的解决,可能需要更详细的代码分析和调试。建议您根据问题的具体表现和错误信息,结合相关文档和开发者社区的帮助,逐步排查和解决问题。
可能在CIA402从站结构体的定义上。
确认正确地定义了CIA402从站结构体,并且包含了所有必要的成员变量和函数指针。
检查是否正确地初始化了CIA402从站结构体。例如,你需要使用ECAT_InitSlave()
函数来初始化从站,并将CIA402从站结构体作为参数传递给该函数。
ECAT_Main()状态机处理
/
/**
\brief 这个函数被周期性得调用.
*////
void ECAT_Main(void)
{
UINT16 ALEventReg;
UINT16 EscAlControl = 0x0000;
#if MAILBOX_SUPPORTED
UINT8 sm1Activate = SM_SETTING_ENABLE_VALUE;
#endif
#if MAILBOX_SUPPORTED
/* 检查是否有服务存储在邮箱里面 */
MBX_Main();
if ( bMbxRunning )
{
/* 从站至少工作在PREOP状态,邮箱才可以运行 */
/* 获得SM1(寄存器0x80E)的Activate-字节来检查是否重复请求被接收 */
HW_EscReadByte(sm1Activate,(ESC_SYNCMAN_ACTIVE_OFFSET + SIZEOF_SM_REGISTER));
}
#endif //#if MAILBOX_SUPPORTED
/* 从ESC里读取AL 事件-寄存器 */
ALEventReg = HW_GetALEventRegister();
ALEventReg = SWAPWORD(ALEventReg);
#if ESC_EEPROM_EMULATION
if ((ALEventReg & EEPROM_CMD_PENDING))
{
EEPROM_CommandHandler();
}
#endif
if ((ALEventReg & AL_CONTROL_EVENT) && !bEcatWaitForAlControlRes)
{
/* AL的控制事件寄存器被设置,获得从主站发过来的AL控制寄存器来响应这个事件(对应的AL事件寄存器对应的位将会被重置) */
HW_EscReadByte( EscAlControl, ESC_AL_CONTROL_OFFSET);
/* 重置AL控制事件和SM转变事件(因为SM设置将会被检查在AL_ControlInd里面 )*/
ALEventReg &= ~((AL_CONTROL_EVENT) | (SM_CHANGE_EVENT));
AL_ControlInd((UINT8)EscAlControl, 0); /* 在AL_ControlInd函数里面状态转换将被检查和操作 */
/* SM-Change-Event 也被操作 */
}
if ( (ALEventReg & SM_CHANGE_EVENT) && !bEcatWaitForAlControlRes && (nAlStatus & STATE_CHANGE) == 0 && (nAlStatus & ~STATE_CHANGE) != STATE_INIT )
{
/* SM的转换被设置(寄存器0x220里面的第4位),Sync Manager通道的当6位(使能,低字节寄存器的0x806,0x80E,0x816……)被写 */
ALEventReg &= ~(SM_CHANGE_EVENT);
/* 带实际状态的AL_ControlInd函数被调用,所以,正确的SM设置将被检查 */
AL_ControlInd(nAlStatus & STATE_MASK, 0);
}
if(bEcatWaitForAlControlRes)
{
AL_ControlRes();
}
#if MAILBOX_SUPPORTED
/*<span style="white-space:pre"> </span>邮箱事件的处理顺序被改变防止竞争条件错误.
SM1的激活字符(寄存器0x80E)被读,在读AL 事件寄存器之前.
1. 处理邮箱读事件
2. 处理重复计划请求
3. 处理邮箱写事件Handle Mailbox write event
*/
if ( bMbxRunning )
{
/*SM转变事件(0x220:4)可以被认可通过读SM1控制寄存器没有给通知给本地应用程序=>检查是否SM1仍然为使能SnycManger change event (0x220:4) could be acknowledged by reading the SM1 control register without notification to the local application
=> check if the SyncManger 1 is still enabled*/
if(!(sm1Activate & SM_SETTING_ENABLE_VALUE))
AL_ControlInd(nAlStatus & STATE_MASK, 0);
if ( ALEventReg & (MAILBOX_READ_EVENT) )
{
/* SM 1 (邮箱读事件) 事件被设置,当邮箱由主站读的时候,来响应事件,邮箱里的第一个字节被写,通过写邮箱的第一个字节,邮箱也被锁 */
u8dummy = 0;
HW_EscWriteByte(u8dummy,u16EscAddrSendMbx);
/* 邮箱读事件在变量,ALEventReg应该被重置,在调用MBX_MailboxReadInd函数之前,一个新的邮箱数据包(如果可用)应该被存储在发送邮箱里面。 */
ALEventReg &= ~(MAILBOX_READ_EVENT);
MBX_MailboxReadInd();
}
DISABLE_MBX_INT;
/* bMbxRepeatToggle 保持上个状态的Repeat位(Bit1) */
if ( ( (sm1Activate & SM_SETTING_REPAET_REQ_MASK) && !bMbxRepeatToggle )
||( !(sm1Activate & SM_SETTING_REPAET_REQ_MASK) && bMbxRepeatToggle ))
{
/* 重复位(位1)被触发,这里有个一重复请求,在MBX_MailboxRepeatReq函数里,正确的响应将会再次放入发送邮箱 */
MBX_MailboxRepeatReq();
/* 响应重复请求在发送邮箱被更新,通过写入重复位RepeatAck Bit(第一位)在SM1的PDI控制字节(寄存器0x80F)acknowledge the repeat request after the send mailbox was updated by writing the Repeat Bit
in the Repeat Ack Bit (Bit 1) of the PDI Ctrl-Byte of SM 1 (Register 0x80F) */
sm1Activate &= SM_SETTING_REPEAT_ACK;
HW_EscWriteByte(sm1Activate,(ESC_SM_PDICONTROL_OFFSET + SIZEOF_SM_REGISTER));
}
ENABLE_MBX_INT;
/* 重新加载ALEvent,因为它可以被改变由于SM的去使能,使能以至于重复请求 */
ALEventReg = HW_GetALEventRegister();
ALEventReg = SWAPWORD(ALEventReg);
if ( ALEventReg & (MAILBOX_WRITE_EVENT) )
{
/* SM 0 (邮箱写操作) 事件被设置,当邮箱由主站写来响应事件,邮箱的第一个字节可以被读,它将会在MBX_CheckAndCopyMailbox函数里面被操作event is set, when the mailbox was written from the master,
to acknowledge the event the first byte of the mailbox has to be read,
which will be done in MBX_CheckAndCopyMailbox */
/* 邮箱写事件在变量ALEventReg应该被重置,在调用MBX_CheckAndCopyMailbox之前,在哪里接收邮箱的数据包将会被处理 */
ALEventReg &= ~(MAILBOX_WRITE_EVENT);
MBX_CheckAndCopyMailbox();
}
}
#endif
}
由于你是使用的别人的代码,所以你要确保你们的环境是一样的,你现在是修改了MCU的驱动,那你要对比下之前的代码使用的是什么驱动,和你现在的驱动在调用方式上是否有区别。因此,可能需要根据你目前的驱动对相应的代码就行修改。具体怎么修改,还是要先查看下对应芯片和驱动的使用手册。
检查PDO映射生成逻辑,确认与TWINCAT配置一致,并且打印并检查内部PDO映射结果,找到问题根源,再检查最大支持PDO数量,避免超出硬件最大数量等,你都排查下