test: sensor: ina230: Add INA236

Update tests to validate INA236 chip

Signed-off-by: Tomáš Juřena <jurenatomas@gmail.com>
This commit is contained in:
Tomáš Juřena 2024-08-23 16:11:09 +02:00 committed by Anas Nashif
commit 953436b185
4 changed files with 123 additions and 52 deletions

View file

@ -15,4 +15,12 @@
current-lsb-microamps = <1000>; current-lsb-microamps = <1000>;
status = "okay"; status = "okay";
}; };
ina236_default_test: ina236@41 {
compatible = "ti,ina236";
reg = <0x41>;
rshunt-micro-ohms = <2000>;
current-lsb-microamps = <1000>;
status = "okay";
};
}; };

View file

@ -5,7 +5,6 @@
* *
* Emulator for the TI INA230 I2C power monitor * Emulator for the TI INA230 I2C power monitor
*/ */
#define DT_DRV_COMPAT ti_ina230
#include <zephyr/device.h> #include <zephyr/device.h>
#include <zephyr/drivers/emul.h> #include <zephyr/drivers/emul.h>
@ -30,17 +29,23 @@ struct ina230_emul_cfg {
uint16_t addr; uint16_t addr;
}; };
#define MAX_REGS 0xff
struct ina230_emul_data { struct ina230_emul_data {
struct ina230_reg ina230_regs[INA230_REGISTER_COUNT]; struct ina230_reg *regs;
}; };
static struct ina230_reg *get_register(struct ina230_emul_data *data, int reg) static struct ina230_reg *get_register(struct ina230_emul_data *data, int reg)
{ {
for (int i = 0; i < INA230_REGISTER_COUNT; i++) { struct ina230_reg *c_reg = data->regs;
if (data->ina230_regs[i].id == reg) {
return &data->ina230_regs[i]; while (c_reg->bytes) {
if (c_reg->id == reg) {
return c_reg;
} }
c_reg++;
} }
return NULL; return NULL;
} }
@ -151,22 +156,40 @@ static const struct i2c_emul_api ina230_emul_api_i2c = {
.transfer = ina230_emul_transfer_i2c, .transfer = ina230_emul_transfer_i2c,
}; };
#define INA230_EMUL(n) \ /* clang-format off */
static const struct ina230_emul_cfg ina230_emul_cfg_##n = { \
.addr = DT_INST_REG_ADDR(n), \
}; \
static struct ina230_emul_data ina230_emul_data_##n = { \
.ina230_regs = { \
{INA230_REG_CONFIG, 2, 0x4127}, \
{INA230_REG_SHUNT_VOLT, 2, 0}, \
{INA230_REG_BUS_VOLT, 2, 0}, \
{INA230_REG_POWER, 2, 0}, \
{INA230_REG_CURRENT, 2, 0}, \
{INA230_REG_CALIB, 2, 0}, \
{INA230_REG_MASK, 2, 0}, \
{INA230_REG_ALERT, 2, 0}, \
}}; \
EMUL_DT_INST_DEFINE(n, ina230_emul_init, &ina230_emul_data_##n, &ina230_emul_cfg_##n, \
&ina230_emul_api_i2c, NULL)
DT_INST_FOREACH_STATUS_OKAY(INA230_EMUL) #define CREATE_INA230_REGS \
{INA230_REG_CONFIG, 2, 0x4127}, \
{INA230_REG_SHUNT_VOLT, 2, 0}, \
{INA230_REG_BUS_VOLT, 2, 0}, \
{INA230_REG_POWER, 2, 0}, \
{INA230_REG_CURRENT, 2, 0}, \
{INA230_REG_CALIB, 2, 0}, \
{INA230_REG_MASK, 2, 0}, \
{INA230_REG_ALERT, 2, 0}
#define CREATE_INA236_REGS \
CREATE_INA230_REGS, \
{INA236_REG_MANUFACTURER_ID, 2, 0x449}, \
{INA236_REG_DEVICE_ID, 2, 0xa080}
/* clang-format on */
#define INA230_EMUL(n, v) \
static const struct ina230_emul_cfg ina23##v##_emul_cfg_##n = { \
.addr = DT_INST_REG_ADDR(n), \
}; \
static struct ina230_reg ina23##v##_regs_##n[] = {CREATE_INA23##v##_REGS, {}}; \
static struct ina230_emul_data ina23##v##_emul_data_##n = { \
.regs = (struct ina230_reg *)ina23##v##_regs_##n, \
}; \
EMUL_DT_INST_DEFINE(n, ina230_emul_init, &ina23##v##_emul_data_##n, \
&ina23##v##_emul_cfg_##n, &ina230_emul_api_i2c, NULL)
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT ti_ina230
DT_INST_FOREACH_STATUS_OKAY_VARGS(INA230_EMUL, 0)
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT ti_ina236
DT_INST_FOREACH_STATUS_OKAY_VARGS(INA230_EMUL, 6)

View file

@ -9,6 +9,7 @@
#define INA230_EMUL_H_ #define INA230_EMUL_H_
#define INA230_REGISTER_COUNT 8 #define INA230_REGISTER_COUNT 8
#define INA236_REGISTER_COUNT 2
int ina230_mock_set_register(void *data_ptr, int reg, uint32_t value); int ina230_mock_set_register(void *data_ptr, int reg, uint32_t value);
int ina230_mock_get_register(void *data_ptr, int reg, uint32_t *value_ptr); int ina230_mock_get_register(void *data_ptr, int reg, uint32_t *value_ptr);

View file

@ -14,12 +14,18 @@
#include <ina230_emul.h> #include <ina230_emul.h>
#include <ina230.h> #include <ina230.h>
enum ina23x_ids {
INA230,
INA236
};
struct ina230_fixture { struct ina230_fixture {
const struct device *dev; const struct device *dev;
const struct emul *mock; const struct emul *mock;
const uint16_t current_lsb_uA; const uint16_t current_lsb_uA;
const uint16_t rshunt_uOhms; const uint16_t rshunt_uOhms;
const uint16_t config; const uint16_t config;
const enum ina23x_ids dev_type;
}; };
/** /**
@ -44,6 +50,7 @@ ZTEST(ina230_0, test_default_config)
static void test_datasheet_example(struct ina230_fixture *fixture) static void test_datasheet_example(struct ina230_fixture *fixture)
{ {
struct sensor_value sensor_val; struct sensor_value sensor_val;
uint16_t raw_voltage, raw_current, raw_power;
double actual; double actual;
/* only run test for datasheet example of 1mA current LSB and 2 mOhm shunt */ /* only run test for datasheet example of 1mA current LSB and 2 mOhm shunt */
@ -51,9 +58,19 @@ static void test_datasheet_example(struct ina230_fixture *fixture)
ztest_test_skip(); ztest_test_skip();
} }
ina230_mock_set_register(fixture->mock->data, INA230_REG_BUS_VOLT, 9584); if (fixture->dev_type == INA230) {
ina230_mock_set_register(fixture->mock->data, INA230_REG_CURRENT, 10000); raw_voltage = 9584;
ina230_mock_set_register(fixture->mock->data, INA230_REG_POWER, 4792); raw_current = 10000;
raw_power = 4792;
} else {
raw_voltage = 7487;
raw_current = 10000;
raw_power = 3744;
}
ina230_mock_set_register(fixture->mock->data, INA230_REG_BUS_VOLT, raw_voltage);
ina230_mock_set_register(fixture->mock->data, INA230_REG_CURRENT, raw_current);
ina230_mock_set_register(fixture->mock->data, INA230_REG_POWER, raw_power);
zassert_ok(sensor_sample_fetch(fixture->dev)); zassert_ok(sensor_sample_fetch(fixture->dev));
zassert_ok(sensor_channel_get(fixture->dev, SENSOR_CHAN_VOLTAGE, &sensor_val)); zassert_ok(sensor_channel_get(fixture->dev, SENSOR_CHAN_VOLTAGE, &sensor_val));
@ -136,6 +153,8 @@ static void test_bus_voltage(struct ina230_fixture *fixture)
0, 0,
}; };
double bitres = fixture->dev_type == INA236 ? 1.6e-3 : 1.25e-3;
for (int idx = 0; idx < ARRAY_SIZE(voltage_reg_vectors); idx++) { for (int idx = 0; idx < ARRAY_SIZE(voltage_reg_vectors); idx++) {
struct sensor_value sensor_val; struct sensor_value sensor_val;
@ -147,7 +166,7 @@ static void test_bus_voltage(struct ina230_fixture *fixture)
zassert_ok(sensor_channel_get(fixture->dev, SENSOR_CHAN_VOLTAGE, &sensor_val)); zassert_ok(sensor_channel_get(fixture->dev, SENSOR_CHAN_VOLTAGE, &sensor_val));
double voltage_actual_V = sensor_value_to_double(&sensor_val); double voltage_actual_V = sensor_value_to_double(&sensor_val);
double voltage_expected_V = voltage_reg_vectors[idx] * 1.25e-3; double voltage_expected_V = voltage_reg_vectors[idx] * bitres;
zexpect_within(voltage_expected_V, voltage_actual_V, 1e-6, zexpect_within(voltage_expected_V, voltage_actual_V, 1e-6,
"Expected %.6f A, got %.6f A", voltage_expected_V, voltage_actual_V); "Expected %.6f A, got %.6f A", voltage_expected_V, voltage_actual_V);
@ -167,12 +186,14 @@ static void test_power(struct ina230_fixture *fixture)
0, 0,
}; };
int scale = fixture->dev_type == INA236 ? 32 : 25;
for (int idx = 0; idx < ARRAY_SIZE(power_reg_vectors); idx++) { for (int idx = 0; idx < ARRAY_SIZE(power_reg_vectors); idx++) {
struct sensor_value sensor_val; struct sensor_value sensor_val;
uint32_t power_register = power_reg_vectors[idx]; uint32_t power_register = power_reg_vectors[idx];
/* power is power_register * 25 * current_lsb */ /* power is power_register * SCALE * current_lsb */
double power_expected_W = power_register * 25 * fixture->current_lsb_uA * 1e-6; double power_expected_W = power_register * scale * fixture->current_lsb_uA * 1e-6;
/* set current reading */ /* set current reading */
ina230_mock_set_register(fixture->mock->data, INA230_REG_POWER, power_register); ina230_mock_set_register(fixture->mock->data, INA230_REG_POWER, power_register);
@ -183,33 +204,51 @@ static void test_power(struct ina230_fixture *fixture)
double power_actual_W = sensor_value_to_double(&sensor_val); double power_actual_W = sensor_value_to_double(&sensor_val);
zexpect_within(power_expected_W, power_actual_W, 1e-6, zexpect_within(power_expected_W, power_actual_W, 1e-6,
"Expected %.6f W, got %.6f W for %d", "Expected %.6f W, got %.6f W for %d", power_expected_W,
power_expected_W, power_actual_W, power_register); power_actual_W, power_register);
} }
} }
/* Create a test fixture for each enabled ina230 device node */ /* Create a test fixture for each enabled ina230 device node */
#define DT_DRV_COMPAT ti_ina230 #define INA230_FIXTURE_ENTRY(inst, v) \
#define INA230_FIXTURE_ENTRY(inst) \ static struct ina230_fixture fixture_23##v##_##inst = { \
{ \ .dev = DEVICE_DT_INST_GET(inst), \
.dev = DEVICE_DT_INST_GET(inst), \ .mock = EMUL_DT_GET(DT_DRV_INST(inst)), \
.mock = EMUL_DT_GET(DT_DRV_INST(inst)), \ .current_lsb_uA = DT_INST_PROP(inst, current_lsb_microamps), \
.current_lsb_uA = DT_INST_PROP(inst, current_lsb_microamps), \ .rshunt_uOhms = DT_INST_PROP(inst, rshunt_micro_ohms), \
.rshunt_uOhms = DT_INST_PROP(inst, rshunt_micro_ohms), \ .config = DT_INST_PROP(inst, config), \
.config = DT_INST_PROP(inst, config), \ .dev_type = INA23##v, \
}, }
static struct ina230_fixture fixtures[] = {
DT_INST_FOREACH_STATUS_OKAY(INA230_FIXTURE_ENTRY)
};
/* Create a test suite for each enabled ina230 device node */ /* Create a test suite for each enabled ina230 device node */
#define INA230_TESTS(inst) \ #define INA230_TESTS(inst, v) \
ZTEST(ina230_##inst, test_datasheet_example) { test_datasheet_example(&fixtures[inst]); } \ INA230_FIXTURE_ENTRY(inst, v); \
ZTEST(ina230_##inst, test_shunt_cal) { test_shunt_cal(&fixtures[inst]); } \ ZTEST(ina23##v##_##inst, test_datasheet_example) \
ZTEST(ina230_##inst, test_current) { test_current(&fixtures[inst]); } \ { \
ZTEST(ina230_##inst, test_bus_voltage) { test_bus_voltage(&fixtures[inst]); } \ test_datasheet_example(&fixture_23##v##_##inst); \
ZTEST(ina230_##inst, test_power) { test_power(&fixtures[inst]); } \ } \
ZTEST_SUITE(ina230_##inst, NULL, NULL, NULL, NULL, NULL); ZTEST(ina23##v##_##inst, test_shunt_cal) \
{ \
test_shunt_cal(&fixture_23##v##_##inst); \
} \
ZTEST(ina23##v##_##inst, test_current) \
{ \
test_current(&fixture_23##v##_##inst); \
} \
ZTEST(ina23##v##_##inst, test_bus_voltage) \
{ \
test_bus_voltage(&fixture_23##v##_##inst); \
} \
ZTEST(ina23##v##_##inst, test_power) \
{ \
test_power(&fixture_23##v##_##inst); \
} \
ZTEST_SUITE(ina23##v##_##inst, NULL, NULL, NULL, NULL, NULL);
DT_INST_FOREACH_STATUS_OKAY(INA230_TESTS) #undef DT_DRV_COMPAT
#define DT_DRV_COMPAT ti_ina230
DT_INST_FOREACH_STATUS_OKAY_VARGS(INA230_TESTS, 0)
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT ti_ina236
DT_INST_FOREACH_STATUS_OKAY_VARGS(INA230_TESTS, 6)