diff --git a/cpu/stm32/periph/fdcan.c b/cpu/stm32/periph/fdcan.c index 343b4a760e9a..33579ed07c4a 100644 --- a/cpu/stm32/periph/fdcan.c +++ b/cpu/stm32/periph/fdcan.c @@ -876,12 +876,6 @@ static int _send(candev_t *candev, const can_frame_t *frame) return -EINVAL; } - if (frame->len > CANFD_MAX_DLEN) { - DEBUG("%s: FDCAN%u frame %lu DLC is upper 64 bytes (%d)\n", - __func__, get_channel_id(can), frame->can_id, frame->len); - return -EINVAL; - } - /* Determine if it a standard or extended identifier */ uint32_t xtd_bit = ((((frame->can_id & CAN_EFF_FLAG) == CAN_EFF_FLAG) || (frame->flags & CANFD_FDF)) ? 1 : 0) << FDCAN_SRAM_TXBUFFER_T0_XTD_Pos; @@ -906,25 +900,46 @@ static int _send(candev_t *candev, const can_frame_t *frame) | rtr_bit /* Always a data frame */ | id); /* Message ID */ + /* Bit rate switching is specific to FDCAN. */ + if (!(frame->flags & CANFD_FDF) && (frame->flags & CANFD_BRS)) { + DEBUG("%s: FDCAN%u frame %lu BRS is enabled on a non-fd frame\n", + __func__, get_channel_id(can), frame->can_id); + return -EINVAL; + } + + /* Check length */ + if ((frame->flags & CANFD_FDF) && (frame->len > CANFD_MAX_DLEN)) { + DEBUG("%s: FDCAN%u frame %lu len is upper than 64 bytes (%d)\n", + __func__, get_channel_id(can), frame->can_id, frame->len); + return -EINVAL; + } + if (!(frame->flags & CANFD_FDF) && (frame->len > CAN_MAX_DLEN)) { + DEBUG("%s: FDCAN%u frame %lu len is upper than 8 bytes (%d)\n", + __func__, get_channel_id(can), frame->can_id, frame->len); + return -EINVAL; + } + + /* ESI bit in CAN FD format transmitted recessive */ *tx_buffer_element_t1 &= ~FDCAN_SRAM_TXBUFFER_T1_EFC; *tx_buffer_element_t1 |= FDCAN_SRAM_TXBUFFER_T1_EFC_DISABLE; /* Bit Rate Switching */ *tx_buffer_element_t1 &= ~FDCAN_SRAM_TXBUFFER_T1_BRS; - *tx_buffer_element_t1 |= ((frame->flags & CANFD_BRS) ? 1 : 0) << FDCAN_SRAM_TXBUFFER_T1_BRS_Pos; + *tx_buffer_element_t1 |= frame->flags & CANFD_BRS + ? FDCAN_SRAM_TXBUFFER_T1_BRS_ON + : FDCAN_SRAM_TXBUFFER_T1_BRS_OFF; + + /* CAN FD frame */ + *tx_buffer_element_t1 &= ~FDCAN_SRAM_TXBUFFER_T1_FDF; + *tx_buffer_element_t1 |= frame->flags & CANFD_FDF + ? FDCAN_SRAM_TXBUFFER_T1_FDF_FD + : FDCAN_SRAM_TXBUFFER_T1_FDF_CLASSIC; + /* Data Length Code*/ *tx_buffer_element_t1 &= ~FDCAN_SRAM_TXBUFFER_T1_DLC; *tx_buffer_element_t1 |= dlc_to_fddlc(frame->len) << FDCAN_SRAM_TXBUFFER_T1_DLC_Pos; - /* Bit rate switching and a payload data length greater than 8 are specific to FDCAN. - Thus consider frame as a FDCAN one only if one of those two specifics is fulfilled */ - *tx_buffer_element_t1 &= ~FDCAN_SRAM_TXBUFFER_T1_FDF; - *tx_buffer_element_t1 |= ((frame->flags & CANFD_FDF) - || (frame->flags & CANFD_BRS) - || (frame->len > CAN_MAX_DLEN)) - ? FDCAN_SRAM_TXBUFFER_T1_FDF_FD - : FDCAN_SRAM_TXBUFFER_T1_FDF_CLASSIC; DEBUG("%s: FDCAN%u *tx_buffer_element_t0 = %lx\n", __func__, get_channel_id(can), *tx_buffer_element_t0);