Reputation: 21
A little background, I want to receive CAN frames to Linux SOM, which does not have CAN peripheral, so I use stm32 which acts just like a bridge that sends CAN frames over UART to SoM. That part is already sorted out with custom kernel driver. Now when trying to include spawning CAN device I come to problem.
Custom kernel driver where I am registering CAN device with following simple program:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/can.h>
#include <linux/can/dev.h>
#include <linux/netdevice.h>
#include <linux/uaccess.h>
#include "main.h"
#include "can_dev.h"
static struct net_device *can_dev;
void uart_receive_handler(can_frame_stm *frame_stm, uint32_t Len)
{
struct sk_buff *skb;
struct can_frame *cf;
// Allocate a new skb and can_frame
skb = alloc_can_skb(can_dev, &cf);
if (!skb) {
printk(KERN_ERR "DEBUG %s can_dev: Failed to allocating can skb\n", MODULE_NAME);
return;
}
cf->can_id = frame_stm->can_id;
cf->can_dlc = frame_stm->can_dlc;
memcpy(cf->data, frame_stm->data, frame_stm->can_dlc);
// Process the received CAN frame
netif_rx(skb);
}
// Transmit CAN frames
static netdev_tx_t can_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct can_frame *cf = (struct can_frame *)skb->data;
// Transmit the CAN frame via UART to STM32 here
printk(KERN_INFO "DEBUG %s can_dev: transmit data\n", MODULE_NAME);
// uart_send(cf, sizeof(struct can_frame));
netif_trans_update(dev);
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
static int simple_can_open(struct net_device *dev)
{
netif_start_queue(dev);
printk(KERN_INFO "DEBUG %s can_dev: device opened\n", MODULE_NAME);
return 0;
}
static int simple_can_close(struct net_device *dev)
{
netif_stop_queue(dev);
printk(KERN_INFO "DEBUG %s can_dev: device closed\n", MODULE_NAME);
return 0;
}
// Net device operations
static const struct net_device_ops can_netdev_ops = {
.ndo_open = simple_can_open,
.ndo_stop = simple_can_close,
.ndo_start_xmit = can_start_xmit,
};
static void simple_can_setup(struct net_device *dev)
{
dev->netdev_ops = &can_netdev_ops;
dev->flags |= IFF_NOARP;
dev->mtu = CAN_MTU;
}
void init_can(void)
{
printk(KERN_INFO "DEBUG %s can_dev: Start init\n", MODULE_NAME);
can_dev = alloc_candev(0,10);
if (!can_dev) {
printk(KERN_ALERT "DEBUG %s can_dev: Failed to create can dev\n", MODULE_NAME);
return;
}
simple_can_setup(can_dev);
if (register_candev(can_dev)) {
printk(KERN_ERR "DEBUG %s can_dev: Failed to register CAN device\n", MODULE_NAME);
free_candev(can_dev);
return;
}
printk(KERN_INFO "DEBUG %s can_dev: Finish\n", MODULE_NAME);
}
void exit_can(void)
{
unregister_candev(can_dev);
free_candev(can_dev);
}
So to load module first I have to load can-dev module modprobe can-dev
then I load my module insmod can_module.ko
and also need to bring link up ip link set can0 up.
When I try to watch receiving data with candump can0
I get the CAN frames printed on console. But when I try to use cansend
it does print nothing not even error. However if I have candump can0
and I cansend command, it shows the CAN frame.
Here is the dmesg output:
[ 79.623157] CAN device driver interface
[ 79.633722] DEBUG CAN_MODULE can_dev: Start init
[ 79.634380] DEBUG CAN_MODULE can_dev: Finish
[ 79.643978] DEBUG CAN_MODULE can_dev: device opened
////////// here I called `candump can0` ////////////////
[ 98.963006] can: controller area network core
[ 98.963140] NET: Registered PF_CAN protocol family
[ 98.972396] can: raw protocol
////////// here I called `cansend can0 123#DEADBEEF` a bunch of times ////////////////
Upvotes: 1
Views: 40
Reputation: 21
I have resolved this, I have forgot to open can device in simple_can_open(). so this is how simple_can_open() looks now:
static int simple_can_open(struct net_device *dev)
{
int err = open_candev(dev);
if (err) {
printk(KERN_WARNING "LXNAV %s can_dev: Failed opening\n", MODULE_NAME);
return err;
}
netif_start_queue(dev);
printk(KERN_INFO "DEBUG %s can_dev: device opened\n", MODULE_NAME);
return 0;
}
Upvotes: 0