http://blog.csdn.net/huangxianxinalice/article/details/9997981
Ethercat 程序与完整的EtherCAT 应用程序存在着区别。
- unsigned short Ecat_Open(void)
- {
- UINT16 result = 0;
- //开始函数应该被调用一次
- if(HardwareOpened != 0)
- return 1;
- u32Input = 0;
- u32Output = 0;
- pApplication = NULL;
- result = HW_Init();
- if(result == 0)
- { MainInit();
- HardwareOpened = 1;
- }
- return result;
- }
- /
- /**
- <span style="white-space:pre"> </span>\return 0 如果初始化成功的话,则返回0
- <span style="white-space:pre"> </span>\brief 文件:Tieschw.c里面
- \brief 这个函数初始化EtherCAT的从站接口.
- *////
- Uint8 HW_Init(void)
- {
- Uint8 i;
- Uint16 u16PdiCtrl;
- /* ESC的内存接口,ESC的中断和给看门狗检测的ECAT定时器应该在这里被初始化微控制器的特殊区域 */
- bsp_init();
- /* 我们在这里等待,直到ESC完全启动 */
- do {
- HW_EscReadWord(u16PdiCtrl, ESC_ADDR_PDI_CONTROL);
- u16PdiCtrl = SWAPWORD(u16PdiCtrl) & 0xFF;
- } while (u16PdiCtrl != 0x80); //寻找线上总线
- //printf ("Detected ESC Onchip Bus interface\n");
- /* 初始化AL_Event Mask 寄存器 */
- /* AL Event-Mask 寄存器是被初始化为0,因此没有ESC中断产生,AL Event-Mask寄存器将被适应在函数StartInputHandler在ecatslv.c这个文件里面。当状态转换从PREOP到SAFEOP状态 */
- nAlEventMask = 0;
- HW_ResetALEventMask(0);
- bsp_start_esc_isr();
- /* 禁止所有的SM通道 */
- for (i = 0; i < MAX_SYNC_MAN; i++)
- HW_DisableSyncManChannel(i);
- return 0;
- }
- void bsp_init(void)
- {
- Semaphore_Params semParams;
- #ifndef USE_ECAT_TIMER
- Types_FreqHz frg;
- #endif
- t_mdio_params mdioParamsInit;
- // 初始化定时器数据
- current_low = current_high = 0;
- pd_read_addr_err = pd_write_addr_err = 0;
- pdi_read_fail_cnt = pdi_write_fail_cnt = 0;
- prev_low = prev_high = 0;
- tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;
- #ifndef USE_ECAT_TIMER
- BIOS_getCpuFreq(&frg);
- ecat_timer_inc_p_ms = (frg.lo/1000);
- #endif
- pEsc = (Uint8*) PRUSS_SHAREDRAM_BASE; //初始化参数数据
- pHost2PruIntfc = (volatile t_host_interface *) DATARAM0_PHYS_BASE;
- pRegPerm = (volatile t_register_properties *) DATARAM1_PHYS_BASE;
- pIep = (volatile void *) PRUSS_IEP_BASE;
- pMdio =(volatile void *)PRUSS_MDIO_BASE;
- #ifdef ENABLE_PRUSS_HW_FIREWALL
- PRUSSDRVFireWallInit();
- #endif
- bsp_hwspinlock_init();
- if(get_app_reload_flag() != 0xAA)
- {
- ENABLE_PRUSS_ACCESS_FROM_HOST
- prussdrv_pruintc_init(&pruss_intc_initdata);
- /* 初始化ESC DPRAM指针 微控制器的特殊区域指向ESC物理内存的开始部分
- 结构体MAKE_PTR_TO_ESC应该被定义在tieschw.h里面 */
- memset ((void*)sm_properties, 0, sizeof(sm_properties));
- memset (pEsc, 0, 12*1024); //初始化ICSS的共享内存
- memset ((void*)pHost2PruIntfc, 0, 8*1024); //初始化PRU0的数据内存
- memset ((void*)pRegPerm, 0, 1024); //初始化PRU1的数据内存
- memset ((void*)&pRegPerm->reg_properties, 3, 4*1024);//初始化PRU1的数据内存
- bsp_pruss_cmd_intfc_write_word(0xFF, &pHost2PruIntfc->cmdhigh);
- bsp_pruss_cmd_intfc_write_word(0xFF, &pHost2PruIntfc->cmdlow);
- bsp_write_word(TIESC_PORT0_TX_DELAY, ESC_ADDR_TI_PORT0_TX_START_DELAY);
- bsp_write_word(TIESC_PORT1_TX_DELAY, ESC_ADDR_TI_PORT1_TX_START_DELAY);
- mdioParamsInit.clkdiv = TIESC_MDIO_CLKDIV;
- mdioParamsInit.addr0 = TIESC_MDIO_PHY0_ADDR;
- mdioParamsInit.addr1 = TIESC_MDIO_PHY1_ADDR;
- mdioParamsInit.enhancedlink_enable = TIESC_MDIO_RX_LINK_ENABLE;
- if(TIESC_MDIO_RX_LINK_ENABLE == mdioParamsInit.enhancedlink_enable)
- {
- //增强链接检测使能
- mdioParamsInit.link0pol = TIESC_LINK_POL_ACTIVE_LOW;
- mdioParamsInit.link1pol = TIESC_LINK_POL_ACTIVE_LOW;
- }
- else
- {
- //增强型连接检查禁止
- mdioParamsInit.link0pol = TIESC_LINK_POL_ACTIVE_HIGH;
- mdioParamsInit.link1pol = TIESC_LINK_POL_ACTIVE_HIGH;
- }
- bsp_pruss_mdio_init (&mdioParamsInit);
- bsp_esc_reg_perm_init();
- //触发PDI的看门狗在LATCH_IN里面,或者每个命令发送内固件
- bsp_set_pdi_wd_trigger_mode(PDI_WD_TRIGGER_LATCH_IN);
- prussdrv_pru_reset(0);
- prussdrv_pru_reset(1);
- if((NULL != pru_frame_proc ) &&
- (NULL != pru_host_proc ) &&
- (0 != pru_frame_proc_len ) &&
- (0 != pru_host_proc_len))
- {
- /* PRU的固件被载入作为一个头文件在应用程序里面 */
- PRUSSDRVSetPRUBuffer(0, (Uint32*)pru_frame_proc, pru_frame_proc_len);
- PRUSSDRVSetPRUBuffer(1, (Uint32*)pru_host_proc, pru_host_proc_len);
- prussdrv_exec_program(1, "./ecat_host_interface.bin");
- prussdrv_exec_program(0, "./ecat_frame_handler.bin");
- }
- else
- {
- /* PRU 固件存储在SPI的flash里面. */
- PRUSSDRVLoadBinary(0,SPI_PRU0_BINARY_OFFSET);
- PRUSSDRVLoadBinary(1,SPI_PRU1_BINARY_OFFSET);
- }
- }
- set_app_reload_flag(0);
- bsp_eeprom_emulation_init(); //载入eeprom的文件到内存
- if(bsp_eeprom_load_esc_registers(0) == -1)
- {
- Uint16 EEPROMReg = 0;
- HW_EscReadWord(EEPROMReg,ESC_ADDR_EEPROM_CTRL);
- EEPROMReg = SWAPWORD(EEPROMReg);
- EEPROMReg |= ESC_EEPROM_ERROR_CRC;
- EEPROMReg = SWAPWORD(EEPROMReg);
- bsp_write_word (EEPROMReg, ESC_ADDR_EEPROM_CTRL);
- }
- Semaphore_Params_init(&semParams);
- semParams.mode = Semaphore_Mode_BINARY;
- semcmdhigh_handle = Semaphore_create(1, &semParams, NULL);
- semcmdlow_handle = Semaphore_create(1, &semParams, NULL);
- escGlobalGateHandle = GateAll_create (NULL, NULL);
- #ifdef PROFILE_SEND_CMD_TO_FIRMWARE
- memset (cmd_profile_array, 0, sizeof(cmd_profile_array));
- #endif
- }
文件:Tiescbsp.c
- void bsp_start_esc_isr(void)
- {
- /* 使能ESC-中断微控制器的特殊领域,这个数据结构ENABLE_ESC_INT应该被ecat_def.h定义 */
- // 使能RTOS中断
- PRUSSDRVRegisterIrqHandler(HOST_AL_EVENT, 1, &EcatIsr);
- PRUSSDRVRegisterIrqHandler(HOST_CMD_HIGH_ACK_EVENT, 1, &EscCmdAckIsr);
- PRUSSDRVRegisterIrqHandler(HOST_CMD_LOW_ACK_EVENT, 1, &EscCmdLowAckIsr);
- PRUSSDRVRegisterIrqHandler(HOST_SYNC1_EVENT, 0, &Sync1Isr);
- }
- /
- /**
- \param pObjectDictionary 指针指向应用程序特殊的对象字典
- NULL 如果没有特殊的对象可用
- \return 0 如果初始化成功的话
- \brief 这个函数初始化EtherCAT的参考代码
- *////
- UINT16 MainInit()
- {
- UINT16 Error = 0;
- /*硬件初始化函数需要在应用程序层被调用*/
- /* 初始化EtherCAT从站接口 */
- ECAT_Init();
- /* 初始化对象 */
- COE_ObjInit();
- #if DIAGNOSIS_SUPPORTED
- /*initialize Diagnose Message memory*/
- Diag_InitMemory();
- #endif
- #if COE_SUPPORTED
- /*定时器的初始化*/
- u16BusCycleCntMs = 0;
- StartTimerCnt = 0;
- bCycleTimeMeasurementStarted = FALSE;
- #endif
- #if ESC_EEPROM_ACCESS_SUPPORT
- /*重置PDI的接口*/
- {
- UINT32 eepromConfigControl = 0; //register (0x0500 : 0x0503) values
- HW_EscReadDWord(eepromConfigControl,ESC_EEPROM_CONFIG_OFFSET);
- /*清除接入寄存器(0x0501)*/
- eepromConfigControl &= SWAPDWORD(0xFFFF00FF);
- HW_EscWriteDWord(eepromConfigControl,ESC_EEPROM_CONFIG_OFFSET);
- }
- #endif
- /*应用程序的初始化应该在应用层被调用*/
- return Error;
- }
- /
- /**
- \brief 这个函数初始化几个对象字典
- *////
- void COE_ObjInit(void)
- {
- /* 初始化SM 输出参数对象 0x1C32 */
- sSyncManOutPar.subindex0 = 32;
- /*子索引subindex 1 包含实际的同步模式,它可以被主站写来转换ECAT自由运行模式到ECAT同步运行模式
- 如果从站支持两种模式的话,这个值将会被重写位SYNCTYPE_DCSYNC0或者SYNCTYPE_DCSYNC1在DC分布时钟模式当中 */
- /*缺省的模式是ECAT同步运行模式 */
- sSyncManOutPar.u16SyncType = SYNCTYPE_SYNCHRON;
- /* 子索引subindex 2 包含应用程序的周期时间,在ECAT 自由运行模式下,它可以被用做一个定时器中断来运行应用程序,在同步模式下,它可以被主站写用它的本地周期时间,从站可以检查是否这个周期时间被支持,在分布时钟模式下,这个值将会被覆盖用它的DC周期寄存器 */
- sSyncManOutPar.u32CycleTime = 0;
- /* 只是给DC模式:子索引3包含时间偏移在SYNC0(SYNC1)之间和当输出到硬件来允许来精确得计算延迟时间,
- (在这个例子,我们将使ESC中断程序里面做在线的测量) */
- sSyncManOutPar.u32ShiftTime = 0;
- /* 子索引 subindex 4 包含支持的同步类型 */
- sSyncManOutPar.u16SyncTypesSupported = SYNCTYPE_TIMESVARIABLE /* 根据连接的模块,可执行的定时器 */
- | SYNCTYPE_FREERUNSUPP /* ECAT 自由运行模式被支持 */
- | SYNCTYPE_SYNCHRONSUPP /* ECAT 同步模式被支持 */
- #if DC_SUPPORTED
- | SYNCTYPE_DCSYNC0SUPP /* DC 同步模式被支持 */
- #endif
- ;
- /* 子索引5包含从站可以支持的最小的周期时间,它将会被动态得计算,因为它是根据连接的模块的,(在这个例子里,我们将在ESC中断处理里面实现在线测量)对于例子程序里面,这个值是MIN_PD_CYCLE_TIME*/
- sSyncManOutPar.u32MinCycleTime = MIN_PD_CYCLE_TIME;
- /* 只有在DC模式上,子索引6包含从站需要的在接收到SM2事件以后的最小的延迟时间在SYNC0(SYNC1)可以接收之前,没有延迟,它将被动态得计算因为它是根据连接模块的(在这个例子我们将是在线测量在ESC中断处理中完成) */
- sSyncManOutPar.u32CalcAndCopyTime = (PD_OUTPUT_CALC_AND_COPY_TIME);
- /*subindex 8: 触发周期时间测量*/
- sSyncManOutPar.u16GetCycleTime = 0;
- /*subindex 9: 从开始输出到输出有效的时间*/
- sSyncManOutPar.u32DelayTime = (PD_OUTPUT_DELAY_TIME);
- /*subindex 32: 指示是否同步错误发生*/
- sSyncManOutPar.u16SyncError = 0;
- /* 初始化SM的输入参数对象0x1C33 */
- sSyncManInPar.subindex0 = 32;
- /* 缺省的模式是ECAT同步模式,如果输出大小是大于0,输入被SM2事件更新 */
- sSyncManInPar.u16SyncType = SYNCTYPE_SM2INT;
- /* subindex 2: 与 0x1C32:02相一样 */
- sSyncManInPar.u32CycleTime = sSyncManOutPar.u32CycleTime;
- /* only for DC Mode important: subindex 3 包含时间偏移在SYNC0(SYNC1)信号当输入已经到了硬件,允许主站精确得计算延迟时间,将会动态得计算,更具它连接的模块(在例子里面我们将在ESC中断处理里面做在线测量) */
- sSyncManInPar.u32ShiftTime = 0;
- /* subindex 4: same as 0x1C32:04 */
- sSyncManInPar.u16SyncTypesSupported = sSyncManOutPar.u16SyncTypesSupported;
- /* subindex 5: same as 0x1C32:05 */
- sSyncManInPar.u32MinCycleTime = sSyncManOutPar.u32MinCycleTime;
- /* subindex 6: delay read inputs, calculation and copy to SM buffer*/
- sSyncManInPar.u32CalcAndCopyTime = (PD_INPUT_CALC_AND_COPY_TIME);
- /*subindex 8: t触发周期时间的测量 */
- sSyncManInPar.u16GetCycleTime = 0;
- /*subindex 9: 准备输入的延迟delay to prepare input latch*/
- sSyncManInPar.u32DelayTime = (PD_INPUT_DELAY_TIME);
- /*subindex 32: 如果同步错误发生的话,它将增加*/
- sSyncManInPar.u16SyncError = 0;
- #if !STATIC_OBJECT_DIC && COE_SUPPORTED
- {
- UINT16 result = COE_ObjDictionaryInit();
- if(result != 0)
- {
- /*清除已经存在的连接对象*/
- COE_ClearObjDictionary();
- }
- }
- #endif
- #if SDO_RES_INTERFACE
- /* ECATCHANGE_START(V5.01) SDO6*/
- u8PendingSdo = 0;
- bStoreCompleteAccess = FALSE;
- u16StoreIndex = 0;
- u8StoreSubindex = 0;
- u32StoreDataSize = 0;
- pStoreData = NULL;
- pSdoPendFunc = NULL;
- /* ECATCHANGE_END(V5.01) SDO6*/
- #endif
- #if SEGMENTED_SDO_SUPPORTED
- pSdoSegData = NULL;
- #endif
- }
- /
- /**
- \return 0 对象字典创建成功
- ALSTATUSCODE_XX 创建对象字典失败
- \brief 这个函数初始化对象字典T
- *////
- UINT16 COE_ObjDictionaryInit(void)
- {
- UINT16 result = 0;
- /*重置对象字典的指针*/
- ObjDicList = NULL;
- result = AddObjectsToObjDictionary((TOBJECT OBJMEM *) GenObjDic);
- if(result != 0)
- return result;
- if(ApplicationObjDic != NULL)
- {
- result = AddObjectsToObjDictionary((TOBJECT OBJMEM *) ApplicationObjDic);
- }
- return result;
- }
- #endif //#if !STATIC_OBJECT_DIC
- Parameters
- <pre name="code" class="cpp">• outputs_running: 如果设置了,只是运行在OP状态
- • Return value: none
- Description:函数只是用户应用程序,它更新从从站来的32位的数据输入(u32Input)和执行来自主站的32位数据输出(u32Output)。这个由Beckhoff SSC library的例子应用程序接口从SYNC0 ISR(DC同步模式)或者PDI ISR(SM同步模式)根据主站选择的同步模式。u32Input应该被设置根据8位数据I/O或者任何预先设定的数据,u32</pre><pre name="code" class="cpp">output应该被用来更新数据输出LEDs 。</pre><pre name="code" class="cpp"></pre><pre name="code" class="cpp">*pApplication</pre>void (* pApplication)(unsigned short);<br>
- <pre></pre>
- <br>
- <br>
- <p><br>
- </p>
- <p><br>
- </p>