stats: i2c: I2C stats

Adds the ability for I2C drivers to report synchronous transfer stats
using a I2C specific macro to define the device instance.

The macro creates a container for device_state which allows for per
instance device class common data structure to be used in the device
class api (ex: i2c.h). This is used to maintain per driver instance
stats for all i2c drivers. This is a reusable idea across other device
classes as desired.

Using Kconfig device class stats may be turned on/off individually
this way as well, in this case I2C_STATS.

Signed-off-by: Tom Burdick <thomas.burdick@intel.com>
This commit is contained in:
Tom Burdick 2021-10-27 15:07:10 -05:00 committed by Anas Nashif
parent e29d9e1e2f
commit 7b1349cfe6
37 changed files with 253 additions and 66 deletions

View file

@ -22,6 +22,12 @@ config I2C_SHELL
The I2C shell currently support scanning and bus recovery.
config I2C_STATS
bool "Enable I2C device Stats"
depends on STATS
help
Enable I2C Stats.
# Include these first so that any properties (e.g. defaults) below can be
# overridden (by defining symbols in multiple locations)
source "drivers/i2c/Kconfig.b91"

View file

@ -177,7 +177,7 @@ BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) <= 1,
.pinctrl_list = i2c_pins_##inst \
}; \
\
DEVICE_DT_INST_DEFINE(inst, i2c_b91_init, \
I2C_DEVICE_DT_INST_DEFINE(inst, i2c_b91_init, \
NULL, \
&i2c_b91_data_##inst, \
&i2c_b91_cfg_##inst, \

View file

@ -437,7 +437,7 @@ static struct i2c_cc13xx_cc26xx_data i2c_cc13xx_cc26xx_data = {
PM_DEVICE_DT_INST_DEFINE(0, i2c_cc13xx_cc26xx_pm_action);
DEVICE_DT_INST_DEFINE(0,
I2C_DEVICE_DT_INST_DEFINE(0,
i2c_cc13xx_cc26xx_init,
PM_DEVICE_DT_INST_REF(0),
&i2c_cc13xx_cc26xx_data, &i2c_cc13xx_cc26xx_config,

View file

@ -382,7 +382,7 @@ static const struct i2c_cc32xx_config i2c_cc32xx_config = {
static struct i2c_cc32xx_data i2c_cc32xx_data;
DEVICE_DT_INST_DEFINE(0, &i2c_cc32xx_init, NULL,
I2C_DEVICE_DT_INST_DEFINE(0, i2c_cc32xx_init, NULL,
&i2c_cc32xx_data, &i2c_cc32xx_config,
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
&i2c_cc32xx_driver_api);

View file

@ -728,7 +728,7 @@ static int i2c_dw_initialize(const struct device *dev)
I2C_DW_INIT_PCIE(n) \
}; \
static struct i2c_dw_dev_config i2c_##n##_runtime; \
DEVICE_DT_INST_DEFINE(n, &i2c_dw_initialize, NULL, \
I2C_DEVICE_DT_INST_DEFINE(n, i2c_dw_initialize, NULL, \
&i2c_##n##_runtime, &i2c_config_dw_##n, \
POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \
&funcs); \

View file

@ -153,7 +153,7 @@ static struct i2c_driver_api i2c_emul_api = {
.num_children = ARRAY_SIZE(emuls_##n), \
}; \
static struct i2c_emul_data i2c_emul_data_##n; \
DEVICE_DT_INST_DEFINE(n, \
I2C_DEVICE_DT_INST_DEFINE(n, \
i2c_emul_init, \
NULL, \
&i2c_emul_data_##n, \

View file

@ -706,8 +706,8 @@ static int IRAM_ATTR i2c_esp32_init(const struct device *dev)
.bitrate = I2C_FREQUENCY(idx), \
.default_config = I2C_MODE_MASTER, \
}; \
DEVICE_DT_DEFINE(DT_NODELABEL(i2c##idx), \
&i2c_esp32_init, \
I2C_DEVICE_DT_DEFINE(DT_NODELABEL(i2c##idx), \
i2c_esp32_init, \
NULL, \
&i2c_esp32_data_##idx, \
&i2c_esp32_config_##idx, \

View file

@ -226,7 +226,7 @@ static const struct i2c_gecko_config i2c_gecko_config_##idx = { \
\
static struct i2c_gecko_data i2c_gecko_data_##idx; \
\
DEVICE_DT_INST_DEFINE(idx, &i2c_gecko_init, \
I2C_DEVICE_DT_INST_DEFINE(idx, i2c_gecko_init, \
NULL, \
&i2c_gecko_data_##idx, &i2c_gecko_config_##idx, \
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \

View file

@ -182,7 +182,7 @@ static const struct i2c_gpio_config i2c_gpio_dev_cfg_##_num = { \
.bitrate = DT_INST_PROP(_num, clock_frequency), \
}; \
\
DEVICE_DT_INST_DEFINE(_num, \
I2C_DEVICE_DT_INST_DEFINE(_num, \
i2c_gpio_init, \
NULL, \
&i2c_gpio_dev_data_##_num, \

View file

@ -371,8 +371,8 @@ static const struct i2c_driver_api i2c_imx_driver_api = {
\
static struct i2c_imx_data i2c_imx_data_##n; \
\
DEVICE_DT_INST_DEFINE(n, \
&i2c_imx_init, \
I2C_DEVICE_DT_INST_DEFINE(n, \
i2c_imx_init, \
NULL, \
&i2c_imx_data_##n, &i2c_imx_config_##n, \
POST_KERNEL, \

View file

@ -1065,8 +1065,8 @@ static const struct i2c_driver_api i2c_it8xxx2_driver_api = {
\
static struct i2c_it8xxx2_data i2c_it8xxx2_data_##idx; \
\
DEVICE_DT_INST_DEFINE(idx, \
&i2c_it8xxx2_init, NULL, \
I2C_DEVICE_DT_INST_DEFINE(idx, \
i2c_it8xxx2_init, NULL, \
&i2c_it8xxx2_data_##idx, \
&i2c_it8xxx2_cfg_##idx, POST_KERNEL, \
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \

View file

@ -124,7 +124,7 @@ static const struct i2c_driver_api i2c_litex_driver_api = {
\
static struct i2c_bitbang i2c_bitbang_##n; \
\
DEVICE_DT_INST_DEFINE(n, \
I2C_DEVICE_DT_INST_DEFINE(n, \
i2c_litex_init, \
NULL, \
&i2c_bitbang_##n, \

View file

@ -343,7 +343,7 @@ static const struct i2c_stm32_config i2c_stm32_cfg_##name = { \
\
static struct i2c_stm32_data i2c_stm32_dev_data_##name; \
\
DEVICE_DT_DEFINE(DT_NODELABEL(name), &i2c_stm32_init, \
I2C_DEVICE_DT_DEFINE(DT_NODELABEL(name), i2c_stm32_init, \
NULL, &i2c_stm32_dev_data_##name, \
&i2c_stm32_cfg_##name, \
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \

View file

@ -401,8 +401,8 @@ static const struct lpc11u6x_i2c_config i2c_cfg_##idx = { \
\
static struct lpc11u6x_i2c_data i2c_data_##idx; \
\
DEVICE_DT_INST_DEFINE(idx, \
&lpc11u6x_i2c_init, \
I2C_DEVICE_DT_INST_DEFINE(idx, \
lpc11u6x_i2c_init, \
NULL, \
&i2c_data_##idx, &i2c_cfg_##idx, \
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS, \

View file

@ -1163,7 +1163,7 @@ static int i2c_xec_init(const struct device *dev)
.pcr_bitpos = DT_INST_PROP_BY_IDX(n, pcrs, 1), \
.irq_config_func = i2c_xec_irq_config_func_##n, \
}; \
DEVICE_DT_INST_DEFINE(n, &i2c_xec_init, NULL, \
I2C_DEVICE_DT_INST_DEFINE(n, i2c_xec_init, NULL, \
&i2c_xec_data_##n, &i2c_xec_config_##n, \
POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \
&i2c_xec_driver_api); \

View file

@ -230,8 +230,8 @@ static const struct i2c_driver_api i2c_mcux_driver_api = {
\
static struct i2c_mcux_data i2c_mcux_data_ ## n; \
\
DEVICE_DT_INST_DEFINE(n, \
&i2c_mcux_init, NULL, \
I2C_DEVICE_DT_INST_DEFINE(n, \
i2c_mcux_init, NULL, \
&i2c_mcux_data_ ## n, \
&i2c_mcux_config_ ## n, POST_KERNEL, \
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \

View file

@ -225,8 +225,8 @@ static const struct i2c_driver_api mcux_flexcomm_driver_api = {
.bitrate = DT_INST_PROP(id, clock_frequency), \
}; \
static struct mcux_flexcomm_data mcux_flexcomm_data_##id; \
DEVICE_DT_INST_DEFINE(id, \
&mcux_flexcomm_init, \
I2C_DEVICE_DT_INST_DEFINE(id, \
mcux_flexcomm_init, \
NULL, \
&mcux_flexcomm_data_##id, \
&mcux_flexcomm_config_##id, \

View file

@ -260,7 +260,7 @@ static const struct i2c_driver_api mcux_lpi2c_driver_api = {
\
static struct mcux_lpi2c_data mcux_lpi2c_data_##n; \
\
DEVICE_DT_INST_DEFINE(n, &mcux_lpi2c_init, NULL, \
I2C_DEVICE_DT_INST_DEFINE(n, mcux_lpi2c_init, NULL, \
&mcux_lpi2c_data_##n, \
&mcux_lpi2c_config_##n, POST_KERNEL, \
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \

View file

@ -165,7 +165,7 @@ static struct i2c_nios2_config i2c_nios2_cfg = {
},
};
DEVICE_DT_INST_DEFINE(0, &i2c_nios2_init, NULL,
I2C_DEVICE_DT_INST_DEFINE(0, i2c_nios2_init, NULL,
NULL, &i2c_nios2_cfg,
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
&i2c_nios2_driver_api);

View file

@ -962,7 +962,7 @@ static int i2c_ctrl_init(const struct device *dev)
\
static struct i2c_ctrl_data i2c_ctrl_data_##inst; \
\
DEVICE_DT_INST_DEFINE(inst, \
I2C_DEVICE_DT_INST_DEFINE(inst, \
NPCX_I2C_CTRL_INIT_FUNC(inst), \
NULL, \
&i2c_ctrl_data_##inst, &i2c_ctrl_cfg_##inst, \

View file

@ -287,7 +287,7 @@ static int twi_nrfx_pm_action(const struct device *dev,
} \
}; \
PM_DEVICE_DT_DEFINE(I2C(idx), twi_nrfx_pm_action); \
DEVICE_DT_DEFINE(I2C(idx), \
I2C_DEVICE_DT_DEFINE(I2C(idx), \
twi_##idx##_init, \
PM_DEVICE_DT_REF(I2C(idx)), \
&twi_##idx##_data, \

View file

@ -372,7 +372,7 @@ static int twim_nrfx_pm_action(const struct device *dev,
.flash_buf_max_size = FLASH_BUF_MAX_SIZE(idx), \
}; \
PM_DEVICE_DT_DEFINE(I2C(idx), twim_nrfx_pm_action); \
DEVICE_DT_DEFINE(I2C(idx), \
I2C_DEVICE_DT_DEFINE(I2C(idx), \
twim_##idx##_init, \
PM_DEVICE_DT_REF(I2C(idx)), \
&twim_##idx##_data, \

View file

@ -367,7 +367,7 @@ static const struct i2c_driver_api i2c_rcar_driver_api = {
\
static struct i2c_rcar_data i2c_rcar_data_##n; \
\
DEVICE_DT_INST_DEFINE(n, \
I2C_DEVICE_DT_INST_DEFINE(n, \
i2c_rcar_init, \
NULL, \
&i2c_rcar_data_##n, \

View file

@ -264,8 +264,8 @@ static const struct i2c_driver_api rv32m1_lpi2c_driver_api = {
.completion_sync = Z_SEM_INITIALIZER( \
rv32m1_lpi2c_##id##_data.completion_sync, 0, 1), \
}; \
DEVICE_DT_INST_DEFINE(id, \
&rv32m1_lpi2c_init, \
I2C_DEVICE_DT_INST_DEFINE(id, \
rv32m1_lpi2c_init, \
NULL, \
&rv32m1_lpi2c_##id##_data, \
&rv32m1_lpi2c_##id##_config, \

View file

@ -807,8 +807,8 @@ static const struct i2c_sam0_dev_config i2c_sam0_dev_config_##n = { \
static void i2c_sam0_irq_config_##n(const struct device *dev); \
I2C_SAM0_CONFIG(n); \
static struct i2c_sam0_dev_data i2c_sam0_dev_data_##n; \
DEVICE_DT_INST_DEFINE(n, \
&i2c_sam0_initialize, \
I2C_DEVICE_DT_INST_DEFINE(n, \
i2c_sam0_initialize, \
NULL, \
&i2c_sam0_dev_data_##n, \
&i2c_sam0_dev_config_##n, POST_KERNEL, \

View file

@ -628,7 +628,7 @@ static const struct i2c_driver_api i2c_sam_twim_driver_api = {
\
static struct i2c_sam_twim_dev_data i2c##n##_sam_data; \
\
DEVICE_DT_INST_DEFINE(n, &i2c_sam_twim_initialize, \
I2C_DEVICE_DT_INST_DEFINE(n, i2c_sam_twim_initialize, \
NULL, \
&i2c##n##_sam_data, &i2c##n##_sam_config, \
POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \

View file

@ -360,7 +360,7 @@ static const struct i2c_driver_api i2c_sam_twi_driver_api = {
\
static struct i2c_sam_twi_dev_data i2c##n##_sam_data; \
\
DEVICE_DT_INST_DEFINE(n, &i2c_sam_twi_initialize, \
I2C_DEVICE_DT_INST_DEFINE(n, i2c_sam_twi_initialize, \
NULL, \
&i2c##n##_sam_data, &i2c##n##_sam_config, \
POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \

View file

@ -347,7 +347,7 @@ static const struct i2c_driver_api i2c_sam_twihs_driver_api = {
\
static struct i2c_sam_twihs_dev_data i2c##n##_sam_data; \
\
DEVICE_DT_INST_DEFINE(n, &i2c_sam_twihs_initialize, \
I2C_DEVICE_DT_INST_DEFINE(n, i2c_sam_twihs_initialize, \
NULL, \
&i2c##n##_sam_data, &i2c##n##_sam_config, \
POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \

View file

@ -116,7 +116,7 @@ static const struct i2c_sbcon_config i2c_sbcon_dev_cfg_##_num = { \
.sbcon = (void *)DT_INST_REG_ADDR(_num), \
}; \
\
DEVICE_DT_INST_DEFINE(_num, \
I2C_DEVICE_DT_INST_DEFINE(_num, \
i2c_sbcon_init, \
NULL, \
&i2c_sbcon_dev_data_##_num, \

View file

@ -329,7 +329,7 @@ static struct i2c_driver_api i2c_sifive_api = {
.f_sys = DT_INST_PROP(n, input_frequency), \
.f_bus = DT_INST_PROP(n, clock_frequency), \
}; \
DEVICE_DT_INST_DEFINE(n, \
I2C_DEVICE_DT_INST_DEFINE(n, \
i2c_sifive_init, \
NULL, \
NULL, \

View file

@ -158,7 +158,7 @@ const struct i2c_driver_api tca9546a_api_funcs = {
static struct tca9546a_root_data tca9546a_data_##inst = { \
.lock = Z_MUTEX_INITIALIZER(tca9546a_data_##inst.lock), \
}; \
DEVICE_DT_INST_DEFINE(inst, \
I2C_DEVICE_DT_INST_DEFINE(inst, \
tca9546_root_init, NULL, \
&tca9546a_data_##inst, &tca9546a_cfg_##inst, \
POST_KERNEL, CONFIG_I2C_TCA9546_ROOT_INIT_PRIO, \

View file

@ -38,7 +38,7 @@ static int vnd_i2c_init(const struct device *dev)
}
#define VND_I2C_INIT(n) \
DEVICE_DT_INST_DEFINE(n, &vnd_i2c_init, NULL, \
I2C_DEVICE_DT_INST_DEFINE(n, vnd_i2c_init, NULL, \
NULL, NULL, POST_KERNEL, \
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
&vnd_i2c_api);

View file

@ -92,6 +92,31 @@ typedef int16_t device_handle_t;
DEVICE_DEFINE(Z_SYS_NAME(init_fn), drv_name, init_fn, NULL, \
NULL, NULL, level, prio, NULL)
/* Node paths can exceed the maximum size supported by device_get_binding() in user mode,
* so synthesize a unique dev_name from the devicetree node.
*
* The ordinal used in this name can be mapped to the path by
* examining zephyr/include/generated/device_extern.h header. If the
* format of this conversion changes, gen_defines should be updated to
* match it.
*/
#define Z_DEVICE_DT_DEV_NAME(node_id) _CONCAT(dts_ord_, DT_DEP_ORD(node_id))
/* Synthesize a unique name for the device state associated with
* dev_name.
*/
#define Z_DEVICE_STATE_NAME(dev_name) _CONCAT(__devstate_, dev_name)
/**
* @brief Utility macro to define and initialize the device state.
*
* @param node_id Devicetree node id of the device.
* @param dev_name Device name.
*/
#define Z_DEVICE_STATE_DEFINE(node_id, dev_name) \
static struct device_state Z_DEVICE_STATE_NAME(dev_name) \
__attribute__((__section__(".z_devstate")));
/**
* @def DEVICE_DEFINE
*
@ -129,9 +154,11 @@ typedef int16_t device_handle_t;
*/
#define DEVICE_DEFINE(dev_name, drv_name, init_fn, pm_device, \
data_ptr, cfg_ptr, level, prio, api_ptr) \
Z_DEVICE_STATE_DEFINE(DT_INVALID_NODE, dev_name) \
Z_DEVICE_DEFINE(DT_INVALID_NODE, dev_name, drv_name, init_fn, \
pm_device, \
data_ptr, cfg_ptr, level, prio, api_ptr)
data_ptr, cfg_ptr, level, prio, api_ptr, \
&Z_DEVICE_STATE_NAME(dev_name))
/**
* @def DEVICE_DT_NAME
@ -187,11 +214,14 @@ typedef int16_t device_handle_t;
#define DEVICE_DT_DEFINE(node_id, init_fn, pm_device, \
data_ptr, cfg_ptr, level, prio, \
api_ptr, ...) \
Z_DEVICE_STATE_DEFINE(node_id, Z_DEVICE_DT_DEV_NAME(node_id)) \
Z_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_NAME(node_id), \
DEVICE_DT_NAME(node_id), init_fn, \
pm_device, \
data_ptr, cfg_ptr, level, prio, \
api_ptr, __VA_ARGS__)
api_ptr, \
&Z_DEVICE_STATE_NAME(Z_DEVICE_DT_DEV_NAME(node_id)), \
__VA_ARGS__)
/**
* @def DEVICE_DT_INST_DEFINE
@ -693,21 +723,6 @@ static inline bool device_is_ready(const struct device *dev)
* @}
*/
/* Node paths can exceed the maximum size supported by device_get_binding() in user mode,
* so synthesize a unique dev_name from the devicetree node.
*
* The ordinal used in this name can be mapped to the path by
* examining zephyr/include/generated/device_extern.h header. If the
* format of this conversion changes, gen_defines should be updated to
* match it.
*/
#define Z_DEVICE_DT_DEV_NAME(node_id) _CONCAT(dts_ord_, DT_DEP_ORD(node_id))
/* Synthesize a unique name for the device state associated with
* dev_name.
*/
#define Z_DEVICE_STATE_NAME(dev_name) _CONCAT(__devstate_, dev_name)
/** Synthesize the name of the object that holds device ordinal and
* dependency data. If the object doesn't come from a devicetree
* node, use dev_name.
@ -735,8 +750,7 @@ static inline bool device_is_ready(const struct device *dev)
* include power management and dependency handles.
*/
#define Z_DEVICE_DEFINE_PRE(node_id, dev_name, ...) \
Z_DEVICE_DEFINE_HANDLES(node_id, dev_name, __VA_ARGS__) \
Z_DEVICE_STATE_DEFINE(node_id, dev_name)
Z_DEVICE_DEFINE_HANDLES(node_id, dev_name, __VA_ARGS__)
/* Initial build provides a record that associates the device object
* with its devicetree ordinal, and provides the dependency ordinals.
@ -805,7 +819,7 @@ BUILD_ASSERT(sizeof(device_handle_t) == 2, "fix the linker scripts");
* dependency handles that come from outside devicetree.
*/
#define Z_DEVICE_DEFINE(node_id, dev_name, drv_name, init_fn, pm_device,\
data_ptr, cfg_ptr, level, prio, api_ptr, ...) \
data_ptr, cfg_ptr, level, prio, api_ptr, state_ptr, ...) \
Z_DEVICE_DEFINE_PRE(node_id, dev_name, __VA_ARGS__) \
COND_CODE_1(DT_NODE_EXISTS(node_id), (), (static)) \
const Z_DECL_ALIGN(struct device) \
@ -814,7 +828,7 @@ BUILD_ASSERT(sizeof(device_handle_t) == 2, "fix the linker scripts");
.name = drv_name, \
.config = (cfg_ptr), \
.api = (api_ptr), \
.state = &Z_DEVICE_STATE_NAME(dev_name), \
.state = (state_ptr), \
.data = (data_ptr), \
COND_CODE_1(CONFIG_PM_DEVICE, (.pm = pm_device,), ()) \
Z_DEVICE_DEFINE_INIT(node_id, dev_name) \

View file

@ -337,6 +337,163 @@ struct i2c_slave_config {
const struct i2c_slave_callbacks *callbacks;
};
#if defined(CONFIG_I2C_STATS) || defined(__DOXYGEN__)
#include <stats/stats.h>
/** @cond INTERNAL_HIDDEN */
STATS_SECT_START(i2c)
STATS_SECT_ENTRY32(bytes_read)
STATS_SECT_ENTRY32(bytes_written)
STATS_SECT_ENTRY32(message_count)
STATS_SECT_ENTRY32(transfer_call_count)
STATS_SECT_END;
STATS_NAME_START(i2c)
STATS_NAME(i2c, bytes_read)
STATS_NAME(i2c, bytes_written)
STATS_NAME(i2c, message_count)
STATS_NAME(i2c, transfer_call_count)
STATS_NAME_END(i2c);
/** @endcond */
/**
* @brief I2C specific device state which allows for i2c device class specific additions
*/
struct i2c_device_state {
struct device_state devstate;
struct stats_i2c stats;
};
/**
* @brief Updates the i2c stats for i2c transfers
*
* @param dev I2C device to update stats for
* @param msgs Array of struct i2c_msg
* @param num_msgs Number of i2c_msgs
*/
static inline void i2c_xfer_stats(const struct device *dev, struct i2c_msg *msgs,
uint8_t num_msgs)
{
struct i2c_device_state *state =
CONTAINER_OF(dev->state, struct i2c_device_state, devstate);
uint32_t bytes_read = 0U;
uint32_t bytes_written = 0U;
STATS_INC(state->stats, transfer_call_count);
STATS_INCN(state->stats, message_count, num_msgs);
for (uint8_t i = 0U; i < num_msgs; i++) {
if (msgs[i].flags & I2C_MSG_READ) {
bytes_read += msgs[i].len;
}
if (msgs[i].flags & I2C_MSG_WRITE) {
bytes_written += msgs[i].len;
}
}
STATS_INCN(state->stats, bytes_read, bytes_read);
STATS_INCN(state->stats, bytes_written, bytes_written);
}
/** @cond INTERNAL_HIDDEN */
/**
* @brief Define a statically allocated and section assigned i2c device state
*/
#define Z_I2C_DEVICE_STATE_DEFINE(node_id, dev_name) \
static struct i2c_device_state Z_DEVICE_STATE_NAME(dev_name) \
__attribute__((__section__(".z_devstate")));
/**
* @brief Define an i2c device init wrapper function
*
* This does device instance specific initialization of common data (such as stats)
* and calls the given init_fn
*/
#define Z_I2C_INIT_FN(dev_name, init_fn) \
static inline int UTIL_CAT(dev_name, _init)(const struct device *dev) \
{ \
struct i2c_device_state *state = \
CONTAINER_OF(dev->state, struct i2c_device_state, devstate); \
stats_init(&state->stats.s_hdr, STATS_SIZE_32, 4, \
STATS_NAME_INIT_PARMS(i2c)); \
stats_register(dev->name, &(state->stats.s_hdr)); \
return init_fn(dev); \
}
/** @endcond */
/**
* @brief Like DEVICE_DT_DEFINE() with I2C specifics.
*
* @details Defines a device which implements the I2C API. May
* generate a custom device_state container struct and init_fn
* wrapper when needed depending on I2C @kconfig{CONFIG_I2C_STATS}.
*
* @param node_id The devicetree node identifier.
*
* @param init_fn Name of the init function of the driver.
*
* @param pm_device PM device resources reference (NULL if device does not use PM).
*
* @param data_ptr Pointer to the device's private data.
*
* @param cfg_ptr The address to the structure containing the
* configuration information for this instance of the driver.
*
* @param level The initialization level. See SYS_INIT() for
* details.
*
* @param prio Priority within the selected initialization level. See
* SYS_INIT() for details.
*
* @param api_ptr Provides an initial pointer to the API function struct
* used by the driver. Can be NULL.
*/
#define I2C_DEVICE_DT_DEFINE(node_id, init_fn, pm_device, \
data_ptr, cfg_ptr, level, prio, \
api_ptr, ...) \
Z_I2C_DEVICE_STATE_DEFINE(node_id, Z_DEVICE_DT_DEV_NAME(node_id)); \
Z_I2C_INIT_FN(Z_DEVICE_DT_DEV_NAME(node_id), init_fn) \
Z_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_NAME(node_id), \
DEVICE_DT_NAME(node_id), \
&UTIL_CAT(Z_DEVICE_DT_DEV_NAME(node_id), _init), \
pm_device, \
data_ptr, cfg_ptr, level, prio, \
api_ptr, \
&(Z_DEVICE_STATE_NAME(Z_DEVICE_DT_DEV_NAME(node_id)).devstate), \
__VA_ARGS__)
#else /* CONFIG_I2C_STATS */
static inline void i2c_xfer_stats(const struct device *dev, struct i2c_msg *msgs,
uint8_t num_msgs)
{
}
#define I2C_DEVICE_DT_DEFINE(node_id, init_fn, pm_device, \
data_ptr, cfg_ptr, level, prio, \
api_ptr, ...) \
DEVICE_DT_DEFINE(node_id, &init_fn, pm_device, \
data_ptr, cfg_ptr, level, prio, \
api_ptr, __VA_ARGS__)
#endif /* CONFIG_I2C_STATS */
/**
* @brief Like I2C_DEVICE_DT_DEFINE() for an instance of a DT_DRV_COMPAT compatible
*
* @param inst instance number. This is replaced by
* <tt>DT_DRV_COMPAT(inst)</tt> in the call to I2C_DEVICE_DT_DEFINE().
*
* @param ... other parameters as expected by I2C_DEVICE_DT_DEFINE().
*/
#define I2C_DEVICE_DT_INST_DEFINE(inst, ...) \
I2C_DEVICE_DT_DEFINE(DT_DRV_INST(inst), __VA_ARGS__)
/**
* @brief Configure operation of a host controller.
*
@ -429,7 +586,11 @@ static inline int z_impl_i2c_transfer(const struct device *dev,
const struct i2c_driver_api *api =
(const struct i2c_driver_api *)dev->api;
return api->transfer(dev, msgs, num_msgs, addr);
int res = api->transfer(dev, msgs, num_msgs, addr);
i2c_xfer_stats(dev, msgs, num_msgs);
return res;
}
/**

View file

@ -828,9 +828,10 @@ static inline bool net_eth_get_vlan_status(struct net_if *iface)
#if defined(CONFIG_NET_VLAN)
#define Z_ETH_NET_DEVICE_INIT(node_id, dev_name, drv_name, init_fn, \
pm_action_cb, data, cfg, prio, api, mtu) \
Z_DEVICE_STATE_DEFINE(node_id, dev_name) \
Z_DEVICE_DEFINE(node_id, dev_name, drv_name, init_fn, \
pm_action_cb, data, cfg, POST_KERNEL, \
prio, api); \
prio, api, &Z_DEVICE_STATE_NAME(dev_name)); \
NET_L2_DATA_INIT(dev_name, 0, NET_L2_GET_CTX_TYPE(ETHERNET_L2));\
NET_IF_INIT(dev_name, 0, ETHERNET_L2, mtu, NET_VLAN_MAX_COUNT)

View file

@ -2250,9 +2250,11 @@ struct net_if_api {
#define Z_NET_DEVICE_INIT(node_id, dev_name, drv_name, init_fn, \
pm_action_cb, data, cfg, prio, api, l2, \
l2_ctx_type, mtu) \
Z_DEVICE_STATE_DEFINE(node_id, dev_name) \
Z_DEVICE_DEFINE(node_id, dev_name, drv_name, init_fn, \
pm_action_cb, data, \
cfg, POST_KERNEL, prio, api); \
cfg, POST_KERNEL, prio, api, \
&Z_DEVICE_STATE_NAME(dev_name)); \
NET_L2_DATA_INIT(dev_name, 0, l2_ctx_type); \
NET_IF_INIT(dev_name, 0, l2, mtu, NET_IF_MAX_CONFIGS)
@ -2328,9 +2330,10 @@ struct net_if_api {
instance, init_fn, pm_action_cb, \
data, cfg, prio, api, l2, \
l2_ctx_type, mtu) \
Z_DEVICE_STATE_DEFINE(node_id, dev_name) \
Z_DEVICE_DEFINE(node_id, dev_name, drv_name, init_fn, \
pm_action_cb, data, cfg, POST_KERNEL, \
prio, api); \
prio, api, &Z_DEVICE_STATE_NAME(dev_name)); \
NET_L2_DATA_INIT(dev_name, instance, l2_ctx_type); \
NET_IF_INIT(dev_name, instance, l2, mtu, NET_IF_MAX_CONFIGS)
@ -2417,8 +2420,10 @@ struct net_if_api {
#define Z_NET_DEVICE_OFFLOAD_INIT(node_id, dev_name, drv_name, init_fn, \
pm_action_cb, data, cfg, prio, \
api, mtu) \
Z_DEVICE_STATE_DEFINE(node_id, dev_name) \
Z_DEVICE_DEFINE(node_id, dev_name, drv_name, init_fn, \
pm_action_cb, data, cfg, POST_KERNEL, prio, api);\
pm_action_cb, data, cfg, POST_KERNEL, prio, api, \
&Z_DEVICE_STATE_NAME(dev_name)); \
NET_IF_OFFLOAD_INIT(dev_name, 0, mtu)
/**

View file

@ -373,7 +373,7 @@ struct stats_hdr *stats_group_find(const char *name);
#define STATS_NAME_MAP_NAME(sectname__) stats_map_ ## sectname__
#define STATS_NAME_START(sectname__) \
const struct stats_name_map STATS_NAME_MAP_NAME(sectname__)[] = {
static const struct stats_name_map STATS_NAME_MAP_NAME(sectname__)[] = {
#define STATS_NAME(sectname__, entry__) \
{ offsetof(STATS_SECT_DECL(sectname__), entry__), #entry__ },