diff --git a/drivers/can/can_mcp2515.c b/drivers/can/can_mcp2515.c index 1ee6a9cd113..d57081cbad3 100644 --- a/drivers/can/can_mcp2515.c +++ b/drivers/can/can_mcp2515.c @@ -17,6 +17,23 @@ LOG_MODULE_REGISTER(mcp2515_can); #include "can_mcp2515.h" +#define SP_IS_SET(inst) DT_INST_NODE_HAS_PROP(inst, sample_point) || + +/* Macro to exclude the sample point algorithm from compilation if not used + * Without the macro, the algorithm would always waste ROM + */ +#define USE_SP_ALGO (DT_INST_FOREACH_STATUS_OKAY(SP_IS_SET) 0) + +#define SP_AND_TIMING_NOT_SET(inst) \ + (!DT_INST_NODE_HAS_PROP(inst, sample_point) && \ + !(DT_INST_NODE_HAS_PROP(inst, prop_seg) && \ + DT_INST_NODE_HAS_PROP(inst, phase_seg1) && \ + DT_INST_NODE_HAS_PROP(inst, phase_seg2))) || + +#if DT_INST_FOREACH_STATUS_OKAY(SP_AND_TIMING_NOT_SET) 0 +#error You must either set a sampling-point or timings (phase-seg* and prop-seg) +#endif + static int mcp2515_cmd_soft_reset(const struct device *dev) { uint8_t cmd_buf[] = { MCP2515_OPCODE_RESET }; @@ -886,7 +903,7 @@ static int mcp2515_init(const struct device *dev) dev_data->old_state = CAN_ERROR_ACTIVE; timing.sjw = dev_cfg->tq_sjw; - if (dev_cfg->sample_point) { + if (dev_cfg->sample_point && USE_SP_ALGO) { ret = can_calc_timing(dev, &timing, dev_cfg->bus_speed, dev_cfg->sample_point); if (ret == -EINVAL) { @@ -944,18 +961,12 @@ static const struct mcp2515_config mcp2515_config_1 = { .spi_cs_flags = DT_INST_SPI_DEV_CS_GPIOS_FLAGS(0), #endif /* DT_INST_SPI_DEV_HAS_CS_GPIOS(0) */ .tq_sjw = DT_INST_PROP(0, sjw), -#if DT_INST_PROP(0, prop_seg) > 0 && \ - DT_INST_PROP(0, phase_seg1) > 0 && \ - DT_INST_PROP(0, phase_seg2) > 0 - .tq_prop = DT_INST_PROP(0, prop_seg), - .tq_bs1 = DT_INST_PROP(0, phase_seg1), - .tq_bs2 = DT_INST_PROP(0, phase_seg2), -#endif + .tq_prop = DT_INST_PROP_OR(0, prop_seg, 0), + .tq_bs1 = DT_INST_PROP_OR(0, phase_seg1, 0), + .tq_bs2 = DT_INST_PROP_OR(0, phase_seg2, 0), .bus_speed = DT_INST_PROP(0, bus_speed), - .osc_freq = DT_INST_PROP(0, osc_freq) -#if DT_INST_PROP(0, sample_point) - .sample_point = DT_INST_PROP(0, sample_point), -#endif + .osc_freq = DT_INST_PROP(0, osc_freq), + .sample_point = DT_INST_PROP_OR(0, sample_point, 0) }; DEVICE_AND_API_INIT(can_mcp2515_1, DT_INST_LABEL(0), &mcp2515_init, diff --git a/drivers/can/can_mcux_flexcan.c b/drivers/can/can_mcux_flexcan.c index 9b0ddcf2040..b0d5d69ac7d 100644 --- a/drivers/can/can_mcux_flexcan.c +++ b/drivers/can/can_mcux_flexcan.c @@ -18,6 +18,23 @@ #include LOG_MODULE_REGISTER(can_mcux_flexcan); +#define SP_IS_SET(inst) DT_INST_NODE_HAS_PROP(inst, sample_point) || + +/* Macro to exclude the sample point algorithm from compilation if not used + * Without the macro, the algorithm would always waste ROM + */ +#define USE_SP_ALGO (DT_INST_FOREACH_STATUS_OKAY(SP_IS_SET) 0) + +#define SP_AND_TIMING_NOT_SET(inst) \ + (!DT_INST_NODE_HAS_PROP(inst, sample_point) && \ + !(DT_INST_NODE_HAS_PROP(inst, prop_seg) && \ + DT_INST_NODE_HAS_PROP(inst, phase_seg1) && \ + DT_INST_NODE_HAS_PROP(inst, phase_seg2))) || + +#if DT_INST_FOREACH_STATUS_OKAY(SP_AND_TIMING_NOT_SET) 0 +#error You must either set a sampling-point or timings (phase-seg* and prop-seg) +#endif + /* * RX message buffers (filters) will take up the first N message * buffers. The rest are available for TX use. @@ -669,7 +686,7 @@ static int mcux_flexcan_init(const struct device *dev) } timing.sjw = config->sjw; - if (config->sample_point) { + if (config->sample_point && USE_SP_ALGO) { err = can_calc_timing(dev, &timing, config->bitrate, config->sample_point); if (err == -EINVAL) { @@ -679,7 +696,7 @@ static int mcux_flexcan_init(const struct device *dev) LOG_DBG("Presc: %d, Seg1S1: %d, Seg2: %d", timing.prescaler, timing.phase_seg1, timing.phase_seg2); LOG_DBG("Sample-point err : %d", err); - } else if (config->phase_seg1) { + } else { timing.prop_seg = config->prop_seg; timing.phase_seg1 = config->phase_seg1; timing.phase_seg2 = config->phase_seg2; @@ -687,9 +704,6 @@ static int mcux_flexcan_init(const struct device *dev) if (err) { LOG_WRN("Bitrate error: %d", err); } - } else { - LOG_ERR("Timing not configured"); - return -EINVAL; } data->timing.preDivider = timing.prescaler; @@ -770,9 +784,10 @@ static const struct can_driver_api mcux_flexcan_driver_api = { .clk_source = DT_INST_PROP(id, clk_source), \ .bitrate = DT_INST_PROP(id, bus_speed), \ .sjw = DT_INST_PROP(id, sjw), \ - .prop_seg = DT_INST_PROP(id, prop_seg), \ - .phase_seg1 = DT_INST_PROP(id, phase_seg1), \ - .phase_seg2 = DT_INST_PROP(id, phase_seg2), \ + .prop_seg = DT_INST_PROP_OR(id, prop_seg, 0), \ + .phase_seg1 = DT_INST_PROP_OR(id, phase_seg1, 0), \ + .phase_seg2 = DT_INST_PROP_OR(id, phase_seg2, 0), \ + .sample_point = DT_INST_PROP_OR(id, sample_point, 0), \ .irq_config_func = mcux_flexcan_irq_config_##id, \ }; \ \ diff --git a/drivers/can/can_stm32.c b/drivers/can/can_stm32.c index fa0c851fe83..1615308cae3 100644 --- a/drivers/can/can_stm32.c +++ b/drivers/can/can_stm32.c @@ -26,6 +26,25 @@ LOG_MODULE_DECLARE(can_driver, CONFIG_CAN_LOG_LEVEL); #error Simultaneous use of CAN_1 and CAN_2 not supported yet #endif +#define DT_DRV_COMPAT st_stm32_can + +#define SP_IS_SET(inst) DT_INST_NODE_HAS_PROP(inst, sample_point) || + +/* Macro to exclude the sample point algorithm from compilation if not used + * Without the macro, the algorithm would always waste ROM + */ +#define USE_SP_ALGO (DT_INST_FOREACH_STATUS_OKAY(SP_IS_SET) 0) + +#define SP_AND_TIMING_NOT_SET(inst) \ + (!DT_INST_NODE_HAS_PROP(inst, sample_point) && \ + !(DT_INST_NODE_HAS_PROP(inst, prop_seg) && \ + DT_INST_NODE_HAS_PROP(inst, phase_seg1) && \ + DT_INST_NODE_HAS_PROP(inst, phase_seg2))) || + +#if DT_INST_FOREACH_STATUS_OKAY(SP_AND_TIMING_NOT_SET) 0 +#error You must either set a sampling-point or timings (phase-seg* and prop-seg) +#endif + /* * Translation tables * filter_in_bank[enum can_filter_type] = number of filters in bank for this type @@ -462,7 +481,7 @@ static int can_stm32_init(const struct device *dev) can->MCR |= CAN_MCR_ABOM; #endif timing.sjw = cfg->sjw; - if (cfg->sample_point) { + if (cfg->sample_point && USE_SP_ALGO) { ret = can_calc_timing(dev, &timing, cfg->bus_speed, cfg->sample_point); if (ret == -EINVAL) { @@ -472,7 +491,7 @@ static int can_stm32_init(const struct device *dev) LOG_DBG("Presc: %d, TS1: %d, TS2: %d", timing.prescaler, timing.phase_seg1, timing.phase_seg2); LOG_DBG("Sample-point err : %d", ret); - } else if (cfg->prop_ts1) { + } else { timing.prop_seg = 0; timing.phase_seg1 = cfg->prop_ts1; timing.phase_seg2 = cfg->ts2; @@ -480,9 +499,6 @@ static int can_stm32_init(const struct device *dev) if (ret) { LOG_WRN("Bitrate error: %d", ret); } - } else { - LOG_ERR("Timing not configured"); - return -EINVAL; } ret = can_stm32_set_timing(dev, &timing, NULL); @@ -1118,16 +1134,11 @@ static const struct can_stm32_config can_stm32_cfg_1 = { .can = (CAN_TypeDef *)DT_REG_ADDR(DT_NODELABEL(can1)), .master_can = (CAN_TypeDef *)DT_REG_ADDR(DT_NODELABEL(can1)), .bus_speed = DT_PROP(DT_NODELABEL(can1), bus_speed), -#if DT_PROP(DT_NODELABEL(can1), sample_point) > 0 - .sample_point = DT_PROP(DT_NODELABEL(can1), sample_point), -#endif - .sjw = DT_PROP(DT_NODELABEL(can1), sjw), -#if DT_PROP(DT_NODELABEL(can1), phase_seg1) > 0 && \ - DT_PROP(DT_NODELABEL(can1), phase_seg2) > 0 - .prop_ts1 = DT_PROP(DT_NODELABEL(can1), prop_seg) + - DT_PROP(DT_NODELABEL(can1), phase_seg1), - .ts2 = DT_PROP(DT_NODELABEL(can1), phase_seg2), -#endif + .sample_point = DT_PROP_OR(DT_NODELABEL(can1), sample_point, 0), + .sjw = DT_PROP_OR(DT_NODELABEL(can1), sjw, 1), + .prop_ts1 = DT_PROP_OR(DT_NODELABEL(can1), prop_seg, 0) + + DT_PROP_OR(DT_NODELABEL(can1), phase_seg1, 0), + .ts2 = DT_PROP_OR(DT_NODELABEL(can1), phase_seg2, 0), .pclken = { .enr = DT_CLOCKS_CELL(DT_NODELABEL(can1), bits), .bus = DT_CLOCKS_CELL(DT_NODELABEL(can1), bus), @@ -1219,16 +1230,11 @@ static const struct can_stm32_config can_stm32_cfg_2 = { .master_can = (CAN_TypeDef *)DT_PROP(DT_NODELABEL(can2), master_can_reg), .bus_speed = DT_PROP(DT_NODELABEL(can2), bus_speed), -#if DT_PROP(DT_NODELABEL(can2), sample_point) > 0 - .sample_point = DT_PROP(DT_NODELABEL(can2), sample_point), -#endif - .sjw = DT_PROP(DT_NODELABEL(can2), sjw), -#if DT_PROP(DT_NODELABEL(can2), phase_seg1) > 0 && \ - DT_PROP(DT_NODELABEL(can2), phase_seg2) > 0 - .prop_ts1 = DT_PROP(DT_NODELABEL(can2), prop_seg) + - DT_PROP(DT_NODELABEL(can2), phase_seg1), - .ts2 = DT_PROP(DT_NODELABEL(can2), phase_seg2), -#endif + .sample_point = DT_PROP_OR(DT_NODELABEL(can2), sample_point, 0), + .sjw = DT_PROP_OR(DT_NODELABEL(can2), sjw, 1), + .prop_ts1 = DT_PROP_OR(DT_NODELABEL(can2), prop_seg, 0) + + DT_PROP_OR(DT_NODELABEL(can2), phase_seg1, 0), + .ts2 = DT_PROP_OR(DT_NODELABEL(can2), phase_seg2, 0), .pclken = { .enr = DT_CLOCKS_CELL(DT_NODELABEL(can2), bits), .bus = DT_CLOCKS_CELL(DT_NODELABEL(can2), bus),