Part Number:AM6442
运行ethercat_slave_simple_demo_am64x-evm_r5fss0-0_freertos_ti-arm-clang例程,参考ti的那个倍福的例程,添加发送数据的程序,但是电脑作为主站接收到的数据却是断断续续而且有规律的,下面是接收到的数据图,从站一直发送发送100,间隔2s,2s这个时间段有数据,然后4s这个时间段就为0,之前测试过发送一个变量,变量一直累加,打印出变量的数据,变量会一直递增,但是主站那里看的时候数据也是一样大约两个数变0,比如主站是1-0-0-3-0-0-5-0-0-7这样子收到数据,现在不清楚是不是自己配置的 PRUICSS_Handle 有问题
下面是PRU实例对象的初始化
void tiesc_socEvmInit() {const PRUICSS_HwAttrs *pruicssHwAttrs;uint32_t inEventLatch0, inEventLatch1, outEventLatch0, outEventLatch1;pruIcss1Handle = PRUICSS_open(CONFIG_PRU_ICSS1);pruicssHwAttrs = PRUICSS_getAttrs(CONFIG_PRU_ICSS1);/* Selecting MII-RT mode in GPCFG mux */ //PRUICSS_setGpMuxSelect(pruIcss1Handle, PRUICSS_PRU0, PRUICSS_GP_MUX_SEL_MODE_MII);PRUICSS_setGpMuxSelect(pruIcss1Handle, PRUICSS_PRU1, PRUICSS_GP_MUX_SEL_MODE_MII); //PRUICSS_setGpiMode(pruIcss1Handle, PRUICSS_PRU0, PRUICSS_GPI_MODE_MII_RT);PRUICSS_setGpiMode(pruIcss1Handle, PRUICSS_PRU1, PRUICSS_GPI_MODE_MII_RT); //PRUICSS_setIcssCfgMiiMode(pruIcss1Handle, 0, PRUICSS_ICSS_CFG_MII_MODE_MII);PRUICSS_setIcssCfgMiiMode(pruIcss1Handle, 1, PRUICSS_ICSS_CFG_MII_MODE_MII); //PRUICSS_setIcssCfgTxFifo(pruIcss1Handle, PRUICSS_TX_L1_FIFO, 1);PRUICSS_setIcssCfgTxFifo(pruIcss1Handle, PRUICSS_TX_L2_FIFO, 0);/* Making the clock for ICSSG core and IEP same */PRUICSS_setIepClkSrc(pruIcss1Handle, 1U);/* Disable PRUs. This is to ensure PRUs are not running when application is not initialized */ //PRUICSS_disableCore(pruIcss1Handle, PRUICSS_PRU0);PRUICSS_disableCore(pruIcss1Handle, PRUICSS_PRU1);/* TimeSync Router configuration for latch pins */if(pruicssHwAttrs->instance == 0){inEventLatch0 = CSLR_TIMESYNC_EVENT_INTROUTER0_IN_PINFUNCTION_PRG0_IEP0_EDC_LATCH_IN0IN_PRG0_IEP0_EDC_LATCH_IN0_0;inEventLatch1 = CSLR_TIMESYNC_EVENT_INTROUTER0_IN_PINFUNCTION_PRG0_IEP0_EDC_LATCH_IN1IN_PRG0_IEP0_EDC_LATCH_IN1_0;outEventLatch0 = TIMESYNC_EVENT_INTROUTER0_MUXCNTL_8;outEventLatch1 = TIMESYNC_EVENT_INTROUTER0_MUXCNTL_9;}else{inEventLatch0 = CSLR_TIMESYNC_EVENT_INTROUTER0_IN_PINFUNCTION_PRG1_IEP0_EDC_LATCH_IN0IN_PRG1_IEP0_EDC_LATCH_IN0_0;inEventLatch1 = CSLR_TIMESYNC_EVENT_INTROUTER0_IN_PINFUNCTION_PRG1_IEP0_EDC_LATCH_IN1IN_PRG1_IEP0_EDC_LATCH_IN1_0;outEventLatch0 = TIMESYNC_EVENT_INTROUTER0_MUXCNTL_12;outEventLatch1 = TIMESYNC_EVENT_INTROUTER0_MUXCNTL_13;}HW_WR_REG32((CSL_TIMESYNC_EVENT_INTROUTER0_CFG_BASE + outEventLatch0), (inEventLatch0 | 0x10000));HW_WR_REG32((CSL_TIMESYNC_EVENT_INTROUTER0_CFG_BASE + outEventLatch1), (inEventLatch1 | 0x10000));PRUICSS_enableCore(pruIcss1Handle, PRUICSS_PRU1); }
下面是连接上主站,状态为OP的时候,间隔2s发送数据100
for(;;) {EC_API_SLV_mainLoopCyclic();if (EC_API_SLV_eESM_op == EC_API_SLV_getState()){bsp_write_byte(pruIcss1Handle,100,0x1e00);OSAL_SCHED_sleep(2000);}else{/* for carve up give some air */OSAL_SCHED_sleep(100);} }
Gary Lu:
我需要与您确认一下:
1. 您设置了PRU1为MII-RT模式,但你的注释中提到发送数据的代码是在for循环中调用的。这里应该要确认你的发送数据代码是在哪个PRU上运行的。如果是在PRU1上运行,那么初始化是正确的。
2. 确保PRU在发送数据之前已经正确初始化,包括加载了正确的程序。在你的代码中,你禁用了PRU,然后又启用了PRU1。但应确保你的PRU程序已经正确加载到了PRU内存中,并且PRU处于正确的状态。
在你的for循环中,你使用了`bsp_write_byte()`函数来向EtherCAT发送数据。但我没有看到`bsp_write_byte()`定义,因此我假设这是一个你自己实现的函数,用于向EtherCAT发送数据。你需要确保这个函数能够正确地将数据发送到EtherCAT网络中。
你需要确认以下几点:
1. PRUICSS的初始化是否正确 并且PRU程序已经正确加载并运行2. 发送数据的函数是否能够正确地将数据发送到EtherCAT网络中3. 在发送数据后,检查发送是否成功,并处理发送数据的结果
,
Gary Lu:
你在主站状态为OP时发送数据,但你的代码中并没有检查发送是否成功,也没有处理发送数据的结果。这可能会导致数据发送失败,从而导致主站接收到的数据不连续。你可以在发送数据后添加一些错误处理代码,以确保数据成功发送到了EtherCAT网络中。
,
yy z:
你好,下面是我回复您需要我确认的点
1、配置的是在PRU1上运行的,这一部分初始化的代码是我拷贝ethercat_slave_beckhoff_ssc_demo_am64x-evm_r5fss0-0_freertos_ti-arm-clang例程里面的,同一个开发板,电路上用的也是pru1,但是他一开始把pru0也给初始化了,但是后面没用到,我就屏蔽了那一部分,他后面有部分程序是像pru1内存写入数据,但是他例程的源程序是用了TX_PRU0写入,导致的我调用了就程序卡住,后面我发现了改成TX_PRU1,程序正常运行,但是也是依然会断断续续,而且后面的初始化中还会再写入一次数据到pru1内存中,前后两次的数据不一样,用的是PRU1和PRU0两个内存,还有就是我屏蔽了bsp_esc_reg_perm_init,不屏蔽也跑不起来
void tiesc_socEvmInit() {const PRUICSS_HwAttrs *pruicssHwAttrs;uint32_t inEventLatch0, inEventLatch1, outEventLatch0, outEventLatch1;pruIcss1Handle = PRUICSS_open(CONFIG_PRU_ICSS1);pruicssHwAttrs = PRUICSS_getAttrs(CONFIG_PRU_ICSS1);/* Selecting MII-RT mode in GPCFG mux */PRUICSS_setGpMuxSelect(pruIcss1Handle, PRUICSS_PRU1, PRUICSS_GP_MUX_SEL_MODE_MII);PRUICSS_setGpiMode(pruIcss1Handle, PRUICSS_PRU1, PRUICSS_GPI_MODE_MII_RT);PRUICSS_setIcssCfgMiiMode(pruIcss1Handle, 1, PRUICSS_ICSS_CFG_MII_MODE_MII);PRUICSS_setIcssCfgTxFifo(pruIcss1Handle, PRUICSS_TX_L2_FIFO, 0);/* Making the clock for ICSSG core and IEP same */PRUICSS_setIepClkSrc(pruIcss1Handle, 1U);/* Disable PRUs. This is to ensure PRUs are not running when application is not initialized */PRUICSS_disableCore(pruIcss1Handle, PRUICSS_PRU1);/* TimeSync Router configuration for latch pins */if(pruicssHwAttrs->instance == 0){inEventLatch0 = CSLR_TIMESYNC_EVENT_INTROUTER0_IN_PINFUNCTION_PRG0_IEP0_EDC_LATCH_IN0IN_PRG0_IEP0_EDC_LATCH_IN0_0;inEventLatch1 = CSLR_TIMESYNC_EVENT_INTROUTER0_IN_PINFUNCTION_PRG0_IEP0_EDC_LATCH_IN1IN_PRG0_IEP0_EDC_LATCH_IN1_0;outEventLatch0 = TIMESYNC_EVENT_INTROUTER0_MUXCNTL_8;outEventLatch1 = TIMESYNC_EVENT_INTROUTER0_MUXCNTL_9;}else{inEventLatch0 = CSLR_TIMESYNC_EVENT_INTROUTER0_IN_PINFUNCTION_PRG1_IEP0_EDC_LATCH_IN0IN_PRG1_IEP0_EDC_LATCH_IN0_0;inEventLatch1 = CSLR_TIMESYNC_EVENT_INTROUTER0_IN_PINFUNCTION_PRG1_IEP0_EDC_LATCH_IN1IN_PRG1_IEP0_EDC_LATCH_IN1_0;outEventLatch0 = TIMESYNC_EVENT_INTROUTER0_MUXCNTL_12;outEventLatch1 = TIMESYNC_EVENT_INTROUTER0_MUXCNTL_13;}HW_WR_REG32((CSL_TIMESYNC_EVENT_INTROUTER0_CFG_BASE + outEventLatch0), (inEventLatch0 | 0x10000));HW_WR_REG32((CSL_TIMESYNC_EVENT_INTROUTER0_CFG_BASE + outEventLatch1), (inEventLatch1 | 0x10000));//PRUICSS_enableCore(pruIcss1Handle, PRUICSS_PRU1);//第二部分的初始化int32_t status;/* ----------------------------------------------------------------- *//* Load the MDIO firmware binary on PRU Core;*//* ----------------------------------------------------------------- *//* Reset Core */status = PRUICSS_resetCore(pruIcss1Handle, PRUICSS_PRUx);DebugP_assert(SystemP_SUCCESS == status);/* Disabe Core */status = PRUICSS_disableCore(pruIcss1Handle, PRUICSS_PRUx);DebugP_assert(SystemP_SUCCESS == status);//PRUICSS_IRAM_TX_PRU(0)---> PRUICSS_IRAM_TX_PRU(1)/* Load firmware. Set buffer = write to PRU memory */status = PRUICSS_writeMemory(pruIcss1Handle, PRUICSS_IRAM_TX_PRU(1), 0,(uint32_t *) PRUFirmware, sizeof(PRUFirmware));DebugP_assert(status != 0);/* Pass value to R10 of TX_PRU core for MDIO FW WA Configuration */CSL_REG32_WR(CSL_PRU_ICSSG1_DRAM0_SLV_RAM_BASE + CSL_ICSS_G_PR1_PDSP_TX0_IRAM_DEBUG_REGS_BASE + PRU_REG_10, MDIO_MANUAL_MODE_FW_CONFIG_VALUE);/* Pass value to R12 of TX_PRU core for emulated MDIO Base Address */CSL_REG32_WR(CSL_PRU_ICSSG1_DRAM0_SLV_RAM_BASE + CSL_ICSS_G_PR1_PDSP_TX0_IRAM_DEBUG_REGS_BASE + PRU_REG_12, MDIO_MANUAL_MODE_BASE_ADDRESS);/* Run firmware */status = PRUICSS_enableCore(pruIcss1Handle, PRUICSS_PRUx);DebugP_assert(SystemP_SUCCESS == status);//第三部分的初始化uint16_t u16PdiCtrl;status = SystemP_FAILURE;bsp_params bspInitParams;/* the memory interface to the ESC, the ESC-interrupt and the ECAT-timer for thewatchdog monitoring should be initialized here microcontroller specific */tiesc_socParamsInit(&bspInitParams);//bsp_init里面屏蔽了bsp_esc_reg_perm_init(pruIcssHandle),查了文档这个是默认不开启的,status = bsp_init(&bspInitParams);DebugP_assert(status == SystemP_SUCCESS);/* we have to wait here, until the ESC is started */do{HW_EscReadWord(u16PdiCtrl, ESC_ADDR_PDI_CONTROL);u16PdiCtrl = SWAPWORD(u16PdiCtrl) & 0xFF;}while((u16PdiCtrl != ESC_PDI_INTERFACE_ON_CHIP_BUS)&& (u16PdiCtrl !=ESC_PDI_INTERFACE_SPI_SLAVE));//Looking for onchip bus or SPI Slave}2、发送数据的函数也是一样从那个例程移植过来,我看函数内容很少,下面是函数的实现源码,至于能不能正确发送到Ethercat网络中,因为可以间断的收到数据,我感觉应该问题不大,并且官网也可以查找到对应那个api的说明
/** \brief Data RAM2 (shared) */ #define PRUICSS_SHARED_RAM(0x10000U)#define ASSERT_DMB() __asm__ __volatile__ ("dmb" "\n\t": : : "memory")void bsp_write_byte(PRUICSS_Handle pruIcssHandle, uint8_t val, uint16_t address) {uint8_t *pEsc = (uint8_t *)(((PRUICSS_HwAttrs *)(pruIcssHandle->hwAttrs))->baseAddr + PRUICSS_SHARED_RAM);pEsc[address] = val;ASSERT_DMB(); }3、现在还没有找到具体的检测发送结果的API,因为那个例程他只是接收数据,他不发送,所以就是自己先参考文档测试发送,我后面再查下看看怎么实现判断发送结果
,
yy z:
你好,我找到哪个地方被清零了,对应的函数是一个被封装了的函数,看不到源码,我看最开始我修改的内存的值是100,主站正常接收到数据,运行一次那个函数,内存里面数据还是100,但是主站收到的数据就变0了,这时候我手动修改内存的数据,主站接收的数据没变化,第二次运行那个函数,内存数据依然不变,主站接收任然是0,第三次运行那个函数,他会把我那个内存的数据清零,这时候我手动修改内存的数据,修改成多少主站就接收到是多少,第四次运行那个函数,就重复上面的情况,内存数据不变,主站接收变0,那个函数还不能屏蔽,他是处理从站堆栈的,屏蔽了之后都不工作了,主站扫不到
,
Gary Lu:
yy z 说:3、现在还没有找到具体的检测发送结果的API,因为那个例程他只是接收数据,他不发送,所以就是自己先参考文档测试发送,我后面再查下看看怎么实现判断发送结果
了解,我有一些个人的方法推荐给您
1. 超时检测:在发送数据后,等待一段时间,如果在预期的时间内没有收到来自从站的响应,则可以认为发送失败
2. 重试机制:如果发送失败,可以尝试重新发送数据。你可以设置一个重试次数,如果发送失败,则重复发送,直到达到最大重试次数为止。
3. 添加校验机制:在发送数据时,可以在数据中添加一些校验位或校验和,以便接收端可以验证数据的完整性。如果接收端发现数据不完整或损坏,则可以向发送端发送一个错误消息。
,
Gary Lu:
可能还是与EtherCAT通信相关
,
yy z:
好的,刚刚才把twincat环境重新搭了一遍,之前老版本没法写C++程序,我后面试试,那个被封装了的函数没法修改,那实在不行只能在这方面处理了
,
Gary Lu:
好的~