Part Number:TMS320F28388D
f2838x_cm_cia402_solution例程对象字典建立过程
本文为大家分析一下f2838x_cm_cia402_solution例程对象字典的建立过程。
图1. cia402appl.h
如图1所示,在cia402appl.c文件的启始,引用了cia402appl.h头文件。在该头文件中,有三个与对象字典相关的定义。
第一个定义是CiA402对象的默认值:
图2. 各CiA402对象默认值
第二个定义是CiA402应用对象字典:
图3. CiA402应用对象字典
图4. 对象字典中对象结构体定义
由图4对象结构体定义可知,应用对象字典中的对象与相应的对象buffer建立了联系,即每个应用对象字典中对象结构体指向对象buffer的指针*pEntryDesc被赋值了,如&sRxPDOassign、&sTxPDOassign等,这使得应用对象字典不再是一个空字典。
第三个定义是CiA402轴对象字典:
图5. CiA402轴对象字典
与CiA402应用对象字典不同,指向对象buffer指针是“NULL”,即每个对象结构的倒数第4个参数为NULL。因此,此时的CiA402轴对象字典可以理解为一个空字典。
需要注意的是,以上两个字典的每个对象结构中指向当前对象前一个对象的*pPrev指针与指向当前对象后一个对象的*pNext均为NULL,对象间还没有建立链接关系。
在CCS中查看以上三部分的定义,全部为未参与编译的状态。其实这三部分在代码中是正常定义的,因为在引用cia402appl.h文件前定义了“_CiA402_”宏。之所以显示未参与编译,是因为在引用cia402appl.h文件后,通过“#undef _CiA402_”语句取消了“_CiA402_”的定义,从而避免在后续代码中引起定义冲突。
对象字典的建立,开始于COE_ObjInit函数。
图6. COE_ObjInit()函数
COE_ObjInit()函数位于coeappl.c文件中,该函数首先初始化与同步方式相关的两个对象0x1C32、0x1C33,随后调用COE_ObjDictionaryInit函数开始建立对象字典。
图7. COE_ObjDictionaryInit函数定义
其中,GenObjDic是一个与应用无关的通用对象字典,它的定义也是在coeappl.c文件中
图8. 通用对象字典GenObjDic
通用对象字典不是一个空字典(这个字典每个对象结构中的指向对象buffer的指针被赋予了相应的地址数值),但是各个对象之间依然彼此独立,不存在前后关联的链接关系,AddObjectsToObjDictionary将会在各个对象结构之间建立前后相关的链接关系。
在图7的COE_ObjDictionaryInit函数调用第一个AddObjectsToObjDictionary函数前,将该函数中的ObjDicList变量赋值为NULL,即复位对象字典指针。因此,在执行COE_AddObjectToDic函数时,会执行以下部分,下图绿色箭头标注了字典指针参数的传递过程。
这部分代码将对象字典列表指针指向了GenObjDic字典的首地址,即指向了GenObjDic字典中的第一个对象,其index数值为0x1000,该对象是对象字典的第一个对象,目前其指向前一个对象的指针及指向后一个对象的指针均为NULL。
接下来AddObjectsToObjDictionary函数会轮询GenObjDic字典中的每一个对象,将它们按照index的大小,顺序添加到ObjDicList中。由于GenObjDic中对象的index是从小到大依次建立的,所以ObjDicList后续对象的添加是类似的,都是在前一个对象的后面增加新的对象,会调用COE_AddObjectToDic的以下部分:
图11. 在当前对象的后面添加对象(新对象index值大于前一对象)
对这段代码的解释是:
- 在这个case中,新对象的index大于当前对象;
- 如果当前对象指向后一个对象的指针为NULL,表明该对象是目前对象字典中最后一个对象;
- 插入新对象的过程为
将当前对象指向后一对象的指针赋值为新对象指针,
将新对象中指向前一对象的指针赋值为当前对象指针,
将新对象指向后一对象的指针赋值为NULL,
经过这三步的处理,将新对象插入到了链表的末尾
执行完COE_ObjDictionaryInit函数中的第一个AddObjectsToObjDictionary函数后,得到了一个如下图所示链表形式的对象字典:
图12. 第一步建立的链表形式的对象字典
AddObjectsToObjDictionary函数轮询结束的条件式字典中出现index为0xFFFF的对象,因此GenObjDic字典的最后需要方式一个“空”对象,其index值为0xFFFF:
图13. 作为轮询结束条件的“空”对象
COE_ObjDictionaryInit函数中第二次调用AddObjectsToObjDictionary函数,是将应用对象字典添加到前面已经建立的链式对象字典(图12)中,其对象插入过程与前面讲解的类似,但是会涉及到两个新的判断条件。以应用对象字典中的第一个对象为例,其index值为0x1C12,该index数值意味着我们需要将这个对象插入到已经建立的链式对象字典中间的某一个位置。
图14. 查找插入点
已建立链表的第一个对象的index值为0x1000,且每个对象(除去最后一个对象)指向下一个对象的指针均不为NULL,因此会重复执行图14高亮部分的代码,查找第一个index数值大于0x1C12的对象。找到这个对象后(0x1C32),将0x1C12对象插入到0x1C32对象的前面:
图15. 0x1C12对象插入
对这部分代码的解释为:
- 将0x1C32对象指向前一个对象的指针赋值给0x1C12对象指向前一个对象的指针;
- 将指向0x1C32的指针赋值给0x1C12指向后一个对象的指针;
- 将原0x1C32前一个对象的指向后一对象的指针赋值为指向0x1C12对象的指针
- 将0x1C32指向前一个对象指针赋值为指向0x1C12对象的指针
应用字典中其他对象的插入过程与上面讲解的类似,执行完COE_ObjDictionaryInit函数中第二个AddObjectsToObjDictionary函数后,得到了如下图所示的链式对象字典:
图16. 第二阶段建立的链式对象字典
至此,完成了MainInit函数中对象字典建立部分代码的分析。
CiA402_Init这个函数中对已建立的空对象字典DefCiA402AxisObjDic中指向对象buffer的指针进行赋值,即填充字典,并将指向字典的指针赋值给轴结构体中指向对象字典的指针ObjDic:
图17. 轴结构体中指向对象字典的指针
图18. CiA402对象字典分配空间及指针赋值
图19. 填充字典(一部分代码)
最后的字典整合在APPL_GenerateMapping中进行:
图20. 整合CiA402_Init中的CiA402轴对象字典
对象的插入过程不再赘述,最终得到的链式对象字典如下图所示:
图21. 最终建立的链表形式的对象字典
总结:
本文总结了例程中CiA402对象字典的建立过程,整个过程经历了MainInit、CiA402_Init及APPL_GenerateMapping三个上层函数的处理,最终建立的是一个链表形式的CiA402对象字典。
Green Deng:
非常感谢一直以来的技术分享!