mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #11101 from kyle-cypress/pr/spi-i2c-fixes
PSoC 6 I2C and SPI driver updatespull/11099/head
commit
7d15882746
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#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;
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue