blob: 565af2fcfd64874d93b488a230e66f6573f7634b [file] [log] [blame]
/*
* Copyright (c) 2017 BayLibre, SAS
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <errno.h>
#include <string.h>
#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(main);
#include <zephyr.h>
#include <device.h>
#include <stdio.h>
#include <misc/util.h>
#include <i2c.h>
#include <drivers/i2c/slave/eeprom.h>
#include <ztest.h>
#define TEST_DATA_SIZE 20
static u8_t eeprom_0_data[TEST_DATA_SIZE] = "0123456789abcdefghij";
static u8_t eeprom_1_data[TEST_DATA_SIZE] = "jihgfedcba9876543210";
static u8_t i2c_buffer[TEST_DATA_SIZE];
/*
* We need 5x(buffer size) + 1 to print a comma-separated list of each
* byte in hex, plus a null.
*/
u8_t buffer_print_eeprom[TEST_DATA_SIZE * 5 + 1];
u8_t buffer_print_i2c[TEST_DATA_SIZE * 5 + 1];
static void to_display_format(const u8_t *src, size_t size, char *dst)
{
size_t i;
for (i = 0; i < size; i++) {
sprintf(dst + 5 * i, "0x%02x,", src[i]);
}
}
static void run_full_read(struct device *i2c, u8_t addr, u8_t *comp_buffer)
{
int ret;
LOG_INF("Start full read. Master: %s, address: 0x%x",
i2c->config->name, addr);
/* Read EEPROM from I2C Master requests, then compare */
ret = i2c_burst_read(i2c, addr,
0, i2c_buffer, TEST_DATA_SIZE);
zassert_equal(ret, 0, "Failed to read EEPROM");
if (memcmp(i2c_buffer, comp_buffer, TEST_DATA_SIZE)) {
to_display_format(i2c_buffer, TEST_DATA_SIZE,
buffer_print_i2c);
to_display_format(comp_buffer, TEST_DATA_SIZE,
buffer_print_eeprom);
LOG_ERR("Buffer contents are different: %s",
buffer_print_i2c);
LOG_ERR(" vs: %s",
buffer_print_eeprom);
ztest_test_fail();
}
}
static void run_partial_read(struct device *i2c, u8_t addr, u8_t *comp_buffer,
unsigned int offset)
{
int ret;
LOG_INF("Start partial read. Master: %s, address: 0x%x, off=%d",
i2c->config->name, addr, offset);
ret = i2c_burst_read(i2c, addr,
offset, i2c_buffer, TEST_DATA_SIZE-offset);
zassert_equal(ret, 0, "Failed to read EEPROM");
if (memcmp(i2c_buffer, &comp_buffer[offset], TEST_DATA_SIZE-offset)) {
to_display_format(i2c_buffer, TEST_DATA_SIZE-offset,
buffer_print_i2c);
to_display_format(&comp_buffer[offset], TEST_DATA_SIZE-offset,
buffer_print_eeprom);
LOG_ERR("Buffer contents are different: %s",
buffer_print_i2c);
LOG_ERR(" vs: %s",
buffer_print_eeprom);
ztest_test_fail();
}
}
static void run_program_read(struct device *i2c, u8_t addr, unsigned int offset)
{
int ret, i;
LOG_INF("Start program. Master: %s, address: 0x%x, off=%d",
i2c->config->name, addr, offset);
for (i = 0 ; i < TEST_DATA_SIZE-offset ; ++i) {
i2c_buffer[i] = i;
}
ret = i2c_burst_write(i2c, addr,
offset, i2c_buffer, TEST_DATA_SIZE-offset);
zassert_equal(ret, 0, "Failed to write EEPROM");
(void)memset(i2c_buffer, 0xFF, TEST_DATA_SIZE);
/* Read back EEPROM from I2C Master requests, then compare */
ret = i2c_burst_read(i2c, addr,
offset, i2c_buffer, TEST_DATA_SIZE-offset);
zassert_equal(ret, 0, "Failed to read EEPROM");
for (i = 0 ; i < TEST_DATA_SIZE-offset ; ++i) {
if (i2c_buffer[i] != i) {
to_display_format(i2c_buffer, TEST_DATA_SIZE-offset,
buffer_print_i2c);
LOG_ERR("Invalid Buffer content: %s",
buffer_print_i2c);
ztest_test_fail();
}
}
}
void test_eeprom_slave(void)
{
struct device *eeprom_0;
struct device *eeprom_1;
struct device *i2c_0;
struct device *i2c_1;
int ret, offset;
i2c_0 = device_get_binding(
DT_ATMEL_AT24_0_BUS_NAME);
zassert_not_null(i2c_0, "I2C device %s not found",
DT_ATMEL_AT24_0_BUS_NAME);
LOG_INF("Found I2C Master device %s",
DT_ATMEL_AT24_0_BUS_NAME);
i2c_1 = device_get_binding(
DT_ATMEL_AT24_1_BUS_NAME);
zassert_not_null(i2c_1, "I2C device %s not found",
DT_ATMEL_AT24_1_BUS_NAME);
LOG_INF("Found I2C Master device %s",
DT_ATMEL_AT24_1_BUS_NAME);
/*
* Normal applications would interact with an EEPROM
* identified by the string literal used in the binding node
* label property ("EEPROM_SLAVE_0") rather than the generated
* macro DT_ATMEL_AT24_0_LABEL. There is no guarantee that
* the index for the compatible is persistent across builds;
* for example DT_ATMEL_AT24_0 might refer to "EEPROM_SLAVE_1"
* if the order of the node declarations were changed in the
* overlay file.
*
* The label string cannot be directly used to determine the
* correct parent bus and device index for whitebox testing in
* this application. So for this application only, where the
* devices are interchangeable, the device is selected the
* using the generated macro.
*/
eeprom_0 = device_get_binding(DT_ATMEL_AT24_0_LABEL);
zassert_not_null(eeprom_0, "EEPROM device %s not found",
DT_ATMEL_AT24_0_LABEL);
LOG_INF("Found EEPROM device %s", DT_ATMEL_AT24_0_LABEL);
eeprom_1 = device_get_binding(DT_ATMEL_AT24_1_LABEL);
zassert_not_null(eeprom_1, "EEPROM device %s not found",
DT_ATMEL_AT24_1_LABEL);
LOG_INF("Found EEPROM device %s", DT_ATMEL_AT24_1_LABEL);
/* Program dummy bytes */
ret = eeprom_slave_program(eeprom_0, eeprom_0_data, TEST_DATA_SIZE);
zassert_equal(ret, 0, "Failed to program EEPROM %s",
DT_ATMEL_AT24_0_LABEL);
ret = eeprom_slave_program(eeprom_1, eeprom_1_data, TEST_DATA_SIZE);
zassert_equal(ret, 0, "Failed to program EEPROM %s",
DT_ATMEL_AT24_1_LABEL);
/* Attach EEPROM */
ret = i2c_slave_driver_register(eeprom_0);
zassert_equal(ret, 0, "Failed to register EEPROM %s",
DT_ATMEL_AT24_0_LABEL);
LOG_INF("EEPROM %s Attached !", DT_ATMEL_AT24_0_LABEL);
ret = i2c_slave_driver_register(eeprom_1);
zassert_equal(ret, 0, "Failed to register EEPROM %s",
DT_ATMEL_AT24_1_LABEL);
LOG_INF("EEPROM %s Attached !", DT_ATMEL_AT24_1_LABEL);
/* Run Tests without bus access conflicts */
run_full_read(i2c_0, DT_ATMEL_AT24_1_BASE_ADDRESS, eeprom_1_data);
run_full_read(i2c_1, DT_ATMEL_AT24_0_BASE_ADDRESS, eeprom_0_data);
for (offset = 0 ; offset < TEST_DATA_SIZE-1 ; ++offset) {
run_partial_read(i2c_0, DT_ATMEL_AT24_1_BASE_ADDRESS,
eeprom_1_data, offset);
}
for (offset = 0 ; offset < TEST_DATA_SIZE-1 ; ++offset) {
run_partial_read(i2c_1, DT_ATMEL_AT24_0_BASE_ADDRESS,
eeprom_0_data, offset);
}
for (offset = 0 ; offset < TEST_DATA_SIZE-1 ; ++offset) {
run_program_read(i2c_0, DT_ATMEL_AT24_1_BASE_ADDRESS,
offset);
}
for (offset = 0 ; offset < TEST_DATA_SIZE-1 ; ++offset) {
run_program_read(i2c_1, DT_ATMEL_AT24_0_BASE_ADDRESS,
offset);
}
LOG_INF("Success !");
/* Detach EEPROM */
ret = i2c_slave_driver_unregister(eeprom_0);
zassert_equal(ret, 0, "Failed to unregister EEPROM %s",
DT_ATMEL_AT24_0_LABEL);
LOG_INF("EEPROM %s Detached !",
DT_ATMEL_AT24_0_LABEL);
ret = i2c_slave_driver_unregister(eeprom_1);
zassert_equal(ret, 0, "Failed to unregister EEPROM %s",
DT_ATMEL_AT24_1_LABEL);
LOG_INF("EEPROM %s Detached !",
DT_ATMEL_AT24_1_LABEL);
}
void test_main(void)
{
ztest_test_suite(test_eeprom_slave, ztest_unit_test(test_eeprom_slave));
ztest_run_test_suite(test_eeprom_slave);
}