drivers: can: Compile time check of can timing not set
Check if the timing is not set from device tree and exclude sample-point algorithm if it is not used from device-tree. Signed-off-by: Alexander Wachter <alexander@wachter.cloud>
This commit is contained in:
parent
05275ecf6e
commit
b6ec3cb59e
3 changed files with 77 additions and 45 deletions
|
@ -17,6 +17,23 @@ LOG_MODULE_REGISTER(mcp2515_can);
|
||||||
|
|
||||||
#include "can_mcp2515.h"
|
#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)
|
static int mcp2515_cmd_soft_reset(const struct device *dev)
|
||||||
{
|
{
|
||||||
uint8_t cmd_buf[] = { MCP2515_OPCODE_RESET };
|
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;
|
dev_data->old_state = CAN_ERROR_ACTIVE;
|
||||||
|
|
||||||
timing.sjw = dev_cfg->tq_sjw;
|
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,
|
ret = can_calc_timing(dev, &timing, dev_cfg->bus_speed,
|
||||||
dev_cfg->sample_point);
|
dev_cfg->sample_point);
|
||||||
if (ret == -EINVAL) {
|
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),
|
.spi_cs_flags = DT_INST_SPI_DEV_CS_GPIOS_FLAGS(0),
|
||||||
#endif /* DT_INST_SPI_DEV_HAS_CS_GPIOS(0) */
|
#endif /* DT_INST_SPI_DEV_HAS_CS_GPIOS(0) */
|
||||||
.tq_sjw = DT_INST_PROP(0, sjw),
|
.tq_sjw = DT_INST_PROP(0, sjw),
|
||||||
#if DT_INST_PROP(0, prop_seg) > 0 && \
|
.tq_prop = DT_INST_PROP_OR(0, prop_seg, 0),
|
||||||
DT_INST_PROP(0, phase_seg1) > 0 && \
|
.tq_bs1 = DT_INST_PROP_OR(0, phase_seg1, 0),
|
||||||
DT_INST_PROP(0, phase_seg2) > 0
|
.tq_bs2 = DT_INST_PROP_OR(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
|
|
||||||
.bus_speed = DT_INST_PROP(0, bus_speed),
|
.bus_speed = DT_INST_PROP(0, bus_speed),
|
||||||
.osc_freq = DT_INST_PROP(0, osc_freq)
|
.osc_freq = DT_INST_PROP(0, osc_freq),
|
||||||
#if DT_INST_PROP(0, sample_point)
|
.sample_point = DT_INST_PROP_OR(0, sample_point, 0)
|
||||||
.sample_point = DT_INST_PROP(0, sample_point),
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DEVICE_AND_API_INIT(can_mcp2515_1, DT_INST_LABEL(0), &mcp2515_init,
|
DEVICE_AND_API_INIT(can_mcp2515_1, DT_INST_LABEL(0), &mcp2515_init,
|
||||||
|
|
|
@ -18,6 +18,23 @@
|
||||||
#include <logging/log.h>
|
#include <logging/log.h>
|
||||||
LOG_MODULE_REGISTER(can_mcux_flexcan);
|
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
|
* RX message buffers (filters) will take up the first N message
|
||||||
* buffers. The rest are available for TX use.
|
* 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;
|
timing.sjw = config->sjw;
|
||||||
if (config->sample_point) {
|
if (config->sample_point && USE_SP_ALGO) {
|
||||||
err = can_calc_timing(dev, &timing, config->bitrate,
|
err = can_calc_timing(dev, &timing, config->bitrate,
|
||||||
config->sample_point);
|
config->sample_point);
|
||||||
if (err == -EINVAL) {
|
if (err == -EINVAL) {
|
||||||
|
@ -679,7 +696,7 @@ static int mcux_flexcan_init(const struct device *dev)
|
||||||
LOG_DBG("Presc: %d, Seg1S1: %d, Seg2: %d",
|
LOG_DBG("Presc: %d, Seg1S1: %d, Seg2: %d",
|
||||||
timing.prescaler, timing.phase_seg1, timing.phase_seg2);
|
timing.prescaler, timing.phase_seg1, timing.phase_seg2);
|
||||||
LOG_DBG("Sample-point err : %d", err);
|
LOG_DBG("Sample-point err : %d", err);
|
||||||
} else if (config->phase_seg1) {
|
} else {
|
||||||
timing.prop_seg = config->prop_seg;
|
timing.prop_seg = config->prop_seg;
|
||||||
timing.phase_seg1 = config->phase_seg1;
|
timing.phase_seg1 = config->phase_seg1;
|
||||||
timing.phase_seg2 = config->phase_seg2;
|
timing.phase_seg2 = config->phase_seg2;
|
||||||
|
@ -687,9 +704,6 @@ static int mcux_flexcan_init(const struct device *dev)
|
||||||
if (err) {
|
if (err) {
|
||||||
LOG_WRN("Bitrate error: %d", err);
|
LOG_WRN("Bitrate error: %d", err);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
LOG_ERR("Timing not configured");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data->timing.preDivider = timing.prescaler;
|
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), \
|
.clk_source = DT_INST_PROP(id, clk_source), \
|
||||||
.bitrate = DT_INST_PROP(id, bus_speed), \
|
.bitrate = DT_INST_PROP(id, bus_speed), \
|
||||||
.sjw = DT_INST_PROP(id, sjw), \
|
.sjw = DT_INST_PROP(id, sjw), \
|
||||||
.prop_seg = DT_INST_PROP(id, prop_seg), \
|
.prop_seg = DT_INST_PROP_OR(id, prop_seg, 0), \
|
||||||
.phase_seg1 = DT_INST_PROP(id, phase_seg1), \
|
.phase_seg1 = DT_INST_PROP_OR(id, phase_seg1, 0), \
|
||||||
.phase_seg2 = DT_INST_PROP(id, phase_seg2), \
|
.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, \
|
.irq_config_func = mcux_flexcan_irq_config_##id, \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
|
|
|
@ -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
|
#error Simultaneous use of CAN_1 and CAN_2 not supported yet
|
||||||
#endif
|
#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
|
* Translation tables
|
||||||
* filter_in_bank[enum can_filter_type] = number of filters in bank for this type
|
* 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;
|
can->MCR |= CAN_MCR_ABOM;
|
||||||
#endif
|
#endif
|
||||||
timing.sjw = cfg->sjw;
|
timing.sjw = cfg->sjw;
|
||||||
if (cfg->sample_point) {
|
if (cfg->sample_point && USE_SP_ALGO) {
|
||||||
ret = can_calc_timing(dev, &timing, cfg->bus_speed,
|
ret = can_calc_timing(dev, &timing, cfg->bus_speed,
|
||||||
cfg->sample_point);
|
cfg->sample_point);
|
||||||
if (ret == -EINVAL) {
|
if (ret == -EINVAL) {
|
||||||
|
@ -472,7 +491,7 @@ static int can_stm32_init(const struct device *dev)
|
||||||
LOG_DBG("Presc: %d, TS1: %d, TS2: %d",
|
LOG_DBG("Presc: %d, TS1: %d, TS2: %d",
|
||||||
timing.prescaler, timing.phase_seg1, timing.phase_seg2);
|
timing.prescaler, timing.phase_seg1, timing.phase_seg2);
|
||||||
LOG_DBG("Sample-point err : %d", ret);
|
LOG_DBG("Sample-point err : %d", ret);
|
||||||
} else if (cfg->prop_ts1) {
|
} else {
|
||||||
timing.prop_seg = 0;
|
timing.prop_seg = 0;
|
||||||
timing.phase_seg1 = cfg->prop_ts1;
|
timing.phase_seg1 = cfg->prop_ts1;
|
||||||
timing.phase_seg2 = cfg->ts2;
|
timing.phase_seg2 = cfg->ts2;
|
||||||
|
@ -480,9 +499,6 @@ static int can_stm32_init(const struct device *dev)
|
||||||
if (ret) {
|
if (ret) {
|
||||||
LOG_WRN("Bitrate error: %d", ret);
|
LOG_WRN("Bitrate error: %d", ret);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
LOG_ERR("Timing not configured");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = can_stm32_set_timing(dev, &timing, NULL);
|
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)),
|
.can = (CAN_TypeDef *)DT_REG_ADDR(DT_NODELABEL(can1)),
|
||||||
.master_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),
|
.bus_speed = DT_PROP(DT_NODELABEL(can1), bus_speed),
|
||||||
#if DT_PROP(DT_NODELABEL(can1), sample_point) > 0
|
.sample_point = DT_PROP_OR(DT_NODELABEL(can1), sample_point, 0),
|
||||||
.sample_point = DT_PROP(DT_NODELABEL(can1), sample_point),
|
.sjw = DT_PROP_OR(DT_NODELABEL(can1), sjw, 1),
|
||||||
#endif
|
.prop_ts1 = DT_PROP_OR(DT_NODELABEL(can1), prop_seg, 0) +
|
||||||
.sjw = DT_PROP(DT_NODELABEL(can1), sjw),
|
DT_PROP_OR(DT_NODELABEL(can1), phase_seg1, 0),
|
||||||
#if DT_PROP(DT_NODELABEL(can1), phase_seg1) > 0 && \
|
.ts2 = DT_PROP_OR(DT_NODELABEL(can1), phase_seg2, 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
|
|
||||||
.pclken = {
|
.pclken = {
|
||||||
.enr = DT_CLOCKS_CELL(DT_NODELABEL(can1), bits),
|
.enr = DT_CLOCKS_CELL(DT_NODELABEL(can1), bits),
|
||||||
.bus = DT_CLOCKS_CELL(DT_NODELABEL(can1), bus),
|
.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 = (CAN_TypeDef *)DT_PROP(DT_NODELABEL(can2),
|
||||||
master_can_reg),
|
master_can_reg),
|
||||||
.bus_speed = DT_PROP(DT_NODELABEL(can2), bus_speed),
|
.bus_speed = DT_PROP(DT_NODELABEL(can2), bus_speed),
|
||||||
#if DT_PROP(DT_NODELABEL(can2), sample_point) > 0
|
.sample_point = DT_PROP_OR(DT_NODELABEL(can2), sample_point, 0),
|
||||||
.sample_point = DT_PROP(DT_NODELABEL(can2), sample_point),
|
.sjw = DT_PROP_OR(DT_NODELABEL(can2), sjw, 1),
|
||||||
#endif
|
.prop_ts1 = DT_PROP_OR(DT_NODELABEL(can2), prop_seg, 0) +
|
||||||
.sjw = DT_PROP(DT_NODELABEL(can2), sjw),
|
DT_PROP_OR(DT_NODELABEL(can2), phase_seg1, 0),
|
||||||
#if DT_PROP(DT_NODELABEL(can2), phase_seg1) > 0 && \
|
.ts2 = DT_PROP_OR(DT_NODELABEL(can2), phase_seg2, 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
|
|
||||||
.pclken = {
|
.pclken = {
|
||||||
.enr = DT_CLOCKS_CELL(DT_NODELABEL(can2), bits),
|
.enr = DT_CLOCKS_CELL(DT_NODELABEL(can2), bits),
|
||||||
.bus = DT_CLOCKS_CELL(DT_NODELABEL(can2), bus),
|
.bus = DT_CLOCKS_CELL(DT_NODELABEL(can2), bus),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue