diff --git a/arch b/arch index 478948e2fd0..b331b89caf5 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit 478948e2fd0c1621bce15195c6f207df4156fbe6 +Subproject commit b331b89caf5aa68bc8b8e585b35e10777f469e1c diff --git a/drivers/Kconfig b/drivers/Kconfig index b94ad60f990..263001d9cca 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -99,13 +99,20 @@ menuconfig CAN See include/nuttx/can.h for further CAN driver information. if CAN + config CAN_EXTID bool "CAN extended IDs" default n ---help--- - Enables support for the 29-bit extended ID. Default Standard 11-bit + Enables support for the 28-bit extended ID. Default Standard 11-bit IDs. +config CAN_FD + bool "CAN FD" + default n + ---help--- + Enables support for the CAN_FD mode. + config CAN_FIFOSIZE int "CAN driver I/O buffer size" default 8 diff --git a/drivers/can.c b/drivers/can.c index def854e1384..f11e7d66eb3 100644 --- a/drivers/can.c +++ b/drivers/can.c @@ -89,6 +89,15 @@ * Private Function Prototypes ****************************************************************************/ +/* CAN helpers */ + +static uint8_t can_dlc2bytes(uint8_t dlc); +#if 0 /* Not used */ +static uint8_t can_bytes2dlc(uint8_t nbytes); +#endif + +/* Character driver methods */ + static int can_open(FAR struct file *filep); static int can_close(FAR struct file *filep); static ssize_t can_read(FAR struct file *filep, FAR char *buffer, @@ -125,6 +134,101 @@ static const struct file_operations g_canops = * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: can_dlc2bytes and can_bytes2dlc + * + * Description: + * In the CAN FD format, the coding of the DLC differs from the standard + * CAN format. The DLC codes 0 to 8 have the same coding as in standard + * CAN. But the codes 9 to 15 all imply a data field of 8 bytes with + * standard CAN. In CAN FD mode, the values 9 to 15 are encoded to values + * in the range 12 to 64. + * + * Input Parameter: + * dlc - the DLC to convert to a byte count, OR + * nbytes - the byte count to convert to a DLC + * + * Returned Value: + * The converted value + * + ****************************************************************************/ + +static uint8_t can_dlc2bytes(uint8_t dlc) +{ + if (dlc > 8) + { +#ifdef CONFIG_CAN_FD + switch (dlc) + { + case 9: + return 12; + case 10: + return 16; + case 11: + return 20; + case 12: + return 24; + case 13: + return 32; + case 14: + return 48; + default: + case 15: + return 64; + } +#else + return 8; +#endif + } + + return dlc; +} + +#if 0 /* Not used */ +static uint8_t can_bytes2dlc(FAR struct sam_can_s *priv, uint8_t nbytes) +{ + if (nbytes <= 8) + { + return nbytes; + } +#ifdef CONFIG_CAN_FD + else if (nbytes <= 12) + { + return 9; + } + else if (nbytes <= 16) + { + return 10; + } + else if (nbytes <= 20) + { + return 11; + } + else if (nbytes <= 24) + { + return 12; + } + else if (nbytes <= 32) + { + return 13; + } + else if (nbytes <= 48) + { + return 14; + } + else /* if (nbytes <= 64) */ + { + return 15; + } +#else + else + { + return 8; + } +#endif +} +#endif + /**************************************************************************** * Name: can_open * @@ -351,7 +455,8 @@ static ssize_t can_read(FAR struct file *filep, FAR char *buffer, /* Will the next message in the FIFO fit into the user buffer? */ FAR struct can_msg_s *msg = &dev->cd_recv.rx_buffer[dev->cd_recv.rx_head]; - int msglen = CAN_MSGLEN(msg->cm_hdr.ch_dlc); + int nbytes = can_dlc2bytes(msg->cm_hdr.ch_dlc); + int msglen = CAN_MSGLEN(nbytes); if (nread + msglen > buflen) { @@ -472,6 +577,7 @@ static ssize_t can_write(FAR struct file *filep, FAR const char *buffer, ssize_t nsent = 0; irqstate_t flags; int nexttail; + int nbytes; int msglen; int ret = 0; @@ -562,7 +668,8 @@ static ssize_t can_write(FAR struct file *filep, FAR const char *buffer, */ msg = (FAR struct can_msg_s *)&buffer[nsent]; - msglen = CAN_MSGLEN(msg->cm_hdr.ch_dlc); + nbytes = can_dlc2bytes(msg->cm_hdr.ch_dlc); + msglen = CAN_MSGLEN(nbytes); memcpy(&fifo->tx_buffer[fifo->tx_tail], msg, msglen); /* Increment the tail of the circular buffer */