| /* |
| * 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); |
| } |