From ca902d0fc7f752be4568ee2a398e06cd1d657d94 Mon Sep 17 00:00:00 2001 From: Maciej Bocianski Date: Tue, 4 Dec 2018 11:10:37 +0100 Subject: [PATCH 1/3] Add Ice Tea I2C communication test --- TEST_APPS/device/i2c_com/common.cpp | 92 ++++ TEST_APPS/device/i2c_com/common.h | 95 ++++ TEST_APPS/device/i2c_com/main.cpp | 279 ++++++++++++ TEST_APPS/device/i2c_com/master.cpp | 478 ++++++++++++++++++++ TEST_APPS/device/i2c_com/master.h | 31 ++ TEST_APPS/device/i2c_com/mbed_app.json | 8 + TEST_APPS/device/i2c_com/slave.cpp | 287 ++++++++++++ TEST_APPS/device/i2c_com/slave.h | 39 ++ TEST_APPS/testcases/i2c_com/README.md | 57 +++ TEST_APPS/testcases/i2c_com/__init__.py | 0 TEST_APPS/testcases/i2c_com/i2c_Diagram.png | Bin 0 -> 4531 bytes TEST_APPS/testcases/i2c_com/test_i2c_com.py | 366 +++++++++++++++ 12 files changed, 1732 insertions(+) create mode 100644 TEST_APPS/device/i2c_com/common.cpp create mode 100644 TEST_APPS/device/i2c_com/common.h create mode 100644 TEST_APPS/device/i2c_com/main.cpp create mode 100644 TEST_APPS/device/i2c_com/master.cpp create mode 100644 TEST_APPS/device/i2c_com/master.h create mode 100644 TEST_APPS/device/i2c_com/mbed_app.json create mode 100644 TEST_APPS/device/i2c_com/slave.cpp create mode 100644 TEST_APPS/device/i2c_com/slave.h create mode 100644 TEST_APPS/testcases/i2c_com/README.md create mode 100644 TEST_APPS/testcases/i2c_com/__init__.py create mode 100644 TEST_APPS/testcases/i2c_com/i2c_Diagram.png create mode 100644 TEST_APPS/testcases/i2c_com/test_i2c_com.py diff --git a/TEST_APPS/device/i2c_com/common.cpp b/TEST_APPS/device/i2c_com/common.cpp new file mode 100644 index 00000000000..924e6298629 --- /dev/null +++ b/TEST_APPS/device/i2c_com/common.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2019, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" +#include +#include "drivers/DigitalOut.h" + +#if I2C_DEBUG_PIN_MASTER==1 || I2C_DEBUG_PIN_SLAVE==1 + +static mbed::DigitalOut test_pin(D8); + +void test_pin_init() +{ + test_pin.write(0); +} + + +void test_pin_toggle(int count) +{ + int cv = test_pin.read(); + for (int i = 0; i < count; i++) { + test_pin.write(cv == 0 ? 1 : 0); + } + test_pin.write(cv == 0 ? 0 : 1); +} + + +bool test_check(bool condition, const char *condition_str, const char *file, int line) +{ + if (!condition) { + printf("assertion failed: %s %s:%d\r\n", condition_str, file, line); + return false; + } else { + return true; + } +} + +#endif // I2C_DEBUG_PIN_MASTER==1 || I2C_DEBUG_PIN_SLAVE==1 + +bool test_check_message(bool condition, const char *condition_str, const char *message, const char *file, int line) +{ + if (!condition) { + printf("assertion failed: %s %s %s:%d\r\n", condition_str, message, file, line); + return false; + } else { + return true; + } +} + +bool test_check_equal_int(int32_t expected, int32_t actual, const char *file, int line) +{ + if (expected != actual) { + printf("assertion failed: %d != %d %s:%d\r\n", expected, actual, file, line); + return false; + } else { + return true; + } +} + +bool test_check_equal_uint(uint32_t expected, uint32_t actual, const char *file, int line) +{ + if (expected != actual) { + printf("assertion failed: %u != %u %s:%d\r\n", expected, actual, file, line); + return false; + } else { + return true; + } +} + +bool test_check_uint_within(uint32_t min, uint32_t max, uint32_t actual, const char *file, int line) +{ + if (actual < min || actual > max) { + printf("assertion failed: %u not in range (%u,%u) %s:%d\r\n", actual, min, max, file, line); + return false; + } else { + return true; + } +} diff --git a/TEST_APPS/device/i2c_com/common.h b/TEST_APPS/device/i2c_com/common.h new file mode 100644 index 00000000000..ec37cd557ce --- /dev/null +++ b/TEST_APPS/device/i2c_com/common.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2019, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mbed.h" + +#ifndef I2C_TEST_COMMON_H +#define I2C_TEST_COMMON_H + + +// uncomment this in order to test i2c driver layer +//#define TEST_I2C_DRIVER + +#define I2C_DEBUG 0 +#define I2C_DEBUG_PIN_SLAVE 0 +#define I2C_DEBUG_PIN_MASTER 0 + +#define EMPTY_PARAM_INT (-1) + + +#define MASTER_1_ID 111 +#define MASTER_2_ID 222 + +#define DEVICE_AS_MASTER false +#define DEVICE_AS_SLAVE true + +#define I2C_ADDRESS_MASK_7BIT (0x7F) +#define I2C_ADDRESS_MASK_10BIT (0x3FF) +#define I2C_10BIT_FIRST_BYTE (0xF0) + +// 7bit addressing, allowed values from 0x8 to 0x77 +#define I2C_7BIT_ADDRESS_MIN (0x08) +#define I2C_7BIT_ADDRESS_MAX (0x77) +#define I2C_7BIT_ADDRESS (0x55) + +#define MAKE_7BIT_SLAVE_ADDRESS(addr) ((I2C_ADDRESS_MASK_7BIT & addr) << 1) +#define MAKE_7BIT_READ_ADDRESS(addr) (((I2C_ADDRESS_MASK_7BIT & addr) << 1) | 1) +#define MAKE_7BIT_WRITE_ADDRESS(addr) ((I2C_ADDRESS_MASK_7BIT & addr) << 1) +#define MAKE_10BIT_READ_ADDRESS(addr) ((((I2C_10BIT_FIRST_BYTE | (((addr & I2C_ADDRESS_MASK_10BIT)) >> 7)) | 1) << 8) | (addr & 0xFF)) +#define MAKE_10BIT_WRITE_ADDRESS(addr) ((((I2C_10BIT_FIRST_BYTE | (((addr & I2C_ADDRESS_MASK_10BIT)) >> 7)) & ~1) << 8) | (addr & 0xFF)) + +void test_pin_init(); +void test_pin_toggle(int count = 1); + +#if I2C_DEBUG_PIN_SLAVE +#define SLAVE_PIN_TOGGLE(n) test_pin_toggle(n) +#else +#define SLAVE_PIN_TOGGLE(n) (void)0 +#endif + +#if I2C_DEBUG_PIN_MASTER +#define MASTER_PIN_TOGGLE(n) test_pin_toggle(n) +#else +#define MASTER_PIN_TOGGLE(n) (void)0 +#endif + +#if I2C_DEBUG +#define I2C_DEBUG_PRINTF(...) printf(__VA_ARGS__) +#else +#define I2C_DEBUG_PRINTF(...) (void)0 +#endif + +bool test_check(bool condition, const char *condition_str, const char *file, int line); +bool test_check_message(bool condition, const char *condition_str, const char *message, const char *file, int line); +bool test_check_equal_int(int32_t expected, int32_t actual, const char *file, int line); +bool test_check_equal_uint(uint32_t expected, uint32_t actual, const char *file, int line); +bool test_check_uint_within(uint32_t min, uint32_t max, uint32_t actual, const char *file, int line); + +#define TEST_CHECK(condition) test_check(condition, #condition, __FILE__, __LINE__) +#define TEST_CHECK_MESSAGE(condition, message) test_check_message(condition, #condition, message, __FILE__, __LINE__) +#define TEST_CHECK_EQUAL_INT(expected, actual) test_check_equal_int(expected, actual, __FILE__, __LINE__) +#define TEST_CHECK_EQUAL_UINT(expected, actual) test_check_equal_uint(expected, actual, __FILE__, __LINE__) +#define TEST_CHECK_UINT_WITHIN(min, max, actual) test_check_uint_within(min, max, actual, __FILE__, __LINE__) + +template +class WorkerThread : public Thread { + unsigned char stack_mem[SS]; +public: + WorkerThread(osPriority priority = osPriorityNormal) : Thread(priority, SS, stack_mem) { } +}; + +#endif diff --git a/TEST_APPS/device/i2c_com/main.cpp b/TEST_APPS/device/i2c_com/main.cpp new file mode 100644 index 00000000000..2128297af83 --- /dev/null +++ b/TEST_APPS/device/i2c_com/main.cpp @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2019, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "common.h" +#include "mbed.h" +#include "mbed-client-cli/ns_cmdline.h" +#include "master.h" +#if DEVICE_I2CSLAVE +#include "slave.h" +#endif // DEVICE_I2CSLAVE + +/** + * Macros for setting console flow control. + */ +#define CONSOLE_FLOWCONTROL_RTS 1 +#define CONSOLE_FLOWCONTROL_CTS 2 +#define CONSOLE_FLOWCONTROL_RTSCTS 3 +#define mbed_console_concat_(x) CONSOLE_FLOWCONTROL_##x +#define mbed_console_concat(x) mbed_console_concat_(x) +#define CONSOLE_FLOWCONTROL mbed_console_concat(MBED_CONF_TARGET_CONSOLE_UART_FLOW_CONTROL) + +#define SERIAL_CONSOLE_BAUD_RATE 115200 + + +#define BLOCKING_WRITE_READ "blocking_write-read" +#if DEVICE_I2C_ASYNCH +#define ASYNC_WRITE_READ "async_write-read" +#define ASYNC_TRANSFER "async_transfer" +#endif + + +#define GET_PARAM_STR(key, str) \ + if (!cmd_parameter_val(argc, argv, key, &str)) { \ + printf("invalid parameter key \"%s\" not found!!!\r\n", key); \ + return CMDLINE_RETCODE_INVALID_PARAMETERS; \ + } + +#define GET_PARAM_INT(key, value, optional) \ + if (!cmd_parameter_int(argc, argv, key, &value) && !optional) { \ + printf("invalid parameter key \"%s\" not found!!!\r\n", key); \ + return CMDLINE_RETCODE_INVALID_PARAMETERS; \ + } + +#define GET_PARAM_BOOL(key, value, optional) \ + if (!cmd_parameter_bool(argc, argv, key, &value) && !optional) { \ + printf("invalid parameter key \"%s\" not found!!!\r\n", key); \ + return CMDLINE_RETCODE_INVALID_PARAMETERS; \ + } + + +bool supports_async() +{ +#if DEVICE_I2C_ASYNCH + return true; +#else + return false; +#endif +} + +int send_capabilities(int argc, char *argv[]) +{ + i2c_capabilities_t cap; + i2c_get_capabilities(&cap); + cmd_printf("min_freq: %u max_freq: %u slave_mode: %s 10bit_addressing: %s multi_master: %s clock_stretching: %s async: %s\r\n", + cap.minimum_frequency, cap.maximum_frequency, cap.supports_slave_mode ? "True" : "False", cap.supports_10bit_addressing ? "True" : "False", + cap.supports_multi_master ? "True" : "False", cap.supports_clock_stretching ? "True" : "False", supports_async() ? "True" : "False"); + + return CMDLINE_RETCODE_SUCCESS; +} + +int test_init_master(int argc, char *argv[]) +{ + bool ret = false; + + int32_t frequency; + GET_PARAM_INT("frequency:", frequency, false); + + ret = master_init((uint32_t)frequency); + + return ret ? CMDLINE_RETCODE_SUCCESS : CMDLINE_RETCODE_FAIL; +} + +int test_deinit_master(int argc, char *argv[]) +{ + bool ret = false; + + ret = master_deinit(); + + return ret ? CMDLINE_RETCODE_SUCCESS : CMDLINE_RETCODE_FAIL; +} + +int test_exec_master(int argc, char *argv[]) +{ + char *com_type; + GET_PARAM_STR("communication:", com_type); + + int32_t write_size; + GET_PARAM_INT("write_size:", write_size, false); + + int32_t write_result_size = write_size; + GET_PARAM_INT("write_resulting_size:", write_result_size, true); + + int32_t read_size; + GET_PARAM_INT("read_size:", read_size, false); + + int32_t read_result_size = read_size; + GET_PARAM_INT("read_resulting_size:", read_result_size, true); + + int32_t iterations; + GET_PARAM_INT("iterations:", iterations, false); + + int32_t address7 = -1; + GET_PARAM_INT("address7:", address7, true); + + int32_t address10 = -1; + GET_PARAM_INT("address10:", address10, true); + + uint32_t write_address = address7 != -1 ? MAKE_7BIT_WRITE_ADDRESS(address7) : MAKE_10BIT_WRITE_ADDRESS(address10); + uint32_t read_address = address7 != -1 ? MAKE_7BIT_READ_ADDRESS(address7) : MAKE_10BIT_READ_ADDRESS(address10); + + bool ret = false; + if (strcmp(BLOCKING_WRITE_READ, com_type) == 0) { + if (write_size && read_size) { + ret = master_write_read(write_size, read_size, write_address, read_address, iterations); + } else if (write_size) { + ret = master_write(write_size, write_result_size, write_address, iterations); + } else if (read_size) { + ret = master_read(read_size, read_result_size, read_address, iterations); + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } +#if DEVICE_I2C_ASYNCH + else if (strcmp(ASYNC_WRITE_READ, com_type) == 0) { + if (write_size && read_size) { + ret = master_write_read_async(write_size, read_size, address7, iterations); + } else if (write_size) { + ret = master_write_async(write_size, write_result_size, address7, iterations); + } else if (read_size) { + ret = master_read_async(write_size, read_result_size, address7, iterations); + } else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + } else if (strcmp(ASYNC_TRANSFER, com_type) == 0) { + ret = master_transfer_async(write_size, read_size, address7, iterations); + } +#endif + else { + return CMDLINE_RETCODE_INVALID_PARAMETERS; + } + + return ret ? CMDLINE_RETCODE_SUCCESS : CMDLINE_RETCODE_FAIL; +} + +#if DEVICE_I2CSLAVE +int test_init_slave(int argc, char *argv[]) +{ + bool ret = false; + + int32_t frequency; + GET_PARAM_INT("frequency:", frequency, false); + + ret = slave_init((uint32_t)frequency); + + return ret ? CMDLINE_RETCODE_SUCCESS : CMDLINE_RETCODE_FAIL; +} + +int test_deinit_slave(int argc, char *argv[]) +{ + bool ret = false; + + ret = slave_deinit(); + + return ret ? CMDLINE_RETCODE_SUCCESS : CMDLINE_RETCODE_FAIL; +} + +int test_exec_slave(int argc, char *argv[]) +{ + int32_t write_size; + GET_PARAM_INT("write_size:", write_size, false); + + int32_t write_result_size = write_size; + GET_PARAM_INT("write_resulting_size:", write_result_size, true); + + int32_t read_size; + GET_PARAM_INT("read_size:", read_size, false); + + int32_t read_result_size = read_size; + GET_PARAM_INT("read_resulting_size:", read_result_size, true); + + int32_t iterations; + GET_PARAM_INT("iterations:", iterations, false); + + int32_t address7 = -1; + GET_PARAM_INT("address7:", address7, true); + + int32_t address10 = -1; + GET_PARAM_INT("address10:", address10, true); + + bool ret = false; + uint32_t address = address7 != -1 ? MAKE_7BIT_SLAVE_ADDRESS(address7) : address10; + ret = slave_transfer(write_size, write_result_size, read_size, read_result_size, address, iterations); + + return ret ? CMDLINE_RETCODE_SUCCESS : CMDLINE_RETCODE_FAIL; +} + +int test_finish_slave(int argc, char *argv[]) +{ + slave_finish(); + + return CMDLINE_RETCODE_SUCCESS; +} +#endif // DEVICE_I2CSLAVE + +void cmd_ready_cb(int retcode) +{ + cmd_next(retcode); +} + +void wrap_printf(const char *f, va_list a) +{ + vprintf(f, a); +} + +int main() +{ +#if I2C_DEBUG_PIN_MASTER==1 || I2C_DEBUG_PIN_SLAVE==1 + test_pin_init(); +#endif + + cmd_init(&wrap_printf); + cmd_add("get_capabilities", send_capabilities, "Send capabilities.", 0); + + cmd_add("test_init_master", test_init_master, "Test initialize.", 0); + cmd_add("test_exec_master", test_exec_master, "Test execute.", 0); + cmd_add("test_deinit_master", test_deinit_master, "Test deinitialize.", 0); +#if DEVICE_I2CSLAVE + cmd_add("test_init_slave", test_init_slave, "Test initialize.", 0); + cmd_add("test_exec_slave", test_exec_slave, "Test execute.", 0); + cmd_add("test_deinit_slave", test_deinit_slave, "Test deinitialize.", 0); + cmd_add("test_stop_slave", test_finish_slave, "Test deinitialize.", 0); +#endif // DEVICE_I2CSLAVE + + int c; + while ((c = getchar()) != EOF) { + cmd_char_input(c); + } + return 0; +} + +FileHandle *mbed::mbed_override_console(int) +{ + static UARTSerial console(STDIO_UART_TX, STDIO_UART_RX, SERIAL_CONSOLE_BAUD_RATE); +#if CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTS + console.set_flow_control(SerialBase::RTS, STDIO_UART_RTS, NC); +#elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_CTS + console.set_flow_control(SerialBase::CTS, NC, STDIO_UART_CTS); +#elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTSCTS + console.set_flow_control(SerialBase::RTSCTS, STDIO_UART_RTS, STDIO_UART_CTS); +#endif + return &console; +} diff --git a/TEST_APPS/device/i2c_com/master.cpp b/TEST_APPS/device/i2c_com/master.cpp new file mode 100644 index 00000000000..4a15a06345a --- /dev/null +++ b/TEST_APPS/device/i2c_com/master.cpp @@ -0,0 +1,478 @@ +/* + * Copyright (c) 2019, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" +#include "mbed.h" + +#define I2C_MASTER_SDA MBED_CONF_APP_I2C_MASTER_SDA +#define I2C_MASTER_SCL MBED_CONF_APP_I2C_MASTER_SCL + +#undef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +#if DEVICE_I2C_ASYNCH +struct async_status { + volatile i2c_async_event_t event; + volatile bool done; +}; +#endif + +#ifdef TEST_I2C_DRIVER + +class I2CTest : public I2C { +public: + I2CTest(PinName sda, PinName scl) : I2C(sda, scl) + { + + } +#if DEVICE_I2C_ASYNCH + async_status *transfer_status; +#endif +}; + +static I2CTest *i2c_obj; + +static void _i2c_init() +{ + i2c_obj = new I2CTest(I2C_MASTER_SDA, I2C_MASTER_SCL); +} + +static void _i2c_free() +{ + delete i2c_obj; +} + +static uint32_t _i2c_frequency(uint32_t frequency) +{ + i2c_obj->frequency(frequency); + return frequency; +} + +static int32_t _i2c_read(uint16_t address, void *data, uint32_t length, bool last) +{ + int ret = i2c_obj->read(address, (char *)data, length); + if (last) { + i2c_obj->stop(); + } + return ret == 0 ? length : -1; +} + +static int32_t _i2c_write(uint16_t address, const void *data, uint32_t length, bool stop) +{ + int ret = i2c_obj->write(address, (char *)data, length); + if (stop) { + i2c_obj->stop(); + } + return ret == 0 ? length : -1; +} + +#if DEVICE_I2C_ASYNCH +void _i2c_transfer_async(const void *tx, uint32_t tx_length, void *rx, uint32_t rx_length, + uint16_t address, bool stop, event_callback_t &callback, void *ctx) +{ + i2c_obj->transfer_status = (async_status *)ctx; + i2c_obj->transfer_status->event.sent_bytes = tx_length; + i2c_obj->transfer_status->event.received_bytes = rx_length; + i2c_obj->transfer(address, (const char *)tx, tx_length, (char *)rx, rx_length, callback, I2C_EVENT_TRANSFER_COMPLETE, !stop); +} +#endif +#else // TEST_I2C_DRIVER + +static i2c_t i2c_obj; + +static void _i2c_init() +{ + memset(&i2c_obj, 0, sizeof(i2c_t)); + i2c_init(&i2c_obj, I2C_MASTER_SDA, I2C_MASTER_SCL, DEVICE_AS_MASTER); +} + +static void _i2c_free() +{ + i2c_free(&i2c_obj); +} + +static uint32_t _i2c_frequency(uint32_t frequency) +{ + return i2c_frequency(&i2c_obj, frequency); +} + +static int32_t _i2c_read(uint16_t address, void *data, uint32_t length, bool last) +{ + return i2c_read(&i2c_obj, address, data, length, last); +} + +static int32_t _i2c_write(uint16_t address, const void *data, uint32_t length, bool stop) +{ + return i2c_write(&i2c_obj, address, data, length, stop); +} +#if DEVICE_I2C_ASYNCH +void _i2c_transfer_async(const void *tx, uint32_t tx_length, void *rx, uint32_t rx_length, + uint16_t address, bool stop, i2c_async_handler_f handler, void *ctx) +{ + i2c_transfer_async(&i2c_obj, tx, tx_length, rx, rx_length, address, stop, handler, ctx); +} +#endif +#endif // TEST_I2C_DRIVER + + + +bool master_init(uint32_t frequency) +{ + i2c_capabilities_t cap; + i2c_get_capabilities(&cap); + + _i2c_init(); + uint32_t set_freq = _i2c_frequency(frequency); + bool result = TEST_CHECK_UINT_WITHIN(cap.minimum_frequency, cap.maximum_frequency, set_freq); + + return result; +} + +bool master_deinit() +{ + _i2c_free(); + return true; +} + + +bool master_write_read(uint32_t write_size, uint32_t read_size, uint16_t write_address, uint16_t read_address, uint32_t iterations) +{ + bool result = true; + + uint8_t *tx_buf = new uint8_t[write_size]; + uint8_t *rx_buf = new uint8_t[read_size]; + + srand(ticker_read(get_us_ticker_data())); + + for (uint32_t i = 0; i < iterations && result; i++) { + int ret; + + for (uint32_t j = 0; j < write_size; j++) { + tx_buf[j] = (uint8_t)(rand() % 100); + } + + MASTER_PIN_TOGGLE(5); + ret = _i2c_write(write_address, tx_buf, write_size, false); + MASTER_PIN_TOGGLE(5); + result = TEST_CHECK_EQUAL_INT(write_size, ret); + I2C_DEBUG_PRINTF("[master] write count: %d\n", ret); + + if (result) { + MASTER_PIN_TOGGLE(5); + ret = _i2c_read(read_address, rx_buf, read_size, true); + MASTER_PIN_TOGGLE(5); + result = TEST_CHECK_EQUAL_INT(read_size, ret); + I2C_DEBUG_PRINTF("[master] read count: %d\n", ret); + } + + if (result) { + for (uint32_t j = 0; j < MIN(write_size, read_size); j++) { + if (rx_buf[j] != tx_buf[j]) { + result = TEST_CHECK_EQUAL_INT(tx_buf[j], rx_buf[j]); + break; + } + } + } + + I2C_DEBUG_PRINTF("[master] write data: "); + for (uint32_t j = 0; j < write_size; j++) { + I2C_DEBUG_PRINTF("%X ", tx_buf[j]); + } + I2C_DEBUG_PRINTF("\r\n"); + I2C_DEBUG_PRINTF("[master] read data: "); + for (uint32_t j = 0; j < read_size; j++) { + I2C_DEBUG_PRINTF("%X ", rx_buf[j]); + } + I2C_DEBUG_PRINTF("\r\n"); + } + delete []tx_buf; + delete []rx_buf; + + return result; +} + +bool master_read(uint32_t read_size, uint32_t read_result, uint16_t address, uint32_t iterations) +{ + bool result = true; + + uint8_t *rx_buf = new uint8_t[read_size]; + + for (uint32_t i = 0; i < iterations && result; i++) { + MASTER_PIN_TOGGLE(5); + int ret = _i2c_read(MAKE_7BIT_READ_ADDRESS(address), rx_buf, read_size, true); + MASTER_PIN_TOGGLE(5); + result = TEST_CHECK_EQUAL_INT(read_result, ret); + I2C_DEBUG_PRINTF("[master] read count: %d\n", ret); + + I2C_DEBUG_PRINTF("[master] read data: "); + for (uint32_t j = 0; j < read_size; j++) { + I2C_DEBUG_PRINTF("%X ", rx_buf[j]); + } + I2C_DEBUG_PRINTF("\r\n"); + + if (result) { + for (uint32_t j = 0; j < read_result; j++) { + if (j != rx_buf[j]) { + result = TEST_CHECK_EQUAL_INT(j, rx_buf[j]); + break; + } + } + } + } + delete []rx_buf; + + return result; +} + +bool master_write(uint32_t write_size, uint32_t write_result, uint16_t address, uint32_t iterations) +{ + bool result = true; + + uint8_t *tx_buf = new uint8_t[write_size]; + + for (uint32_t j = 0; j < write_size; j++) { + tx_buf[j] = j; + } + + for (uint32_t i = 0; i < iterations && result; i++) { + MASTER_PIN_TOGGLE(5); + int ret = _i2c_write(MAKE_7BIT_WRITE_ADDRESS(address), tx_buf, write_size, false); + MASTER_PIN_TOGGLE(5); + result = TEST_CHECK_EQUAL_INT(write_result, ret); + I2C_DEBUG_PRINTF("[master] write count: %d\n", ret); + + I2C_DEBUG_PRINTF("[master] written data: "); + for (uint32_t j = 0; j < write_result; j++) { + I2C_DEBUG_PRINTF("%X ", tx_buf[j]); + } + I2C_DEBUG_PRINTF("\r\n"); + } + delete []tx_buf; + + return result; +} + + +#if DEVICE_I2C_ASYNCH + +#ifdef TEST_I2C_DRIVER +void async_callback_handler(int event) +{ + async_status *s = i2c_obj->transfer_status; + s->event.error = event != I2C_EVENT_TRANSFER_COMPLETE; + if (s->event.error) { + i2c_obj->transfer_status->event.sent_bytes = 0; + i2c_obj->transfer_status->event.received_bytes = 0; + } + s->done = true; +} +event_callback_t async_callback(async_callback_handler); +#else // TEST_I2C_DRIVER +void async_callback(i2c_t *obj, i2c_async_event_t *event, void *ctx) +{ + async_status *s = ((async_status *)ctx); + s->event.sent_bytes = event->sent_bytes; + s->event.received_bytes = event->received_bytes; + s->event.error = event->error; + s->done = true; +} +#endif // TEST_I2C_DRIVER + +bool master_write_read_async(uint32_t write_size, uint32_t read_size, uint16_t address, uint32_t iterations) +{ + async_status transmit_status = {}; + async_status receive_status = {}; + uint8_t *tx_buf = new uint8_t[write_size]; + uint8_t *rx_buf = new uint8_t[read_size]; + bool result = true; + + srand(ticker_read(get_us_ticker_data())); + + for (uint32_t i = 0; i < iterations && result; i++) { + for (uint32_t j = 0; j < write_size; j++) { + tx_buf[j] = (uint8_t)(rand() % 100); + } + transmit_status.done = false; + MASTER_PIN_TOGGLE(5); + _i2c_transfer_async(tx_buf, write_size, NULL, 0, MAKE_7BIT_WRITE_ADDRESS(address), false, async_callback, &transmit_status); + MASTER_PIN_TOGGLE(5); + while (!transmit_status.done); + MASTER_PIN_TOGGLE(5); + result = TEST_CHECK_EQUAL_INT(write_size, transmit_status.event.sent_bytes); + I2C_DEBUG_PRINTF("[master] sent_bytes: %u\r\n", transmit_status.event.sent_bytes); + + MASTER_PIN_TOGGLE(5); + + if (result) { + receive_status.done = false; + MASTER_PIN_TOGGLE(5); + _i2c_transfer_async(NULL, 0, rx_buf, read_size, MAKE_7BIT_READ_ADDRESS(address), true, async_callback, &receive_status); + MASTER_PIN_TOGGLE(5); + while (!receive_status.done); + MASTER_PIN_TOGGLE(5); + result = TEST_CHECK_EQUAL_INT(read_size, receive_status.event.received_bytes); + I2C_DEBUG_PRINTF("[master] received_bytes: %u\r\n", receive_status.event.received_bytes); + } + MASTER_PIN_TOGGLE(5); + I2C_DEBUG_PRINTF("[master] write data: "); + for (uint32_t j = 0; j < write_size; j++) { + I2C_DEBUG_PRINTF("%X ", tx_buf[j]); + } + I2C_DEBUG_PRINTF("\r\n"); + I2C_DEBUG_PRINTF("[master] read data: "); + for (uint32_t j = 0; j < read_size; j++) { + I2C_DEBUG_PRINTF("%X ", rx_buf[j]); + } + I2C_DEBUG_PRINTF("\r\n"); + + if (result) { + for (uint32_t j = 0; j < MIN(write_size, read_size); j++) { + if (rx_buf[j] != tx_buf[j]) { + result = TEST_CHECK_EQUAL_INT(tx_buf[j], rx_buf[j]); + break; + } + } + } + } + + delete [] tx_buf; + delete [] rx_buf; + + return result; +} + +bool master_write_async(uint32_t write_size, uint32_t write_reulting_size, uint16_t address, uint32_t iterations) +{ + async_status transmit_status = {}; + uint8_t *tx_buf = new uint8_t[write_size]; + bool result = true; + + for (uint32_t j = 0; j < write_size; j++) { + tx_buf[j] = j; + } + + for (uint32_t i = 0; i < iterations && result; i++) { + transmit_status.done = false; + MASTER_PIN_TOGGLE(5); + _i2c_transfer_async(tx_buf, write_size, NULL, 0, MAKE_7BIT_WRITE_ADDRESS(address), false, async_callback, &transmit_status); + MASTER_PIN_TOGGLE(5); + while (!transmit_status.done); + MASTER_PIN_TOGGLE(5); + result = TEST_CHECK_EQUAL_INT(write_reulting_size, transmit_status.event.sent_bytes); + I2C_DEBUG_PRINTF("[master] sent_bytes: %u\r\n", transmit_status.event.sent_bytes); + I2C_DEBUG_PRINTF("[master] write data: "); + for (uint32_t j = 0; j < write_reulting_size; j++) { + I2C_DEBUG_PRINTF("%X ", tx_buf[j]); + } + I2C_DEBUG_PRINTF("\r\n"); + } + + delete [] tx_buf; + + return result; +} + +bool master_read_async(uint32_t read_size, uint32_t read_resulting_size, uint16_t address, uint32_t iterations) +{ + async_status receive_status = {}; + uint8_t *rx_buf = new uint8_t[read_size]; + bool result = true; + + for (uint32_t i = 0; i < iterations && result; i++) { + receive_status.done = false; + MASTER_PIN_TOGGLE(5); + _i2c_transfer_async(NULL, 0, rx_buf, read_size, MAKE_7BIT_READ_ADDRESS(address), true, async_callback, &receive_status); + MASTER_PIN_TOGGLE(5); + while (!receive_status.done); + MASTER_PIN_TOGGLE(5); + result = TEST_CHECK_EQUAL_INT(read_resulting_size, receive_status.event.received_bytes); + I2C_DEBUG_PRINTF("[master] received_bytes: %u\r\n", receive_status.event.received_bytes); + I2C_DEBUG_PRINTF("[master] read data: "); + for (uint32_t j = 0; j < read_resulting_size; j++) { + I2C_DEBUG_PRINTF("%X ", rx_buf[j]); + } + I2C_DEBUG_PRINTF("\r\n"); + + if (result) { + for (uint32_t j = 0; j < read_resulting_size; j++) { + if (rx_buf[j] != j) { + result = TEST_CHECK_EQUAL_INT(j, rx_buf[j]); + break; + } + } + } + } + delete [] rx_buf; + + return result; +} + +bool master_transfer_async(uint32_t write_size, uint32_t read_size, uint16_t address, uint32_t iterations) +{ + async_status transfer_status = {}; + uint8_t *tx_buf = new uint8_t[write_size]; + uint8_t *rx_buf = new uint8_t[read_size]; + bool result = true; + + srand(ticker_read(get_us_ticker_data())); + + for (uint32_t i = 0; i < iterations && true; i++) { + for (uint32_t j = 0; j < write_size; j++) { + tx_buf[j] = (uint8_t)(rand() % 100); + } + transfer_status.done = false; + MASTER_PIN_TOGGLE(5); + _i2c_transfer_async(tx_buf, write_size, rx_buf, read_size, MAKE_7BIT_WRITE_ADDRESS(address), true, async_callback, &transfer_status); + MASTER_PIN_TOGGLE(5); + while (!transfer_status.done); + MASTER_PIN_TOGGLE(5); + result = TEST_CHECK_EQUAL_INT(write_size, transfer_status.event.sent_bytes); + I2C_DEBUG_PRINTF("[master] sent_bytes: %u\n", transfer_status.event.sent_bytes); + + if (result) { + result = TEST_CHECK_EQUAL_INT(read_size, transfer_status.event.received_bytes); + I2C_DEBUG_PRINTF("[master] received_bytes: %u\n", transfer_status.event.received_bytes); + } + + I2C_DEBUG_PRINTF("[master] written data: "); + for (uint32_t j = 0; j < write_size; j++) { + I2C_DEBUG_PRINTF("%X ", tx_buf[j]); + } + I2C_DEBUG_PRINTF("\r\n"); + I2C_DEBUG_PRINTF("[master] read data: "); + for (uint32_t j = 0; j < read_size; j++) { + I2C_DEBUG_PRINTF("%X ", rx_buf[j]); + } + I2C_DEBUG_PRINTF("\r\n"); + + if (result) { + for (uint32_t j = 0; j < write_size; j++) { + if (rx_buf[j] != tx_buf[j]) { + result = TEST_CHECK_EQUAL_INT(tx_buf[j], rx_buf[j]); + break; + } + } + } + } + + delete [] tx_buf; + delete [] rx_buf; + + return result; +} + +#endif diff --git a/TEST_APPS/device/i2c_com/master.h b/TEST_APPS/device/i2c_com/master.h new file mode 100644 index 00000000000..ca3d0bbd85b --- /dev/null +++ b/TEST_APPS/device/i2c_com/master.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TEST_APPS_DEVICE_I2C_COM_MASTER_H_ +#define TEST_APPS_DEVICE_I2C_COM_MASTER_H_ + +bool master_write(uint32_t write_size, uint32_t write_result, uint16_t address, uint32_t iterations); +bool master_read(uint32_t read_size, uint32_t read_result, uint16_t address, uint32_t iterations); +bool master_write_read(uint32_t write_size, uint32_t read_size, uint16_t write_address, uint16_t read_address, uint32_t iterations); +bool master_write_async(uint32_t write_size, uint32_t write_reulting_size, uint16_t address, uint32_t iterations); +bool master_read_async(uint32_t read_size, uint32_t read_resulting_size, uint16_t address, uint32_t iterations); +bool master_write_read_async(uint32_t write_size, uint32_t read_size, uint16_t address, uint32_t iterations); +bool master_transfer_async(uint32_t write_size, uint32_t read_size, uint16_t address, uint32_t iterations); +bool master_init(uint32_t frequency); +bool master_deinit(); + +#endif /* TEST_APPS_DEVICE_I2C_COM_MASTER_H_ */ diff --git a/TEST_APPS/device/i2c_com/mbed_app.json b/TEST_APPS/device/i2c_com/mbed_app.json new file mode 100644 index 00000000000..c1e494c0723 --- /dev/null +++ b/TEST_APPS/device/i2c_com/mbed_app.json @@ -0,0 +1,8 @@ +{ + "config": { + "I2C_MASTER_SDA": "I2C_SDA", + "I2C_MASTER_SCL": "I2C_SCL", + "I2C_SLAVE_SDA": "I2C_SDA", + "I2C_SLAVE_SCL": "I2C_SCL" + } +} diff --git a/TEST_APPS/device/i2c_com/slave.cpp b/TEST_APPS/device/i2c_com/slave.cpp new file mode 100644 index 00000000000..8032d6625b3 --- /dev/null +++ b/TEST_APPS/device/i2c_com/slave.cpp @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2019, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if DEVICE_I2CSLAVE + +#include "slave.h" +#include "common.h" + +#define I2C_SLAVE_SDA MBED_CONF_APP_I2C_SLAVE_SDA +#define I2C_SLAVE_SCL MBED_CONF_APP_I2C_SLAVE_SCL + +#undef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +volatile bool done; + + +#ifdef TEST_I2C_DRIVER +static I2CSlave *i2c_obj; + +static void _i2c_init() +{ + i2c_obj = new I2CSlave(I2C_SLAVE_SDA, I2C_SLAVE_SCL); +} + +static void _i2c_free() +{ + delete i2c_obj; +} + +static uint32_t _i2c_frequency(uint32_t frequency) +{ + i2c_obj->frequency(frequency); + return frequency; +} + +static void _i2c_slave_address(uint16_t address) +{ + i2c_obj->address(address); +} + +static i2c_slave_status_t _i2c_slave_status() +{ + return (i2c_slave_status_t)i2c_obj->receive(); +} + +static int32_t _i2c_read(void *data, uint32_t length, bool last) +{ + int ret = i2c_obj->read((char *)data, length); + if (last) { + i2c_obj->stop(); + } + return ret == 0 ? length : -1; +} + +static int32_t _i2c_write(const void *data, uint32_t length, bool stop) +{ + int ret = i2c_obj->write((char *)data, length); + if (stop) { + i2c_obj->stop(); + } + return ret == 0 ? length : -1; +} + +#else // TEST_I2C_DRIVER + +static i2c_t i2c_obj; + +static void _i2c_init() +{ + memset(&i2c_obj, 0, sizeof(i2c_t)); + i2c_init(&i2c_obj, I2C_SLAVE_SDA, I2C_SLAVE_SCL, DEVICE_AS_SLAVE); +} + +static void _i2c_free() +{ + i2c_free(&i2c_obj); +} + +static uint32_t _i2c_frequency(uint32_t frequency) +{ + return i2c_frequency(&i2c_obj, frequency); +} + + +static void _i2c_slave_address(uint16_t address) +{ + i2c_slave_address(&i2c_obj, address); +} + +static i2c_slave_status_t _i2c_slave_status() +{ + return i2c_slave_status(&i2c_obj); +} + +static int32_t _i2c_read(void *data, uint32_t length, bool last) +{ + return i2c_read(&i2c_obj, 0, data, length, last); +} + +static int32_t _i2c_write(const void *data, uint32_t length, bool stop) +{ + return i2c_write(&i2c_obj, 0, data, length, stop); +} + +#endif // TEST_I2C_DRIVER + + + +bool slave_init(uint32_t frequency) +{ + i2c_capabilities_t cap; + i2c_get_capabilities(&cap); + + _i2c_init(); + uint32_t set_freq = _i2c_frequency(frequency); + bool result = TEST_CHECK_UINT_WITHIN(cap.minimum_frequency, cap.maximum_frequency, set_freq); + + return result; +} + +bool slave_deinit() +{ + _i2c_free(); + return true; +} + +void slave_finish() +{ + done = true; +} + +void slave_transfer_job(TransferConfig *tc) +{ + bool result; + uint8_t *data = new uint8_t[MAX(tc->read_size, tc->write_size)]; + _i2c_slave_address(tc->address); + + for (uint32_t i = 0; i < tc->iterations; i++) { + int ret; + result = true; + SLAVE_PIN_TOGGLE(1); + while (_i2c_slave_status() != WriteAddressed && !done); + SLAVE_PIN_TOGGLE(1); + ret = _i2c_read(data, tc->read_size, false); + SLAVE_PIN_TOGGLE(1); + result = TEST_CHECK_EQUAL_INT(tc->read_size_resulting, ret); + + I2C_DEBUG_PRINTF("[slave] read data count: %d\n", ret); + I2C_DEBUG_PRINTF("[slave] read data: "); + for (int i = 0; i < tc->read_size; i++) { + I2C_DEBUG_PRINTF("%X ", data[i]); + } + I2C_DEBUG_PRINTF("\r\n"); + + if (result) { + SLAVE_PIN_TOGGLE(1); + while (_i2c_slave_status() != ReadAddressed && !done); + SLAVE_PIN_TOGGLE(1); + ret = _i2c_write(data, tc->write_size, false); + SLAVE_PIN_TOGGLE(1); + result = TEST_CHECK_EQUAL_INT(tc->write_size_resulting, ret); + I2C_DEBUG_PRINTF("[slave] write data count: %d\n", ret); + } + + if (!result || done) { + break; + } + } + tc->result = result; + + delete []data; +} + +void slave_read_job(TransferConfig *tc) +{ + uint8_t *data = new uint8_t[tc->read_size]; + bool result = true; + + _i2c_slave_address(tc->address); + + for (uint32_t i = 0; i < tc->iterations; i++) { + SLAVE_PIN_TOGGLE(1); + while (_i2c_slave_status() != WriteAddressed && !done); + SLAVE_PIN_TOGGLE(1); + int ret = _i2c_read(data, tc->read_size, false); + SLAVE_PIN_TOGGLE(1); + result = TEST_CHECK_EQUAL_INT(tc->read_size_resulting, ret); + + I2C_DEBUG_PRINTF("[slave] read data count: %d\n", ret); + I2C_DEBUG_PRINTF("[slave] read data: "); + for (int i = 0; i < tc->read_size; i++) { + I2C_DEBUG_PRINTF("%X ", data[i]); + } + I2C_DEBUG_PRINTF("\r\n"); + + if (result) { + for (uint32_t j = 0; j < tc->read_size_resulting; j++) { + if (data[j] != j) { + result = TEST_CHECK_EQUAL_INT(j, data[j]); + break; + } + } + } + + if (!result || done) { + break; + } + } + tc->result = result; + + delete []data; +} + +void slave_write_job(TransferConfig *tc) +{ + uint8_t *data = new uint8_t[tc->write_size]; + bool result = true; + + // prepare data to send + for (uint32_t i = 0; i < tc->write_size; i++) { + data[i] = i; + } + + _i2c_slave_address(tc->address); + + for (uint32_t i = 0; i < tc->iterations; i++) { + SLAVE_PIN_TOGGLE(5); + while (_i2c_slave_status() != ReadAddressed && !done); + SLAVE_PIN_TOGGLE(1); + int ret = _i2c_write(data, tc->write_size, false); + SLAVE_PIN_TOGGLE(1); + result = TEST_CHECK_EQUAL_INT(tc->write_size_resulting, ret); + I2C_DEBUG_PRINTF("[slave] write data count: %d\n", ret); + + if (!result || done) { + break; + } + } + tc->result = result; + + delete []data; +} + +bool slave_transfer(uint32_t write_size, uint32_t write_size_resulting, uint32_t read_size, uint32_t read_size_resulting, uint16_t address, uint32_t iterations) +{ + TransferConfig tc = {}; + tc.write_size = write_size; + tc.read_size = read_size; + tc.iterations = iterations; + tc.address = address; + tc.write_size_resulting = write_size_resulting; + tc.read_size_resulting = read_size_resulting; + tc.result = false; + done = false; + + void (*job)(TransferConfig * tc); + if (write_size && read_size) { + job = slave_transfer_job; + } else if (write_size) { + job = slave_write_job; + } else if (read_size) { + job = slave_read_job; + } + + WorkerThread<1024> slave_thread; + slave_thread.start(callback(job, &tc)); + slave_thread.join(); + + return tc.result; +} + +#endif // DEVICE_I2CSLAVE diff --git a/TEST_APPS/device/i2c_com/slave.h b/TEST_APPS/device/i2c_com/slave.h new file mode 100644 index 00000000000..a0d190e9b65 --- /dev/null +++ b/TEST_APPS/device/i2c_com/slave.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TEST_APPS_DEVICE_I2C_COM_SLAVE_H_ +#define TEST_APPS_DEVICE_I2C_COM_SLAVE_H_ + +#include + +struct TransferConfig { + bool result; + uint32_t write_size; + uint32_t write_size_resulting; + uint32_t read_size; + uint32_t read_size_resulting; + uint32_t iterations; + uint16_t address; +}; + +bool slave_transfer(uint32_t write_size, uint32_t write_size_resulting, uint32_t read_size, uint32_t read_size_resulting, uint16_t address, uint32_t iterations); +bool slave_init(uint32_t frequency); +bool slave_deinit(); +void slave_finish(); + + +#endif /* TEST_APPS_DEVICE_I2C_COM_SLAVE_H_ */ diff --git a/TEST_APPS/testcases/i2c_com/README.md b/TEST_APPS/testcases/i2c_com/README.md new file mode 100644 index 00000000000..4e5333e4623 --- /dev/null +++ b/TEST_APPS/testcases/i2c_com/README.md @@ -0,0 +1,57 @@ +I2C Communication Test +============= + +Overview +---------------- +This is the I2C communication test which verifies various I2C configuration variants. This test is based on Ice Tea framework. Information how to install and use Ice Tea can be found [here](https://github.com/ARMmbed/icetea). This test transfers data between I2C master and I2C slave. + +Test Setup +---------------- + +1. **Pre-requirements** + - Two Mbed boards (can be different) with I2C support + - Both boards must have I2C peripheral available + - At least one board must support I2C slave mode + - Wire connection between I2C interface on master board and I2C interface on slave board + + ![alt text](i2c_Diagram.png) + +**Note:** +Boards need to share common ground, otherwise noises during the transmission are very likely. +Both SDA and SCL lines must be connected to a positive supply voltage via a pull-up resistor + +2. **Running the test** + - Adjust pins configuration to your needs in `./TEST_APPS/device/i2c_com/app_config.json` in `"target_overrides"` section + - Connect I2C interfaces as configured in `./TEST_APPS/device/i2c_com/app_config.json`. + - Same boards are used + - Run the test using the following command: + `mbed test -m BOARD -t TOOLCHAIN --icetea --app-config ./TEST_APPS/device/i2c_com/mbed_app.json -n I2C_COM_MASTER-SLAVE_*` + - Different boards are used + - Adjust `allowed_platforms` section in `test_i2c_com.py` in order to specify which board should be used as I2C master and which as I2C slave + - Build test binaries using the following command: + `mbed test -m BOARD -t TOOLCHAIN --icetea --app-config ./TEST_APPS/device/i2c_com/mbed_app.json -n I2C_COM_MASTER-SLAVE_* --compile` + - Flash the master and slave boards + - Run the test using the following command: + `icetea --tcdir ./TEST_APPS/testcases/i2c_com/ --tc all --reset` + +**Note:** +- To run only one test case type its full name. +- Remember to connect also ground pins between the boards. + +Test Configuration +---------------- +Test configuration file can be found in the following location: `./TEST_APPS/device/i2c_com/app_config.json`. + +Configuration parameters: + - `I2C_MASTER/SLAVE_SCL`: master/slave clock pin + - `I2C_MASTER/SLAVE_SDA`: master/slave data pin + +Test scenario +---------------- + + +Test steps: +- Host collects I2C devices capabilities +- If the testcase configuration is not supported by any of DUT's then testcase is skipped and host tries next one. +- If the testcase configuration is supported by both sides, then host requests to perform the I2C communication test. +- Status of the test is sent back to the host. \ No newline at end of file diff --git a/TEST_APPS/testcases/i2c_com/__init__.py b/TEST_APPS/testcases/i2c_com/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/TEST_APPS/testcases/i2c_com/i2c_Diagram.png b/TEST_APPS/testcases/i2c_com/i2c_Diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..d87c078efb142a8fbd0c6c5c31457109f0c55f08 GIT binary patch literal 4531 zcmcgwc|4SR7uU_r$bJ*qJrg40y^?*%po}bCWXW2MkY#E@c3m^b)iT4Nv809EvR#uU zO-Ku4geb<)m}F2HCd4Ee?;}gS%b)js|9L*Y=XuWWob#OTIp1@BPugLJgCbjHxAO7v zi6CsOocQ=QA;EPMWD9t0%eo!K$0reku(EK8%AYLoz2FtVXzgOF(e)VB4eAXjDQY-1 z*6m%gWK4IYM2NbxKyrp$^7hAr>ay-TgziZ`ojUdOL$dU5hg0B0rx20;Ku!HXUtgp; zG*c9Q{qXKGTb>$DS z46%xpZ)UIDAY)_YE+*k7u@wVbfLK0w?Y0M}EG05c|;i2VKjUVX6K%S zapv`_%o(>`(m%PrUo2H;UEKj%P2mlNx^C+^McXU-?oCZ^%;&1wSEaoyix66|PvxN+ zy1g*=WAlW5XIh>d4zO2HeA=9iwQsdYGSV6paFFBNG_xH)e{VK?oAQr(FxKRx?;o)byFTZhEYb)aY{)VyIFGcrE>I=SP4-k?T_8-~k}GmOO` z*)(K|9l?1w;CS!Jh_QQ7Kw4NTzkIAHymLv7t$4Bfy*1Tw2+kP{wXGRae8_ymxlt)? zl#E!E#m`j`3a5zhPIq7Jnftdeb|FO%;n)5Gl^7nl?!gd6T`?`;Z+QOUE(v#zb{QHB zOLM+-lQWogvO$9}S^H{YvY&Q{Y-kX6(gdTL9?4ip-i!^|H7YqHX>3}7sfV?{pAR&5 zI@$gl_pC=JZR`2W9v(;vBy==;ZO%GBMpMe2-xC zQ3XX>^TTVS5hii9rt=T*W-;(iQylp<&s*w-kcfu)5pu_=PGuXP;etu)hGxf4CPu~N zCoA5&z^|Q5ZH@RxNx%X_(NwYN-c|s$i=P;YLb2pxJ-I-t0OD&GrZD3U#!sE`8HU?d z0SKH(Ac^@%H|+^^5trGbJ?}tyb*Fi{nx86J&QRyO?Srs4@Cgh+maCOtLsInTbHDGtx*hHQ2>J}EsSw0}qDUdZp$+a9iowAi zRp4&5OW{>7+R>%1TDMyJ-h6RnP#G!qmlmtR;|w)~D5J~X3sS&UDblB+Bf&Pi8mID9 z2OTVv&a}%8j}x@Qd-Wmo%^^b3=kDC>4z%Ljf1@qbpSq$zo8?{AlD*@;n9Mu?iaZyh z-&$3@pAxxhn-3Ti^sW(s&+~yPw5mv)RIn=a(Sov+;H$5%U&Q2;Hnx^ou6p|bx46{k zvU@wRurSBA7<~|4&=Pwe@=eM4C3RL!P0iD#X8+@%q4uMTt493Hw=P8XaJZ_FpNM&R zc~L3y{G0Y74^Qrf>tBul(l6v2o`GLhGB=x+oq7B?DV)sEn4*WTSrY&XjU#M*qDQmR znB(udZ;@(h_9eq|?ble5_11!NopA&kB9HYlg~(Ks|G-_s;L-&EOr)Cx>5MpfS{eCb z3N$1N*H**|4|rQsS}Z8fFgOcxDTHnasgDxZ4Lr9UkP`r;#o${eE1<{`<^P3JcPVsV zz!1ZMWY*+3adviQ4f+ST^pN)Ufq|p&#-Kr}_!{XOnL}i#Kdpe0uY?u$-?Y*ZI>q2A zr1Ll!A22QeSbFSV=>)SF+zl-d=>3!h3(8@sl{Ufps*F?@0>KtXCy473eqQMz|8sTc zBY;_AjNgi}>||5nLSqrBZ~p!LI4GRqrFY#u25W?PoD~k@whD-oEISjYJ?eQDG$Rnr zc?_8Nl;jmnsc*I_+oi%l>Rc^gdqx+^$>8+vru>7yLf=PiW4Z z9taknQSeXPO7GawGj&Bw8JVimUhP>l-p8$t|5$SZPl^MtX-N%VT>d-^@vw@MB9VVB zVkjx?r-&j58Z{75ck{2&({rB-pMKEeDpSH(}Yh=R&&pxrP@ZCzlX{*J6ywHgy`TLj|-0P|;;N+#%l(XuYD8lh9<| zy-2X2SjvcXAyX2i+Uoxt_gjzMR&O9N-da&n>ciaj=qTHJd3u{X@#rRIjxq!p7Ur-! zi)!W6Cx!NUH2s6S>dr0f(cY32>7d(nJZ|T#Z-%B)V!rsJLQfs4NmruBoWUct(bDBv zN?>Hv=SRP%4NX*R7GULcC0I-{XF&06^Ew|p`4VuG7RPj1wRb&$8t7zGpX)*1K%JRo zh0AVTb92tHFrBdugd{mt&tHG~uv(;DquiDu|KYIpkESXkCGxm{qo%(E$)<2Ttm>t|n&ed9gxcSUJI)vPQV*>DLi7@0s@{g{MHV z|Hf>oVoKS;w2Gh~UwgQ_@26ZJSmQn+AtChAmxxIQMR<+Ry-ZU@72w|`z`G1NgRsCK zbr?l`REBTq1zGRl!|*U`5hpDHF-1a`*`i&nf$lA%l2YbT29!u$9E6R_9P3<$7;S$4nBrE+wqg{ z;R)O)1}xt~o-;yY)S=i3?^zcX#7Vhu!K;CXGGeADe5f8<&oz|*0~EC_HK~DacQmMn zDrsILoHZfPr4nFv3}{*$mYcc7+&8+5Qx1$02-Xz0%4N@lFR2{Ll|=631;V~HpiNX} zlb+K@UwrW?Q@P_W+j(-{;kSb&#DE;ts4=^{IOftvk%fgtX6A$mjkR=W9FNul`)!gk zE?rvZ?o{jH7HM9jL)g;z?T25M&E*l_2@fpVrqfQ@Ed^l*P8wijocgQ_EQpVF71gvx zO}(!$L8`ak$Blv72OTn4Yq)ir6G zFOHns)*3W1(1cu?tSr3@O!7YS!6R+(nye8Wik0td-}~ZMrK7_cpla2KG-zlaJNU~| z0y5<_hkImxXQLJHi}&Lf8-#Y8i)*1R&rAXF&JJdJyrhoPB1T&N$b37HkuF^l*(W2m zEgKytXt}}t)Q@>F9A9G{=5mJt{!H6m!VHm_ph>#+9QA>|1u!WRhD*`2bak~8zr~ST z=WAUHAi?1(6+{iWyagBph4_I?1O^9AVhTyPwjv7(c*+vBpdfpczX>WMb%Vr7;1SGH z&s^+M|AqAw5qslY@^>HCOjLMxM6?0@n;VsP^tcrz^7}1>XeYbIGj?hs->S{#rd`2- z@PdkNdTbdulZx9!y&RfP35R#3Rn9&0#o#8bHi8B9|DdO`Bl~!rYR}!Dor33}{(qS5 zDz~d@E#7&_{RTMq1+L>q@gYX0XBwZqQ&S|ZZCirZooLf^X2-u(mBRP-9$9#I>x$C{ z2P&bX!#;XASsFUHPHiSgm)m8(JQeyi%ArJJw+~(yaZuL6K4n|+UpO~6x6x(+CBi|) zXnu_xLvRk90o71@dNT5jBTiL&|KR1;4zrdlMA6PmpUZaD*};N(GvGen-dU|miC(p} zwaEB*1&tg%OPR{@^0v;-%ce`8UhdQgUU%JQjID+~=6^V;|7=Y8z|_DSh0d_m+9)sI zqrU0bN(zzIK}@~qy)2ZY{2QV9VzKjeyMh${s=20}2QS-H=HxrVrk`#@Gvm2!Z{OaO zhs8(|>bXO)qgAbnhvZ8f%@(Yt>c%&u>K?xoKf< z4@pA1RfWG(+v|kv`vQ6iTXXa4KOL=cC;q`qmCpuK6!qBYvd*y$2yA2$oKf-d-cwD> z2}rLQ;o`54Hj7#HWiHsmzU8k41xj{0&@$QuhM@XrIYs|lUf@U&BAfZ|nJcbK)LZLW z|CvCPGV@t2vEw_}#}U|h$AZ82_d^~Y*R22aKy|Cc^J~jLeeQl>YmLY+0)NKvA*>y& JD&T%e{{$w@flUAa literal 0 HcmV?d00001 diff --git a/TEST_APPS/testcases/i2c_com/test_i2c_com.py b/TEST_APPS/testcases/i2c_com/test_i2c_com.py new file mode 100644 index 00000000000..064a7f3f92e --- /dev/null +++ b/TEST_APPS/testcases/i2c_com/test_i2c_com.py @@ -0,0 +1,366 @@ +""" +Copyright (c) 2019, Arm Limited and affiliates. +SPDX-License-Identifier: Apache-2.0 + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +""" + +from icetea_lib.bench import Bench +from icetea_lib.bench import TestStepError +from icetea_lib.tools.tools import test_case +from icetea_lib.TestStepError import TestStepFail +from icetea_lib.bench import ReturnCodes +#from mbed_clitest.TestStepError import SkippedTestcaseException +import re + + +class I2CComTest(Bench): + + capabilities_names = ("minimum_frequency", "maximum_frequency", "supports_slave_mode", + "supports_10bit_addressing", "supports_multi_master", "supports_clock_stretching", "supports_async") + master_init_config_str = "test_init_master frequency: {0}" + master_exec_rw_config_str = "test_exec_master communication: {0} iterations: {1} write_size: {2} read_size: {3} address{4}: {5}" + master_exec_r_or_w_config_str = "test_exec_master communication: {0} iterations: {1} write_size: {2} write_resulting_size: {3} read_size: {4} read_resulting_size: {5} address{6}: {7}" + slave_init_config_str = "test_init_slave frequency: {0}" + slave_exec_rw_config_str = "test_exec_slave iterations: {0} write_size: {1} read_size: {2} address{3}: {4}" + slave_exec_r_or_w_config_str = "test_exec_slave iterations: {0} write_size: {1} write_resulting_size: {2} read_size: {3} read_resulting_size: {4} address{5}: {6}" + + caps_master = {} + caps_slave = {} + caps = {} + + I2C_7BIT_ADDRESS_MIN = 8 + I2C_7BIT_ADDRESS_MAX = 119 + I2C_7BIT_ADDRESS = 85 + address_range_7bit = (I2C_7BIT_ADDRESS_MIN, + I2C_7BIT_ADDRESS, I2C_7BIT_ADDRESS_MAX) + I2C_10BIT_ADDRESS_MIN = 0 + I2C_10BIT_ADDRESS_MAX = 1023 + I2C_10BIT_ADDRESS = 512 + address_range_10bit = (I2C_10BIT_ADDRESS_MIN, + I2C_10BIT_ADDRESS, I2C_10BIT_ADDRESS_MAX) + + def __init__(self, **kwargs): + testcase_args = { + 'name': "test_i2c_com", + 'title': "I2C Communication Test", + 'status': "released", + 'purpose': "Verify I2C HAL API", + 'component': ["I2C"], + 'type': "compatibility", + 'requirements': { + "duts": { + '*': { + "count": 2, + "type": "hardware" + }, + "1": {"nick": "master", + "allowed_platforms": ["K64F", "NUCLEO_F070RB", "NUCLEO_F429ZI"], + "application": { + "name": "TEST_APPS-device-i2c_com" + }}, + "2": {"nick": "slave", + "allowed_platforms": ["K64F", "NUCLEO_F070RB", "NUCLEO_F429ZI"], + "application": { + "name": "TEST_APPS-device-i2c_com" + }} + } + }} + + testcase_args.update(kwargs) + Bench.__init__(self, **testcase_args) + + def log_capabilities(self, cap): + for name in self.capabilities_names: + print("{}: {} ({})".format(name, cap[name], type(cap[name]))) + + def parse_capabilities(self, resp): + regex = re.compile(r''' + [\S]+: # a key (any word followed by a colon) + (?: + \s # then a space in between + (?!\S+:)\S+ # then a value (any word not followed by a colon) + )+ # match multiple values if present + ''', re.VERBOSE) + matches = regex.findall(resp.lines[0]) + cap = dict([matches.split(': ', 1) for matches in matches]) + + cap["minimum_frequency"] = int(cap["min_freq"]) + cap["maximum_frequency"] = int(cap["max_freq"]) + cap["supports_slave_mode"] = cap["slave_mode"] == "True" + cap["supports_10bit_addressing"] = cap["10bit_addressing"] == "True" + cap["supports_multi_master"] = cap["multi_master"] == "True" + cap["supports_clock_stretching"] = cap["clock_stretching"] == "True" + cap["supports_async"] = cap["async"] == "True" + + return cap + + def get_capabilities(self): + resp_slave = self.command("slave", "get_capabilities") + self.caps_slave = self.parse_capabilities(resp_slave) + + resp_master = self.command("master", "get_capabilities") + self.caps_master = self.parse_capabilities(resp_master) + + def set_test_capabilities(self): + self.caps["minimum_frequency"] = max( + self.caps_slave["minimum_frequency"], self.caps_master["minimum_frequency"]) + self.caps["maximum_frequency"] = min( + self.caps_slave["maximum_frequency"], self.caps_master["maximum_frequency"]) + self.caps["supports_slave_mode"] = self.caps_slave["supports_slave_mode"] and self.caps_master["supports_slave_mode"] + self.caps["supports_10bit_addressing"] = self.caps_slave["supports_10bit_addressing"] and self.caps_master["supports_10bit_addressing"] + self.caps["supports_multi_master"] = self.caps_slave["supports_multi_master"] and self.caps_master["supports_multi_master"] + self.caps["supports_clock_stretching"] = self.caps_slave["supports_clock_stretching"] and self.caps_master["supports_clock_stretching"] + self.caps["supports_async"] = self.caps_slave["supports_async"] and self.caps_master["supports_async"] + + def test_execute(self, config): + + if not self.caps_slave["supports_slave_mode"]: + raise TestStepFail("Slave mode UNSUPPORTED") + #raise SkippedTestcaseException("Slave mode UNSUPPORTED") + + slave_init_config = self.slave_init_config_str.format( + config["frequency"]) + master_init_config = self.master_init_config_str.format( + config["frequency"]) + + addressing_types = {"7bit": (0, 7), "10bit": (1, 10)} + + for addressing_key, addressing_value in addressing_types.iteritems(): + if addressing_key == "10bit" and not self.caps["supports_10bit_addressing"]: + continue + for address in config["address"][addressing_value[0]]: + if type(config["write_size"]) is tuple and type(config["read_size"]) is tuple: + slave_exec_config = self.slave_exec_r_or_w_config_str.format( + config["iterations"], config["write_size"][2], config["write_size"][3], config["read_size"][2], config["read_size"][3], addressing_value[1], address) + master_exec_config = self.master_exec_r_or_w_config_str.format( + config["communication"], config["iterations"], config["write_size"][0], config["write_size"][1], config["read_size"][0], config["read_size"][1], addressing_value[1], address) + else: + slave_exec_config = self.slave_exec_rw_config_str.format( + config["iterations"], config["write_size"], config["read_size"], addressing_value[1], address) + master_exec_config = self.master_exec_rw_config_str.format( + config["communication"], config["iterations"], config["write_size"], config["read_size"], addressing_value[1], address) + + resp_slave_init = self.command( + "slave", slave_init_config, report_cmd_fail=False) + resp_master_init = self.command( + "master", master_init_config, report_cmd_fail=False) + + async_slave_exec = self.command( + "slave", slave_exec_config, asynchronous=True) + resp_master_exec = self.command( + "master", master_exec_config, report_cmd_fail=False) + + resp_slave_finish = self.command( + "slave", "test_stop_slave", report_cmd_fail=False) + resp_slave_exec = self.wait_for_async_response( + slave_exec_config, async_slave_exec) + + self.command("slave", "test_deinit_slave", + report_cmd_fail=False) + self.command("master", "test_deinit_master", + report_cmd_fail=False) + + master_error = resp_master_init.retcode != ReturnCodes.RETCODE_SUCCESS or resp_master_exec.retcode != ReturnCodes.RETCODE_SUCCESS + slave_error = resp_slave_init.retcode != ReturnCodes.RETCODE_SUCCESS or resp_slave_exec.retcode != ReturnCodes.RETCODE_SUCCESS + + if(master_error or slave_error): + raise TestStepFail("Communication failure") + + def setup(self): + self.get_capabilities() + self.set_test_capabilities() + + def teardown(self): + pass + +########################### +# blocking_write-read +########################### + +# minimum_frequency + + +@test_case(I2CComTest, + name="I2C_COM_MASTER-SLAVE_BLOCKING_WRITE-READ_1B_MIN_FREQUENCY", + title="test write read") +def I2C_COM_MASTER_SLAVE_BLOCKING_WRITE_READ_1B_MIN_FREQUENCY(self): + self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "blocking_write-read", + "iterations": 10, "write_size": 1, "read_size": 1, "address": [self.address_range_7bit, self.address_range_10bit]}) + + +@test_case(I2CComTest, + name="I2C_COM_MASTER-SLAVE_BLOCKING_WRITE-READ_10B_MIN_FREQUENCY", + title="test write read") +def I2C_COM_MASTER_SLAVE_BLOCKING_WRITE_READ_10B_MIN_FREQUENCY(self): + self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "blocking_write-read", "iterations": 10, + "write_size": 10, "read_size": 10, "address": [self.address_range_7bit, self.address_range_10bit]}) + + +@test_case(I2CComTest, + name="I2C_COM_MASTER-SLAVE_BLOCKING_WRITE-READ_257B_MIN_FREQUENCY", + title="test write read") +def I2C_COM_MASTER_SLAVE_BLOCKING_WRITE_READ_257B_MIN_FREQUENCY(self): + self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "blocking_write-read", "iterations": 10, + "write_size": 257, "read_size": 257, "address": [self.address_range_7bit, self.address_range_10bit]}) + +# maximum_frequency + + +@test_case(I2CComTest, + name="I2C_COM_MASTER-SLAVE_BLOCKING_WRITE-READ_1B_MAX_FREQUENCY", + title="test write read") +def I2C_COM_MASTER_SLAVE_BLOCKING_WRITE_READ_1B_MAX_FREQUENCY(self): + self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "blocking_write-read", + "iterations": 10, "write_size": 1, "read_size": 1, "address": [self.address_range_7bit, self.address_range_10bit]}) + + +@test_case(I2CComTest, + name="I2C_COM_MASTER-SLAVE_BLOCKING_WRITE-READ_10B_MAX_FREQUENCY", + title="test write read") +def I2C_COM_MASTER_SLAVE_BLOCKING_WRITE_READ_10B_MAX_FREQUENCY(self): + self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "blocking_write-read", "iterations": 10, + "write_size": 10, "read_size": 10, "address": [self.address_range_7bit, self.address_range_10bit]}) + + +@test_case(I2CComTest, + name="I2C_COM_MASTER-SLAVE_BLOCKING_WRITE-READ_257B_MAX_FREQUENCY", + title="test write read") +def I2C_COM_MASTER_SLAVE_BLOCKING_WRITE_READ_257B_MAX_FREQUENCY(self): + self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "blocking_write-read", "iterations": 10, + "write_size": 257, "read_size": 257, "address": [self.address_range_7bit, self.address_range_10bit]}) + +@test_case(I2CComTest, + name="I2C_COM_MASTER-SLAVE_BLOCKING_WRITE-READ_1025B_MAX_FREQUENCY", + title="test write read") +def I2C_COM_MASTER_SLAVE_BLOCKING_WRITE_READ_1025B_MAX_FREQUENCY(self): + self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "blocking_write-read", "iterations": 10, + "write_size": 1025, "read_size": 1025, "address": [self.address_range_7bit, self.address_range_10bit]}) + +########################### +# async_write-read +########################### + +# minimum_frequency + + +@test_case(I2CComTest, + name="I2C_COM_MASTER-SLAVE_ASYNC_WRITE-READ_1B_MIN_FREQUENCY", + title="test write read") +def I2C_COM_MASTER_SLAVE_ASYNC_WRITE_READ_1B_MIN_FREQUENCY(self): + self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "async_write-read", "iterations": 10, + "write_size": 1, "read_size": 1, "address": [self.address_range_7bit, self.address_range_10bit]}) + + +@test_case(I2CComTest, + name="I2C_COM_MASTER-SLAVE_ASYNC_WRITE-READ_10B_MIN_FREQUENCY", + title="test write read") +def ASYNCI2C_COM_MASTER_SLAVE_BLOCKING_WRITE_READ_10B_MIN_FREQUENCY(self): + self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "async_write-read", "iterations": 10, + "write_size": 10, "read_size": 10, "address": [self.address_range_7bit, self.address_range_10bit]}) + + +@test_case(I2CComTest, + name="I2C_COM_MASTER-SLAVE_ASYNC_WRITE-READ_257B_MIN_FREQUENCY", + title="test write read") +def I2C_COM_MASTER_SLAVE_ASYNC_WRITE_READ_257B_MIN_FREQUENCY(self): + self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "async_write-read", "iterations": 10, + "write_size": 257, "read_size": 257, "address": [self.address_range_7bit, self.address_range_10bit]}) + +# maximum_frequency + + +@test_case(I2CComTest, + name="I2C_COM_MASTER-SLAVE_ASYNC_WRITE-READ_1B_MAX_FREQUENCY", + title="test write read") +def I2C_COM_MASTER_SLAVE_ASYNC_WRITE_READ_1B_MAX_FREQUENCY(self): + self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_write-read", "iterations": 10, + "write_size": 1, "read_size": 1, "address": [self.address_range_7bit, self.address_range_10bit]}) + + +@test_case(I2CComTest, + name="I2C_COM_MASTER-SLAVE_ASYNC_WRITE-READ_10B_MAX_FREQUENCY", + title="test write read") +def I2C_COM_MASTER_SLAVE_ASYNC_WRITE_READ_10B_MAX_FREQUENCY(self): + self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_write-read", "iterations": 10, + "write_size": 10, "read_size": 10, "address": [self.address_range_7bit, self.address_range_10bit]}) + + +@test_case(I2CComTest, + name="I2C_COM_MASTER-SLAVE_ASYNC_WRITE-READ_257B_MAX_FREQUENCY", + title="test write read") +def I2C_COM_MASTER_SLAVE_ASYNC_WRITE_READ_257B_MAX_FREQUENCY(self): + self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_write-read", "iterations": 10, + "write_size": 257, "read_size": 257, "address": [self.address_range_7bit, self.address_range_10bit]}) + +########################### +# async_transfer +########################### + +# minimum_frequency + + +@test_case(I2CComTest, + name="I2C_COM_MASTER-SLAVE_ASYNC_TRANSFER_1B_MIN_FREQUENCY", + title="test write read") +def I2C_COM_MASTER_SLAVE_ASYNC_TRANSFER_1B_MIN_FREQUENCY(self): + self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "async_transfer", "iterations": 10, + "write_size": 1, "read_size": 1, "address": [self.address_range_7bit, self.address_range_10bit]}) + + +@test_case(I2CComTest, + name="I2C_COM_MASTER-SLAVE_ASYNC_TRANSFER_10B_MIN_FREQUENCY", + title="test write read") +def ASYNCI2C_COM_MASTER_SLAVE_BLOCKING_TRANSFER_10B_MIN_FREQUENCY(self): + self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "async_transfer", "iterations": 10, + "write_size": 10, "read_size": 10, "address": [self.address_range_7bit, self.address_range_10bit]}) + + +@test_case(I2CComTest, + name="I2C_COM_MASTER-SLAVE_ASYNC_TRANSFER_257B_MIN_FREQUENCY", + title="test write read") +def I2C_COM_MASTER_SLAVE_ASYNC_TRANSFER_257B_MIN_FREQUENCY(self): + self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "async_transfer", "iterations": 10, + "write_size": 257, "read_size": 257, "address": [self.address_range_7bit, self.address_range_10bit]}) + +# maximum_frequency + + +@test_case(I2CComTest, + name="I2C_COM_MASTER-SLAVE_ASYNC_TRANSFER_1B_MAX_FREQUENCY", + title="test write read") +def I2C_COM_MASTER_SLAVE_ASYNC_TRANSFER_1B_MAX_FREQUENCY(self): + self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_transfer", "iterations": 10, + "write_size": 1, "read_size": 1, "address": [self.address_range_7bit, self.address_range_10bit]}) + + +@test_case(I2CComTest, + name="I2C_COM_MASTER-SLAVE_ASYNC_TRANSFER_10B_MAX_FREQUENCY", + title="test write read") +def I2C_COM_MASTER_SLAVE_ASYNC_TRANSFER_10B_MAX_FREQUENCY(self): + self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_transfer", "iterations": 10, + "write_size": 10, "read_size": 10, "address": [self.address_range_7bit, self.address_range_10bit]}) + + +@test_case(I2CComTest, + name="I2C_COM_MASTER-SLAVE_ASYNC_TRANSFER_257B_MAX_FREQUENCY", + title="test write read") +def I2C_COM_MASTER_SLAVE_ASYNC_TRANSFER_257B_MAX_FREQUENCY(self): + self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_transfer", "iterations": 10, + "write_size": 257, "read_size": 257, "address": [self.address_range_7bit, self.address_range_10bit]}) + +@test_case(I2CComTest, + name="I2C_COM_MASTER-SLAVE_ASYNC_TRANSFER_1025B_MAX_FREQUENCY", + title="test write read") +def I2C_COM_MASTER_SLAVE_ASYNC_TRANSFER_1025B_MAX_FREQUENCY(self): + self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_transfer", "iterations": 10, + "write_size": 1025, "read_size": 1025, "address": [self.address_range_7bit, self.address_range_10bit]}) From 7c6ec9c209a807950afce5826b41573e7b4d2f26 Mon Sep 17 00:00:00 2001 From: Maciej Bocianski Date: Fri, 10 May 2019 10:17:40 +0200 Subject: [PATCH 2/3] i2c communication test update - sync with HAL I2C API changes - add stop signal configuration - add timeout functionality - update testcases --- TEST_APPS/device/i2c_com/common.cpp | 6 +- TEST_APPS/device/i2c_com/main.cpp | 24 +- TEST_APPS/device/i2c_com/master.cpp | 92 +++++-- TEST_APPS/device/i2c_com/master.h | 14 +- TEST_APPS/device/i2c_com/slave.cpp | 19 +- TEST_APPS/testcases/i2c_com/test_i2c_com.py | 267 +++++++++++--------- 6 files changed, 250 insertions(+), 172 deletions(-) diff --git a/TEST_APPS/device/i2c_com/common.cpp b/TEST_APPS/device/i2c_com/common.cpp index 924e6298629..1ac6d9751df 100644 --- a/TEST_APPS/device/i2c_com/common.cpp +++ b/TEST_APPS/device/i2c_com/common.cpp @@ -64,7 +64,7 @@ bool test_check_message(bool condition, const char *condition_str, const char *m bool test_check_equal_int(int32_t expected, int32_t actual, const char *file, int line) { if (expected != actual) { - printf("assertion failed: %d != %d %s:%d\r\n", expected, actual, file, line); + printf("assertion failed: %ld != %ld %s:%d\r\n", expected, actual, file, line); return false; } else { return true; @@ -74,7 +74,7 @@ bool test_check_equal_int(int32_t expected, int32_t actual, const char *file, in bool test_check_equal_uint(uint32_t expected, uint32_t actual, const char *file, int line) { if (expected != actual) { - printf("assertion failed: %u != %u %s:%d\r\n", expected, actual, file, line); + printf("assertion failed: %lu != %lu %s:%d\r\n", expected, actual, file, line); return false; } else { return true; @@ -84,7 +84,7 @@ bool test_check_equal_uint(uint32_t expected, uint32_t actual, const char *file, bool test_check_uint_within(uint32_t min, uint32_t max, uint32_t actual, const char *file, int line) { if (actual < min || actual > max) { - printf("assertion failed: %u not in range (%u,%u) %s:%d\r\n", actual, min, max, file, line); + printf("assertion failed: %lu not in range (%lu,%lu) %s:%d\r\n", actual, min, max, file, line); return false; } else { return true; diff --git a/TEST_APPS/device/i2c_com/main.cpp b/TEST_APPS/device/i2c_com/main.cpp index 2128297af83..cab5d9281ba 100644 --- a/TEST_APPS/device/i2c_com/main.cpp +++ b/TEST_APPS/device/i2c_com/main.cpp @@ -44,6 +44,9 @@ #define ASYNC_WRITE_READ "async_write-read" #define ASYNC_TRANSFER "async_transfer" #endif +#define STOP_EACH_TRANSFER 2 +#define STOP_EACH_ITERATION 1 +#define STOP_AT_THE_END 0 #define GET_PARAM_STR(key, str) \ @@ -132,17 +135,23 @@ int test_exec_master(int argc, char *argv[]) int32_t address10 = -1; GET_PARAM_INT("address10:", address10, true); + int32_t stop; + GET_PARAM_INT("stop:", stop, false); + + bool stop_each = (stop == STOP_EACH_TRANSFER); + bool stop_each_iter = (stop == STOP_EACH_ITERATION); + uint32_t write_address = address7 != -1 ? MAKE_7BIT_WRITE_ADDRESS(address7) : MAKE_10BIT_WRITE_ADDRESS(address10); uint32_t read_address = address7 != -1 ? MAKE_7BIT_READ_ADDRESS(address7) : MAKE_10BIT_READ_ADDRESS(address10); bool ret = false; if (strcmp(BLOCKING_WRITE_READ, com_type) == 0) { if (write_size && read_size) { - ret = master_write_read(write_size, read_size, write_address, read_address, iterations); + ret = master_write_read(write_size, read_size, write_address, read_address, iterations, stop_each, stop_each_iter); } else if (write_size) { - ret = master_write(write_size, write_result_size, write_address, iterations); + ret = master_write(write_size, write_result_size, write_address, iterations, stop_each || stop_each_iter); } else if (read_size) { - ret = master_read(read_size, read_result_size, read_address, iterations); + ret = master_read(read_size, read_result_size, read_address, iterations, stop_each || stop_each_iter); } else { return CMDLINE_RETCODE_INVALID_PARAMETERS; } @@ -150,16 +159,16 @@ int test_exec_master(int argc, char *argv[]) #if DEVICE_I2C_ASYNCH else if (strcmp(ASYNC_WRITE_READ, com_type) == 0) { if (write_size && read_size) { - ret = master_write_read_async(write_size, read_size, address7, iterations); + ret = master_write_read_async(write_size, read_size, address7, iterations, stop_each, stop_each_iter); } else if (write_size) { - ret = master_write_async(write_size, write_result_size, address7, iterations); + ret = master_write_async(write_size, write_result_size, address7, iterations, stop_each || stop_each_iter); } else if (read_size) { - ret = master_read_async(write_size, read_result_size, address7, iterations); + ret = master_read_async(write_size, read_result_size, address7, iterations, stop_each || stop_each_iter); } else { return CMDLINE_RETCODE_INVALID_PARAMETERS; } } else if (strcmp(ASYNC_TRANSFER, com_type) == 0) { - ret = master_transfer_async(write_size, read_size, address7, iterations); + ret = master_transfer_async(write_size, read_size, address7, iterations, stop_each || stop_each_iter); } #endif else { @@ -241,6 +250,7 @@ void wrap_printf(const char *f, va_list a) int main() { + ticker_read(get_us_ticker_data()); // start ticker here for future use in srand #if I2C_DEBUG_PIN_MASTER==1 || I2C_DEBUG_PIN_SLAVE==1 test_pin_init(); #endif diff --git a/TEST_APPS/device/i2c_com/master.cpp b/TEST_APPS/device/i2c_com/master.cpp index 4a15a06345a..89d055af3a6 100644 --- a/TEST_APPS/device/i2c_com/master.cpp +++ b/TEST_APPS/device/i2c_com/master.cpp @@ -62,6 +62,17 @@ static uint32_t _i2c_frequency(uint32_t frequency) return frequency; } +static void _i2c_timeout(uint32_t timeout) +{ + i2c_obj->timeout(timeout); +} + +static void _i2c_stop() +{ + i2c_obj->stop(); +} + + static int32_t _i2c_read(uint16_t address, void *data, uint32_t length, bool last) { int ret = i2c_obj->read(address, (char *)data, length); @@ -110,17 +121,27 @@ static uint32_t _i2c_frequency(uint32_t frequency) return i2c_frequency(&i2c_obj, frequency); } -static int32_t _i2c_read(uint16_t address, void *data, uint32_t length, bool last) +static void _i2c_timeout(uint32_t timeout) +{ + i2c_timeout(&i2c_obj, timeout); +} + +static void _i2c_stop() +{ + i2c_stop(&i2c_obj); +} + +static int32_t _i2c_read(uint16_t address, uint8_t *data, uint32_t length, bool last) { return i2c_read(&i2c_obj, address, data, length, last); } -static int32_t _i2c_write(uint16_t address, const void *data, uint32_t length, bool stop) +static int32_t _i2c_write(uint16_t address, const uint8_t *data, uint32_t length, bool stop) { return i2c_write(&i2c_obj, address, data, length, stop); } #if DEVICE_I2C_ASYNCH -void _i2c_transfer_async(const void *tx, uint32_t tx_length, void *rx, uint32_t rx_length, +void _i2c_transfer_async(const uint8_t *tx, uint32_t tx_length, uint8_t *rx, uint32_t rx_length, uint16_t address, bool stop, i2c_async_handler_f handler, void *ctx) { i2c_transfer_async(&i2c_obj, tx, tx_length, rx, rx_length, address, stop, handler, ctx); @@ -149,7 +170,7 @@ bool master_deinit() } -bool master_write_read(uint32_t write_size, uint32_t read_size, uint16_t write_address, uint16_t read_address, uint32_t iterations) +bool master_write_read(uint32_t write_size, uint32_t read_size, uint16_t write_address, uint16_t read_address, uint32_t iterations, bool stop_each, bool stop_each_iter) { bool result = true; @@ -166,14 +187,14 @@ bool master_write_read(uint32_t write_size, uint32_t read_size, uint16_t write_a } MASTER_PIN_TOGGLE(5); - ret = _i2c_write(write_address, tx_buf, write_size, false); + ret = _i2c_write(write_address, tx_buf, write_size, stop_each); MASTER_PIN_TOGGLE(5); result = TEST_CHECK_EQUAL_INT(write_size, ret); I2C_DEBUG_PRINTF("[master] write count: %d\n", ret); if (result) { MASTER_PIN_TOGGLE(5); - ret = _i2c_read(read_address, rx_buf, read_size, true); + ret = _i2c_read(read_address, rx_buf, read_size, stop_each || stop_each_iter); MASTER_PIN_TOGGLE(5); result = TEST_CHECK_EQUAL_INT(read_size, ret); I2C_DEBUG_PRINTF("[master] read count: %d\n", ret); @@ -182,7 +203,7 @@ bool master_write_read(uint32_t write_size, uint32_t read_size, uint16_t write_a if (result) { for (uint32_t j = 0; j < MIN(write_size, read_size); j++) { if (rx_buf[j] != tx_buf[j]) { - result = TEST_CHECK_EQUAL_INT(tx_buf[j], rx_buf[j]); + result = TEST_CHECK_EQUAL_INT(tx_buf[j] + 1, rx_buf[j]); break; } } @@ -199,13 +220,17 @@ bool master_write_read(uint32_t write_size, uint32_t read_size, uint16_t write_a } I2C_DEBUG_PRINTF("\r\n"); } + if (!stop_each && !stop_each_iter) { + _i2c_stop(); + } + delete []tx_buf; delete []rx_buf; return result; } -bool master_read(uint32_t read_size, uint32_t read_result, uint16_t address, uint32_t iterations) +bool master_read(uint32_t read_size, uint32_t read_result, uint16_t address, uint32_t iterations, bool stop_each_iter) { bool result = true; @@ -213,7 +238,7 @@ bool master_read(uint32_t read_size, uint32_t read_result, uint16_t address, uin for (uint32_t i = 0; i < iterations && result; i++) { MASTER_PIN_TOGGLE(5); - int ret = _i2c_read(MAKE_7BIT_READ_ADDRESS(address), rx_buf, read_size, true); + int ret = _i2c_read(MAKE_7BIT_READ_ADDRESS(address), rx_buf, read_size, stop_each_iter); MASTER_PIN_TOGGLE(5); result = TEST_CHECK_EQUAL_INT(read_result, ret); I2C_DEBUG_PRINTF("[master] read count: %d\n", ret); @@ -233,12 +258,16 @@ bool master_read(uint32_t read_size, uint32_t read_result, uint16_t address, uin } } } + if (!stop_each_iter) { + _i2c_stop(); + } + delete []rx_buf; return result; } -bool master_write(uint32_t write_size, uint32_t write_result, uint16_t address, uint32_t iterations) +bool master_write(uint32_t write_size, uint32_t write_result, uint16_t address, uint32_t iterations, bool stop_each_iter) { bool result = true; @@ -250,7 +279,7 @@ bool master_write(uint32_t write_size, uint32_t write_result, uint16_t address, for (uint32_t i = 0; i < iterations && result; i++) { MASTER_PIN_TOGGLE(5); - int ret = _i2c_write(MAKE_7BIT_WRITE_ADDRESS(address), tx_buf, write_size, false); + int ret = _i2c_write(MAKE_7BIT_WRITE_ADDRESS(address), tx_buf, write_size, stop_each_iter); MASTER_PIN_TOGGLE(5); result = TEST_CHECK_EQUAL_INT(write_result, ret); I2C_DEBUG_PRINTF("[master] write count: %d\n", ret); @@ -261,6 +290,10 @@ bool master_write(uint32_t write_size, uint32_t write_result, uint16_t address, } I2C_DEBUG_PRINTF("\r\n"); } + if (!stop_each_iter) { + _i2c_stop(); + } + delete []tx_buf; return result; @@ -292,7 +325,7 @@ void async_callback(i2c_t *obj, i2c_async_event_t *event, void *ctx) } #endif // TEST_I2C_DRIVER -bool master_write_read_async(uint32_t write_size, uint32_t read_size, uint16_t address, uint32_t iterations) +bool master_write_read_async(uint32_t write_size, uint32_t read_size, uint16_t address, uint32_t iterations, bool stop_each, bool stop_each_iter) { async_status transmit_status = {}; async_status receive_status = {}; @@ -308,7 +341,7 @@ bool master_write_read_async(uint32_t write_size, uint32_t read_size, uint16_t a } transmit_status.done = false; MASTER_PIN_TOGGLE(5); - _i2c_transfer_async(tx_buf, write_size, NULL, 0, MAKE_7BIT_WRITE_ADDRESS(address), false, async_callback, &transmit_status); + _i2c_transfer_async(tx_buf, write_size, NULL, 0, MAKE_7BIT_WRITE_ADDRESS(address), stop_each, async_callback, &transmit_status); MASTER_PIN_TOGGLE(5); while (!transmit_status.done); MASTER_PIN_TOGGLE(5); @@ -320,7 +353,7 @@ bool master_write_read_async(uint32_t write_size, uint32_t read_size, uint16_t a if (result) { receive_status.done = false; MASTER_PIN_TOGGLE(5); - _i2c_transfer_async(NULL, 0, rx_buf, read_size, MAKE_7BIT_READ_ADDRESS(address), true, async_callback, &receive_status); + _i2c_transfer_async(NULL, 0, rx_buf, read_size, MAKE_7BIT_READ_ADDRESS(address), stop_each || stop_each_iter, async_callback, &receive_status); MASTER_PIN_TOGGLE(5); while (!receive_status.done); MASTER_PIN_TOGGLE(5); @@ -341,13 +374,16 @@ bool master_write_read_async(uint32_t write_size, uint32_t read_size, uint16_t a if (result) { for (uint32_t j = 0; j < MIN(write_size, read_size); j++) { - if (rx_buf[j] != tx_buf[j]) { + if (rx_buf[j] != (tx_buf[j] + 1)) { result = TEST_CHECK_EQUAL_INT(tx_buf[j], rx_buf[j]); break; } } } } + if (!stop_each && !stop_each_iter) { + _i2c_stop(); + } delete [] tx_buf; delete [] rx_buf; @@ -355,7 +391,7 @@ bool master_write_read_async(uint32_t write_size, uint32_t read_size, uint16_t a return result; } -bool master_write_async(uint32_t write_size, uint32_t write_reulting_size, uint16_t address, uint32_t iterations) +bool master_write_async(uint32_t write_size, uint32_t write_reulting_size, uint16_t address, uint32_t iterations, bool stop_each) { async_status transmit_status = {}; uint8_t *tx_buf = new uint8_t[write_size]; @@ -368,7 +404,7 @@ bool master_write_async(uint32_t write_size, uint32_t write_reulting_size, uint1 for (uint32_t i = 0; i < iterations && result; i++) { transmit_status.done = false; MASTER_PIN_TOGGLE(5); - _i2c_transfer_async(tx_buf, write_size, NULL, 0, MAKE_7BIT_WRITE_ADDRESS(address), false, async_callback, &transmit_status); + _i2c_transfer_async(tx_buf, write_size, NULL, 0, MAKE_7BIT_WRITE_ADDRESS(address), stop_each, async_callback, &transmit_status); MASTER_PIN_TOGGLE(5); while (!transmit_status.done); MASTER_PIN_TOGGLE(5); @@ -380,13 +416,16 @@ bool master_write_async(uint32_t write_size, uint32_t write_reulting_size, uint1 } I2C_DEBUG_PRINTF("\r\n"); } + if (!stop_each) { + _i2c_stop(); + } delete [] tx_buf; return result; } -bool master_read_async(uint32_t read_size, uint32_t read_resulting_size, uint16_t address, uint32_t iterations) +bool master_read_async(uint32_t read_size, uint32_t read_resulting_size, uint16_t address, uint32_t iterations, bool stop_each) { async_status receive_status = {}; uint8_t *rx_buf = new uint8_t[read_size]; @@ -395,7 +434,7 @@ bool master_read_async(uint32_t read_size, uint32_t read_resulting_size, uint16_ for (uint32_t i = 0; i < iterations && result; i++) { receive_status.done = false; MASTER_PIN_TOGGLE(5); - _i2c_transfer_async(NULL, 0, rx_buf, read_size, MAKE_7BIT_READ_ADDRESS(address), true, async_callback, &receive_status); + _i2c_transfer_async(NULL, 0, rx_buf, read_size, MAKE_7BIT_READ_ADDRESS(address), stop_each, async_callback, &receive_status); MASTER_PIN_TOGGLE(5); while (!receive_status.done); MASTER_PIN_TOGGLE(5); @@ -416,12 +455,16 @@ bool master_read_async(uint32_t read_size, uint32_t read_resulting_size, uint16_ } } } + if (!stop_each) { + _i2c_stop(); + } + delete [] rx_buf; return result; } -bool master_transfer_async(uint32_t write_size, uint32_t read_size, uint16_t address, uint32_t iterations) +bool master_transfer_async(uint32_t write_size, uint32_t read_size, uint16_t address, uint32_t iterations, bool stop_each) { async_status transfer_status = {}; uint8_t *tx_buf = new uint8_t[write_size]; @@ -436,7 +479,7 @@ bool master_transfer_async(uint32_t write_size, uint32_t read_size, uint16_t add } transfer_status.done = false; MASTER_PIN_TOGGLE(5); - _i2c_transfer_async(tx_buf, write_size, rx_buf, read_size, MAKE_7BIT_WRITE_ADDRESS(address), true, async_callback, &transfer_status); + _i2c_transfer_async(tx_buf, write_size, rx_buf, read_size, MAKE_7BIT_WRITE_ADDRESS(address), stop_each, async_callback, &transfer_status); MASTER_PIN_TOGGLE(5); while (!transfer_status.done); MASTER_PIN_TOGGLE(5); @@ -461,13 +504,16 @@ bool master_transfer_async(uint32_t write_size, uint32_t read_size, uint16_t add if (result) { for (uint32_t j = 0; j < write_size; j++) { - if (rx_buf[j] != tx_buf[j]) { - result = TEST_CHECK_EQUAL_INT(tx_buf[j], rx_buf[j]); + if (rx_buf[j] != (tx_buf[j] + 1)) { + result = TEST_CHECK_EQUAL_INT(tx_buf[j] + 1, rx_buf[j]); break; } } } } + if (!stop_each) { + _i2c_stop(); + } delete [] tx_buf; delete [] rx_buf; diff --git a/TEST_APPS/device/i2c_com/master.h b/TEST_APPS/device/i2c_com/master.h index ca3d0bbd85b..ab76586e74c 100644 --- a/TEST_APPS/device/i2c_com/master.h +++ b/TEST_APPS/device/i2c_com/master.h @@ -18,13 +18,13 @@ #ifndef TEST_APPS_DEVICE_I2C_COM_MASTER_H_ #define TEST_APPS_DEVICE_I2C_COM_MASTER_H_ -bool master_write(uint32_t write_size, uint32_t write_result, uint16_t address, uint32_t iterations); -bool master_read(uint32_t read_size, uint32_t read_result, uint16_t address, uint32_t iterations); -bool master_write_read(uint32_t write_size, uint32_t read_size, uint16_t write_address, uint16_t read_address, uint32_t iterations); -bool master_write_async(uint32_t write_size, uint32_t write_reulting_size, uint16_t address, uint32_t iterations); -bool master_read_async(uint32_t read_size, uint32_t read_resulting_size, uint16_t address, uint32_t iterations); -bool master_write_read_async(uint32_t write_size, uint32_t read_size, uint16_t address, uint32_t iterations); -bool master_transfer_async(uint32_t write_size, uint32_t read_size, uint16_t address, uint32_t iterations); +bool master_write(uint32_t write_size, uint32_t write_result, uint16_t address, uint32_t iterations, bool stop_each); +bool master_read(uint32_t read_size, uint32_t read_result, uint16_t address, uint32_t iterations, bool stop_each); +bool master_write_read(uint32_t write_size, uint32_t read_size, uint16_t write_address, uint16_t read_address, uint32_t iterations, bool stop_each, bool stop_each_iter); +bool master_write_async(uint32_t write_size, uint32_t write_reulting_size, uint16_t address, uint32_t iterations, bool stop_each); +bool master_read_async(uint32_t read_size, uint32_t read_resulting_size, uint16_t address, uint32_t iterations, bool stop_each); +bool master_write_read_async(uint32_t write_size, uint32_t read_size, uint16_t address, uint32_t iterations, bool stop_each, bool stop_each_iter); +bool master_transfer_async(uint32_t write_size, uint32_t read_size, uint16_t address, uint32_t iterations, bool stop_each); bool master_init(uint32_t frequency); bool master_deinit(); diff --git a/TEST_APPS/device/i2c_com/slave.cpp b/TEST_APPS/device/i2c_com/slave.cpp index 8032d6625b3..986cdeb771e 100644 --- a/TEST_APPS/device/i2c_com/slave.cpp +++ b/TEST_APPS/device/i2c_com/slave.cpp @@ -96,6 +96,10 @@ static uint32_t _i2c_frequency(uint32_t frequency) return i2c_frequency(&i2c_obj, frequency); } +static void _i2c_timeout(uint32_t timeout) +{ + i2c_timeout(&i2c_obj, timeout); +} static void _i2c_slave_address(uint16_t address) { @@ -107,12 +111,12 @@ static i2c_slave_status_t _i2c_slave_status() return i2c_slave_status(&i2c_obj); } -static int32_t _i2c_read(void *data, uint32_t length, bool last) +static int32_t _i2c_read(uint8_t *data, uint32_t length, bool last) { return i2c_read(&i2c_obj, 0, data, length, last); } -static int32_t _i2c_write(const void *data, uint32_t length, bool stop) +static int32_t _i2c_write(const uint8_t *data, uint32_t length, bool stop) { return i2c_write(&i2c_obj, 0, data, length, stop); } @@ -162,8 +166,9 @@ void slave_transfer_job(TransferConfig *tc) I2C_DEBUG_PRINTF("[slave] read data count: %d\n", ret); I2C_DEBUG_PRINTF("[slave] read data: "); - for (int i = 0; i < tc->read_size; i++) { - I2C_DEBUG_PRINTF("%X ", data[i]); + for (uint32_t j = 0; j < tc->read_size; j++) { + data[j]++; + I2C_DEBUG_PRINTF("%X ", data[j]); } I2C_DEBUG_PRINTF("\r\n"); @@ -203,8 +208,8 @@ void slave_read_job(TransferConfig *tc) I2C_DEBUG_PRINTF("[slave] read data count: %d\n", ret); I2C_DEBUG_PRINTF("[slave] read data: "); - for (int i = 0; i < tc->read_size; i++) { - I2C_DEBUG_PRINTF("%X ", data[i]); + for (uint32_t j = 0; j < tc->read_size; j++) { + I2C_DEBUG_PRINTF("%X ", data[j]); } I2C_DEBUG_PRINTF("\r\n"); @@ -239,7 +244,7 @@ void slave_write_job(TransferConfig *tc) _i2c_slave_address(tc->address); for (uint32_t i = 0; i < tc->iterations; i++) { - SLAVE_PIN_TOGGLE(5); + SLAVE_PIN_TOGGLE(1); while (_i2c_slave_status() != ReadAddressed && !done); SLAVE_PIN_TOGGLE(1); int ret = _i2c_write(data, tc->write_size, false); diff --git a/TEST_APPS/testcases/i2c_com/test_i2c_com.py b/TEST_APPS/testcases/i2c_com/test_i2c_com.py index 064a7f3f92e..ac91d66b9a8 100644 --- a/TEST_APPS/testcases/i2c_com/test_i2c_com.py +++ b/TEST_APPS/testcases/i2c_com/test_i2c_com.py @@ -28,7 +28,7 @@ class I2CComTest(Bench): capabilities_names = ("minimum_frequency", "maximum_frequency", "supports_slave_mode", "supports_10bit_addressing", "supports_multi_master", "supports_clock_stretching", "supports_async") master_init_config_str = "test_init_master frequency: {0}" - master_exec_rw_config_str = "test_exec_master communication: {0} iterations: {1} write_size: {2} read_size: {3} address{4}: {5}" + master_exec_rw_config_str = "test_exec_master communication: {0} iterations: {1} write_size: {2} read_size: {3} address{4}: {5} stop: {6}" master_exec_r_or_w_config_str = "test_exec_master communication: {0} iterations: {1} write_size: {2} write_resulting_size: {3} read_size: {4} read_resulting_size: {5} address{6}: {7}" slave_init_config_str = "test_init_slave frequency: {0}" slave_exec_rw_config_str = "test_exec_slave iterations: {0} write_size: {1} read_size: {2} address{3}: {4}" @@ -38,6 +38,10 @@ class I2CComTest(Bench): caps_slave = {} caps = {} + STOP_EACH_TRANSFER = 2 + STOP_EACH_ITERATION = 1 + STOP_AT_THE_END = 0 + I2C_7BIT_ADDRESS_MIN = 8 I2C_7BIT_ADDRESS_MAX = 119 I2C_7BIT_ADDRESS = 85 @@ -138,43 +142,45 @@ def test_execute(self, config): for addressing_key, addressing_value in addressing_types.iteritems(): if addressing_key == "10bit" and not self.caps["supports_10bit_addressing"]: continue - for address in config["address"][addressing_value[0]]: - if type(config["write_size"]) is tuple and type(config["read_size"]) is tuple: - slave_exec_config = self.slave_exec_r_or_w_config_str.format( - config["iterations"], config["write_size"][2], config["write_size"][3], config["read_size"][2], config["read_size"][3], addressing_value[1], address) - master_exec_config = self.master_exec_r_or_w_config_str.format( - config["communication"], config["iterations"], config["write_size"][0], config["write_size"][1], config["read_size"][0], config["read_size"][1], addressing_value[1], address) - else: - slave_exec_config = self.slave_exec_rw_config_str.format( - config["iterations"], config["write_size"], config["read_size"], addressing_value[1], address) - master_exec_config = self.master_exec_rw_config_str.format( - config["communication"], config["iterations"], config["write_size"], config["read_size"], addressing_value[1], address) - - resp_slave_init = self.command( - "slave", slave_init_config, report_cmd_fail=False) - resp_master_init = self.command( - "master", master_init_config, report_cmd_fail=False) - - async_slave_exec = self.command( - "slave", slave_exec_config, asynchronous=True) - resp_master_exec = self.command( - "master", master_exec_config, report_cmd_fail=False) - - resp_slave_finish = self.command( - "slave", "test_stop_slave", report_cmd_fail=False) - resp_slave_exec = self.wait_for_async_response( - slave_exec_config, async_slave_exec) - - self.command("slave", "test_deinit_slave", - report_cmd_fail=False) - self.command("master", "test_deinit_master", - report_cmd_fail=False) - - master_error = resp_master_init.retcode != ReturnCodes.RETCODE_SUCCESS or resp_master_exec.retcode != ReturnCodes.RETCODE_SUCCESS - slave_error = resp_slave_init.retcode != ReturnCodes.RETCODE_SUCCESS or resp_slave_exec.retcode != ReturnCodes.RETCODE_SUCCESS - - if(master_error or slave_error): - raise TestStepFail("Communication failure") + for stop in config["stop"]: + for address in config["address"][addressing_value[0]]: + if type(config["write_size"]) is tuple and type(config["read_size"]) is tuple: + slave_exec_config = self.slave_exec_r_or_w_config_str.format( + config["iterations"], config["write_size"][2], config["write_size"][3], config["read_size"][2], config["read_size"][3], addressing_value[1], address) + master_exec_config = self.master_exec_r_or_w_config_str.format( + config["communication"], config["iterations"], config["write_size"][0], config["write_size"][1], config["read_size"][0], config["read_size"][1], addressing_value[1], address) + else: + slave_exec_config = self.slave_exec_rw_config_str.format( + config["iterations"], config["write_size"], config["read_size"], addressing_value[1], address) + master_exec_config = self.master_exec_rw_config_str.format( + config["communication"], config["iterations"], config["write_size"], config["read_size"], addressing_value[1], address, stop) + + resp_slave_init = self.command( + "slave", slave_init_config, report_cmd_fail=False) + resp_master_init = self.command( + "master", master_init_config, report_cmd_fail=False) + + async_slave_exec = self.command( + "slave", slave_exec_config, asynchronous=True) + resp_master_exec = self.command( + "master", master_exec_config, report_cmd_fail=False) + + resp_slave_finish = self.command( + "slave", "test_stop_slave", report_cmd_fail=False) + resp_slave_exec = self.wait_for_async_response( + slave_exec_config, async_slave_exec) + + self.command("slave", "test_deinit_slave", + report_cmd_fail=False) + self.command("master", "test_deinit_master", + report_cmd_fail=False) + + master_error = resp_master_init.retcode != ReturnCodes.RETCODE_SUCCESS or resp_master_exec.retcode != ReturnCodes.RETCODE_SUCCESS + slave_error = resp_slave_init.retcode != ReturnCodes.RETCODE_SUCCESS or resp_slave_exec.retcode != ReturnCodes.RETCODE_SUCCESS + + if(master_error or slave_error): + raise TestStepFail("Communication failure") + def setup(self): self.get_capabilities() @@ -189,62 +195,64 @@ def teardown(self): # minimum_frequency - @test_case(I2CComTest, - name="I2C_COM_MASTER-SLAVE_BLOCKING_WRITE-READ_1B_MIN_FREQUENCY", + name="I2C_COM_BLOCKING_WRITE-READ_1B_MIN_FREQUENCY", title="test write read") -def I2C_COM_MASTER_SLAVE_BLOCKING_WRITE_READ_1B_MIN_FREQUENCY(self): - self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "blocking_write-read", - "iterations": 10, "write_size": 1, "read_size": 1, "address": [self.address_range_7bit, self.address_range_10bit]}) +def I2C_COM_BLOCKING_WRITE_READ_1B_MIN_FREQUENCY(self): + self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "blocking_write-read", "iterations": 1000, + "write_size": 1, "read_size": 1, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) +@test_case(I2CComTest, + name="I2C_COM_BLOCKING_WRITE-READ_10B_MIN_FREQUENCY", + title="test write read") +def I2C_COM_BLOCKING_WRITE_READ_10B_MIN_FREQUENCY(self): + self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "blocking_write-read", "iterations": 100, + "write_size": 10, "read_size": 10, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) @test_case(I2CComTest, - name="I2C_COM_MASTER-SLAVE_BLOCKING_WRITE-READ_10B_MIN_FREQUENCY", + name="I2C_COM_BLOCKING_WRITE-READ_257B_MIN_FREQUENCY", title="test write read") -def I2C_COM_MASTER_SLAVE_BLOCKING_WRITE_READ_10B_MIN_FREQUENCY(self): +def I2C_COM_BLOCKING_WRITE_READ_257B_MIN_FREQUENCY(self): self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "blocking_write-read", "iterations": 10, - "write_size": 10, "read_size": 10, "address": [self.address_range_7bit, self.address_range_10bit]}) - + "write_size": 257, "read_size": 257, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) @test_case(I2CComTest, - name="I2C_COM_MASTER-SLAVE_BLOCKING_WRITE-READ_257B_MIN_FREQUENCY", + name="I2C_COM_BLOCKING_WRITE-READ_1025B_MIN_FREQUENCY", title="test write read") -def I2C_COM_MASTER_SLAVE_BLOCKING_WRITE_READ_257B_MIN_FREQUENCY(self): - self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "blocking_write-read", "iterations": 10, - "write_size": 257, "read_size": 257, "address": [self.address_range_7bit, self.address_range_10bit]}) +def I2C_COM_BLOCKING_WRITE_READ_1025B_MIN_FREQUENCY(self): + self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "blocking_write-read", "iterations": 1, + "write_size": 1025, "read_size": 1025, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) # maximum_frequency - @test_case(I2CComTest, - name="I2C_COM_MASTER-SLAVE_BLOCKING_WRITE-READ_1B_MAX_FREQUENCY", + name="I2C_COM_BLOCKING_WRITE-READ_1B_MAX_FREQUENCY", title="test write read") -def I2C_COM_MASTER_SLAVE_BLOCKING_WRITE_READ_1B_MAX_FREQUENCY(self): - self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "blocking_write-read", - "iterations": 10, "write_size": 1, "read_size": 1, "address": [self.address_range_7bit, self.address_range_10bit]}) - +def I2C_COM_BLOCKING_WRITE_READ_1B_MAX_FREQUENCY(self): + self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "blocking_write-read", "iterations": 1000, + "write_size": 1, "read_size": 1, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) @test_case(I2CComTest, - name="I2C_COM_MASTER-SLAVE_BLOCKING_WRITE-READ_10B_MAX_FREQUENCY", + name="I2C_COM_BLOCKING_WRITE-READ_10B_MAX_FREQUENCY", title="test write read") -def I2C_COM_MASTER_SLAVE_BLOCKING_WRITE_READ_10B_MAX_FREQUENCY(self): - self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "blocking_write-read", "iterations": 10, - "write_size": 10, "read_size": 10, "address": [self.address_range_7bit, self.address_range_10bit]}) +def I2C_COM_BLOCKING_WRITE_READ_10B_MAX_FREQUENCY(self): + self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "blocking_write-read", "iterations": 100, + "write_size": 10, "read_size": 10, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) @test_case(I2CComTest, - name="I2C_COM_MASTER-SLAVE_BLOCKING_WRITE-READ_257B_MAX_FREQUENCY", + name="I2C_COM_BLOCKING_WRITE-READ_257B_MAX_FREQUENCY", title="test write read") -def I2C_COM_MASTER_SLAVE_BLOCKING_WRITE_READ_257B_MAX_FREQUENCY(self): +def I2C_COM_BLOCKING_WRITE_READ_257B_MAX_FREQUENCY(self): self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "blocking_write-read", "iterations": 10, - "write_size": 257, "read_size": 257, "address": [self.address_range_7bit, self.address_range_10bit]}) + "write_size": 257, "read_size": 257, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) @test_case(I2CComTest, - name="I2C_COM_MASTER-SLAVE_BLOCKING_WRITE-READ_1025B_MAX_FREQUENCY", + name="I2C_COM_BLOCKING_WRITE-READ_1025B_MAX_FREQUENCY", title="test write read") -def I2C_COM_MASTER_SLAVE_BLOCKING_WRITE_READ_1025B_MAX_FREQUENCY(self): - self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "blocking_write-read", "iterations": 10, - "write_size": 1025, "read_size": 1025, "address": [self.address_range_7bit, self.address_range_10bit]}) +def I2C_COM_BLOCKING_WRITE_READ_1025B_MAX_FREQUENCY(self): + self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "blocking_write-read", "iterations": 1, + "write_size": 1025, "read_size": 1025, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) ########################### # async_write-read @@ -252,55 +260,63 @@ def I2C_COM_MASTER_SLAVE_BLOCKING_WRITE_READ_1025B_MAX_FREQUENCY(self): # minimum_frequency - @test_case(I2CComTest, - name="I2C_COM_MASTER-SLAVE_ASYNC_WRITE-READ_1B_MIN_FREQUENCY", + name="I2C_COM_ASYNC_WRITE-READ_1B_MIN_FREQUENCY", title="test write read") -def I2C_COM_MASTER_SLAVE_ASYNC_WRITE_READ_1B_MIN_FREQUENCY(self): - self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "async_write-read", "iterations": 10, - "write_size": 1, "read_size": 1, "address": [self.address_range_7bit, self.address_range_10bit]}) +def I2C_COM_ASYNC_WRITE_READ_1B_MIN_FREQUENCY(self): + self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "async_write-read", "iterations": 1000, + "write_size": 1, "read_size": 1, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) +@test_case(I2CComTest, + name="I2C_COM_ASYNC_WRITE-READ_10B_MIN_FREQUENCY", + title="test write read") +def I2C_COM_ASYNC_WRITE_READ_10B_MIN_FREQUENCY(self): + self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "async_write-read", "iterations": 100, + "write_size": 10, "read_size": 10, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) @test_case(I2CComTest, - name="I2C_COM_MASTER-SLAVE_ASYNC_WRITE-READ_10B_MIN_FREQUENCY", + name="I2C_COM_ASYNC_WRITE-READ_257B_MIN_FREQUENCY", title="test write read") -def ASYNCI2C_COM_MASTER_SLAVE_BLOCKING_WRITE_READ_10B_MIN_FREQUENCY(self): +def I2C_COM_ASYNC_WRITE_READ_257B_MIN_FREQUENCY(self): self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "async_write-read", "iterations": 10, - "write_size": 10, "read_size": 10, "address": [self.address_range_7bit, self.address_range_10bit]}) - + "write_size": 257, "read_size": 257, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) @test_case(I2CComTest, - name="I2C_COM_MASTER-SLAVE_ASYNC_WRITE-READ_257B_MIN_FREQUENCY", + name="I2C_COM_ASYNC_WRITE-READ_1025B_MIN_FREQUENCY", title="test write read") -def I2C_COM_MASTER_SLAVE_ASYNC_WRITE_READ_257B_MIN_FREQUENCY(self): - self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "async_write-read", "iterations": 10, - "write_size": 257, "read_size": 257, "address": [self.address_range_7bit, self.address_range_10bit]}) +def I2C_COM_ASYNC_WRITE_READ_1025B_MIN_FREQUENCY(self): + self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "async_write-read", "iterations": 1, + "write_size": 1025, "read_size": 1025, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) # maximum_frequency - @test_case(I2CComTest, - name="I2C_COM_MASTER-SLAVE_ASYNC_WRITE-READ_1B_MAX_FREQUENCY", + name="I2C_COM_ASYNC_WRITE-READ_1B_MAX_FREQUENCY", title="test write read") -def I2C_COM_MASTER_SLAVE_ASYNC_WRITE_READ_1B_MAX_FREQUENCY(self): - self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_write-read", "iterations": 10, - "write_size": 1, "read_size": 1, "address": [self.address_range_7bit, self.address_range_10bit]}) +def I2C_COM_ASYNC_WRITE_READ_1B_MAX_FREQUENCY(self): + self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_write-read", "iterations": 1000, + "write_size": 1, "read_size": 1, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) +@test_case(I2CComTest, + name="I2C_COM_ASYNC_WRITE-READ_10B_MAX_FREQUENCY", + title="test write read") +def I2C_COM_ASYNC_WRITE_READ_10B_MAX_FREQUENCY(self): + self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_write-read", "iterations": 100, + "write_size": 10, "read_size": 10, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) @test_case(I2CComTest, - name="I2C_COM_MASTER-SLAVE_ASYNC_WRITE-READ_10B_MAX_FREQUENCY", + name="I2C_COM_ASYNC_WRITE-READ_257B_MAX_FREQUENCY", title="test write read") -def I2C_COM_MASTER_SLAVE_ASYNC_WRITE_READ_10B_MAX_FREQUENCY(self): +def I2C_COM_ASYNC_WRITE_READ_257B_MAX_FREQUENCY(self): self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_write-read", "iterations": 10, - "write_size": 10, "read_size": 10, "address": [self.address_range_7bit, self.address_range_10bit]}) - + "write_size": 257, "read_size": 257, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) @test_case(I2CComTest, - name="I2C_COM_MASTER-SLAVE_ASYNC_WRITE-READ_257B_MAX_FREQUENCY", + name="I2C_COM_ASYNC_WRITE-READ_1025B_MAX_FREQUENCY", title="test write read") -def I2C_COM_MASTER_SLAVE_ASYNC_WRITE_READ_257B_MAX_FREQUENCY(self): - self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_write-read", "iterations": 10, - "write_size": 257, "read_size": 257, "address": [self.address_range_7bit, self.address_range_10bit]}) +def I2C_COM_ASYNC_WRITE_READ_1025B_MAX_FREQUENCY(self): + self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_write-read", "iterations": 1, + "write_size": 1025, "read_size": 1025, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) ########################### # async_transfer @@ -308,59 +324,60 @@ def I2C_COM_MASTER_SLAVE_ASYNC_WRITE_READ_257B_MAX_FREQUENCY(self): # minimum_frequency - @test_case(I2CComTest, - name="I2C_COM_MASTER-SLAVE_ASYNC_TRANSFER_1B_MIN_FREQUENCY", + name="I2C_COM_ASYNC_TRANSFER_1B_MIN_FREQUENCY", title="test write read") -def I2C_COM_MASTER_SLAVE_ASYNC_TRANSFER_1B_MIN_FREQUENCY(self): - self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "async_transfer", "iterations": 10, - "write_size": 1, "read_size": 1, "address": [self.address_range_7bit, self.address_range_10bit]}) +def I2C_COM_ASYNC_TRANSFER_1B_MIN_FREQUENCY(self): + self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "async_transfer", "iterations": 1000, + "write_size": 1, "read_size": 1, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) +@test_case(I2CComTest, + name="I2C_COM_ASYNC_TRANSFER_10B_MIN_FREQUENCY", + title="test write read") +def ASYNCI2C_COM_ASYNC_TRANSFER_10B_MIN_FREQUENCY(self): + self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "async_transfer", "iterations": 100, + "write_size": 10, "read_size": 10, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) @test_case(I2CComTest, - name="I2C_COM_MASTER-SLAVE_ASYNC_TRANSFER_10B_MIN_FREQUENCY", + name="I2C_COM_ASYNC_TRANSFER_257B_MIN_FREQUENCY", title="test write read") -def ASYNCI2C_COM_MASTER_SLAVE_BLOCKING_TRANSFER_10B_MIN_FREQUENCY(self): +def I2C_COM_ASYNC_TRANSFER_257B_MIN_FREQUENCY(self): self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "async_transfer", "iterations": 10, - "write_size": 10, "read_size": 10, "address": [self.address_range_7bit, self.address_range_10bit]}) - + "write_size": 257, "read_size": 257, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) @test_case(I2CComTest, - name="I2C_COM_MASTER-SLAVE_ASYNC_TRANSFER_257B_MIN_FREQUENCY", + name="I2C_COM_ASYNC_TRANSFER_1025B_MIN_FREQUENCY", title="test write read") -def I2C_COM_MASTER_SLAVE_ASYNC_TRANSFER_257B_MIN_FREQUENCY(self): - self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "async_transfer", "iterations": 10, - "write_size": 257, "read_size": 257, "address": [self.address_range_7bit, self.address_range_10bit]}) +def I2C_COM_ASYNC_TRANSFER_1025B_MIN_FREQUENCY(self): + self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "async_transfer", "iterations": 1, + "write_size": 1025, "read_size": 1025, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) # maximum_frequency - @test_case(I2CComTest, - name="I2C_COM_MASTER-SLAVE_ASYNC_TRANSFER_1B_MAX_FREQUENCY", + name="I2C_COM_ASYNC_TRANSFER_1B_MAX_FREQUENCY", title="test write read") -def I2C_COM_MASTER_SLAVE_ASYNC_TRANSFER_1B_MAX_FREQUENCY(self): - self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_transfer", "iterations": 10, - "write_size": 1, "read_size": 1, "address": [self.address_range_7bit, self.address_range_10bit]}) - +def I2C_COM_ASYNC_TRANSFER_1B_MAX_FREQUENCY(self): + self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_transfer", "iterations": 1000, + "write_size": 1, "read_size": 1, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) @test_case(I2CComTest, - name="I2C_COM_MASTER-SLAVE_ASYNC_TRANSFER_10B_MAX_FREQUENCY", + name="I2C_COM_ASYNC_TRANSFER_10B_MAX_FREQUENCY", title="test write read") -def I2C_COM_MASTER_SLAVE_ASYNC_TRANSFER_10B_MAX_FREQUENCY(self): - self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_transfer", "iterations": 10, - "write_size": 10, "read_size": 10, "address": [self.address_range_7bit, self.address_range_10bit]}) - +def I2C_COM_ASYNC_TRANSFER_10B_MAX_FREQUENCY(self): + self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_transfer", "iterations": 100, + "write_size": 10, "read_size": 10, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) @test_case(I2CComTest, - name="I2C_COM_MASTER-SLAVE_ASYNC_TRANSFER_257B_MAX_FREQUENCY", + name="I2C_COM_ASYNC_TRANSFER_257B_MAX_FREQUENCY", title="test write read") -def I2C_COM_MASTER_SLAVE_ASYNC_TRANSFER_257B_MAX_FREQUENCY(self): +def I2C_COM_ASYNC_TRANSFER_257B_MAX_FREQUENCY(self): self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_transfer", "iterations": 10, - "write_size": 257, "read_size": 257, "address": [self.address_range_7bit, self.address_range_10bit]}) + "write_size": 257, "read_size": 257, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) @test_case(I2CComTest, - name="I2C_COM_MASTER-SLAVE_ASYNC_TRANSFER_1025B_MAX_FREQUENCY", + name="I2C_COM_ASYNC_TRANSFER_1025B_MAX_FREQUENCY", title="test write read") -def I2C_COM_MASTER_SLAVE_ASYNC_TRANSFER_1025B_MAX_FREQUENCY(self): - self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_transfer", "iterations": 10, - "write_size": 1025, "read_size": 1025, "address": [self.address_range_7bit, self.address_range_10bit]}) +def I2C_COM_ASYNC_TRANSFER_1025B_MAX_FREQUENCY(self): + self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_transfer", "iterations": 1, + "write_size": 1025, "read_size": 1025, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) From dca2370d06e955c0c2ca2d74c2c9c1fedcefeae0 Mon Sep 17 00:00:00 2001 From: Maciej Bocianski Date: Mon, 20 May 2019 12:08:56 +0200 Subject: [PATCH 3/3] i2c communication test: heap memory usage optimization use stack memory for data buffers --- TEST_APPS/device/i2c_com/common.h | 10 + TEST_APPS/device/i2c_com/main.cpp | 1 - TEST_APPS/device/i2c_com/master.cpp | 263 ++++++++++---------- TEST_APPS/device/i2c_com/slave.cpp | 57 +++-- TEST_APPS/testcases/i2c_com/test_i2c_com.py | 18 +- 5 files changed, 184 insertions(+), 165 deletions(-) diff --git a/TEST_APPS/device/i2c_com/common.h b/TEST_APPS/device/i2c_com/common.h index ec37cd557ce..8b60a444d65 100644 --- a/TEST_APPS/device/i2c_com/common.h +++ b/TEST_APPS/device/i2c_com/common.h @@ -21,6 +21,12 @@ #define I2C_TEST_COMMON_H +#undef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +#undef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + // uncomment this in order to test i2c driver layer //#define TEST_I2C_DRIVER @@ -30,6 +36,10 @@ #define EMPTY_PARAM_INT (-1) +// max data buffer allocated on stack, optimization for less heap usage +#define MAX_STACK_DATA 768 + +#define TEST_PATTERN_SIZE 100 #define MASTER_1_ID 111 #define MASTER_2_ID 222 diff --git a/TEST_APPS/device/i2c_com/main.cpp b/TEST_APPS/device/i2c_com/main.cpp index cab5d9281ba..fbaf2fb18a5 100644 --- a/TEST_APPS/device/i2c_com/main.cpp +++ b/TEST_APPS/device/i2c_com/main.cpp @@ -250,7 +250,6 @@ void wrap_printf(const char *f, va_list a) int main() { - ticker_read(get_us_ticker_data()); // start ticker here for future use in srand #if I2C_DEBUG_PIN_MASTER==1 || I2C_DEBUG_PIN_SLAVE==1 test_pin_init(); #endif diff --git a/TEST_APPS/device/i2c_com/master.cpp b/TEST_APPS/device/i2c_com/master.cpp index 89d055af3a6..a43671d60e0 100644 --- a/TEST_APPS/device/i2c_com/master.cpp +++ b/TEST_APPS/device/i2c_com/master.cpp @@ -21,8 +21,6 @@ #define I2C_MASTER_SDA MBED_CONF_APP_I2C_MASTER_SDA #define I2C_MASTER_SCL MBED_CONF_APP_I2C_MASTER_SCL -#undef MIN -#define MIN(a, b) ((a) < (b) ? (a) : (b)) #if DEVICE_I2C_ASYNCH struct async_status { @@ -173,59 +171,54 @@ bool master_deinit() bool master_write_read(uint32_t write_size, uint32_t read_size, uint16_t write_address, uint16_t read_address, uint32_t iterations, bool stop_each, bool stop_each_iter) { bool result = true; - - uint8_t *tx_buf = new uint8_t[write_size]; - uint8_t *rx_buf = new uint8_t[read_size]; - - srand(ticker_read(get_us_ticker_data())); + uint8_t _buf[MAX_STACK_DATA]; + const uint32_t max_size = MAX(write_size, read_size); + uint8_t *buf = max_size <= MAX_STACK_DATA ? _buf : new uint8_t[max_size]; for (uint32_t i = 0; i < iterations && result; i++) { int ret; for (uint32_t j = 0; j < write_size; j++) { - tx_buf[j] = (uint8_t)(rand() % 100); + buf[j] = j % TEST_PATTERN_SIZE; } - MASTER_PIN_TOGGLE(5); - ret = _i2c_write(write_address, tx_buf, write_size, stop_each); - MASTER_PIN_TOGGLE(5); - result = TEST_CHECK_EQUAL_INT(write_size, ret); + MASTER_PIN_TOGGLE(1); + ret = _i2c_write(write_address, buf, write_size, stop_each); + MASTER_PIN_TOGGLE(1); I2C_DEBUG_PRINTF("[master] write count: %d\n", ret); - - if (result) { - MASTER_PIN_TOGGLE(5); - ret = _i2c_read(read_address, rx_buf, read_size, stop_each || stop_each_iter); - MASTER_PIN_TOGGLE(5); - result = TEST_CHECK_EQUAL_INT(read_size, ret); - I2C_DEBUG_PRINTF("[master] read count: %d\n", ret); + I2C_DEBUG_PRINTF("[master] write data: "); + for (uint32_t j = 0; j < write_size; j++) { + I2C_DEBUG_PRINTF("%X ", buf[j]); } + I2C_DEBUG_PRINTF("\r\n"); + result = TEST_CHECK_EQUAL_INT(write_size, ret); if (result) { - for (uint32_t j = 0; j < MIN(write_size, read_size); j++) { - if (rx_buf[j] != tx_buf[j]) { - result = TEST_CHECK_EQUAL_INT(tx_buf[j] + 1, rx_buf[j]); + MASTER_PIN_TOGGLE(1); + ret = _i2c_read(read_address, buf, read_size, stop_each || stop_each_iter); + MASTER_PIN_TOGGLE(1); + I2C_DEBUG_PRINTF("[master] read count: %d\n", ret); + I2C_DEBUG_PRINTF("[master] read data: "); + for (uint32_t j = 0; j < read_size; j++) { + I2C_DEBUG_PRINTF("%X ", buf[j]); + } + I2C_DEBUG_PRINTF("\r\n"); + result = TEST_CHECK_EQUAL_INT(read_size, ret); + for (uint32_t j = 0; j < read_size; j++) { + if (buf[j] != (read_size - j - 1) % TEST_PATTERN_SIZE) { + result = TEST_CHECK_EQUAL_INT((read_size - j - 1) % TEST_PATTERN_SIZE, buf[j]); break; } } } - - I2C_DEBUG_PRINTF("[master] write data: "); - for (uint32_t j = 0; j < write_size; j++) { - I2C_DEBUG_PRINTF("%X ", tx_buf[j]); - } - I2C_DEBUG_PRINTF("\r\n"); - I2C_DEBUG_PRINTF("[master] read data: "); - for (uint32_t j = 0; j < read_size; j++) { - I2C_DEBUG_PRINTF("%X ", rx_buf[j]); - } - I2C_DEBUG_PRINTF("\r\n"); } if (!stop_each && !stop_each_iter) { _i2c_stop(); } - delete []tx_buf; - delete []rx_buf; + if (max_size > MAX_STACK_DATA) { + delete [] buf; + } return result; } @@ -233,26 +226,26 @@ bool master_write_read(uint32_t write_size, uint32_t read_size, uint16_t write_a bool master_read(uint32_t read_size, uint32_t read_result, uint16_t address, uint32_t iterations, bool stop_each_iter) { bool result = true; - - uint8_t *rx_buf = new uint8_t[read_size]; + uint8_t _buf[MAX_STACK_DATA]; + uint8_t *buf = read_size <= MAX_STACK_DATA ? _buf : new uint8_t[read_size]; for (uint32_t i = 0; i < iterations && result; i++) { - MASTER_PIN_TOGGLE(5); - int ret = _i2c_read(MAKE_7BIT_READ_ADDRESS(address), rx_buf, read_size, stop_each_iter); - MASTER_PIN_TOGGLE(5); - result = TEST_CHECK_EQUAL_INT(read_result, ret); + MASTER_PIN_TOGGLE(1); + int ret = _i2c_read(MAKE_7BIT_READ_ADDRESS(address), buf, read_size, stop_each_iter); + MASTER_PIN_TOGGLE(1); I2C_DEBUG_PRINTF("[master] read count: %d\n", ret); - I2C_DEBUG_PRINTF("[master] read data: "); for (uint32_t j = 0; j < read_size; j++) { - I2C_DEBUG_PRINTF("%X ", rx_buf[j]); + I2C_DEBUG_PRINTF("%X ", buf[j]); } I2C_DEBUG_PRINTF("\r\n"); + result = TEST_CHECK_EQUAL_INT(read_result, ret); if (result) { for (uint32_t j = 0; j < read_result; j++) { - if (j != rx_buf[j]) { - result = TEST_CHECK_EQUAL_INT(j, rx_buf[j]); + const uint8_t pat = (read_size - j - 1) % TEST_PATTERN_SIZE; + if (buf[j] != pat) { + result = TEST_CHECK_EQUAL_INT(pat, buf[j]); break; } } @@ -262,7 +255,9 @@ bool master_read(uint32_t read_size, uint32_t read_result, uint16_t address, uin _i2c_stop(); } - delete []rx_buf; + if (read_size > MAX_STACK_DATA) { + delete [] buf; + } return result; } @@ -270,31 +265,33 @@ bool master_read(uint32_t read_size, uint32_t read_result, uint16_t address, uin bool master_write(uint32_t write_size, uint32_t write_result, uint16_t address, uint32_t iterations, bool stop_each_iter) { bool result = true; - - uint8_t *tx_buf = new uint8_t[write_size]; + uint8_t _buf[MAX_STACK_DATA]; + uint8_t *buf = write_size <= MAX_STACK_DATA ? _buf : new uint8_t[write_size]; for (uint32_t j = 0; j < write_size; j++) { - tx_buf[j] = j; + buf[j] = j % TEST_PATTERN_SIZE; } for (uint32_t i = 0; i < iterations && result; i++) { - MASTER_PIN_TOGGLE(5); - int ret = _i2c_write(MAKE_7BIT_WRITE_ADDRESS(address), tx_buf, write_size, stop_each_iter); - MASTER_PIN_TOGGLE(5); - result = TEST_CHECK_EQUAL_INT(write_result, ret); + MASTER_PIN_TOGGLE(1); + int ret = _i2c_write(MAKE_7BIT_WRITE_ADDRESS(address), buf, write_size, stop_each_iter); + MASTER_PIN_TOGGLE(1); I2C_DEBUG_PRINTF("[master] write count: %d\n", ret); - I2C_DEBUG_PRINTF("[master] written data: "); for (uint32_t j = 0; j < write_result; j++) { - I2C_DEBUG_PRINTF("%X ", tx_buf[j]); + I2C_DEBUG_PRINTF("%X ", buf[j]); } I2C_DEBUG_PRINTF("\r\n"); + result = TEST_CHECK_EQUAL_INT(write_result, ret); + } if (!stop_each_iter) { _i2c_stop(); } - delete []tx_buf; + if (write_size > MAX_STACK_DATA) { + delete [] buf; + } return result; } @@ -329,53 +326,46 @@ bool master_write_read_async(uint32_t write_size, uint32_t read_size, uint16_t a { async_status transmit_status = {}; async_status receive_status = {}; - uint8_t *tx_buf = new uint8_t[write_size]; - uint8_t *rx_buf = new uint8_t[read_size]; + uint8_t _buf[MAX_STACK_DATA]; + const uint32_t max_size = MAX(write_size, read_size); + uint8_t *buf = max_size <= MAX_STACK_DATA ? _buf : new uint8_t[max_size]; bool result = true; - srand(ticker_read(get_us_ticker_data())); - for (uint32_t i = 0; i < iterations && result; i++) { for (uint32_t j = 0; j < write_size; j++) { - tx_buf[j] = (uint8_t)(rand() % 100); + buf[j] = j % TEST_PATTERN_SIZE; } transmit_status.done = false; - MASTER_PIN_TOGGLE(5); - _i2c_transfer_async(tx_buf, write_size, NULL, 0, MAKE_7BIT_WRITE_ADDRESS(address), stop_each, async_callback, &transmit_status); - MASTER_PIN_TOGGLE(5); + MASTER_PIN_TOGGLE(1); + _i2c_transfer_async(buf, write_size, NULL, 0, MAKE_7BIT_WRITE_ADDRESS(address), stop_each, async_callback, &transmit_status); + MASTER_PIN_TOGGLE(1); while (!transmit_status.done); - MASTER_PIN_TOGGLE(5); - result = TEST_CHECK_EQUAL_INT(write_size, transmit_status.event.sent_bytes); + MASTER_PIN_TOGGLE(1); I2C_DEBUG_PRINTF("[master] sent_bytes: %u\r\n", transmit_status.event.sent_bytes); - - MASTER_PIN_TOGGLE(5); - - if (result) { - receive_status.done = false; - MASTER_PIN_TOGGLE(5); - _i2c_transfer_async(NULL, 0, rx_buf, read_size, MAKE_7BIT_READ_ADDRESS(address), stop_each || stop_each_iter, async_callback, &receive_status); - MASTER_PIN_TOGGLE(5); - while (!receive_status.done); - MASTER_PIN_TOGGLE(5); - result = TEST_CHECK_EQUAL_INT(read_size, receive_status.event.received_bytes); - I2C_DEBUG_PRINTF("[master] received_bytes: %u\r\n", receive_status.event.received_bytes); - } - MASTER_PIN_TOGGLE(5); I2C_DEBUG_PRINTF("[master] write data: "); for (uint32_t j = 0; j < write_size; j++) { - I2C_DEBUG_PRINTF("%X ", tx_buf[j]); - } - I2C_DEBUG_PRINTF("\r\n"); - I2C_DEBUG_PRINTF("[master] read data: "); - for (uint32_t j = 0; j < read_size; j++) { - I2C_DEBUG_PRINTF("%X ", rx_buf[j]); + I2C_DEBUG_PRINTF("%X ", buf[j]); } I2C_DEBUG_PRINTF("\r\n"); + result = TEST_CHECK_EQUAL_INT(write_size, transmit_status.event.sent_bytes); if (result) { - for (uint32_t j = 0; j < MIN(write_size, read_size); j++) { - if (rx_buf[j] != (tx_buf[j] + 1)) { - result = TEST_CHECK_EQUAL_INT(tx_buf[j], rx_buf[j]); + receive_status.done = false; + MASTER_PIN_TOGGLE(1); + _i2c_transfer_async(NULL, 0, buf, read_size, MAKE_7BIT_READ_ADDRESS(address), stop_each || stop_each_iter, async_callback, &receive_status); + MASTER_PIN_TOGGLE(1); + while (!receive_status.done); + MASTER_PIN_TOGGLE(1); + I2C_DEBUG_PRINTF("[master] received_bytes: %u\r\n", receive_status.event.received_bytes); + I2C_DEBUG_PRINTF("[master] read data: "); + for (uint32_t j = 0; j < read_size; j++) { + I2C_DEBUG_PRINTF("%X ", buf[j]); + } + I2C_DEBUG_PRINTF("\r\n"); + result = TEST_CHECK_EQUAL_INT(read_size, receive_status.event.received_bytes); + for (uint32_t j = 0; j < read_size; j++) { + if (buf[j] != (read_size - j - 1) % TEST_PATTERN_SIZE) { + result = TEST_CHECK_EQUAL_INT((read_size - j - 1) % TEST_PATTERN_SIZE, buf[j]); break; } } @@ -385,8 +375,9 @@ bool master_write_read_async(uint32_t write_size, uint32_t read_size, uint16_t a _i2c_stop(); } - delete [] tx_buf; - delete [] rx_buf; + if (max_size > MAX_STACK_DATA) { + delete [] buf; + } return result; } @@ -394,25 +385,26 @@ bool master_write_read_async(uint32_t write_size, uint32_t read_size, uint16_t a bool master_write_async(uint32_t write_size, uint32_t write_reulting_size, uint16_t address, uint32_t iterations, bool stop_each) { async_status transmit_status = {}; - uint8_t *tx_buf = new uint8_t[write_size]; + uint8_t _buf[MAX_STACK_DATA]; + uint8_t *buf = write_size <= MAX_STACK_DATA ? _buf : new uint8_t[write_size]; bool result = true; for (uint32_t j = 0; j < write_size; j++) { - tx_buf[j] = j; + buf[j] = j % TEST_PATTERN_SIZE; } for (uint32_t i = 0; i < iterations && result; i++) { transmit_status.done = false; - MASTER_PIN_TOGGLE(5); - _i2c_transfer_async(tx_buf, write_size, NULL, 0, MAKE_7BIT_WRITE_ADDRESS(address), stop_each, async_callback, &transmit_status); - MASTER_PIN_TOGGLE(5); + MASTER_PIN_TOGGLE(1); + _i2c_transfer_async(buf, write_size, NULL, 0, MAKE_7BIT_WRITE_ADDRESS(address), stop_each, async_callback, &transmit_status); + MASTER_PIN_TOGGLE(1); while (!transmit_status.done); - MASTER_PIN_TOGGLE(5); + MASTER_PIN_TOGGLE(1); result = TEST_CHECK_EQUAL_INT(write_reulting_size, transmit_status.event.sent_bytes); I2C_DEBUG_PRINTF("[master] sent_bytes: %u\r\n", transmit_status.event.sent_bytes); I2C_DEBUG_PRINTF("[master] write data: "); for (uint32_t j = 0; j < write_reulting_size; j++) { - I2C_DEBUG_PRINTF("%X ", tx_buf[j]); + I2C_DEBUG_PRINTF("%X ", buf[j]); } I2C_DEBUG_PRINTF("\r\n"); } @@ -420,7 +412,9 @@ bool master_write_async(uint32_t write_size, uint32_t write_reulting_size, uint1 _i2c_stop(); } - delete [] tx_buf; + if (write_size > MAX_STACK_DATA) { + delete [] buf; + } return result; } @@ -428,28 +422,29 @@ bool master_write_async(uint32_t write_size, uint32_t write_reulting_size, uint1 bool master_read_async(uint32_t read_size, uint32_t read_resulting_size, uint16_t address, uint32_t iterations, bool stop_each) { async_status receive_status = {}; - uint8_t *rx_buf = new uint8_t[read_size]; + uint8_t _buf[MAX_STACK_DATA]; + uint8_t *buf = read_size <= MAX_STACK_DATA ? _buf : new uint8_t[read_size]; bool result = true; for (uint32_t i = 0; i < iterations && result; i++) { receive_status.done = false; - MASTER_PIN_TOGGLE(5); - _i2c_transfer_async(NULL, 0, rx_buf, read_size, MAKE_7BIT_READ_ADDRESS(address), stop_each, async_callback, &receive_status); - MASTER_PIN_TOGGLE(5); + MASTER_PIN_TOGGLE(1); + _i2c_transfer_async(NULL, 0, buf, read_size, MAKE_7BIT_READ_ADDRESS(address), stop_each, async_callback, &receive_status); + MASTER_PIN_TOGGLE(1); while (!receive_status.done); - MASTER_PIN_TOGGLE(5); - result = TEST_CHECK_EQUAL_INT(read_resulting_size, receive_status.event.received_bytes); + MASTER_PIN_TOGGLE(1); I2C_DEBUG_PRINTF("[master] received_bytes: %u\r\n", receive_status.event.received_bytes); I2C_DEBUG_PRINTF("[master] read data: "); for (uint32_t j = 0; j < read_resulting_size; j++) { - I2C_DEBUG_PRINTF("%X ", rx_buf[j]); + I2C_DEBUG_PRINTF("%X ", buf[j]); } I2C_DEBUG_PRINTF("\r\n"); + result = TEST_CHECK_EQUAL_INT(read_resulting_size, receive_status.event.received_bytes); if (result) { for (uint32_t j = 0; j < read_resulting_size; j++) { - if (rx_buf[j] != j) { - result = TEST_CHECK_EQUAL_INT(j, rx_buf[j]); + if (buf[j] != (read_size - j - 1) % TEST_PATTERN_SIZE) { + result = TEST_CHECK_EQUAL_INT((read_size - j - 1) % TEST_PATTERN_SIZE, buf[j]); break; } } @@ -459,7 +454,9 @@ bool master_read_async(uint32_t read_size, uint32_t read_resulting_size, uint16_ _i2c_stop(); } - delete [] rx_buf; + if (read_size > MAX_STACK_DATA) { + delete [] buf; + } return result; } @@ -467,45 +464,42 @@ bool master_read_async(uint32_t read_size, uint32_t read_resulting_size, uint16_ bool master_transfer_async(uint32_t write_size, uint32_t read_size, uint16_t address, uint32_t iterations, bool stop_each) { async_status transfer_status = {}; - uint8_t *tx_buf = new uint8_t[write_size]; - uint8_t *rx_buf = new uint8_t[read_size]; + uint8_t _buf[MAX_STACK_DATA]; + const uint32_t max_size = MAX(write_size, read_size); + uint8_t *buf = max_size <= MAX_STACK_DATA ? _buf : new uint8_t[max_size]; bool result = true; srand(ticker_read(get_us_ticker_data())); for (uint32_t i = 0; i < iterations && true; i++) { for (uint32_t j = 0; j < write_size; j++) { - tx_buf[j] = (uint8_t)(rand() % 100); + buf[j] = j % TEST_PATTERN_SIZE; } transfer_status.done = false; - MASTER_PIN_TOGGLE(5); - _i2c_transfer_async(tx_buf, write_size, rx_buf, read_size, MAKE_7BIT_WRITE_ADDRESS(address), stop_each, async_callback, &transfer_status); - MASTER_PIN_TOGGLE(5); + MASTER_PIN_TOGGLE(1); + _i2c_transfer_async(buf, write_size, buf, read_size, MAKE_7BIT_WRITE_ADDRESS(address), stop_each, async_callback, &transfer_status); + MASTER_PIN_TOGGLE(1); while (!transfer_status.done); - MASTER_PIN_TOGGLE(5); - result = TEST_CHECK_EQUAL_INT(write_size, transfer_status.event.sent_bytes); + MASTER_PIN_TOGGLE(1); I2C_DEBUG_PRINTF("[master] sent_bytes: %u\n", transfer_status.event.sent_bytes); - - if (result) { - result = TEST_CHECK_EQUAL_INT(read_size, transfer_status.event.received_bytes); - I2C_DEBUG_PRINTF("[master] received_bytes: %u\n", transfer_status.event.received_bytes); - } - I2C_DEBUG_PRINTF("[master] written data: "); for (uint32_t j = 0; j < write_size; j++) { - I2C_DEBUG_PRINTF("%X ", tx_buf[j]); - } - I2C_DEBUG_PRINTF("\r\n"); - I2C_DEBUG_PRINTF("[master] read data: "); - for (uint32_t j = 0; j < read_size; j++) { - I2C_DEBUG_PRINTF("%X ", rx_buf[j]); + I2C_DEBUG_PRINTF("%X ", j % TEST_PATTERN_SIZE;); } I2C_DEBUG_PRINTF("\r\n"); + result = TEST_CHECK_EQUAL_INT(write_size, transfer_status.event.sent_bytes); if (result) { - for (uint32_t j = 0; j < write_size; j++) { - if (rx_buf[j] != (tx_buf[j] + 1)) { - result = TEST_CHECK_EQUAL_INT(tx_buf[j] + 1, rx_buf[j]); + I2C_DEBUG_PRINTF("[master] received_bytes: %u\n", transfer_status.event.received_bytes); + I2C_DEBUG_PRINTF("[master] read data: "); + for (uint32_t j = 0; j < read_size; j++) { + I2C_DEBUG_PRINTF("%X ", (read_size - j - 1) % TEST_PATTERN_SIZE;); + } + I2C_DEBUG_PRINTF("\r\n"); + result = TEST_CHECK_EQUAL_INT(read_size, transfer_status.event.received_bytes); + for (uint32_t j = 0; j < read_size; j++) { + if (buf[j] != (read_size - j - 1) % TEST_PATTERN_SIZE) { + result = TEST_CHECK_EQUAL_INT((read_size - j - 1) % TEST_PATTERN_SIZE, buf[j]); break; } } @@ -515,8 +509,9 @@ bool master_transfer_async(uint32_t write_size, uint32_t read_size, uint16_t add _i2c_stop(); } - delete [] tx_buf; - delete [] rx_buf; + if (max_size > MAX_STACK_DATA) { + delete [] buf; + } return result; } diff --git a/TEST_APPS/device/i2c_com/slave.cpp b/TEST_APPS/device/i2c_com/slave.cpp index 986cdeb771e..cd4bccbcc36 100644 --- a/TEST_APPS/device/i2c_com/slave.cpp +++ b/TEST_APPS/device/i2c_com/slave.cpp @@ -23,9 +23,6 @@ #define I2C_SLAVE_SDA MBED_CONF_APP_I2C_SLAVE_SDA #define I2C_SLAVE_SCL MBED_CONF_APP_I2C_SLAVE_SCL -#undef MAX -#define MAX(a, b) ((a) > (b) ? (a) : (b)) - volatile bool done; @@ -151,7 +148,9 @@ void slave_finish() void slave_transfer_job(TransferConfig *tc) { bool result; - uint8_t *data = new uint8_t[MAX(tc->read_size, tc->write_size)]; + const uint32_t max_size = MAX(tc->read_size, tc->write_size); + uint8_t _data[MAX_STACK_DATA]; + uint8_t *data = max_size <= MAX_STACK_DATA ? _data : new uint8_t[max_size]; _i2c_slave_address(tc->address); for (uint32_t i = 0; i < tc->iterations; i++) { @@ -162,24 +161,31 @@ void slave_transfer_job(TransferConfig *tc) SLAVE_PIN_TOGGLE(1); ret = _i2c_read(data, tc->read_size, false); SLAVE_PIN_TOGGLE(1); - result = TEST_CHECK_EQUAL_INT(tc->read_size_resulting, ret); - I2C_DEBUG_PRINTF("[slave] read data count: %d\n", ret); I2C_DEBUG_PRINTF("[slave] read data: "); for (uint32_t j = 0; j < tc->read_size; j++) { - data[j]++; I2C_DEBUG_PRINTF("%X ", data[j]); } I2C_DEBUG_PRINTF("\r\n"); + result = TEST_CHECK_EQUAL_INT(tc->read_size_resulting, ret); + for (uint32_t j = 0; j < tc->read_size; j++) { + if (data[j] != j % TEST_PATTERN_SIZE) { + result = TEST_CHECK_EQUAL_INT(j, data[j]); + break; + } + } if (result) { + for (uint32_t j = 0; j < tc->write_size; j++) { + data[j] = (tc->write_size - j - 1) % TEST_PATTERN_SIZE; + } SLAVE_PIN_TOGGLE(1); while (_i2c_slave_status() != ReadAddressed && !done); SLAVE_PIN_TOGGLE(1); ret = _i2c_write(data, tc->write_size, false); SLAVE_PIN_TOGGLE(1); - result = TEST_CHECK_EQUAL_INT(tc->write_size_resulting, ret); I2C_DEBUG_PRINTF("[slave] write data count: %d\n", ret); + result = TEST_CHECK_EQUAL_INT(tc->write_size_resulting, ret); } if (!result || done) { @@ -188,13 +194,16 @@ void slave_transfer_job(TransferConfig *tc) } tc->result = result; - delete []data; + if (max_size > MAX_STACK_DATA) { + delete [] data; + } } void slave_read_job(TransferConfig *tc) { - uint8_t *data = new uint8_t[tc->read_size]; bool result = true; + uint8_t _data[MAX_STACK_DATA]; + uint8_t *data = tc->read_size <= MAX_STACK_DATA ? _data : new uint8_t[tc->read_size]; _i2c_slave_address(tc->address); @@ -204,18 +213,17 @@ void slave_read_job(TransferConfig *tc) SLAVE_PIN_TOGGLE(1); int ret = _i2c_read(data, tc->read_size, false); SLAVE_PIN_TOGGLE(1); - result = TEST_CHECK_EQUAL_INT(tc->read_size_resulting, ret); - I2C_DEBUG_PRINTF("[slave] read data count: %d\n", ret); I2C_DEBUG_PRINTF("[slave] read data: "); for (uint32_t j = 0; j < tc->read_size; j++) { I2C_DEBUG_PRINTF("%X ", data[j]); } I2C_DEBUG_PRINTF("\r\n"); + result = TEST_CHECK_EQUAL_INT(tc->read_size_resulting, ret); if (result) { for (uint32_t j = 0; j < tc->read_size_resulting; j++) { - if (data[j] != j) { + if (data[j] != j % TEST_PATTERN_SIZE) { result = TEST_CHECK_EQUAL_INT(j, data[j]); break; } @@ -228,17 +236,20 @@ void slave_read_job(TransferConfig *tc) } tc->result = result; - delete []data; + if (tc->read_size > MAX_STACK_DATA) { + delete [] data; + } } void slave_write_job(TransferConfig *tc) { - uint8_t *data = new uint8_t[tc->write_size]; bool result = true; + uint8_t _data[MAX_STACK_DATA]; + uint8_t *data = tc->write_size <= MAX_STACK_DATA ? _data : new uint8_t[tc->write_size]; // prepare data to send for (uint32_t i = 0; i < tc->write_size; i++) { - data[i] = i; + data[i] = (tc->write_size - i - 1) % TEST_PATTERN_SIZE; } _i2c_slave_address(tc->address); @@ -249,8 +260,8 @@ void slave_write_job(TransferConfig *tc) SLAVE_PIN_TOGGLE(1); int ret = _i2c_write(data, tc->write_size, false); SLAVE_PIN_TOGGLE(1); - result = TEST_CHECK_EQUAL_INT(tc->write_size_resulting, ret); I2C_DEBUG_PRINTF("[slave] write data count: %d\n", ret); + result = TEST_CHECK_EQUAL_INT(tc->write_size_resulting, ret); if (!result || done) { break; @@ -258,7 +269,9 @@ void slave_write_job(TransferConfig *tc) } tc->result = result; - delete []data; + if (tc->read_size > MAX_STACK_DATA) { + delete [] data; + } } bool slave_transfer(uint32_t write_size, uint32_t write_size_resulting, uint32_t read_size, uint32_t read_size_resulting, uint16_t address, uint32_t iterations) @@ -273,16 +286,20 @@ bool slave_transfer(uint32_t write_size, uint32_t write_size_resulting, uint32_t tc.result = false; done = false; - void (*job)(TransferConfig * tc); + void (*job)(TransferConfig * tc) = NULL; if (write_size && read_size) { job = slave_transfer_job; } else if (write_size) { job = slave_write_job; } else if (read_size) { job = slave_read_job; + } else { + return false; } - WorkerThread<1024> slave_thread; + // MBedOS main thread stack is 4kB (3 kB for some small RAM targets) + // so 1.5kB for slave thread is OK + WorkerThread<1536> slave_thread; slave_thread.start(callback(job, &tc)); slave_thread.join(); diff --git a/TEST_APPS/testcases/i2c_com/test_i2c_com.py b/TEST_APPS/testcases/i2c_com/test_i2c_com.py index ac91d66b9a8..eda8fa08458 100644 --- a/TEST_APPS/testcases/i2c_com/test_i2c_com.py +++ b/TEST_APPS/testcases/i2c_com/test_i2c_com.py @@ -45,13 +45,11 @@ class I2CComTest(Bench): I2C_7BIT_ADDRESS_MIN = 8 I2C_7BIT_ADDRESS_MAX = 119 I2C_7BIT_ADDRESS = 85 - address_range_7bit = (I2C_7BIT_ADDRESS_MIN, - I2C_7BIT_ADDRESS, I2C_7BIT_ADDRESS_MAX) + address_range_7bit = (I2C_7BIT_ADDRESS_MIN, I2C_7BIT_ADDRESS_MAX) I2C_10BIT_ADDRESS_MIN = 0 I2C_10BIT_ADDRESS_MAX = 1023 I2C_10BIT_ADDRESS = 512 - address_range_10bit = (I2C_10BIT_ADDRESS_MIN, - I2C_10BIT_ADDRESS, I2C_10BIT_ADDRESS_MAX) + address_range_10bit = (I2C_10BIT_ADDRESS_MIN, I2C_10BIT_ADDRESS_MAX) def __init__(self, **kwargs): testcase_args = { @@ -221,7 +219,7 @@ def I2C_COM_BLOCKING_WRITE_READ_257B_MIN_FREQUENCY(self): title="test write read") def I2C_COM_BLOCKING_WRITE_READ_1025B_MIN_FREQUENCY(self): self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "blocking_write-read", "iterations": 1, - "write_size": 1025, "read_size": 1025, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) + "write_size": 513, "read_size": 513, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) # maximum_frequency @@ -252,7 +250,7 @@ def I2C_COM_BLOCKING_WRITE_READ_257B_MAX_FREQUENCY(self): title="test write read") def I2C_COM_BLOCKING_WRITE_READ_1025B_MAX_FREQUENCY(self): self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "blocking_write-read", "iterations": 1, - "write_size": 1025, "read_size": 1025, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) + "write_size": 513, "read_size": 513, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) ########################### # async_write-read @@ -286,7 +284,7 @@ def I2C_COM_ASYNC_WRITE_READ_257B_MIN_FREQUENCY(self): title="test write read") def I2C_COM_ASYNC_WRITE_READ_1025B_MIN_FREQUENCY(self): self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "async_write-read", "iterations": 1, - "write_size": 1025, "read_size": 1025, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) + "write_size": 513, "read_size": 513, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) # maximum_frequency @@ -316,7 +314,7 @@ def I2C_COM_ASYNC_WRITE_READ_257B_MAX_FREQUENCY(self): title="test write read") def I2C_COM_ASYNC_WRITE_READ_1025B_MAX_FREQUENCY(self): self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_write-read", "iterations": 1, - "write_size": 1025, "read_size": 1025, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) + "write_size": 513, "read_size": 513, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) ########################### # async_transfer @@ -350,7 +348,7 @@ def I2C_COM_ASYNC_TRANSFER_257B_MIN_FREQUENCY(self): title="test write read") def I2C_COM_ASYNC_TRANSFER_1025B_MIN_FREQUENCY(self): self.test_execute({"frequency": self.caps["minimum_frequency"], "communication": "async_transfer", "iterations": 1, - "write_size": 1025, "read_size": 1025, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) + "write_size": 513, "read_size": 513, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) # maximum_frequency @@ -380,4 +378,4 @@ def I2C_COM_ASYNC_TRANSFER_257B_MAX_FREQUENCY(self): title="test write read") def I2C_COM_ASYNC_TRANSFER_1025B_MAX_FREQUENCY(self): self.test_execute({"frequency": self.caps["maximum_frequency"], "communication": "async_transfer", "iterations": 1, - "write_size": 1025, "read_size": 1025, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]}) + "write_size": 513, "read_size": 513, "address": [self.address_range_7bit, self.address_range_10bit], "stop": [self.STOP_EACH_TRANSFER, self.STOP_EACH_ITERATION, self.STOP_AT_THE_END]})