This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
运行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); } }
我需要与您确认一下:
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. 在发送数据后,检查发送是否成功,并处理发送数据的结果
你在主站状态为OP时发送数据,但你的代码中并没有检查发送是否成功,也没有处理发送数据的结果。这可能会导致数据发送失败,从而导致主站接收到的数据不连续。你可以在发送数据后添加一些错误处理代码,以确保数据成功发送到了EtherCAT网络中。
你好,下面是我回复您需要我确认的点
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 the watchdog 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,因为那个例程他只是接收数据,他不发送,所以就是自己先参考文档测试发送,我后面再查下看看怎么实现判断发送结果
你好,我找到哪个地方被清零了,对应的函数是一个被封装了的函数,看不到源码,我看最开始我修改的内存的值是100,主站正常接收到数据,运行一次那个函数,内存里面数据还是100,但是主站收到的数据就变0了,这时候我手动修改内存的数据,主站接收的数据没变化,第二次运行那个函数,内存数据依然不变,主站接收任然是0,第三次运行那个函数,他会把我那个内存的数据清零,这时候我手动修改内存的数据,修改成多少主站就接收到是多少,第四次运行那个函数,就重复上面的情况,内存数据不变,主站接收变0,那个函数还不能屏蔽,他是处理从站堆栈的,屏蔽了之后都不工作了,主站扫不到
3、现在还没有找到具体的检测发送结果的API,因为那个例程他只是接收数据,他不发送,所以就是自己先参考文档测试发送,我后面再查下看看怎么实现判断发送结果
了解,我有一些个人的方法推荐给您
1. 超时检测:在发送数据后,等待一段时间,如果在预期的时间内没有收到来自从站的响应,则可以认为发送失败
2. 重试机制:如果发送失败,可以尝试重新发送数据。你可以设置一个重试次数,如果发送失败,则重复发送,直到达到最大重试次数为止。
3. 添加校验机制:在发送数据时,可以在数据中添加一些校验位或校验和,以便接收端可以验证数据的完整性。如果接收端发现数据不完整或损坏,则可以向发送端发送一个错误消息。