TMS570LC43xx SylixOS can 驱动
1. SylixOS 系统 can驱动注册
在SylixOS系统中在系统启动时首先会注册can驱动,调用API_CanDrvInstall函数
此函数将can驱动注册为字符设备。但是_canOpen等函数并不是设备驱动需要实现的,而是在系统内部已经实现。
__canOpen函数会判断当前字符设备是不是第一打开,如果是第一次打开会调用can设备的ioctl 定义的CAN_DEV_OPEN
功能。这和普通字符设备不同,普通字符设备是open初始化,调用Ioctl函数。
__canclose函数类似Open函数调用can设备的Ioctl函数。
__canRead函数
读函数首先判断读取的帧类型,然后根据要读取的字节数除以帧类型大小,获取读取几帧。然后检测当前读队列中是否有数据
,读写队列初始化并没有在驱动注册这里,而是在设备注册的时候。这里for循环里有个信号量,是用来阻塞,当正在有读取时候,防止在有别的读取调用,保证数据的一致性。在最后判断时候还有数据在队列中,如果有post释放信号量,让其他等待读的线程可以读。
__canWrite函数和读函数基本相同
首先根据帧的类型,判断需要写入多少帧数据。对设备加锁,然后往队列中写入数据,然后调用了 __canTxStartup函数使能发送,调用一次发送后,后面缓冲区里的发送由中断去调用。
在__canTxStartup 调用驱动函数的txStartup,这个需要驱动力实现__canWrite 函数最后判断缓冲队列是否已经满了,如果不满则释放释放信号量,继续写入。
__canIoctl会调用驱动程序的Ioctl函数,另外针对驱动Ioctl不能识别的命令,在__canIoctl进行了部分处理,对驱动ioctl无法识别时需要返回错误
注册驱动这里就结束了。
2.创建can设备
在创建完成驱动后,需要创建can设备。使用INT API_CanDevCreate(PCHAR pcName, CAN_CHAN *pcanchan, UINT uiRdFrameSize, UINT uiWrtFrameSize);创建设备。第一个参数是设备名称,第二个参数是设备通道,
第三个是设备接收缓冲区大小,第四个是发送缓冲区大小。
首先判断驱动有没有正常注册成功。然后从堆里分配一个 __PCAN_PORT。是包含can设备和can通道号的结构体,如下图
can通道号其实就是can功能函数的
can设备结构体体定义如下:
创建完成一个can 设备后,此时要对can设备初始化 初始化主要工作室为缓冲区分配大小,创建can设备使用的信号量
从堆中分出队列结构体和缓冲区相加大小的结构体。can缓冲队列结构体如下:
将pcanq + 1 得到缓冲区首地址,同时将地址转换为帧类型,出队指针和入队指针都赋值为当前缓冲区首地址。
初始化完成队列后,对can设备结构体中的读写状态和总线状态赋值。
初始化完成缓冲区后,会调用安装回调函数,这个会再驱动力调用,将__canITx 等函数复制给驱动力的钩子,然后注册字符设备。
驱动就可以直接调用__canITx函数
它的功能很简单 从对队列中读取数据,然后释放信号量允许在往发送队列中写入数据。
3.创建can通道
在创建can设备时,需要can通道。can通道创建就需要can驱动实现
在tms57lc43xx can驱动中首先定义了can相关的结构体,包含can的中断向量,can的基地址,can的功能函数等等,
在SylixOS中can驱动主要是实现can的三个功能函数
首先是ioctl,在注册驱动时_canOpen 和__canClose函数首先会调用Ioctl 函数
里面初始化,设备波特率等是对TI官方提供的示例代码进行了封装,具体可以看另一篇文章tms57lc43xx上手,如何生成官方代码。在调试时先使用官方裸机代码调试,调试内不循环模式能自发自收,然后在测试往外发。
然后是安装回调函数,这个函数在注册设备的时候会调用
将 确定框架里实现的__canITx 函数复制给了can设备CANCHAN_pcbGetTx, 通过调用CANCHAN_pcbGetTx函数就能从缓冲队队列中读取数据出来。相同原理__canIRx函数地址传给CANCHAN_pcbPutRcv 实现将读取数据写入到当前的接收缺列中。
最后一个功能函数startUp就是使用前面准备好的CANCHAN_pcbGetTx 获取一帧数据,然后解析帧ID,帧类型,设置相应的TI的寄存器,使能发送。
三个功能函数实现完成后,需要把接收和发送中断完成,由于在write函数在把多个数据帧写入发送队列后会使能一次发送,一次发送完成后会有发送完成中断,在中断中再次将单独发送函数加入到工作队列中,发送函数需要实现从发送队列中读取一个帧数据,然后发送。
在TMS57LC43xx中,can有32个message,每个message都可以设置对应的ID号,也就是说can帧的ID好会被存入当前的message中。这个可以通过TI的工具图形界面设置message的ID然后生成源代码,所以中断要读取时哪个message触发中断。
然后再次调用发送函数,发送函数再次使用CANCHAN_pcbGetTx 获取can帧。 接收中断与其类似
流程图如下:
最后在bsp调用