1717
1818#include "i2c_api.h"
1919#include "cyhal_i2c.h"
20+ #include "cyhal_utils.h"
21+ #include "cyhal_hwmgr.h"
2022#include "mbed_error.h"
2123#include "mbed_assert.h"
2224#include "mbed_critical.h"
@@ -84,12 +86,24 @@ static void cy_i2c_event_handler(void *handler_arg, cyhal_i2c_irq_event_t event)
8486void i2c_init (i2c_t * obj , PinName sda , PinName scl )
8587{
8688 struct i2c_s * i2c = cy_get_i2c (obj );
87- if (CY_RSLT_SUCCESS != cyhal_i2c_init (& (i2c -> hal_i2c ), sda , scl , NULL )) {
89+ cy_rslt_t result = cyhal_i2c_init (& (i2c -> hal_i2c ), sda , scl , NULL );
90+ if (result == CYHAL_HWMGR_RSLT_ERR_INUSE ) {
91+ // MBED I2C driver currently does not support free, so we will allow I2C to be reallocated.
92+ // TODO: once the the I2C driver properly supports free, this need to be fixed so that clocks and pins are no longer leaked.
93+ cyhal_hwmgr_free (& (i2c -> hal_i2c .resource ));
94+ cyhal_hwmgr_set_unconfigured (i2c -> hal_i2c .resource .type , i2c -> hal_i2c .resource .block_num , i2c -> hal_i2c .resource .channel_num );
95+ cyhal_resource_inst_t pin_rsc = cyhal_utils_get_gpio_resource (sda );
96+ cyhal_hwmgr_free (& pin_rsc );
97+ pin_rsc = cyhal_utils_get_gpio_resource (scl );
98+ cyhal_hwmgr_free (& pin_rsc );
99+ result = cyhal_i2c_init (& (i2c -> hal_i2c ), sda , scl , NULL );
100+ }
101+ if (CY_RSLT_SUCCESS != result ) {
88102 MBED_ERROR (MBED_MAKE_ERROR (MBED_MODULE_DRIVER_I2C , MBED_ERROR_CODE_FAILED_OPERATION ), "cyhal_i2c_init" );
89103 }
90104 i2c -> cfg .is_slave = false;
91105 i2c -> cfg .address = 0 ;
92- i2c -> cfg .frequencyhal_hz = 400 ;
106+ i2c -> cfg .frequencyhal_hz = 400000 ;
93107 i2c -> async_handler = NULL ;
94108 cyhal_i2c_register_irq (& (i2c -> hal_i2c ), & cy_i2c_event_handler , obj );
95109 cyhal_i2c_irq_enable (& (i2c -> hal_i2c ), (cyhal_i2c_irq_event_t )(CYHAL_I2C_SLAVE_READ_EVENT | CYHAL_I2C_SLAVE_WRITE_EVENT | CYHAL_I2C_SLAVE_ERR_EVENT | CYHAL_I2C_SLAVE_RD_CMPLT_EVENT | CYHAL_I2C_SLAVE_WR_CMPLT_EVENT | CYHAL_I2C_MASTER_ERR_EVENT | CYHAL_I2C_MASTER_RD_CMPLT_EVENT | CYHAL_I2C_MASTER_WR_CMPLT_EVENT ), true);
@@ -112,14 +126,17 @@ int i2c_start(i2c_t *obj)
112126
113127int i2c_stop (i2c_t * obj )
114128{
115- // Not supported; start/stop is generated by i2c_read/i2c_write
116- return -1 ;
129+ struct i2c_s * i2c = cy_get_i2c (obj );
130+ if (i2c -> hal_i2c .context .state != CY_SCB_I2C_IDLE ) {
131+ return Cy_SCB_I2C_MasterSendStop (i2c -> hal_i2c .base , CY_I2C_DEFAULT_TIMEOUT , & (i2c -> hal_i2c .context ));
132+ }
133+ return 0 ;
117134}
118135
119136int i2c_read (i2c_t * obj , int address , char * data , int length , int stop )
120137{
121138 struct i2c_s * i2c = cy_get_i2c (obj );
122- if (CY_RSLT_SUCCESS != cyhal_i2c_master_recv (& (i2c -> hal_i2c ), address >> 1 , (uint8_t * )data , (uint16_t )length , CY_I2C_DEFAULT_TIMEOUT )) {
139+ if (CY_RSLT_SUCCESS != cyhal_i2c_master_read (& (i2c -> hal_i2c ), address >> 1 , (uint8_t * )data , (uint16_t )length , CY_I2C_DEFAULT_TIMEOUT )) {
123140 return (int )I2C_ERROR_NO_SLAVE ;
124141 }
125142 return length ;
@@ -128,7 +145,7 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
128145int i2c_write (i2c_t * obj , int address , const char * data , int length , int stop )
129146{
130147 struct i2c_s * i2c = cy_get_i2c (obj );
131- if (CY_RSLT_SUCCESS != cyhal_i2c_master_send (& (i2c -> hal_i2c ), address >> 1 , (const uint8_t * )data , (uint16_t )length , CY_I2C_DEFAULT_TIMEOUT )) {
148+ if (CY_RSLT_SUCCESS != cyhal_i2c_master_write (& (i2c -> hal_i2c ), address >> 1 , (const uint8_t * )data , (uint16_t )length , CY_I2C_DEFAULT_TIMEOUT )) {
132149 return (int )I2C_ERROR_NO_SLAVE ;
133150 }
134151 // NOTE: HAL does not report how many bytes were actually sent in case of early NAK
@@ -153,7 +170,10 @@ int i2c_byte_read(i2c_t *obj, int last)
153170int i2c_byte_write (i2c_t * obj , int data )
154171{
155172 struct i2c_s * i2c = cy_get_i2c (obj );
156- cy_en_scb_i2c_status_t status = Cy_SCB_I2C_MasterWriteByte (i2c -> hal_i2c .base , (uint8_t )data , CY_I2C_DEFAULT_TIMEOUT , & (i2c -> hal_i2c .context ));
173+ // If we have not yet written the address, the first byte being sent is the address.
174+ cy_en_scb_i2c_status_t status = i2c -> hal_i2c .context .state == CY_SCB_I2C_IDLE
175+ ? Cy_SCB_I2C_MasterSendStart (i2c -> hal_i2c .base , data >> 1 , CY_SCB_I2C_WRITE_XFER , CY_I2C_DEFAULT_TIMEOUT , & (i2c -> hal_i2c .context ))
176+ : Cy_SCB_I2C_MasterWriteByte (i2c -> hal_i2c .base , (uint8_t )data , CY_I2C_DEFAULT_TIMEOUT , & (i2c -> hal_i2c .context ));
157177 switch (status ) {
158178 case CY_SCB_I2C_MASTER_MANUAL_TIMEOUT :
159179 return 2 ;
@@ -203,7 +223,7 @@ int i2c_slave_receive(i2c_t *obj)
203223int i2c_slave_read (i2c_t * obj , char * data , int length )
204224{
205225 struct i2c_s * i2c = cy_get_i2c (obj );
206- if (CY_RSLT_SUCCESS != cyhal_i2c_slave_recv (& (i2c -> hal_i2c ), (uint8_t * )data , (uint16_t )length , CY_I2C_DEFAULT_TIMEOUT )) {
226+ if (CY_RSLT_SUCCESS != cyhal_i2c_slave_config_read_buff (& (i2c -> hal_i2c ), (uint8_t * )data , (uint16_t )length )) {
207227 return 0 ;
208228 }
209229 return 1 ;
@@ -212,7 +232,7 @@ int i2c_slave_read(i2c_t *obj, char *data, int length)
212232int i2c_slave_write (i2c_t * obj , const char * data , int length )
213233{
214234 struct i2c_s * i2c = cy_get_i2c (obj );
215- if (CY_RSLT_SUCCESS != cyhal_i2c_slave_send (& (i2c -> hal_i2c ), (const uint8_t * )data , (uint16_t )length , CY_I2C_DEFAULT_TIMEOUT )) {
235+ if (CY_RSLT_SUCCESS != cyhal_i2c_slave_config_write_buff (& (i2c -> hal_i2c ), (const uint8_t * )data , (uint16_t )length )) {
216236 return 0 ;
217237 }
218238 return 1 ;
@@ -239,8 +259,8 @@ void i2c_transfer_asynch(i2c_t *obj, const void *tx, size_t tx_length, void *rx,
239259 i2c -> async_rx_size = rx_length ;
240260 i2c -> async_handler = (void (* )(void ))handler ;
241261 core_util_critical_section_exit ();
242- if (CY_RSLT_SUCCESS != cyhal_i2c_transfer_async (& (i2c -> hal_i2c ), tx , tx_length , rx , rx_length , address )) {
243- MBED_ERROR (MBED_MAKE_ERROR (MBED_MODULE_DRIVER_I2C , MBED_ERROR_CODE_FAILED_OPERATION ), "cyhal_i2c_transfer_async " );
262+ if (CY_RSLT_SUCCESS != cyhal_i2c_master_transfer_async (& (i2c -> hal_i2c ), address , tx , tx_length , rx , rx_length )) {
263+ MBED_ERROR (MBED_MAKE_ERROR (MBED_MODULE_DRIVER_I2C , MBED_ERROR_CODE_FAILED_OPERATION ), "cyhal_i2c_master_transfer_async " );
244264 }
245265}
246266
0 commit comments