基于Kithara应用程序开发
Kithara学习资料的获取
Kithara目前官方提供的学习资料主要有如下两个:
- 官方网站上的在线文档为了使用户能够迅速学会使用Kithara,Kithara官网上提供了相应的官方文档,以及所有Kithara API的说明,错误代码说明,结构体定义等((用户需要在官网上注册个账户,登录后才能看到))。文档所在官方页面如下:
- Kithara安装目录下的示例教程
Kithara安装目录下的示例教程
用户在开发机上安装完Kithara软件后,在安装目录
<Kithara>
\smp文件夹下,有基本所有的Kithara功能测试示例程序,用户可以这这些测试程序进行学习。如“EtherCATSimple”例程就是用户学习Kithara EtherCAT主站用法的一个不错的例程。
Kithara软件架构分析
如下图所示,windows系统内存地址分为用户空间(普通Windows应用程序加载的内存空间),和内核空间(windows系统以及驱动加载的空间),这两个不同的内存空间是无法直接相互访问的。为了保证实时性能,Kithara在Windows内核空间构建了一个与windows并行运行的实时子系统,其实时应用程序也必须加载到该实时子系统中,也就是Windows内核空间中运行,才能保证实时性能。为了方便用户编写以及加载实时应用程序到内核,Kithara提供相应的API,从而实时应用程序可以以动态链接库(*.dll)的形式,通过调用Kithara提供的API的方式,加载到实时子系统中.
由于实时应用程序是在Kithara构建的实时子系统中运行,因此其代码(支持C/C++)无法调用Windows系统库,此外C/C++运行时库也不能直接调用。为了解决这个问题,Kithara构建了实时子系统下的系统库,其包括数学处理函数,字符串处理函数,内存处理函数等,能满足基本所有的工业应用程序需求。这些系统库函数在windows下基本都有与其对应的函数,如 KSRTL_sin()
对应windows下的sin函数。Kithara内核系统库的详细信息见官网提供的在线文档.
在Kithara实时子系统中,任务(Task,如基于优先级的普通任务、定时器任务、事件触发任务),回调函数(CallBack),共享内存(Share Memory)),事件(Event)),管道(Pipe)),互斥体(Mutex),信号量(Semaphore))等都属于内核资源。为方便用户管理Kithara内核实时应用程序,Kithara提供了一系列API供用户使用。这些API可以在windows普通应用用,目前支持(C/C++,C#Delphi))三种语言。通过这些API用户可以方便的创建并使用这些内核资源,如创建一个内核实时任务,并控制该任务的启停.
说明:
- 为了实现实时应用程序和windows普通应用程序之间的数据通信和同步,Kithara提供了共享内存、管道、Socket、事件和信号量等资源给用户使用,通过调用其提供的相应的API,用户就可以方便的创建、使用以及销毁这些资源.
- 在Kithara内核中,EtherCAT主站任务逻辑还可以使用IEC61131-3规定的ST或IL语言编写后,编译并载入到内核中运行.
- EtherCAT总线是工业实时以太网总线的一种,Kithara在内核中实现了EtherCAT主站,从而用户可以非常方便的开发基于EtherCAT总线的运动控制系统。此外用户还可以基于Kithara提供的实时以太网功能模块,自己开发任何需要的基于实时以太网的总线主站.
- 在Kithara实时核中可以接收USB3.0或GIGE接口相机采集的图像,并可以在实时核中使用Halcon或OpenCV图像处理库进行处理.
- Kithara实时子系统提供了基于优先级,可抢占式的实时多任务运行环境,为了实现更加稳定的实时性能,Kithara还支持用户把指定任务分配在指定的CPU核下,这样通过合理的分配系统的CPU核,既能保证关键任务极其苛刻的实时性要求,也能保证系统的吞吐量,从而能够更加充分利用系统计算性能.
基于Kithara应用编写的一些基本概念
- Windows用户层和内核层Windows用户层可以运行普通的windows应用程序,该应用程序可以通过调用Kithara API以及Kithara提供的内核层资源来管理Kithara内核实时应用程序,该程序中使用的指针都是用户层指针。Windows内核层中可以运动Kithara实时应用程序,该程序中使用的指针全部为内核层指针.注意:
- 如果在内核层的实时应用中使用用户层指针,可能会导致Windows系统直接蓝屏.
- Windows用户层应用程序和内核层实时应用程序不能像普通windows应用程序一样直接相互交互,只能通过Kithara提供的API或内核资源,如共享内存进行交互.
- 内核层代码在编写的时候若出现一些错误,如野指针,调用不支持的C/C++运行时库,可能会导致系统蓝屏(绝大部分不会出现蓝屏).
- Kithara内核资源 任务:
内核资源名称 | 说明 | 部分相关Kithara API |
---|---|---|
回调函数 (CallBack) |
用户可以直接执行内核回调函数, 也可以把回调函数的执行和特定事件绑定 |
KS_createKernelCallBack KS_removeCallBack KS_execKernelFunction KS_installEcatHandler KS_installNetworkHandler |
普通任务 (Task) |
基于优先级(0~255,越大优先级越高), 可抢占式的实时任务. |
KS_createTask KS_triggerTask KS_killTask KS_sleepTask KS_getTaskState KS_removeTask |
数据通讯
内核资源名称 | 说明 | 部分相关Kithara API |
---|---|---|
共享内存 (Share memory) |
可实现windows普通应用和内核实时应用数据共享 | KS_createSharedMem KS_freeSharedMem |
管道(Pipe) | 一种简单且安全的数据通信方案, 可用于普通应用程序和内核实时应用程序之间通信 |
KS_createPipe KS_putPipe KS_getPipe KS_removePipe |
Socket | 在Kithara内核层支持Socket | KS_openSocket KS_closeSocket KS_recvFromSocket KS_sendToSocket KS_recvSocket KS_sendSocket KS_installSocketHandler KS_connectSocket KS_acceptSocket KS_execSocketCommand |
同步
内核资源名称 | 说明 | 部分相关Kithara API |
---|---|---|
事件 (Event) |
一种常用的多任务同步方式 | KS_createEvent KS_setEvent KS_waitForEvent KS_closeEvent |
互斥体 (QuickMutex) |
一种常用的数据同步方式 | KS_createQuickMutex KS_requestQuickMutex KS_releaseQuickMutex KS_removeQuickMutex |
信号量 (Semaphore) |
一种多任务之间同步方式 | KS_createSemaphore KS_requestSemaphore KS_releaseSemaphore KS_removeSemaphore |
详细的Kithara内核资源说明请查看官方在线文档
- Kithara API
Kithara的所有功能,其都以API的形式提供给用户使用,这些API中有些能在内核实时层中调用,而有些只能在非实时层(即普通windows应用程序)。掌握Kithara API的用法是使用Kithara的基础。按照API的功能其可分为如下三大类型:
[1] 实时套件功能模块相关API(KS_XXX())
其一般在普通windows应用程序中调用(部分也支持在内核实时代码中调用),其都提供三种言语(C/C++、Delphi和C#)的API接口。如,对于打开驱动的API其API接口形式分别如下:
c/c++
Error KS_openDriver(const char* customerNumber);
Delphi
function KS_openDriver(customerNumber: PAnsiChar): Error;
C#
int KS_openDriver(string customerNumber);
[2] Kithara实时子系统运行时库API(KSRTL_XXX()) 主要有数学计算、字符串处理、内存操作相关API。在Kithara内核实时应用程序中调用。 [3] 用户硬件驱动开发API(KSDRV_XXX()) 用于用户自定义驱动的实现。
基于Kithara应用程序架构
一个基于Kithara的应用工程至少需要一个Kithara内核管理应用程序,以及一个载入到Kithara实时应用程序。
1. 内核管理应用程序
该程序理论上可以是任何一个windows普通应用程序,如Windows C#窗口应用工程,qt工程,MFC工程,windows控制台工程等。其通过调用Kithara提供的API,以及Kithara提供的资源,如共享内存,对以动态连接块形式,对载入到Kithara内核的实时应用程序进行管理,数据通信,同步控制等。
2. Kithara内核的实时应用程序
Kithara内核的实时应用程序,是以动态链接库(*.dll)的形式加载到Kithara实时子系统中。该内核dll模块和Windows普通dll模块相比基本没有什么区别,但需要注意一下几点:
1. 其主入口函数不会调用,但为了dll能够正常编译在程序结构上其还是需要有.
#include <windows.h>
// 入口函数在kithara内核中不会调用,但是为了不影响编译,程序结构上需要该函数
BOOL QINAPI DllMain(HINSTANCE hInstDll, DWORD reson, LPVOID pReserved) {
return 1;
}
2. 在dll中,一般要有Kithara内核回调函数,其类似dll导出函数,形式如下:
extern "C" _declspec(dllexport) Error _stdcall _Routine_ExecInitial(void* pArgs, void* pContext) {
gpSharedMemEcat = (ShareMem_Ecat *)pArgs
return 0;
}
3. 由于dll载入到windows内核空间,因此其在运行时指针的地址指向windows内核层,因此其创建的指针在普通windows应用中不可以范问.
4. 无法调用windows系统提供的库,以及C/C++运行时库,只能使用Kithara提供的系统库函数.
Kithara实时应用程序调试方法
应用程序的开发都离不开调试。对于Kithara实时应用程序的调试目前主要有两种方法.
1. 采用普通windows调试器调试程序
为了调试Kithara实时应用程序代码,可以把实时代码加载到windows用户层空间。调试加载到windows用户层空间的Kithara实时代码可以像普通windows应用程序一样,例如用户可以使用Visual studio工具进行单步调试,添加断点等。但是由于实时代码加载到windows用户层空间,因此其与加载到windows内核层空间的代码有如下几个不同:
1. 代码的运行不再具有实时性
2. Kithara实时代码中使用的内核层指针也要变成相应的用户层指针。对于EtherCAT主站,区分用户层指针和内核层指针的,主要是共享内存指针和PDO数据指针,如下:
1. 共享内存指针
CallBackData* pAppPtr; //应用层数据接口
CallBackData* pSysPtr; //内核层数据接口
ksError = KS createSharedMem(
reinterpret_cast<void**>(&pAppPtr), reinterpret_cast<void**>(&pSysPtr),
NULL,
sizeof(CallBackData),
0);
if (ksError != KS Ok) {
Demo_OutputKrtsError("Failed to allocate shared memory",ksError);
return;
}
2. PDO数据接口指针
//获职控制字PD0数据接口指针
ksError = KS_getEcatDataObjAddress(
pAppPtr->hDataset,
pAppPtr->hSlave[index],
0x1600,
1,
(void**)&pAppPtr->slavePDOData_user[index]ptrlWord,
(void**)&pAppPtr->slavePDOData_sys[index]ptrlWord,
NULL,
NULL,
0);
if (ksError != KS_OK) {
Demo_OutputKrtsError("KS_getEcatDataObjAddress Error",ksError);
return;
}
-
Kithara实时代码使用的资源(如网卡、事件、回调函数、定时器等)也必须是用户层的资源
Kithara很多API都有个flags参数,其不同的数值表示代码在相应层次运行,或资源在相应层次创建。如下KS_LoadKernel()
函数所示,当代码在实时核下正常运行时,flags参数必须和KSF_KERNEL_EXEC
相或,当需要像普通应用程序一样调试实时代码时,该flag必须是0.
同样对于像打开网卡(KS_openAdapter),创建Event(KS_createEvent),创建回调函数(KS_createKernelCallBack),创建定时器(KS_createTimer),执行内核回调函数(KS_execKernelFunction)等,Kithara API 为了在不同模式下切换,也需要设置不同的flags参数 -
通过kithara提供的“Kithara Kernel Tracer”工具进行调试
对于windows调试器,其对于调试普通的单线程任务特别合适。但是对于多线程,多处理器的系统,采用这种方式调试一般会遇到如下几个常见问题.- 系统的多个任务之间的同步关系,或时序关系被打乱,导致可能调试的时候没问题,但真正运行的时候却出现了问题.
- 系统的多个线程混合在一起,导致无法调试.
- 无法在实时的模式下进行调试.
因此,为了解决这个问题,Kithara就开发了一个“Kithara kernel tracer”工具,供用户调试内核实时代码使用。该工具的界面如下所示,其在windows下是一个可执行程序,用户在运行Kithara应用程序前,运行该工具,系统就能把调试信息(包括Kithara函数的调用,Kithara内核提示、警告及错误信息,用户自定义信息)按照其真实的执行顺序,动态的打印到该工具相应页面中。此外该工具还提供了信息的筛选,过滤等功能,从而方便用户快速找到需要的信息.
对于用户自定义的调试信息,用户可以把Kithara安装目录/dev下的Kithara.cpp文件到工程中,而后就能够调用KS_printk()函数,打印需要的信息。其主要能够打印文本数据和int型数据,用法如下:
int intData = 0;
KS_printK("User debug text infomation");
KS_printK("User debug int data value %d", intData);
为了打印浮点数据,用户可以把浮点数,根据精度要求乘以一个整数,如1000,转换成整数后在打印出来.