Skip to content

Commit 7d15882

Browse files
author
Seppo Takalo
authored
Merge pull request #11101 from kyle-cypress/pr/spi-i2c-fixes
PSoC 6 I2C and SPI driver updates
2 parents 6ce2439 + b65be5f commit 7d15882

File tree

7 files changed

+205
-161
lines changed

7 files changed

+205
-161
lines changed

targets/TARGET_Cypress/TARGET_PSOC6/cy_i2c_api.c

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
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)
8486
void 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

113127
int 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

119136
int 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)
128145
int 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)
153170
int 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)
203223
int 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)
212232
int 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

targets/TARGET_Cypress/TARGET_PSOC6/cy_spi_api.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,9 @@ void spi_format(spi_t *obj, int bits, int mode, int slave)
112112
if (CY_RSLT_SUCCESS != cyhal_spi_init(&(spi->hal_spi), mosi, miso, sclk, ssel, NULL, (uint8_t)bits, hal_mode, slave != 0)) {
113113
MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER_SPI, MBED_ERROR_CODE_FAILED_OPERATION), "cyhal_spi_init");
114114
}
115-
spi_frequency(obj, hz);
115+
if (spi->hz != 0) {
116+
spi_frequency(obj, hz);
117+
}
116118
}
117119

118120
void spi_frequency(spi_t *obj, int hz)
@@ -127,11 +129,14 @@ void spi_frequency(spi_t *obj, int hz)
127129
int spi_master_write(spi_t *obj, int value)
128130
{
129131
struct spi_s *spi = cy_get_spi(obj);
130-
uint8_t received;
131-
if (CY_RSLT_SUCCESS != cyhal_spi_transfer(&(spi->hal_spi), (const uint8_t *)value, 1, &received, 1, 0)) {
132-
MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER_SPI, MBED_ERROR_CODE_FAILED_OPERATION), "cyhal_spi_transfer");
132+
uint32_t received;
133+
if (CY_RSLT_SUCCESS != cyhal_spi_write(&(spi->hal_spi), (uint32_t)value)) {
134+
MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER_SPI, MBED_ERROR_CODE_FAILED_OPERATION), "cyhal_spi_write");
135+
}
136+
if (CY_RSLT_SUCCESS != cyhal_spi_read(&(spi->hal_spi), &received)) {
137+
MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER_SPI, MBED_ERROR_CODE_FAILED_OPERATION), "cyhal_spi_read");
133138
}
134-
return received;
139+
return (int)received;
135140
}
136141

137142
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, char write_fill)

targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/include/cyhal_hw_types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ typedef struct {
350350
uint16_t pending;
351351
void *rx_buffer;
352352
uint32_t rx_buffer_size;
353-
void *tx_buffer;
353+
const void *tx_buffer;
354354
uint32_t tx_buffer_size;
355355
bool is_async;
356356
#else

targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/include/cyhal_utils.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,17 @@ extern "C" {
6868
* \{
6969
*/
7070

71+
/** Calculate the peri clock divider value that need to be set to reach frequency closest to the input frequency
72+
*
73+
* @param[in] frequency The desired frequency
74+
* @param[in] frac_bits The number of fractional bits that the divider has
75+
* @return The calculate divider value to set, NOTE a divider value of x divide the frequency by (x+1)
76+
*/
77+
static inline uint32_t cyhal_divider_value(uint32_t frequency, uint32_t frac_bits)
78+
{
79+
return ((cy_PeriClkFreqHz * (1 << frac_bits)) + (frequency / 2)) / frequency - 1;
80+
}
81+
7182
/** Converts the provided gpio pin to a resource instance object
7283
*
7384
* @param[in] pin The pin to get a resource object for

0 commit comments

Comments
 (0)