Hi Robert,
On 21/03/2020 15.50, Robert Barrows wrote:
I have attempted to write a kernel module that sends a message via CAN but I am
having trouble understanding which level of the socket api I should be using,
and where there may be some documentation or examples of how to use it?
I am on a much older embedded 2.6.31 imx arm kernel, and eventually I
would like to
send this message from within a high res timer triggered ISR.
You can probably use the CAN_BCM sockets for your use-case which uses
high-res timers too - even in the 2.6.31 kernel. But I'll come to that
later ...
This is my code, which is hobbled together from internet examples, and kernel
oops is during sock_sendmsg, for now I am just trying to get it do run as part
of the init of the module:
int SendCanTime(struct timespec *tsCurrentTime) {
int s;
struct sockaddr_can addr;
struct can_frame frame;
struct socket *sock;
int thetime = tsCurrentTime->tv_sec;
mm_segment_t oldfs;
oldfs = get_fs();
set_fs(KERNEL_DS);
printk("cantime.ko: Socket 10\n");
if ((s = sock_create(PF_CAN, SOCK_RAW, CAN_RAW, &sock)) < 0) {
printk("cantime.ko: Socket failure\n");
return 1;
}
Argh - No!
You don't use sockets from INSIDE the kernel.
If you want to send CAN frames from inside the kernel you should use the
can_send() function from af_can.c
printk("cantime.ko: Socket 20\n");
memset(&addr, 0, sizeof(addr));
addr.can_family = PF_CAN;
addr.can_ifindex = 2; // This is bad how do I dynamically find it?
printk("cantime.ko: Socket 30");
if (sock->ops->bind(sock, (struct sockaddr *)&addr, sizeof(struct
sockaddr) ) < 0) {
printk("cantime.ko: Bind failure\n");
return 1;
}
printk("cantime.ko: Socket 40\n");
frame.can_id = 0x00050F93 | CAN_EFF_FLAG;
frame.can_dlc = 6;
frame.data[0] = 0x00;
frame.data[1] = 0x02;
memcpy(frame.data+2, &thetime, sizeof(int));
Is your requirement to send "some content" in a very defined time slot
OR do you need to send the time as content?
printk("cantime.ko: Socket 50\n");
if (sock_sendmsg(sock,(struct msghdr*)&frame,sizeof(struct
can_frame)) != sizeof(struct can_frame)) {
printk("cantime.ko: Write failure");
return 1;
}
sock_release(sock);
set_fs(oldfs);
return 0;
}
Output:
cantime.ko: Socket 10
cantime.ko: Socket 20
cantime.ko: Socket 30cantime.ko: Socket 40
cantime.ko: Socket 50
Unable to handle kernel paging request at virtual address 80050f93
pgd = d14c8000
[80050f93] *pgd=00000000
Internal error: Oops: 1 [#1] PREEMPT
Modules linked in: cantime(+) g_ether arcotg_udc
Funny thing :-)
I also have the user space code that works perfectly that I was trying to model
my kernel module code after:
Ok - but we need to check your use-case.
Sending CAN frames in a very precise (hrtimer) manner can be done with
the broadcast manager (aka CAN_BCM) sockets.
See:
https://elixir.bootlin.com/linux/latest/source/Documentation/networking/can.rst#L677
1. You can send fixed CAN frames and also a sequence of up to 256
(different) CAN frames at a precisely defined time with a CAN_BCM TX job.
2. You can generate the timestamp in user space and send it via CAN_RAW
socket.
3. You write your own kernel module o_O :)
Regards,
Oliver