diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/cy_i2c_api.c b/targets/TARGET_Cypress/TARGET_PSOC6/cy_i2c_api.c index 55830784f7..7ef30bb7de 100644 --- a/targets/TARGET_Cypress/TARGET_PSOC6/cy_i2c_api.c +++ b/targets/TARGET_Cypress/TARGET_PSOC6/cy_i2c_api.c @@ -17,6 +17,8 @@ #include "i2c_api.h" #include "cyhal_i2c.h" +#include "cyhal_utils.h" +#include "cyhal_hwmgr.h" #include "mbed_error.h" #include "mbed_assert.h" #include "mbed_critical.h" @@ -84,12 +86,24 @@ static void cy_i2c_event_handler(void *handler_arg, cyhal_i2c_irq_event_t event) void i2c_init(i2c_t *obj, PinName sda, PinName scl) { struct i2c_s *i2c = cy_get_i2c(obj); - if (CY_RSLT_SUCCESS != cyhal_i2c_init(&(i2c->hal_i2c), sda, scl, NULL)) { + cy_rslt_t result = cyhal_i2c_init(&(i2c->hal_i2c), sda, scl, NULL); + if (result == CYHAL_HWMGR_RSLT_ERR_INUSE) { + // MBED I2C driver currently does not support free, so we will allow I2C to be reallocated. + // TODO: once the the I2C driver properly supports free, this need to be fixed so that clocks and pins are no longer leaked. + cyhal_hwmgr_free(&(i2c->hal_i2c.resource)); + cyhal_hwmgr_set_unconfigured(i2c->hal_i2c.resource.type, i2c->hal_i2c.resource.block_num, i2c->hal_i2c.resource.channel_num); + cyhal_resource_inst_t pin_rsc = cyhal_utils_get_gpio_resource(sda); + cyhal_hwmgr_free(&pin_rsc); + pin_rsc = cyhal_utils_get_gpio_resource(scl); + cyhal_hwmgr_free(&pin_rsc); + result = cyhal_i2c_init(&(i2c->hal_i2c), sda, scl, NULL); + } + if (CY_RSLT_SUCCESS != result) { MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER_I2C, MBED_ERROR_CODE_FAILED_OPERATION), "cyhal_i2c_init"); } i2c->cfg.is_slave = false; i2c->cfg.address = 0; - i2c->cfg.frequencyhal_hz = 400; + i2c->cfg.frequencyhal_hz = 400000; i2c->async_handler = NULL; cyhal_i2c_register_irq(&(i2c->hal_i2c), &cy_i2c_event_handler, obj); 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) int i2c_stop(i2c_t *obj) { - // Not supported; start/stop is generated by i2c_read/i2c_write - return -1; + struct i2c_s *i2c = cy_get_i2c(obj); + 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)); + } + return 0; } int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) { struct i2c_s *i2c = cy_get_i2c(obj); - if (CY_RSLT_SUCCESS != cyhal_i2c_master_recv(&(i2c->hal_i2c), address >> 1, (uint8_t *)data, (uint16_t)length, CY_I2C_DEFAULT_TIMEOUT)) { + if (CY_RSLT_SUCCESS != cyhal_i2c_master_read(&(i2c->hal_i2c), address >> 1, (uint8_t *)data, (uint16_t)length, CY_I2C_DEFAULT_TIMEOUT)) { return (int)I2C_ERROR_NO_SLAVE; } return length; @@ -128,7 +145,7 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) { struct i2c_s *i2c = cy_get_i2c(obj); - if (CY_RSLT_SUCCESS != cyhal_i2c_master_send(&(i2c->hal_i2c), address >> 1, (const uint8_t *)data, (uint16_t)length, CY_I2C_DEFAULT_TIMEOUT)) { + if (CY_RSLT_SUCCESS != cyhal_i2c_master_write(&(i2c->hal_i2c), address >> 1, (const uint8_t *)data, (uint16_t)length, CY_I2C_DEFAULT_TIMEOUT)) { return (int)I2C_ERROR_NO_SLAVE; } // 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) int i2c_byte_write(i2c_t *obj, int data) { struct i2c_s *i2c = cy_get_i2c(obj); - 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)); + // 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)); switch (status) { case CY_SCB_I2C_MASTER_MANUAL_TIMEOUT: return 2; @@ -203,7 +223,7 @@ int i2c_slave_receive(i2c_t *obj) int i2c_slave_read(i2c_t *obj, char *data, int length) { struct i2c_s *i2c = cy_get_i2c(obj); - if (CY_RSLT_SUCCESS != cyhal_i2c_slave_recv(&(i2c->hal_i2c), (uint8_t *)data, (uint16_t)length, CY_I2C_DEFAULT_TIMEOUT)) { + if (CY_RSLT_SUCCESS != cyhal_i2c_slave_config_read_buff(&(i2c->hal_i2c), (uint8_t *)data, (uint16_t)length)) { return 0; } return 1; @@ -212,7 +232,7 @@ int i2c_slave_read(i2c_t *obj, char *data, int length) int i2c_slave_write(i2c_t *obj, const char *data, int length) { struct i2c_s *i2c = cy_get_i2c(obj); - if (CY_RSLT_SUCCESS != cyhal_i2c_slave_send(&(i2c->hal_i2c), (const uint8_t *)data, (uint16_t)length, CY_I2C_DEFAULT_TIMEOUT)) { + if (CY_RSLT_SUCCESS != cyhal_i2c_slave_config_write_buff(&(i2c->hal_i2c), (const uint8_t *)data, (uint16_t)length)) { return 0; } return 1; @@ -239,8 +259,8 @@ void i2c_transfer_asynch(i2c_t *obj, const void *tx, size_t tx_length, void *rx, i2c->async_rx_size = rx_length; i2c->async_handler = (void (*)(void))handler; core_util_critical_section_exit(); - if (CY_RSLT_SUCCESS != cyhal_i2c_transfer_async(&(i2c->hal_i2c), tx, tx_length, rx, rx_length, address)) { - MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER_I2C, MBED_ERROR_CODE_FAILED_OPERATION), "cyhal_i2c_transfer_async"); + if (CY_RSLT_SUCCESS != cyhal_i2c_master_transfer_async(&(i2c->hal_i2c), address, tx, tx_length, rx, rx_length)) { + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER_I2C, MBED_ERROR_CODE_FAILED_OPERATION), "cyhal_i2c_master_transfer_async"); } } diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/cy_spi_api.c b/targets/TARGET_Cypress/TARGET_PSOC6/cy_spi_api.c index b2363969a2..4a6e9a5145 100644 --- a/targets/TARGET_Cypress/TARGET_PSOC6/cy_spi_api.c +++ b/targets/TARGET_Cypress/TARGET_PSOC6/cy_spi_api.c @@ -112,7 +112,9 @@ void spi_format(spi_t *obj, int bits, int mode, int slave) if (CY_RSLT_SUCCESS != cyhal_spi_init(&(spi->hal_spi), mosi, miso, sclk, ssel, NULL, (uint8_t)bits, hal_mode, slave != 0)) { MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER_SPI, MBED_ERROR_CODE_FAILED_OPERATION), "cyhal_spi_init"); } - spi_frequency(obj, hz); + if (spi->hz != 0) { + spi_frequency(obj, hz); + } } void spi_frequency(spi_t *obj, int hz) @@ -127,11 +129,14 @@ void spi_frequency(spi_t *obj, int hz) int spi_master_write(spi_t *obj, int value) { struct spi_s *spi = cy_get_spi(obj); - uint8_t received; - if (CY_RSLT_SUCCESS != cyhal_spi_transfer(&(spi->hal_spi), (const uint8_t *)value, 1, &received, 1, 0)) { - MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER_SPI, MBED_ERROR_CODE_FAILED_OPERATION), "cyhal_spi_transfer"); + uint32_t received; + if (CY_RSLT_SUCCESS != cyhal_spi_write(&(spi->hal_spi), (uint32_t)value)) { + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER_SPI, MBED_ERROR_CODE_FAILED_OPERATION), "cyhal_spi_write"); } - return received; + if (CY_RSLT_SUCCESS != cyhal_spi_read(&(spi->hal_spi), &received)) { + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER_SPI, MBED_ERROR_CODE_FAILED_OPERATION), "cyhal_spi_read"); + } + return (int)received; } int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, char write_fill) diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/include/cyhal_hw_types.h b/targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/include/cyhal_hw_types.h index 196877fb0a..6bbb218aca 100644 --- a/targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/include/cyhal_hw_types.h +++ b/targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/include/cyhal_hw_types.h @@ -350,7 +350,7 @@ typedef struct { uint16_t pending; void *rx_buffer; uint32_t rx_buffer_size; - void *tx_buffer; + const void *tx_buffer; uint32_t tx_buffer_size; bool is_async; #else diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/include/cyhal_utils.h b/targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/include/cyhal_utils.h index 87de28f75c..7322c042b4 100644 --- a/targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/include/cyhal_utils.h +++ b/targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/include/cyhal_utils.h @@ -68,6 +68,17 @@ extern "C" { * \{ */ +/** Calculate the peri clock divider value that need to be set to reach frequency closest to the input frequency + * + * @param[in] frequency The desired frequency + * @param[in] frac_bits The number of fractional bits that the divider has + * @return The calculate divider value to set, NOTE a divider value of x divide the frequency by (x+1) + */ +static inline uint32_t cyhal_divider_value(uint32_t frequency, uint32_t frac_bits) +{ + return ((cy_PeriClkFreqHz * (1 << frac_bits)) + (frequency / 2)) / frequency - 1; +} + /** Converts the provided gpio pin to a resource instance object * * @param[in] pin The pin to get a resource object for diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/src/cyhal_i2c.c b/targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/src/cyhal_i2c.c index a262b41879..4a6eff8ae8 100644 --- a/targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/src/cyhal_i2c.c +++ b/targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/src/cyhal_i2c.c @@ -33,8 +33,20 @@ #define PENDING_TX 2 #define PENDING_TX_RX 3 -#define SCB_PERI_CLOCK_SLAVE 15000000 -#define SCB_PERI_CLOCK_MASTER 1800000 +/* Must be between 1.55 MHz and 12.8 MHz for running i2c master at 100KHz */ +#define SCB_PERI_CLOCK_SLAVE_STD 8000000 +/* Must be between 7.82 MHz and 15.38 MHz for running i2c master at 400KHz */ +#define SCB_PERI_CLOCK_SLAVE_FST 12500000 +/* Must be between 15.84 MHz and 89.0 MHz for running i2c master at 1MHz */ +#define SCB_PERI_CLOCK_SLAVE_FSTP 50000000 +/* Must be between 1.55 MHz and 3.2 MHz for running i2c slave at 100KHz */ +#define SCB_PERI_CLOCK_MASTER_STD 2000000 +/* Must be between 7.82 MHz and 10 MHz for running i2c slave at 400KHz */ +#define SCB_PERI_CLOCK_MASTER_FST 8500000 +/* Must be between 14.32 MHz and 25.8 MHz for running i2c slave at 1MHz */ +#define SCB_PERI_CLOCK_MASTER_FSTP 20000000 + +#define CYHAL_I2C_MASTER_DEFAULT_FREQ 100000 static const cy_stc_scb_i2c_config_t default_i2c_config = { .i2cMode = CY_SCB_I2C_MASTER, @@ -429,10 +441,45 @@ static void (*cyhal_i2c_interrupts_dispatcher_table[CY_IP_MXSCB_INSTANCES])(void #endif }; -static uint32_t cyhal_divider_value(uint32_t frequency, uint32_t frac_bits) +static uint32_t cyhal_set_peri_divider(cyhal_i2c_t *obj, uint32_t freq, bool is_slave) { - /* I2C use peripheral clock */ - return ((cy_PeriClkFreqHz * (1 << frac_bits)) + (frequency / 2)) / frequency; + /* Return the actual data rate on success, 0 otherwise */ + uint32_t peri_freq = 0; + if (freq == 0) + { + return 0; + } + if (freq <= CY_SCB_I2C_STD_DATA_RATE) + { + peri_freq = is_slave ? SCB_PERI_CLOCK_SLAVE_STD : SCB_PERI_CLOCK_MASTER_STD; + } + else if (freq <= CY_SCB_I2C_FST_DATA_RATE) + { + peri_freq = is_slave ? SCB_PERI_CLOCK_SLAVE_FST : SCB_PERI_CLOCK_MASTER_FST; + } + else if (freq <= CY_SCB_I2C_FSTP_DATA_RATE) + { + peri_freq = is_slave ? SCB_PERI_CLOCK_SLAVE_FSTP : SCB_PERI_CLOCK_MASTER_FSTP; + } + else + { + return 0; + } + Cy_SysClk_PeriphAssignDivider((en_clk_dst_t)get_scb_cls(obj->resource.block_num), obj->clock.div_type, obj->clock.div_num); + Cy_SysClk_PeriphDisableDivider(obj->clock.div_type, obj->clock.div_num); + Cy_SysClk_PeriphSetDivider(obj->clock.div_type, obj->clock.div_num, cyhal_divider_value(peri_freq, 0u)); + Cy_SysClk_PeriphEnableDivider(obj->clock.div_type, obj->clock.div_num); + + /* According to PDL API Reference Guide - Cy_SysClk_PeriphGetFrequency() use only for i2c master role */ + if(!is_slave) + { + return Cy_SCB_I2C_SetDataRate(obj->base, freq, Cy_SysClk_PeriphGetFrequency(obj->clock.div_type, obj->clock.div_num)); + } + else + { + return Cy_SCB_I2C_GetDataRate(obj->base, Cy_SysClk_PeriphGetFrequency(obj->clock.div_type, obj->clock.div_num)); + } + } /* Start API implementing */ @@ -454,13 +501,12 @@ cy_rslt_t cyhal_i2c_init(cyhal_i2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t scl, c { return CYHAL_I2C_RSLT_ERR_INVALID_PIN; } - const cyhal_resource_inst_t *rsc = scl_map->inst; - cy_rslt_t result = cyhal_hwmgr_reserve(rsc); + obj->resource = *(scl_map->inst); + cy_rslt_t result = cyhal_hwmgr_reserve(&(obj->resource)); if (result != CY_RSLT_SUCCESS) { return result; } - obj->resource = *rsc; /* Reserve the SDA pin */ cyhal_resource_inst_t pin_rsc = cyhal_utils_get_gpio_resource(sda); @@ -468,7 +514,7 @@ cy_rslt_t cyhal_i2c_init(cyhal_i2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t scl, c if (result == CY_RSLT_SUCCESS) { obj->pin_sda = sda; - } + } Cy_GPIO_SetHSIOM(CYHAL_GET_PORTADDR(sda), CYHAL_GET_PIN(sda), CY_GPIO_CFG_GET_HSIOM(scl_map->cfg)); Cy_GPIO_SetDrivemode(CYHAL_GET_PORTADDR(sda), CYHAL_GET_PIN(sda), CY_GPIO_DM_OD_DRIVESLOW); @@ -481,10 +527,10 @@ cy_rslt_t cyhal_i2c_init(cyhal_i2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t scl, c if (result == CY_RSLT_SUCCESS) { obj->pin_scl = scl; - } + } Cy_GPIO_SetHSIOM(CYHAL_GET_PORTADDR(scl), CYHAL_GET_PIN(scl), CY_GPIO_CFG_GET_HSIOM(scl_map->cfg)); Cy_GPIO_SetDrivemode(CYHAL_GET_PORTADDR(scl), CYHAL_GET_PIN(scl), CY_GPIO_DM_OD_DRIVESLOW); - + } obj->base = CY_SCB_BASE_ADDRESSES[obj->resource.block_num]; @@ -504,18 +550,12 @@ cy_rslt_t cyhal_i2c_init(cyhal_i2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t scl, c if (result == CY_RSLT_SUCCESS) { - /* Connect assigned divider to be a clock source for I2C */ - Cy_SysClk_PeriphAssignDivider((en_clk_dst_t)get_scb_cls(obj->resource.block_num), obj->clock.div_type, obj->clock.div_num); - - /* I2C slave desired data rate is 400 kbps. - * To support this data rate the clk_scb frequency must be in range 7.82 – 15.38 MHz. - * Find clk_scb valid ranges in TRM section I2C sub-section Oversampling and Bit Rate. - * For clk_peri = 50 MHz, select divider value 4 and get clk_scb = (50 MHz / 4) = 12.5 MHz. - * This clock frequency meets requirements above. - */ - Cy_SysClk_PeriphDisableDivider(obj->clock.div_type, obj->clock.div_num); - Cy_SysClk_PeriphSetDivider(obj->clock.div_type, obj->clock.div_num, cyhal_divider_value(SCB_PERI_CLOCK_SLAVE, 0u)); - Cy_SysClk_PeriphEnableDivider(obj->clock.div_type, obj->clock.div_num); + uint32_t dataRate = cyhal_set_peri_divider(obj, CYHAL_I2C_MASTER_DEFAULT_FREQ, false); + if (dataRate == 0) + { + /* Can not reach desired data rate */ + result = CYHAL_I2C_RSLT_ERR_CAN_NOT_REACH_DR; + } } bool configured = cyhal_hwmgr_is_configured(obj->resource.type, obj->resource.block_num, obj->resource.channel_num); @@ -528,6 +568,7 @@ cy_rslt_t cyhal_i2c_init(cyhal_i2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t scl, c (void) Cy_SCB_I2C_Enable(obj->base); Cy_SysInt_Init(&irqCfg, cyhal_i2c_interrupts_dispatcher_table[obj->resource.block_num]); NVIC_EnableIRQ(CY_SCB_IRQ_N[obj->resource.block_num]); + obj->irq_cause = CYHAL_I2C_IRQ_NONE; cyhal_i2c_config_structs[obj->resource.block_num] = obj; cyhal_i2c_config_structs[obj->resource.block_num]->irq_cause = CYHAL_I2C_IRQ_NONE; result = cyhal_hwmgr_set_configured(obj->resource.type, obj->resource.block_num, obj->resource.channel_num); @@ -542,9 +583,12 @@ cy_rslt_t cyhal_i2c_init(cyhal_i2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t scl, c void cyhal_i2c_free(cyhal_i2c_t *obj) { CY_ASSERT(NULL != obj); - + if (CYHAL_RSC_INVALID != obj->resource.type) { + IRQn_Type irqn = CY_SCB_IRQ_N[obj->resource.block_num]; + NVIC_DisableIRQ(irqn); + cyhal_hwmgr_set_unconfigured(obj->resource.type, obj->resource.block_num, obj->resource.channel_num); cyhal_hwmgr_free(&(obj->resource)); obj->base = NULL; @@ -570,9 +614,8 @@ void cyhal_i2c_free(cyhal_i2c_t *obj) cy_rslt_t cyhal_i2c_set_config(cyhal_i2c_t *obj, const cyhal_i2c_cfg_t *cfg) { (void) Cy_SCB_I2C_Disable(obj->base, &obj->context); - uint32_t dataRate; - cy_stc_scb_i2c_config_t config_structure = default_i2c_config; + cy_stc_scb_i2c_config_t config_structure = default_i2c_config; config_structure.i2cMode = (cfg->is_slave) ? CY_SCB_I2C_SLAVE : CY_SCB_I2C_MASTER; @@ -586,28 +629,13 @@ cy_rslt_t cyhal_i2c_set_config(cyhal_i2c_t *obj, const cyhal_i2c_cfg_t *cfg) } /* Set data rate */ - if (!cfg->is_slave) + uint32_t dataRate = cyhal_set_peri_divider(obj, cfg->frequencyhal_hz, cfg->is_slave); + if (dataRate == 0) { - Cy_SysClk_PeriphAssignDivider((en_clk_dst_t)get_scb_cls(obj->resource.block_num), obj->clock.div_type, obj->clock.div_num); - - /* I2C master desired data rate is 100 kbps. - * To support this data rate the clk_scb frequency must be in range 1.55 - 3.2 MHz. - * Find clk_scb valid ranges in TRM section I2C sub-section Oversampling and Bit Rate. - * For clk_peri = 50 MHz, select divider value 32 and get clk_scb = (50 MHz / 32) = 1.563 MHz. - * This clock frequency meets requirements above. - */ - Cy_SysClk_PeriphDisableDivider(obj->clock.div_type, obj->clock.div_num); - Cy_SysClk_PeriphSetDivider (obj->clock.div_type, obj->clock.div_num, cyhal_divider_value(SCB_PERI_CLOCK_MASTER, 0u)); - Cy_SysClk_PeriphEnableDivider(obj->clock.div_type, obj->clock.div_num); - - dataRate = Cy_SCB_I2C_SetDataRate(obj->base, (uint32_t)cfg->frequencyhal_hz, Cy_SysClk_PeriphGetFrequency(obj->clock.div_type, obj->clock.div_num)); - - if ((dataRate > cfg->frequencyhal_hz) || (dataRate == 0U)) - { - /* Can not reach desired data rate */ - return CYHAL_I2C_RSLT_ERR_CAN_NOT_REACH_DR; - } + /* Can not reach desired data rate */ + return CYHAL_I2C_RSLT_ERR_CAN_NOT_REACH_DR; } + cy_rslt_t result = (cy_rslt_t)Cy_SCB_I2C_Init(obj->base, &config_structure, &(obj->context)); (void) Cy_SCB_I2C_Enable(obj->base); @@ -615,7 +643,7 @@ cy_rslt_t cyhal_i2c_set_config(cyhal_i2c_t *obj, const cyhal_i2c_cfg_t *cfg) return result; } -cy_rslt_t cyhal_i2c_master_send(cyhal_i2c_t *obj, uint16_t dev_addr, const uint8_t *data, uint16_t size, uint32_t timeout) +cy_rslt_t cyhal_i2c_master_write(cyhal_i2c_t *obj, uint16_t dev_addr, const uint8_t *data, uint16_t size, uint32_t timeout) { cy_en_scb_i2c_status_t status = CY_SCB_I2C_SUCCESS; @@ -649,7 +677,7 @@ cy_rslt_t cyhal_i2c_master_send(cyhal_i2c_t *obj, uint16_t dev_addr, const uint8 return status; } -cy_rslt_t cyhal_i2c_master_recv(cyhal_i2c_t *obj, uint16_t dev_addr, uint8_t *data, uint16_t size, uint32_t timeout) +cy_rslt_t cyhal_i2c_master_read(cyhal_i2c_t *obj, uint16_t dev_addr, uint8_t *data, uint16_t size, uint32_t timeout) { cy_en_scb_i2c_status_t status = CY_SCB_I2C_SUCCESS; cy_en_scb_i2c_command_t ack = CY_SCB_I2C_ACK; @@ -687,25 +715,25 @@ cy_rslt_t cyhal_i2c_master_recv(cyhal_i2c_t *obj, uint16_t dev_addr, uint8_t *da return status; } -cy_rslt_t cyhal_i2c_slave_send(cyhal_i2c_t *obj, const uint8_t *data, uint16_t size, uint32_t timeout) +cy_rslt_t cyhal_i2c_slave_config_write_buff(cyhal_i2c_t *obj, const uint8_t *data, uint16_t size) { - if (obj->context.state == CY_SCB_I2C_IDLE) + if (obj->context.state == CY_SCB_I2C_IDLE) { Cy_SCB_I2C_SlaveConfigReadBuf(obj->base, (uint8_t *)data, size, &obj->context); - } + } return CY_RSLT_SUCCESS; } -cy_rslt_t cyhal_i2c_slave_recv(cyhal_i2c_t *obj, uint8_t *data, uint16_t size, uint32_t timeout) +cy_rslt_t cyhal_i2c_slave_config_read_buff(cyhal_i2c_t *obj, uint8_t *data, uint16_t size) { if (obj->context.state == CY_SCB_I2C_IDLE) - { + { Cy_SCB_I2C_SlaveConfigWriteBuf(obj->base, (uint8_t *)data, size, &obj->context); } return CY_RSLT_SUCCESS; } -cy_rslt_t cyhal_i2c_mem_write(cyhal_i2c_t *obj, uint16_t address, uint16_t mem_addr, uint16_t mem_addr_size, const uint8_t *data, uint16_t size, uint32_t timeout) +cy_rslt_t cyhal_i2c_master_mem_write(cyhal_i2c_t *obj, uint16_t address, uint16_t mem_addr, uint16_t mem_addr_size, const uint8_t *data, uint16_t size, uint32_t timeout) { cy_en_scb_i2c_status_t status = CY_SCB_I2C_SUCCESS; @@ -753,7 +781,7 @@ cy_rslt_t cyhal_i2c_mem_write(cyhal_i2c_t *obj, uint16_t address, uint16_t mem_a return status; } -cy_rslt_t cyhal_i2c_mem_read(cyhal_i2c_t *obj, uint16_t address, uint16_t mem_addr, uint16_t mem_addr_size, uint8_t *data, uint16_t size, uint32_t timeout) +cy_rslt_t cyhal_i2c_master_mem_read(cyhal_i2c_t *obj, uint16_t address, uint16_t mem_addr, uint16_t mem_addr_size, uint8_t *data, uint16_t size, uint32_t timeout) { cy_en_scb_i2c_status_t status = CY_SCB_I2C_SUCCESS; cy_en_scb_i2c_command_t ack = CY_SCB_I2C_ACK; @@ -779,7 +807,7 @@ cy_rslt_t cyhal_i2c_mem_read(cyhal_i2c_t *obj, uint16_t address, uint16_t mem_ad { status = Cy_SCB_I2C_MasterWriteByte(obj->base, (uint8_t)(mem_addr & 0x00FF), timeout, &obj->context); } - + if (status == CY_SCB_I2C_SUCCESS) { status = Cy_SCB_I2C_MasterSendReStart(obj->base, address, CY_SCB_I2C_READ_XFER, timeout, &obj->context); @@ -814,7 +842,7 @@ cy_rslt_t cyhal_i2c_mem_read(cyhal_i2c_t *obj, uint16_t address, uint16_t mem_ad return status; } -cy_rslt_t cyhal_i2c_transfer_async(cyhal_i2c_t *obj, const void *tx, size_t tx_size, void *rx, size_t rx_size, uint16_t address) +cy_rslt_t cyhal_i2c_master_transfer_async(cyhal_i2c_t *obj, uint16_t address, const void *tx, size_t tx_size, void *rx, size_t rx_size) { obj->rx_config.slaveAddress = address; obj->tx_config.slaveAddress = address; @@ -906,7 +934,7 @@ static cyhal_i2c_irq_event_t cyhal_convert_interrupt_cause(uint32_t pdl_cause) break; case CY_SCB_I2C_MASTER_ERR_EVENT: cause = CYHAL_I2C_MASTER_ERR_EVENT; - break; + break; default: cause = CYHAL_I2C_IRQ_NONE; break; diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/src/cyhal_spi.c b/targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/src/cyhal_spi.c index 9038e79a52..c6347358e1 100644 --- a/targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/src/cyhal_spi.c +++ b/targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/src/cyhal_spi.c @@ -26,6 +26,7 @@ #include #include #include "cyhal_implementation.h" +#include "cyhal_hwmgr.h" #ifdef CY_IP_MXSCB @@ -300,7 +301,6 @@ static void (*cyhal_spi_cb_wrapper_table[CY_IP_MXSCB_INSTANCES])(uint32_t event) static void cyhal_spi_interrupts_dispatcher_IRQHandler(uint32_t spi_num) { cyhal_spi_t *obj = cyhal_spi_config_structs[spi_num]; - void *buf; if (NULL == obj) { @@ -320,15 +320,15 @@ static void cyhal_spi_interrupts_dispatcher_IRQHandler(uint32_t spi_num) { /* Start TX Transfer */ obj->pending = PENDING_TX; - buf = obj->tx_buffer; + const uint8_t *buf = obj->tx_buffer; obj->tx_buffer = NULL; - Cy_SCB_SPI_Transfer(obj->base, buf, NULL, obj->tx_buffer_size, &obj->context); + Cy_SCB_SPI_Transfer(obj->base, (uint8_t *)buf, NULL, obj->tx_buffer_size, &obj->context); } else if (obj->rx_buffer) { /* Start RX Transfer */ obj->pending = PENDING_RX; - buf = obj->rx_buffer; + uint8_t *buf = obj->rx_buffer; obj->rx_buffer = NULL; Cy_SCB_SPI_Transfer(obj->base, NULL, buf, obj->rx_buffer_size, &obj->context); @@ -497,6 +497,7 @@ static void cyhal_spi_install_irq(cyhal_spi_t *obj) Cy_SysInt_Init(&irqCfg, cyhal_spi_interrupts_dispatcher_table[idx]); NVIC_EnableIRQ(CY_SCB_IRQ_N[idx]); cyhal_spi_config_structs[idx] = obj; + cyhal_spi_config_structs[idx]->irq_cause = CYHAL_SPI_IRQ_NONE; } static cy_en_scb_spi_sclk_mode_t cyhal_convert_mode_sclk(cyhal_spi_mode_t mode) @@ -542,7 +543,7 @@ cy_rslt_t cyhal_spi_init(cyhal_spi_t *obj, cyhal_gpio_t mosi, cyhal_gpio_t miso, uint8_t bits, cyhal_spi_mode_t mode, bool is_slave) { CY_ASSERT(NULL != obj); - + cy_rslt_t result = CY_RSLT_SUCCESS; cyhal_resource_inst_t pin_rsc; uint8_t ovr_sample_val = SPI_OVERSAMPLE_MIN; @@ -556,12 +557,12 @@ cy_rslt_t cyhal_spi_init(cyhal_spi_t *obj, cyhal_gpio_t mosi, cyhal_gpio_t miso, if ((NC == sclk) || ((NC == mosi) && (NC == miso))) return CYHAL_SPI_RSLT_PIN_CONFIG_NOT_SUPPORTED; - + const cyhal_resource_pin_mapping_t *mosi_map = NULL; const cyhal_resource_pin_mapping_t *miso_map = NULL; const cyhal_resource_pin_mapping_t *sclk_map = NULL; const cyhal_resource_pin_mapping_t *ssel_map = NULL; - + // Reserve the SPI if (is_slave) { @@ -595,7 +596,7 @@ cy_rslt_t cyhal_spi_init(cyhal_spi_t *obj, cyhal_gpio_t mosi, cyhal_gpio_t miso, } sclk_map = CY_UTILS_GET_RESOURCE(sclk, cyhal_pin_map_scb_spi_m_clk); } - + if ( ((NC != mosi) && (NULL == mosi_map)) || ((NC != miso) && (NULL == miso_map)) || (NULL == sclk_map) @@ -652,7 +653,7 @@ cy_rslt_t cyhal_spi_init(cyhal_spi_t *obj, cyhal_gpio_t mosi, cyhal_gpio_t miso, //reseve the SSEL pin if ((result == CY_RSLT_SUCCESS) && (NC != ssel)) { - if (is_slave) + if (is_slave) { pin_rsc = cyhal_utils_get_gpio_resource(ssel); result = cyhal_hwmgr_reserve(&pin_rsc); @@ -718,7 +719,7 @@ cy_rslt_t cyhal_spi_init(cyhal_spi_t *obj, cyhal_gpio_t mosi, cyhal_gpio_t miso, { result = cyhal_connect_pin(ssel_map); } - else + else { result = cyhal_gpio_init(ssel, CYHAL_GPIO_DIR_OUTPUT, CYHAL_GPIO_DRIVE_STRONG, true); } @@ -767,6 +768,9 @@ void cyhal_spi_free(cyhal_spi_t *obj) if (obj->resource.type != CYHAL_RSC_INVALID) { + IRQn_Type irqn = CY_SCB_IRQ_N[obj->resource.block_num]; + NVIC_DisableIRQ(irqn); + cyhal_hwmgr_set_unconfigured(obj->resource.type, obj->resource.block_num, obj->resource.channel_num); cyhal_hwmgr_free(&(obj->resource)); obj->resource.type = CYHAL_RSC_INVALID; @@ -805,12 +809,6 @@ void cyhal_spi_free(cyhal_spi_t *obj) } } -static uint32_t cyhal_divider_value(uint32_t frequency) -{ - /* SPI use peripheral clock */ - return cy_PeriClkFreqHz / frequency; -} - static inline uint32_t min(uint32_t lhs, uint32_t rhs) { return lhs > rhs ? rhs : lhs; @@ -827,7 +825,7 @@ static cy_rslt_t cyhal_int_spi_frequency(cyhal_spi_t *obj, uint32_t hz, uint8_t { return CYHAL_SPI_RSLT_BAD_ARGUMENT; } - + cy_rslt_t result = CY_RSLT_SUCCESS; uint8_t oversample_value; uint32_t divider_value; @@ -854,8 +852,8 @@ static cy_rslt_t cyhal_int_spi_frequency(cyhal_spi_t *obj, uint32_t hz, uint8_t continue; } - divider_value = cyhal_divider_value(hz * oversample_value); - divided_freq = cy_PeriClkFreqHz /divider_value; + divider_value = cyhal_divider_value(hz * oversample_value, 0); + divided_freq = cy_PeriClkFreqHz /(divider_value + 1); diff = max(oversampled_freq, divided_freq) - min(oversampled_freq, divided_freq); if (diff < last_diff) @@ -874,16 +872,16 @@ static cy_rslt_t cyhal_int_spi_frequency(cyhal_spi_t *obj, uint32_t hz, uint8_t else { /* Slave requires such frequency: fclk_scb = N / ((0.5 * tclk_scb) – 20 nsec - tDSI, - * N is 3 when "Enable Input Glitch Filter" is false and 4 when true. + * N is 3 when "Enable Input Glitch Filter" is false and 4 when true. * tDSI Is external master delay which is assumed to be 16.66 nsec */ float desired_period_us = 1 / (float)hz * 1e6; uint32_t required_frequency = (uint32_t)(3e6 / (0.5f * desired_period_us - 36.66f / 1e3)); - + if (required_frequency > cy_PeriClkFreqHz) { return CYHAL_SPI_RSLT_CLOCK_ERROR; } - + /* Use maximum available clock for slave to make it able to work with any master environment */ last_dvdr_val = 1; } @@ -915,7 +913,7 @@ static void cyhal_set_ssel(cyhal_spi_t *obj) static void cyhal_reset_ssel(cyhal_spi_t *obj) { - if ((!obj->is_slave) && (CYHAL_NC_PIN_VALUE != obj->pin_ssel)) + if ((!obj->is_slave) && (CYHAL_NC_PIN_VALUE != obj->pin_ssel)) { cyhal_gpio_write(obj->pin_ssel, SSEL_INACTIVE); } @@ -974,7 +972,7 @@ cy_rslt_t cyhal_spi_read(cyhal_spi_t *obj, uint32_t *value) { return CYHAL_SPI_RSLT_INVALID_PIN_API_NOT_SUPPORTED; } - + while (read_value == CY_SCB_SPI_RX_NO_DATA) { read_value = Cy_SCB_SPI_Read(obj->base); @@ -1003,7 +1001,7 @@ cy_rslt_t cyhal_spi_write(cyhal_spi_t *obj, uint32_t value) { return CYHAL_SPI_RSLT_INVALID_PIN_API_NOT_SUPPORTED; } - + if (!obj->is_slave) { rx_count = Cy_SCB_SPI_GetNumInRxFifo(obj->base); @@ -1019,11 +1017,11 @@ cy_rslt_t cyhal_spi_write(cyhal_spi_t *obj, uint32_t value) count = Cy_SCB_SPI_Write(obj->base, value); } - if (!obj->is_slave) + if (!obj->is_slave) { while (Cy_SCB_SPI_IsTxComplete(obj->base) == false) ; - while (( Cy_SCB_SPI_GetNumInRxFifo(obj->base) == rx_count ) && (rx_count != Cy_SCB_GetFifoSize(obj->base))) + while (( Cy_SCB_SPI_GetNumInRxFifo(obj->base) == rx_count ) && (rx_count != Cy_SCB_GetFifoSize(obj->base))) { /* Wait for RX FIFO not empty */ } cyhal_reset_ssel(obj); } @@ -1037,7 +1035,6 @@ cy_rslt_t cyhal_spi_transfer(cyhal_spi_t *obj, const uint8_t *tx, size_t tx_leng { uint32_t remaining_rx, remaining_tx, xfr_length; uint8_t dummy[MAX_DUMMY_SIZE]; - uint8_t *bufptr; if (NULL == obj) { @@ -1059,71 +1056,67 @@ cy_rslt_t cyhal_spi_transfer(cyhal_spi_t *obj, const uint8_t *tx, size_t tx_leng xfr_length = (uint32_t) rx_length; remaining_rx = 0; remaining_tx = (uint32_t) (tx_length - rx_length); - Cy_SCB_SPI_Transfer(obj->base, (uint8_t *) tx, rx, xfr_length, &(obj->context)); + if (xfr_length != 0) + { + Cy_SCB_SPI_Transfer(obj->base, (uint8_t *) tx, rx, xfr_length, &(obj->context)); + + while ( CY_SCB_SPI_TRANSFER_ACTIVE & Cy_SCB_SPI_GetTransferStatus(obj->base, &(obj->context))) { }; + } + + const uint8_t *bufptr = tx + (obj->data_bits <= 8 ? xfr_length : (xfr_length * 2)); + + Cy_SCB_SPI_Transfer(obj->base, (uint8_t *)bufptr, NULL, remaining_tx, &(obj->context)); while ( CY_SCB_SPI_TRANSFER_ACTIVE & Cy_SCB_SPI_GetTransferStatus(obj->base, &(obj->context))) { }; - - bufptr = obj->data_bits == 8 ? - (uint8_t *)(((uint8_t *)tx) + xfr_length) : - (uint8_t *)(((uint16_t *)tx) + xfr_length); - - Cy_SCB_SPI_Transfer(obj->base, bufptr, NULL, remaining_tx, &(obj->context)); - - while ( CY_SCB_SPI_TRANSFER_ACTIVE & Cy_SCB_SPI_GetTransferStatus(obj->base, &(obj->context))) { }; - } + } else if (tx_length < rx_length) { xfr_length = (uint32_t) tx_length; remaining_rx = (uint32_t) (rx_length - tx_length); - Cy_SCB_SPI_Transfer(obj->base, (uint8_t *) tx, rx, xfr_length, &(obj->context)); + if (xfr_length != 0) + { + Cy_SCB_SPI_Transfer(obj->base, (uint8_t *) tx, rx, xfr_length, &(obj->context)); - while ( CY_SCB_SPI_TRANSFER_ACTIVE & Cy_SCB_SPI_GetTransferStatus(obj->base, &(obj->context))) { }; + while ( CY_SCB_SPI_TRANSFER_ACTIVE & Cy_SCB_SPI_GetTransferStatus(obj->base, &(obj->context))) { }; + } memset(dummy, write_fill, sizeof(dummy)); while (remaining_rx) { - if (remaining_rx <= MAX_DUMMY_SIZE) - { - bufptr = obj->data_bits == 8 ? - (uint8_t *)(((uint8_t *)rx) + xfr_length) : - (uint8_t *)(((uint16_t *)rx) + xfr_length); - + uint8_t *bufptr = rx + (obj->data_bits <= 8 ? xfr_length : (xfr_length * 2)); + if (remaining_rx <= MAX_DUMMY_SIZE) + { Cy_SCB_SPI_Transfer(obj->base, dummy, bufptr, remaining_rx, &(obj->context)); remaining_rx = 0; - } - else - { - bufptr = obj->data_bits == 8 ? - (uint8_t *)(((uint8_t *)rx) + xfr_length) : - (uint8_t *)(((uint16_t *)rx) + xfr_length); - + } + else + { Cy_SCB_SPI_Transfer(obj->base, dummy, bufptr, MAX_DUMMY_SIZE, &(obj->context)); remaining_rx -= MAX_DUMMY_SIZE; xfr_length += MAX_DUMMY_SIZE; - } + } - while ( CY_SCB_SPI_TRANSFER_ACTIVE & Cy_SCB_SPI_GetTransferStatus(obj->base, &(obj->context))) { }; + while ( CY_SCB_SPI_TRANSFER_ACTIVE & Cy_SCB_SPI_GetTransferStatus(obj->base, &(obj->context))) { }; } - } - else + } + else if (tx_length != 0) // tx_length == rx_length { xfr_length = (uint32_t) tx_length; Cy_SCB_SPI_Transfer(obj->base, (uint8_t *) tx, rx, xfr_length, &(obj->context)); while ( CY_SCB_SPI_TRANSFER_ACTIVE & Cy_SCB_SPI_GetTransferStatus(obj->base, &(obj->context))) { }; } - + if (!obj->is_slave) { cyhal_reset_ssel(obj); } - + return CY_RSLT_SUCCESS; } cy_rslt_t cyhal_spi_transfer_async(cyhal_spi_t *obj, const uint8_t *tx, size_t tx_length, uint8_t *rx, size_t rx_length) { cy_en_scb_spi_status_t spi_status; - uint8_t *bufptr; if (NULL == obj) { @@ -1137,24 +1130,21 @@ cy_rslt_t cyhal_spi_transfer_async(cyhal_spi_t *obj, const uint8_t *tx, size_t t cyhal_set_ssel(obj); obj->is_async = true; - + /* Setup transfer */ - if (tx_length > rx_length) + if (tx_length > rx_length) { - if (rx_length > 0) + if (rx_length > 0) { /* I) write + read, II) write only */ obj->pending = PENDING_TX_RX; obj->rx_buffer = NULL; - bufptr = obj->data_bits == 8 ? - (uint8_t *)(((uint8_t *)tx) + rx_length) : - (uint8_t *)(((uint16_t *)tx) + rx_length); - obj->tx_buffer = bufptr; + obj->tx_buffer = tx + (obj->data_bits <= 8 ? rx_length : (rx_length * 2)); obj->tx_buffer_size = tx_length - rx_length; spi_status = Cy_SCB_SPI_Transfer(obj->base, (void *)tx, rx, rx_length, &obj->context); - } - else + } + else { /* I) write only */ obj->pending = PENDING_TX; @@ -1163,24 +1153,21 @@ cy_rslt_t cyhal_spi_transfer_async(cyhal_spi_t *obj, const uint8_t *tx, size_t t spi_status = Cy_SCB_SPI_Transfer(obj->base, (void *)tx, NULL, tx_length, &obj->context); } - } - else if (rx_length > tx_length) + } + else if (rx_length > tx_length) { - if (tx_length > 0) + if (tx_length > 0) { /* I) write + read, II) read only */ obj->pending = PENDING_TX_RX; - bufptr = obj->data_bits == 8 ? - (uint8_t *)(((uint8_t *)rx) + tx_length) : - (uint8_t *)(((uint16_t *)rx) + tx_length); - obj->rx_buffer = bufptr; + obj->rx_buffer = rx + (obj->data_bits <= 8 ? tx_length : (tx_length * 2)); obj->rx_buffer_size = rx_length - tx_length; obj->tx_buffer = NULL; spi_status = Cy_SCB_SPI_Transfer(obj->base, (void *)tx, rx, tx_length, &obj->context); - } - else + } + else { /* I) read only. */ obj->pending = PENDING_RX; @@ -1189,8 +1176,8 @@ cy_rslt_t cyhal_spi_transfer_async(cyhal_spi_t *obj, const uint8_t *tx, size_t t spi_status = Cy_SCB_SPI_Transfer(obj->base, NULL, rx, rx_length, &obj->context); } - } - else + } + else { /* RX and TX of the same size: I) write + read. */ obj->pending = PENDING_TX_RX; diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/src/cyhal_uart.c b/targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/src/cyhal_uart.c index f61597b0b4..4fee067b17 100644 --- a/targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/src/cyhal_uart.c +++ b/targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/src/cyhal_uart.c @@ -689,13 +689,6 @@ static uint32_t cyhal_uart_baud_perdif(uint32_t desired_baud, uint32_t actual_ba return perdif; } -static uint32_t cyhal_divider_value(uint32_t frequency) -{ - CY_ASSERT(frequency != 0); - /* UARTs use peripheral clock */ - return (((cy_PeriClkFreqHz) + (frequency / 2)) / frequency) - 1; -} - static uint8_t cyhal_uart_best_oversample(uint32_t baudrate) { uint8_t differences[UART_OVERSAMPLE_MAX + 1]; @@ -704,7 +697,7 @@ static uint8_t cyhal_uart_best_oversample(uint32_t baudrate) for(index = UART_OVERSAMPLE_MIN; index < UART_OVERSAMPLE_MAX + 1; index++) { - divider = cyhal_divider_value(baudrate * index); + divider = cyhal_divider_value(baudrate * index, 0); differences[index] = cyhal_uart_baud_perdif(baudrate, cyhal_uart_actual_baud(divider, index)); } @@ -736,7 +729,7 @@ cy_rslt_t cyhal_uart_baud(cyhal_uart_t *obj, uint32_t baudrate, uint32_t *actual oversample_value = cyhal_uart_best_oversample(baudrate); obj->config.oversample = oversample_value; - divider = cyhal_divider_value(baudrate * oversample_value); + divider = cyhal_divider_value(baudrate * oversample_value, 0); /* Set baud rate */ if ((obj->clock.div_type == CY_SYSCLK_DIV_16_5_BIT) || (obj->clock.div_type == CY_SYSCLK_DIV_24_5_BIT))