From 3d09a5a4f170300c26a1bb347da22df0bf408488 Mon Sep 17 00:00:00 2001 From: yarb Date: Wed, 20 Nov 2019 16:49:33 +0200 Subject: [PATCH] I2C byte read/write transmition improvement. Added CY_SCB_I2C_READ_XFER to clear CY_SCB_I2C_WRITE_XFER status in i2c_byte_write() API. --- .../TARGET_Cypress/TARGET_PSOC6/cy_i2c_api.c | 49 ++++++++++++++++--- targets/TARGET_Cypress/TARGET_PSOC6/objects.h | 2 + 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/cy_i2c_api.c b/targets/TARGET_Cypress/TARGET_PSOC6/cy_i2c_api.c index 9e88f5229a..42a4334128 100644 --- a/targets/TARGET_Cypress/TARGET_PSOC6/cy_i2c_api.c +++ b/targets/TARGET_Cypress/TARGET_PSOC6/cy_i2c_api.c @@ -119,13 +119,18 @@ void i2c_frequency(i2c_t *obj, int hz) int i2c_start(i2c_t *obj) { - // Nothing to do; start/stop is generated by i2c_read/i2c_write + /* start/stop is generated by i2c_read/i2c_write */ + struct i2c_s *i2c = cy_get_i2c(obj); + /* Clear state of address */ + i2c->address_set = false; return 0; } int i2c_stop(i2c_t *obj) { struct i2c_s *i2c = cy_get_i2c(obj); + /* Clear state of address */ + i2c->address_set = false; if (i2c->hal_i2c.context.state != CY_SCB_I2C_IDLE) { return Cy_SCB_I2C_MasterSendStop(i2c->hal_i2c.base, CY_I2C_DEFAULT_TIMEOUT, &(i2c->hal_i2c.context)); } @@ -160,19 +165,49 @@ int i2c_byte_read(i2c_t *obj, int last) { struct i2c_s *i2c = cy_get_i2c(obj); uint8_t value; - if (CY_SCB_I2C_SUCCESS != Cy_SCB_I2C_MasterReadByte(i2c->hal_i2c.base, last != 0 ? CY_SCB_I2C_NAK : CY_SCB_I2C_ACK, &value, CY_I2C_DEFAULT_TIMEOUT, &(i2c->hal_i2c.context))) { - MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER_I2C, MBED_ERROR_CODE_FAILED_OPERATION), "i2c_byte_read"); + + /* Slave device address is stored in object by first write operation */ + if (i2c->address_set) { + /* Send slave device address */ + /* Make sure if I2C transaction direction is 'Read' */ + if (CY_SCB_I2C_SUCCESS != Cy_SCB_I2C_MasterSendStart(i2c->hal_i2c.base, i2c->address, CY_SCB_I2C_READ_XFER, CY_I2C_DEFAULT_TIMEOUT, &(i2c->hal_i2c.context))) { + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER_I2C, MBED_ERROR_CODE_FAILED_OPERATION), "i2c_send_start"); + } + /* Clear state of address. It is not needed for next operation. */ + i2c->address_set = false; } + + /* Read next byte */ + if (CY_SCB_I2C_SUCCESS != Cy_SCB_I2C_MasterReadByte(i2c->hal_i2c.base, last != 0 ? CY_SCB_I2C_NAK : CY_SCB_I2C_ACK, &value, CY_I2C_DEFAULT_TIMEOUT, &(i2c->hal_i2c.context))) { + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER_I2C, MBED_ERROR_CODE_FAILED_OPERATION), "i2c_read_byte"); + } + return value; } int i2c_byte_write(i2c_t *obj, int data) { struct i2c_s *i2c = cy_get_i2c(obj); - // If we have not yet written the address, the first byte being sent is the address. - cy_en_scb_i2c_status_t status = i2c->hal_i2c.context.state == CY_SCB_I2C_IDLE - ? Cy_SCB_I2C_MasterSendStart(i2c->hal_i2c.base, data >> 1, CY_SCB_I2C_WRITE_XFER, CY_I2C_DEFAULT_TIMEOUT, &(i2c->hal_i2c.context)) - : Cy_SCB_I2C_MasterWriteByte(i2c->hal_i2c.base, (uint8_t)data, CY_I2C_DEFAULT_TIMEOUT, &(i2c->hal_i2c.context)); + cy_en_scb_i2c_status_t status = CY_SCB_I2C_SUCCESS; + + /* First byte should be address */ + if (i2c->address_set) { + /* Verify if Master is ready for send slave address and send first data byte */ + /* Make sure that I2C transaction direction is 'Write' */ + if (i2c->hal_i2c.context.state == CY_SCB_I2C_IDLE) { + status = Cy_SCB_I2C_MasterSendStart(i2c->hal_i2c.base, i2c->address, CY_SCB_I2C_WRITE_XFER, CY_I2C_DEFAULT_TIMEOUT, &(i2c->hal_i2c.context)); + } + + if (status == CY_SCB_I2C_SUCCESS) { + status = Cy_SCB_I2C_MasterWriteByte(i2c->hal_i2c.base, (uint8_t)data, CY_I2C_DEFAULT_TIMEOUT, &(i2c->hal_i2c.context)); + } + } else { + /* Store slave address and remember status for next byte read or write operation */ + i2c->address = data >> 1; + i2c->address_set = true; + } + + switch (status) { case CY_SCB_I2C_MASTER_MANUAL_TIMEOUT: return 2; diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/objects.h b/targets/TARGET_Cypress/TARGET_PSOC6/objects.h index 73d01e9525..8d77ee0fe6 100644 --- a/targets/TARGET_Cypress/TARGET_PSOC6/objects.h +++ b/targets/TARGET_Cypress/TARGET_PSOC6/objects.h @@ -94,6 +94,8 @@ struct i2c_s { size_t async_rx_size; #endif uint8_t slave_event; + uint32_t address; + bool address_set; }; #endif