SylixOS应用层代码详
-
SylixOS CAN驱动框架
如图 11所示,在SylixOS中CAN总线的框架可分为4层,应用层、系统层、驱动层和硬件层。本文主要介绍应用层的开发和使用。
图 11 SylixOS CAN驱动框架
-
SylixOS CAN设备应用层框架
在SylixOS中CAN应用层的框架如如图 12所示,在本文档中以调用open,read,write,Ioctl等基本应用层函数举例,方便理解操作。
图 12 SylixOS CAN应用层框架
-
SylixOS CAN应用层函数介绍
-
CAN的报文格式
由于SylixOS 的CAN驱动传输过程中涉及到系统层,在系统层中已经定义好了CAN报文的格式(SylixOS系统层以结构体形式定义一帧CAN报文,在下文中会详细介绍),所以必须使用固定的结构体,如程序清单 21所示。
程序清单 21 CAN报文结构体
/*********************************************************************************************************
CAN 帧结构定义
*********************************************************************************************************/
typedefstruct {
UINT32CAN_uiId; /* 标识码 */
UINT32CAN_uiChannel; /* 通道号 */
BOOLCAN_bExtId; /* 是否是扩展帧 */
BOOLCAN_bRtr; /* 是否是远程帧 */
UCHARCAN_ucLen; /* 数据长度 */
UCHARCAN_ucData[CAN_MAX_DATA]; /* 帧数据 */
} CAN_FRAME;
typedefCAN_FRAME *PCAN_FRAME; /* CAN帧指针类型 */
/********************************************************************************************************* CAN 帧结构定义 *********************************************************************************************************/ typedef struct { UINT32 CAN_uiId; /* 标识码 */ UINT32 CAN_uiChannel; /* 通道号 */ BOOL CAN_bExtId; /* 是否是扩展帧 */ BOOL CAN_bRtr; /* 是否是远程帧 */ UCHAR CAN_ucLen; /* 数据长度 */ UCHAR CAN_ucData[CAN_MAX_DATA]; /* 帧数据 */ } CAN_FRAME; typedef CAN_FRAME *PCAN_FRAME; /* CAN帧指针类型 */
-
发送线程
程序清单 22 发送线程
/*********************************************************************************************************
** 函数名称: pthread_test_send
** 功能描述: CAN 驱动测试 pthread 发送线程
** 输 入 : pvArg 线程参数
** 输 出 : 线程返回值
** 全局变量:
** 调用模块:
*********************************************************************************************************/
staticVOID *pthread_test_send(VOID *pvArg)
{
INTiFd;
CAN_FRAMEcanframe;
ssize_tstLen;
ssize_tstFrameNum;
char *devname = (char *)pvArg;
INTiSendCnt;
iFd = open(devname, O_RDWR, 0666);
if (iFd < 0) {
printf("failed to open %s!\n", devname);
return (LW_NULL);
}
if (ioctl(iFd, CAN_DEV_SET_BAUD, _G_iCanBuad)) {
printf("set baud to %d error.\n", _G_iCanBuad);
close (iFd);
return (LW_NULL);
}
ioctl(iFd, FIOFLUSH, 0);
iSendCnt = _G_iSendCnt;
printf("start %s send test with baud %d, send total = %d.\n", devname, _G_iCanBuad, _G_iSendCnt);
while (iSendCnt--) {
canframe.CAN_bExtId = LW_FALSE;
canframe.CAN_bRtr = LW_FALSE;
canframe.CAN_ucLen = CAN_MAX_DATA;
lib_memcpy((CHAR *)canframe.CAN_ucData, "01234567", CAN_MAX_DATA);
canframe.CAN_uiId = 0;
stLen = write(iFd, &canframe, sizeof(CAN_FRAME));
ioctl(iFd, CAN_DEV_STARTUP, 0);
stFrameNum = stLen / sizeof(CAN_FRAME);
if (stFrameNum != 1) {
printf("failed to send can frame!, abort sending\n");
break;
}
printf("send succ\n");
}
/*
* 等待数据全部发送完成
*/
while (1) {
INTiNum;
if (ioctl(iFd, FIONWRITE, &iNum)) {
printf("error");
break;
}
if (iNum == 0) {
break;
}
}
ioctl(iFd, CAN_DEV_STARTUP, 0);
close(iFd);
return (NULL);
}
-
接收线程
接收CAN报文的线程代码如程序清单 23所示。
程序清单 23 接收线程
/*********************************************************************************************************
** 函数名称: pthread_test_recv
** 功能描述: CAN 驱动测试 pthread 接收线程
** 输 入 : pvArg 线程参数
** 输 出 : 线程返回值
** 全局变量:
** 调用模块:
*********************************************************************************************************/
staticVOID *pthread_test_recv(VOID *pvArg)
{
INTiFd;
CAN_FRAMEcanframe;
ssize_tstLen;
ssize_tstFrameNum;
char *devname = (char *)pvArg;
charcFramInfo[64];
memset(&canframe, 0, sizeof(CAN_FRAME));
iFd = open(devname, O_RDWR, 0666);
if (iFd < 0) {
printf("failed to open %s!\n", devname);
return (LW_NULL);
}
printf("Successed to open %s!\n", devname);
if (ioctl(iFd, CAN_DEV_SET_BAUD, _G_iCanBuad)) {
printf("set baud to %d error.\n", _G_iCanBuad);
close (iFd);
return (LW_NULL);
}
printf("start %s recv test with baud %d.\n", devname, _G_iCanBuad);
while (1) {
stLen = read(iFd, &canframe, sizeof(CAN_FRAME));
stFrameNum = stLen / sizeof(CAN_FRAME);
if (stFrameNum != 1) {
printf("failed to recv can frame, abort recving!\n");
break;
} else {
sprintf(cFramInfo, "id=%d, len=%d, data=%02x %02x %02x %02x %02x %02x %02x %02x\n",
canframe.CAN_uiId, (INT)canframe.CAN_ucLen,
canframe.CAN_ucData[0],
canframe.CAN_ucData[1],
canframe.CAN_ucData[2],
canframe.CAN_ucData[3],
canframe.CAN_ucData[4],
canframe.CAN_ucData[5],
canframe.CAN_ucData[6],
canframe.CAN_ucData[7]);
printf(cFramInfo);
}
}
close(iFd);
return (NULL);
}
-
输入参数分析
输入参数分析函数代码如程序清单 24所示。
程序清单 24 输入参数解析
/*********************************************************************************************************
** 函数名称: canParseArg
** 功能描述: 参数解析
** 输 入 : NONE
** 输 出 : ERROR_CODE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
staticintcanParseArg (intargc, char *argv[])
{
intc;
inttmp;
_G_iCanOp = __can_ro;
if (argc < 1) {
return (0);
}
while (1) {
c = getopt(argc, argv, "d:rwxb:c:");
if (c == -1) {
break;
}
switch (c) {
case'r': _G_iCanOp = __can_ro; break;
case'w': _G_iCanOp = __can_wo; break;
case'x': _G_iCanOp = __can_rw; break;
case'b':
if (sscanf(optarg, "%d", &tmp) == 1) {
if (baudValid(tmp)) {
printf("set baud %d\r\n", tmp);
_G_iCanBuad = tmp;
}
}
break;
case'd':
strncpy(_G_cCanDevName, optarg, 32);
_G_cCanDevName[31] = 0;
_G_iCanDev = _G_cCanDevName;
break;
case'c':
if (sscanf(optarg, "%d", &tmp) == 1) {
if (tmp > 0) {
_G_iSendCnt = tmp;
}
}
break;
default:
return (-1);
}
}
return (0);
}
/*********************************************************************************************************
entry :
./can_test -d /dev/can0 -r -b 125000
./can_test -d /dev/can0 -w -b 125000
./can_test -d /dev/can0 -x -b 125000
*********************************************************************************************************/
-
Main函数及线程创建函数
Main函数及线程创建函数如程序清单 25所示。
程序清单 25 main函数
intmain (intargc, char *argv[])
{
intret;
ret = canParseArg(argc, argv);
if (ret) {
printf("invalid options.\n");
return (-1);
}
canTestStart(_G_iCanDev, _G_iCanOp);
return 0;
}
/*********************************************************************************************************
** 函数名称: canTestStart
** 功能描述: CAN 测试
** 输 入 : NONE
** 输 出 : ERROR_CODE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
INTcanTestStart (char *pcdevname, intrw)
{
pthread_ttid_recv;
pthread_ttid_send;
INTiError = ERROR_NONE;
if (rw & __can_ro) {
iError |= pthread_create(&tid_recv, NULL, pthread_test_recv, pcdevname);
pthread_join(tid_recv, NULL);
}
if (rw & __can_wo) {
iError = pthread_create(&tid_send, NULL, pthread_test_send, pcdevname);
pthread_join(tid_send, NULL);
}
return (iError == 0 ? ERROR_NONE : PX_ERROR);
}
Main函数主要是用创建收发线程和输入参数捕获