From 981f708caaea3241cd1bd2614e019d796a6ab3c5 Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Thu, 16 Feb 2023 10:58:41 +0200 Subject: [PATCH 01/22] sn32: build i2c lld --- os/hal/ports/SN32/LLD/SN32F2xx/I2C/driver.mk | 21 ++++++++++++++++++++ os/hal/ports/SN32/SN32F240B/platform.mk | 1 + os/hal/ports/SN32/SN32F260/platform.mk | 1 + 3 files changed, 23 insertions(+) create mode 100644 os/hal/ports/SN32/LLD/SN32F2xx/I2C/driver.mk diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/driver.mk b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/driver.mk new file mode 100644 index 0000000000..0b803ad16c --- /dev/null +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/driver.mk @@ -0,0 +1,21 @@ +ifeq ($(USE_HAL_I2C_FALLBACK),yes) + # Fallback SW driver. + ifeq ($(USE_SMART_BUILD),yes) + ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) + PLATFORMSRC_CONTRIB += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c + endif + else + PLATFORMSRC_CONTRIB += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c + endif + PLATFORMINC_CONTRIB += $(CHIBIOS)/os/hal/lib/fallback/I2C +else + # Default HW driver. + ifeq ($(USE_SMART_BUILD),yes) + ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) + PLATFORMSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/LLD/SN32F2xx/I2C/hal_i2c_lld.c + endif + else + PLATFORMSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/LLD/SN32F2xx/I2C/hal_i2c_lld.c + endif + PLATFORMINC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/LLD/SN32F2xx/I2C +endif diff --git a/os/hal/ports/SN32/SN32F240B/platform.mk b/os/hal/ports/SN32/SN32F240B/platform.mk index 66b64149d0..309a76ac34 100644 --- a/os/hal/ports/SN32/SN32F240B/platform.mk +++ b/os/hal/ports/SN32/SN32F240B/platform.mk @@ -25,6 +25,7 @@ include ${CHIBIOS_CONTRIB}/os/hal/ports/SN32/LLD/SN32F2xx/CT/driver.mk include ${CHIBIOS_CONTRIB}/os/hal/ports/SN32/LLD/SN32F2xx/FLASH/driver.mk include ${CHIBIOS_CONTRIB}/os/hal/ports/SN32/LLD/SN32F2xx/SysTick/driver.mk include ${CHIBIOS_CONTRIB}/os/hal/ports/SN32/LLD/SN32F2xx/SPI/driver.mk +include ${CHIBIOS_CONTRIB}/os/hal/ports/SN32/LLD/SN32F2xx/I2C/driver.mk include ${CHIBIOS_CONTRIB}/os/hal/ports/SN32/LLD/SN32F2xx/WDT/driver.mk # Shared variables diff --git a/os/hal/ports/SN32/SN32F260/platform.mk b/os/hal/ports/SN32/SN32F260/platform.mk index 2082c73908..e6ee0bd0f4 100644 --- a/os/hal/ports/SN32/SN32F260/platform.mk +++ b/os/hal/ports/SN32/SN32F260/platform.mk @@ -25,6 +25,7 @@ include ${CHIBIOS_CONTRIB}/os/hal/ports/SN32/LLD/SN32F2xx/CT/driver.mk include ${CHIBIOS_CONTRIB}/os/hal/ports/SN32/LLD/SN32F2xx/FLASH/driver.mk include ${CHIBIOS_CONTRIB}/os/hal/ports/SN32/LLD/SN32F2xx/SysTick/driver.mk include ${CHIBIOS_CONTRIB}/os/hal/ports/SN32/LLD/SN32F2xx/SPI/driver.mk +include ${CHIBIOS_CONTRIB}/os/hal/ports/SN32/LLD/SN32F2xx/I2C/driver.mk include ${CHIBIOS_CONTRIB}/os/hal/ports/SN32/LLD/SN32F2xx/WDT/driver.mk # Shared variables From fe6b0003521e8973606a522d0b95511342d36561 Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Thu, 16 Feb 2023 11:01:09 +0200 Subject: [PATCH 02/22] sn32: initial i2c lld draft --- .../ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c | 236 ++++++++++++++++++ .../ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h | 178 +++++++++++++ os/hal/ports/SN32/LLD/SN32F2xx/I2C/sn32_i2c.h | 84 +++++++ 3 files changed, 498 insertions(+) create mode 100644 os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c create mode 100644 os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h create mode 100644 os/hal/ports/SN32/LLD/SN32F2xx/I2C/sn32_i2c.h diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c new file mode 100644 index 0000000000..ecbfa5ae76 --- /dev/null +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c @@ -0,0 +1,236 @@ +/* + ChibiOS - Copyright (C) 2023 1Conan + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file hal_i2c_lld.c + * @brief SN32 I2C subsystem low level driver source. + * + * @addtogroup I2C + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief I2C0 driver identifier. + */ +#if (SN32_I2C_USE_I2C0 == TRUE) || defined(__DOXYGEN__) +I2CDriver I2CD0; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static inline void i2c_lld_configure(I2CDriver *i2cp) { + i2cp->i2c->SCLHT = i2cp->config->high_time; + i2cp->i2c->SCLLT = i2cp->config->low_time; + i2cp->i2c->TOCTRL = i2cp->config->timeout; + i2cp->i2c->CTRL_b.I2CEN = true; +} + +static inline void i2c_lld_irq_handler(I2CDriver *i2cp) { + chSysLockFromISR(); + i2cp->i2c->STAT_b.I2CIF = true; + chSysUnlockFromISR(); + + if (i2cp->i2c->STAT_b.LOST_ARB) { + i2cp->state = I2C_ARBITRATION_LOST; + _i2c_wakeup_error_isr(i2cp); + return; + } else if (i2cp->i2c->STAT_b.RX_DN && i2cp->rx_buffer && i2cp->count < i2cp->rx_len) { + i2cp->rx_buffer[i2cp->count++] = i2cp->i2c->RXDATA; + } + + if (i2cp->rx_buffer && !i2cp->tx_buffer) { + if (i2cp->count == i2cp->rx_len) { + i2cp->i2c->CTRL_b.STO = true; + i2cp->i2c->CTRL_b.I2CEN = false; + i2cp->i2c->CTRL_b.I2CEN = true; + i2cp->state = I2C_STOP; + _i2c_wakeup_isr(i2cp); + return; + } + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if SN32_I2C_USE_I2C0 +OSAL_IRQ_HANDLER(SN32_I2C0_GLOBAL_HANDLER) { + OSAL_IRQ_PROLOGUE(); + + i2c_lld_irq_handler(&I2C0); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level I2C driver initialization. + * + * @notapi + */ +void i2c_lld_init(void) { + +#if SN32_I2C_USE_I2C0 == TRUE + i2cObjectInit(&I2CD0); + I2CD0.i2c = SN32_I2C0; +#endif +} + +/** + * @brief Configures and activates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +void i2c_lld_start(I2CDriver *i2cp) { + + if (i2cp->state == I2C_STOP) { + /* Enables the peripheral.*/ +#if SN32_I2C_USE_I2C0 == TRUE + if (&I2CD0 == i2cp) { + sys1EnableI2C0(); + nvicClearPending(SN32_I2C0_GLOBAL_NUMBER); + nvicEnableVector(SN32_I2C0_GLOBAL_NUMBER, SN32_I2C_I2C0_IRQ_PRIORITY); + } +#endif + } + + i2c_lld_configure(i2cp); +} + +/** + * @brief Deactivates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +void i2c_lld_stop(I2CDriver *i2cp) { + + if (i2cp->state != I2C_STOP) { + + i2cp->i2c->CTRL_b.I2CEN = false; + + /* Disables the peripheral.*/ +#if SN32_I2C_USE_I2C0 == TRUE + if (&I2CD0 == i2cp) { + sys1DisableI2C0(); + nvicDisableVector(SN32_I2C0_GLOBAL_NUMBER); + } +#endif + } +} + +/** + * @brief Receives data via the I2C bus as master. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * @param[out] rxbuf pointer to the receive buffer + * @param[in] rxbytes number of bytes to be received + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a + * timeout the driver must be stopped and restarted + * because the bus is in an uncertain state. + * + * @notapi + */ +msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, + uint8_t *rxbuf, size_t rxbytes, + sysinterval_t timeout) { + + (void)timeout; + i2cp->rx_buffer = rxbuf; + i2cp->rx_len = rxbytes; + i2cp->i2c->CTRL_b.STA = true; + i2cp->i2c->TX_DATA = addr; + + return MSG_OK; +} + +/** + * @brief Transmits data via the I2C bus as master. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * @param[in] txbuf pointer to the transmit buffer + * @param[in] txbytes number of bytes to be transmitted + * @param[out] rxbuf pointer to the receive buffer + * @param[in] rxbytes number of bytes to be received + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a + * timeout the driver must be stopped and restarted + * because the bus is in an uncertain state. + * + * @notapi + */ +msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, + const uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + sysinterval_t timeout) { + + (void)i2cp; + (void)addr; + (void)txbuf; + (void)txbytes; + (void)rxbuf; + (void)rxbytes; + (void)timeout; + + return MSG_OK; +} + +#endif /* HAL_USE_I2C == TRUE */ + +/** @} */ \ No newline at end of file diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h new file mode 100644 index 0000000000..a30f171104 --- /dev/null +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h @@ -0,0 +1,178 @@ +/* + ChibiOS - Copyright (C) 2023 1Conan + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file hal_i2c_lld.h + * @brief SN32 I2C subsystem low level driver header. + * + * @addtogroup I2C + * @{ + */ + +#ifndef HAL_I2C_LLD_H +#define HAL_I2C_LLD_H + +#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name SN32 configuration options + * @{ + */ +/** + * @brief I2C0 driver enable switch. + * @details If set to @p TRUE the support for I2C0 is included. + * @note The default is @p FALSE. + */ +#if !defined(SN32_I2C_USE_I2C0) || defined(__DOXYGEN__) +#define SN32_I2C_USE_I2C0 FALSE +#endif + +/** + * @brief I2C0 interrupt priority level setting. + */ +#if !defined(SN32_I2C_I2C0_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define SN32_I2C_I2C0_IRQ_PRIORITY 3 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +#if SN32_HAS_I2C0 +#define SN32_I2C0_BASE SN_I2C0_BASE +#define SN32_I2C0 ((sn32_i2c_t *)SN_I2C_BASE) +#endif + +/** + * @brief Type representing an I2C address. + */ +typedef uint16_t i2caddr_t; + +/** + * @brief Type of I2C Driver condition flags. + */ +typedef uint32_t i2cflags_t; + +/** + * @brief I2C driver configuration structure. + * @note Implementations may extend this structure to contain more, + * architecture dependent, fields. + */ +struct hal_i2c_config { + /* End of the mandatory fields.*/ + uint8_t high_time; + uint8_t low_time; + uint16_t timeout; +}; + +/** + * @brief Type of a structure representing an I2C configuration. + */ +typedef struct hal_i2c_config I2CConfig; + +/** + * @brief Type of a structure representing an I2C driver. + */ +typedef struct hal_i2c_driver I2CDriver; + +/** + * @brief Structure representing an I2C driver. + */ +struct hal_i2c_driver { + /** + * @brief Driver state. + */ + i2cstate_t state; + /** + * @brief Current configuration data. + */ + const I2CConfig *config; + /** + * @brief Error flags. + */ + i2cflags_t errors; +#if (I2C_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__) + mutex_t mutex; +#endif +#if defined(I2C_DRIVER_EXT_FIELDS) + I2C_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + + sn32_i2c_t *i2c; + uint8_t *rx_buffer; + uint8_t rx_len; + uint8_t *tx_buffer; + uint8_t tx_len; + uint8_t count; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Get errors from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_errors(i2cp) ((i2cp)->errors) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if (SN32_I2C_USE_I2C0 == TRUE) && !defined(__DOXYGEN__) +extern I2CDriver I2CD0; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void i2c_lld_init(void); + void i2c_lld_start(I2CDriver *i2cp); + void i2c_lld_stop(I2CDriver *i2cp); + msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, + const uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + sysinterval_t timeout); + msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, + uint8_t *rxbuf, size_t rxbytes, + sysinterval_t timeout); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_I2C == TRUE */ + +#endif /* HAL_I2C_LLD_H */ + +/** @} */ \ No newline at end of file diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/sn32_i2c.h b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/sn32_i2c.h new file mode 100644 index 0000000000..2c43058d33 --- /dev/null +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/sn32_i2c.h @@ -0,0 +1,84 @@ +/* + ChibiOS - Copyright (C) 2023 1Conan + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef SN32_I2C_H +#define SN32_I2C_H + +typedef struct { + union { + uint32_t CTRL; + + struct { + uint32_t : 1; + uint32_t NACK : 1; + uint32_t ACK : 1; + uint32_t : 1; + uint32_t STO : 1; + uint32_t STA : 1; + uint32_t : 1; + uint32_t MODE : 1; + uint32_t I2CEN : 1; + uint32_t : 23; + } CTRL_b; + }; + + union { + uint32_t STAT; + + struct { + uint32_t RX_DN : 1; + uint32_t ACK_STAT : 1; + uint32_t NACK_STATE : 1; + uint32_t STOP_DN : 1; + uint32_t START_DN : 1; + uint32_t MST : 1; + uint32_t SLV_RX_HIT : 1; + uint32_t SLV_TX_HIT : 1; + uint32_t LOST_ARB : 1; + uint32_t TIMEOUT : 1; + uint32_t : 5 + uint32_t I2CIF : 1; + uint32_t : 16; + } STAT_b; + }; + + uint32_t TXDATA; + uint32_t RXDATA; + + union { + uint32_t SLVADRR0; + + struct { + uint32_t ADDR : 10; + uint32_t : 20; + uint32_t GCEN : 1; + uint32_t ADD_MODE : 1; + + } SLVADDR0_b; + }; + + uint32_t SLVADDR1; + uint32_t SLVADDR2; + uint32_t SLVADDR3; + uint32_t SCLHT; + uint32_t SCLLT; + uint32_t SCLCT; + uint32_t TOCTRL; +} sn32_i2c_t; + +#endif /* SN32_I2C_H */ + +/** @} */ \ No newline at end of file From 4a59645bd9a9db4b5404cdd77238a04e9c60db48 Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Thu, 16 Feb 2023 12:14:47 +0200 Subject: [PATCH 03/22] first pass on master receive routine --- .../ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c | 41 +++++++++++++++++-- .../ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h | 8 ++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c index ecbfa5ae76..ae9f79ba31 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c @@ -183,13 +183,46 @@ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, uint8_t *rxbuf, size_t rxbytes, sysinterval_t timeout) { - (void)timeout; + /* Resetting error flags for this transfer.*/ + i2cp->errors = I2C_NO_ERROR; + + /* Initializes driver fields, LSB = 1 -> receive.*/ + i2cp->addr = (addr << 1) | 0x01; + + /* Releases the lock from high level driver.*/ + osalSysUnlock(); + + /* Calculating the time window for the timeout on the busy bus condition.*/ + start = osalOsGetSystemTimeX(); + end = osalTimeAddX(start, OSAL_MS2I(SN32_I2C_BUSY_TIMEOUT)); + + /* Waits until INTERRUPT flag is reset or, alternatively, for a timeout + condition.*/ + while (true) { + osalSysLock(); + + /* If the bus is not busy then the operation can continue, note, the + loop is exited in the locked state.*/ + if (!(i2cp->i2c->STAT_b.I2CIF)) + break; + + /* If the system time went outside the allowed window then a timeout + condition is returned.*/ + if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) + return MSG_TIMEOUT; + + osalSysUnlock(); + } + i2cp->i2c->CTRL_b.STA = true; + if (i2cp->i2c->STAT_b.RX_DN != 0) { + rxbuf = i2cp->i2c->RX_DATA; + } i2cp->rx_buffer = rxbuf; i2cp->rx_len = rxbytes; - i2cp->i2c->CTRL_b.STA = true; - i2cp->i2c->TX_DATA = addr; - return MSG_OK; + /* Waits for the operation completion or a timeout.*/ + return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); + } /** diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h index a30f171104..1569799b77 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h @@ -54,6 +54,14 @@ #if !defined(SN32_I2C_I2C0_IRQ_PRIORITY) || defined(__DOXYGEN__) #define SN32_I2C_I2C0_IRQ_PRIORITY 3 #endif + +/** + * @brief I2C timeout on busy condition in milliseconds. + */ +#if !defined(SN32_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__) +#define SN32_I2C_BUSY_TIMEOUT 50 +#endif + /** @} */ /*===========================================================================*/ From 5fb7bfdeb80ad0bd806f986fbfb6ca604c5721cf Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Thu, 16 Feb 2023 12:56:14 +0200 Subject: [PATCH 04/22] partial revert, this is handled in the interrupt --- os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c index ae9f79ba31..a598ef57b9 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c @@ -196,16 +196,10 @@ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, start = osalOsGetSystemTimeX(); end = osalTimeAddX(start, OSAL_MS2I(SN32_I2C_BUSY_TIMEOUT)); - /* Waits until INTERRUPT flag is reset or, alternatively, for a timeout - condition.*/ + /* Waits for a timeout condition.*/ while (true) { osalSysLock(); - /* If the bus is not busy then the operation can continue, note, the - loop is exited in the locked state.*/ - if (!(i2cp->i2c->STAT_b.I2CIF)) - break; - /* If the system time went outside the allowed window then a timeout condition is returned.*/ if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) @@ -213,12 +207,10 @@ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, osalSysUnlock(); } - i2cp->i2c->CTRL_b.STA = true; - if (i2cp->i2c->STAT_b.RX_DN != 0) { - rxbuf = i2cp->i2c->RX_DATA; - } i2cp->rx_buffer = rxbuf; i2cp->rx_len = rxbytes; + i2cp->i2c->CTRL_b.STA = true; + i2cp->i2c->TX_DATA = addr; /* Waits for the operation completion or a timeout.*/ return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); From 77b6441ab3084688029cc240011c0edaed621bb5 Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Thu, 16 Feb 2023 13:04:05 +0200 Subject: [PATCH 05/22] i2c receive: send an ack after every packet --- os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c | 1 + 1 file changed, 1 insertion(+) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c index a598ef57b9..15ffe21aa4 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c @@ -67,6 +67,7 @@ static inline void i2c_lld_irq_handler(I2CDriver *i2cp) { return; } else if (i2cp->i2c->STAT_b.RX_DN && i2cp->rx_buffer && i2cp->count < i2cp->rx_len) { i2cp->rx_buffer[i2cp->count++] = i2cp->i2c->RXDATA; + i2cp->i2c->CTRL_b.ACK = true; } if (i2cp->rx_buffer && !i2cp->tx_buffer) { From 0a5f0c26d981f50f76fca0b9a556b47d7adcdf06 Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Thu, 16 Feb 2023 14:13:32 +0200 Subject: [PATCH 06/22] sn32: add i2c transmit --- .../ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c | 49 +++++++++++++++---- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c index 15ffe21aa4..911b9df6d0 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c @@ -68,10 +68,13 @@ static inline void i2c_lld_irq_handler(I2CDriver *i2cp) { } else if (i2cp->i2c->STAT_b.RX_DN && i2cp->rx_buffer && i2cp->count < i2cp->rx_len) { i2cp->rx_buffer[i2cp->count++] = i2cp->i2c->RXDATA; i2cp->i2c->CTRL_b.ACK = true; + } else if (i2cp->i2c->STAT_b.START_DN && i2cp->tx_buffer && i2cp->count < i2cp->tx_len) { + i2cp->tx_buffer[i2cp->count++] = i2cp->i2c->TXDATA; + i2cp->i2c->CTRL_b.ACK = true; } - if (i2cp->rx_buffer && !i2cp->tx_buffer) { - if (i2cp->count == i2cp->rx_len) { + if ((i2cp->rx_buffer && !i2cp->tx_buffer) || (!i2cp->rx_buffer && i2cp->tx_buffer)) { + if ((i2cp->count == i2cp->rx_len) || (i2cp->count == i2cp->tx_len)) { i2cp->i2c->CTRL_b.STO = true; i2cp->i2c->CTRL_b.I2CEN = false; i2cp->i2c->CTRL_b.I2CEN = true; @@ -184,6 +187,8 @@ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, uint8_t *rxbuf, size_t rxbytes, sysinterval_t timeout) { + systime_t start, end; + /* Resetting error flags for this transfer.*/ i2cp->errors = I2C_NO_ERROR; @@ -246,15 +251,39 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, uint8_t *rxbuf, size_t rxbytes, sysinterval_t timeout) { - (void)i2cp; - (void)addr; - (void)txbuf; - (void)txbytes; - (void)rxbuf; - (void)rxbytes; - (void)timeout; + systime_t start, end; + + /* Resetting error flags for this transfer.*/ + i2cp->errors = I2C_NO_ERROR; + + /* Initializes driver fields, LSB = 0 -> transmit.*/ + i2cp->addr = (addr << 1); + + /* Releases the lock from high level driver.*/ + osalSysUnlock(); + + /* Calculating the time window for the timeout on the busy bus condition.*/ + start = osalOsGetSystemTimeX(); + end = osalTimeAddX(start, OSAL_MS2I(SN32_I2C_BUSY_TIMEOUT)); + + /* Waits for a timeout condition.*/ + while (true) { + osalSysLock(); + + /* If the system time went outside the allowed window then a timeout + condition is returned.*/ + if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) + return MSG_TIMEOUT; + + osalSysUnlock(); + } + i2cp->tx_buffer = txbuf; + i2cp->tx_len = txbytes; + i2cp->i2c->CTRL_b.STA = true; + i2cp->i2c->TX_DATA = addr; - return MSG_OK; + /* Waits for the operation completion or a timeout.*/ + return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); } #endif /* HAL_USE_I2C == TRUE */ From 8354f4fc378f4efadde7e2224b6ec3886906db24 Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Tue, 21 Feb 2023 21:33:53 +0200 Subject: [PATCH 07/22] status checking while in transmission --- .../ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c index 911b9df6d0..9fbeb019b8 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c @@ -65,12 +65,18 @@ static inline void i2c_lld_irq_handler(I2CDriver *i2cp) { i2cp->state = I2C_ARBITRATION_LOST; _i2c_wakeup_error_isr(i2cp); return; - } else if (i2cp->i2c->STAT_b.RX_DN && i2cp->rx_buffer && i2cp->count < i2cp->rx_len) { - i2cp->rx_buffer[i2cp->count++] = i2cp->i2c->RXDATA; - i2cp->i2c->CTRL_b.ACK = true; - } else if (i2cp->i2c->STAT_b.START_DN && i2cp->tx_buffer && i2cp->count < i2cp->tx_len) { - i2cp->tx_buffer[i2cp->count++] = i2cp->i2c->TXDATA; - i2cp->i2c->CTRL_b.ACK = true; + } else { + if (i2cp->i2c->STAT_b.NACK_STAT) { + i2cp->i2c->CTRL_b.ACK = true; + } else { + if (i2cp->i2c->STAT_b.RX_DN && i2cp->rx_buffer && i2cp->count < i2cp->rx_len) { + i2cp->rx_buffer[i2cp->count++] = i2cp->i2c->RXDATA; + i2cp->i2c->CTRL_b.ACK = true; + } + if (i2cp->i2c->STAT_b.ACK_STAT && i2cp->tx_buffer && i2cp->count < i2cp->tx_len) { + i2cp->tx_buffer[i2cp->count++] = i2cp->i2c->TXDATA; + } + } } if ((i2cp->rx_buffer && !i2cp->tx_buffer) || (!i2cp->rx_buffer && i2cp->tx_buffer)) { From 228935645141e236b9450b71ba6eb015af0c3808 Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Tue, 21 Feb 2023 21:56:16 +0200 Subject: [PATCH 08/22] return after each interrupt pass --- os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c index 9fbeb019b8..bbbe350b9d 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c @@ -72,9 +72,11 @@ static inline void i2c_lld_irq_handler(I2CDriver *i2cp) { if (i2cp->i2c->STAT_b.RX_DN && i2cp->rx_buffer && i2cp->count < i2cp->rx_len) { i2cp->rx_buffer[i2cp->count++] = i2cp->i2c->RXDATA; i2cp->i2c->CTRL_b.ACK = true; + return; } if (i2cp->i2c->STAT_b.ACK_STAT && i2cp->tx_buffer && i2cp->count < i2cp->tx_len) { i2cp->tx_buffer[i2cp->count++] = i2cp->i2c->TXDATA; + return; } } } From a7bd49eda71eee89f49e91188f2841968410e1b9 Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Tue, 21 Feb 2023 22:02:38 +0200 Subject: [PATCH 09/22] small cleanup --- .../ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c index bbbe350b9d..a6ec58b6fb 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c @@ -65,20 +65,19 @@ static inline void i2c_lld_irq_handler(I2CDriver *i2cp) { i2cp->state = I2C_ARBITRATION_LOST; _i2c_wakeup_error_isr(i2cp); return; - } else { - if (i2cp->i2c->STAT_b.NACK_STAT) { - i2cp->i2c->CTRL_b.ACK = true; + } + if (i2cp->i2c->STAT_b.NACK_STAT) { + i2cp->i2c->CTRL_b.ACK = true; } else { if (i2cp->i2c->STAT_b.RX_DN && i2cp->rx_buffer && i2cp->count < i2cp->rx_len) { - i2cp->rx_buffer[i2cp->count++] = i2cp->i2c->RXDATA; - i2cp->i2c->CTRL_b.ACK = true; - return; + i2cp->rx_buffer[i2cp->count++] = i2cp->i2c->RXDATA; + i2cp->i2c->CTRL_b.ACK = true; + return; } if (i2cp->i2c->STAT_b.ACK_STAT && i2cp->tx_buffer && i2cp->count < i2cp->tx_len) { - i2cp->tx_buffer[i2cp->count++] = i2cp->i2c->TXDATA; - return; + i2cp->tx_buffer[i2cp->count++] = i2cp->i2c->TXDATA; + return; } - } } if ((i2cp->rx_buffer && !i2cp->tx_buffer) || (!i2cp->rx_buffer && i2cp->tx_buffer)) { From b078a56d8ae1d8dbcb02c98e353d544b20e011e6 Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Thu, 2 Mar 2023 13:54:00 +0200 Subject: [PATCH 10/22] add slave handling flags --- os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c index a6ec58b6fb..b66a898ad7 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c @@ -73,6 +73,15 @@ static inline void i2c_lld_irq_handler(I2CDriver *i2cp) { i2cp->rx_buffer[i2cp->count++] = i2cp->i2c->RXDATA; i2cp->i2c->CTRL_b.ACK = true; return; + } else { + if (i2cp->i2c->STAT_b.SLV_RX_HIT) { + i2cp->i2c->CTRL_b.ACK = true; + return; + } + if (i2cp->i2c->STAT_b.SLV_TX_HIT) { + //silent return + return; + } } if (i2cp->i2c->STAT_b.ACK_STAT && i2cp->tx_buffer && i2cp->count < i2cp->tx_len) { i2cp->tx_buffer[i2cp->count++] = i2cp->i2c->TXDATA; @@ -295,4 +304,6 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, #endif /* HAL_USE_I2C == TRUE */ -/** @} */ \ No newline at end of file +/** @} */ + + From 6cf8a1b49f24ab44324f25e8fce14645de2a5887 Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Thu, 2 Mar 2023 13:55:21 +0200 Subject: [PATCH 11/22] reformat the irq handler for readability --- .../ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c | 63 +++++++++---------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c index b66a898ad7..9e7be3dc48 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c @@ -56,51 +56,50 @@ static inline void i2c_lld_configure(I2CDriver *i2cp) { i2cp->i2c->CTRL_b.I2CEN = true; } -static inline void i2c_lld_irq_handler(I2CDriver *i2cp) { +static inline void i2c_lld_irq_handler(I2CDriver * i2cp) { chSysLockFromISR(); - i2cp->i2c->STAT_b.I2CIF = true; + i2cp -> i2c -> STAT_b.I2CIF = true; chSysUnlockFromISR(); - if (i2cp->i2c->STAT_b.LOST_ARB) { - i2cp->state = I2C_ARBITRATION_LOST; + if (i2cp -> i2c -> STAT_b.LOST_ARB) { + i2cp -> state = I2C_ARBITRATION_LOST; _i2c_wakeup_error_isr(i2cp); return; } - if (i2cp->i2c->STAT_b.NACK_STAT) { - i2cp->i2c->CTRL_b.ACK = true; - } else { - if (i2cp->i2c->STAT_b.RX_DN && i2cp->rx_buffer && i2cp->count < i2cp->rx_len) { - i2cp->rx_buffer[i2cp->count++] = i2cp->i2c->RXDATA; - i2cp->i2c->CTRL_b.ACK = true; - return; - } else { - if (i2cp->i2c->STAT_b.SLV_RX_HIT) { - i2cp->i2c->CTRL_b.ACK = true; - return; - } - if (i2cp->i2c->STAT_b.SLV_TX_HIT) { - //silent return - return; - } - } - if (i2cp->i2c->STAT_b.ACK_STAT && i2cp->tx_buffer && i2cp->count < i2cp->tx_len) { - i2cp->tx_buffer[i2cp->count++] = i2cp->i2c->TXDATA; - return; - } + if (i2cp -> i2c -> STAT_b.NACK_STAT) { + i2cp -> i2c -> CTRL_b.ACK = true; + } else { + if (i2cp -> i2c -> STAT_b.RX_DN && i2cp -> rx_buffer && i2cp -> count < i2cp -> rx_len) { + i2cp -> rx_buffer[i2cp -> count++] = i2cp -> i2c -> RXDATA; + i2cp -> i2c -> CTRL_b.ACK = true; + return; + } else { + if (i2cp -> i2c -> STAT_b.SLV_RX_HIT) { + i2cp -> i2c -> CTRL_b.ACK = true; + return; + } + if (i2cp -> i2c -> STAT_b.SLV_TX_HIT) { + //silent return + return; + } + } + if (i2cp -> i2c -> STAT_b.ACK_STAT && i2cp -> tx_buffer && i2cp -> count < i2cp -> tx_len) { + i2cp -> tx_buffer[i2cp -> count++] = i2cp -> i2c -> TXDATA; + return; + } } - if ((i2cp->rx_buffer && !i2cp->tx_buffer) || (!i2cp->rx_buffer && i2cp->tx_buffer)) { - if ((i2cp->count == i2cp->rx_len) || (i2cp->count == i2cp->tx_len)) { - i2cp->i2c->CTRL_b.STO = true; - i2cp->i2c->CTRL_b.I2CEN = false; - i2cp->i2c->CTRL_b.I2CEN = true; - i2cp->state = I2C_STOP; + if ((i2cp -> rx_buffer && !i2cp -> tx_buffer) || (!i2cp -> rx_buffer && i2cp -> tx_buffer)) { + if ((i2cp -> count == i2cp -> rx_len) || (i2cp -> count == i2cp -> tx_len)) { + i2cp -> i2c -> CTRL_b.STO = true; + i2cp -> i2c -> CTRL_b.I2CEN = false; + i2cp -> i2c -> CTRL_b.I2CEN = true; + i2cp -> state = I2C_STOP; _i2c_wakeup_isr(i2cp); return; } } } - /*===========================================================================*/ /* Driver interrupt handlers. */ /*===========================================================================*/ From 757248759d397a9e113fdd4e12b8ed2183adcb8f Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Sat, 8 Apr 2023 11:13:17 +0300 Subject: [PATCH 12/22] sn32: add i2c slave hooks --- .../ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c | 73 +++++++++++++++++++ .../ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h | 11 +++ 2 files changed, 84 insertions(+) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c index 9e7be3dc48..ca9f5b5a49 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c @@ -301,6 +301,79 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); } +#if (I2C_SUPPORTS_SLAVE_MODE == TRUE) || defined(__DOXYGEN__) +/** + * @brief Listen I2C bus for address match. + * @details Use 7 bit address (10 bit,dual and general call address dosn't implement yet) . + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * + * @notapi + */ +msg_t i2c_lld_match_address(I2CDriver *i2cp, i2caddr_t addr) { + +} + +/** + * @brief Receive data via the I2C bus as slave and call handler. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[out] rxbuf pointer to the receive buffer + * @param[in] rxbytes size of receive buffer + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a + * timeout the driver must be stopped and restarted + * because the bus is in an uncertain state. + * + * @api + */ +msg_t i2c_lld_slave_receive_timeout(I2CDriver *i2cp, + uint8_t *rxbuf, + size_t rxbytes, + sysinterval_t timeout) { + +} + +/** + * @brief Transmits data via the I2C bus as slave. + * @details Call this function when Master request data (in request handler) + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] txbuf pointer to the transmit buffer + * @param[in] txbytes number of bytes to be transmitted + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a + * timeout the driver must be stopped and restarted + * because the bus is in an uncertain state. + * + * @api + */ +msg_t i2c_lld_slave_transmit_timeout(I2CDriver *i2cp, + const uint8_t *txbuf, + size_t txbytes, + sysinterval_t timeout) { + +} +#endif /* I2C_SUPPORTS_SLAVE_MODE == TRUE */ #endif /* HAL_USE_I2C == TRUE */ /** @} */ diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h index 1569799b77..58194c0b13 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h @@ -175,6 +175,17 @@ extern "C" { msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, uint8_t *rxbuf, size_t rxbytes, sysinterval_t timeout); +#if (I2C_SUPPORTS_SLAVE_MODE == TRUE) || defined(__DOXYGEN__) + msg_t i2c_lld_match_address(I2CDriver *i2cp, i2caddr_t addr); + msg_t i2c_lld_slave_receive_timeout(I2CDriver *i2cp, + uint8_t *rxbuf, + size_t rxbytes, + sysinterval_t timeout); + msg_t i2c_lld_slave_transmit_timeout(I2CDriver *i2cp, + const uint8_t *txbuf, + size_t txbytes, + sysinterval_t timeout); +#endif /* I2C_SUPPORTS_SLAVE_MODE == TRUE */ #ifdef __cplusplus } #endif From b80092f00d2ccf179ee6128decca22f7e8934755 Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Sat, 8 Apr 2023 12:23:34 +0300 Subject: [PATCH 13/22] sn32: i2c slave: match address --- os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c index ca9f5b5a49..32847738d5 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c @@ -317,6 +317,17 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, */ msg_t i2c_lld_match_address(I2CDriver *i2cp, i2caddr_t addr) { + uint16_t i2cadr = addr << 1; + uint16_t ownAdr = i2cp->i2c->SLVADRR0 & (0x7f<<1); + + if (ownAdr == 0 || ownAdr == i2cadr) + i2cp->i2c->SLVADRR0 = i2cadr; + else + /* cannot add this address to set of those matched */ + return MSG_RESET; + + return MSG_OK; + } /** From b00c1944104627efdba4286704c7390d47d57ffd Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Sat, 8 Apr 2023 12:33:05 +0300 Subject: [PATCH 14/22] sn32: i2c slave: receive and transmit --- os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c index 32847738d5..6538aa17d3 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c @@ -354,7 +354,12 @@ msg_t i2c_lld_slave_receive_timeout(I2CDriver *i2cp, uint8_t *rxbuf, size_t rxbytes, sysinterval_t timeout) { + i2cp->rx_buffer = rxbuf; + i2cp->rx_len = rxbytes; + i2cp->i2c->TX_DATA = addr; + /* Waits for the operation completion or a timeout.*/ + return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); } /** @@ -382,7 +387,12 @@ msg_t i2c_lld_slave_transmit_timeout(I2CDriver *i2cp, const uint8_t *txbuf, size_t txbytes, sysinterval_t timeout) { + i2cp->tx_buffer = txbuf; + i2cp->tx_len = txbytes; + i2cp->i2c->TX_DATA = addr; + /* Waits for the operation completion or a timeout.*/ + return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); } #endif /* I2C_SUPPORTS_SLAVE_MODE == TRUE */ #endif /* HAL_USE_I2C == TRUE */ From 8d3d449fbd6111712477ace4c82f0221201396bf Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Sun, 9 Apr 2023 11:42:26 +0300 Subject: [PATCH 15/22] sn32: i2c LLD: advertise slave mode support --- os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h index 58194c0b13..881e47d9ad 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h @@ -141,6 +141,11 @@ struct hal_i2c_driver { uint8_t count; }; +/* For compatibility, some LLDs could not export this.*/ +#if !defined(I2C_SUPPORTS_SLAVE_MODE) +#define I2C_SUPPORTS_SLAVE_MODE TRUE +#endif + /*===========================================================================*/ /* Driver macros. */ /*===========================================================================*/ From 2a78da4a848cb8efe233544d72d58c28adc7c90d Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Wed, 12 Apr 2023 14:36:17 +0300 Subject: [PATCH 16/22] sn32 i2c: minor cleanup --- os/hal/ports/SN32/LLD/SN32F2xx/I2C/driver.mk | 6 +++--- os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c | 9 ++++----- os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h | 9 +++++++-- os/hal/ports/SN32/LLD/SN32F2xx/I2C/sn32_i2c.h | 4 ++-- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/driver.mk b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/driver.mk index 0b803ad16c..7864517f37 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/driver.mk +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/driver.mk @@ -12,10 +12,10 @@ else # Default HW driver. ifeq ($(USE_SMART_BUILD),yes) ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) - PLATFORMSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/LLD/SN32F2xx/I2C/hal_i2c_lld.c + PLATFORMSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c endif else - PLATFORMSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/LLD/SN32F2xx/I2C/hal_i2c_lld.c + PLATFORMSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c endif - PLATFORMINC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/LLD/SN32F2xx/I2C + PLATFORMINC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/SN32/LLD/SN32F2xx/I2C endif diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c index 6538aa17d3..a93cea9195 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c @@ -108,7 +108,7 @@ static inline void i2c_lld_irq_handler(I2CDriver * i2cp) { OSAL_IRQ_HANDLER(SN32_I2C0_GLOBAL_HANDLER) { OSAL_IRQ_PROLOGUE(); - i2c_lld_irq_handler(&I2C0); + i2c_lld_irq_handler(&I2CD0); OSAL_IRQ_EPILOGUE(); } @@ -127,6 +127,7 @@ void i2c_lld_init(void) { #if SN32_I2C_USE_I2C0 == TRUE i2cObjectInit(&I2CD0); + I2CD0.thread = NULL; I2CD0.i2c = SN32_I2C0; #endif } @@ -231,7 +232,7 @@ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, i2cp->rx_buffer = rxbuf; i2cp->rx_len = rxbytes; i2cp->i2c->CTRL_b.STA = true; - i2cp->i2c->TX_DATA = addr; + i2cp->i2c->TXDATA = addr; /* Waits for the operation completion or a timeout.*/ return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); @@ -295,7 +296,7 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, i2cp->tx_buffer = txbuf; i2cp->tx_len = txbytes; i2cp->i2c->CTRL_b.STA = true; - i2cp->i2c->TX_DATA = addr; + i2cp->i2c->TXDATA = addr; /* Waits for the operation completion or a timeout.*/ return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); @@ -356,7 +357,6 @@ msg_t i2c_lld_slave_receive_timeout(I2CDriver *i2cp, sysinterval_t timeout) { i2cp->rx_buffer = rxbuf; i2cp->rx_len = rxbytes; - i2cp->i2c->TX_DATA = addr; /* Waits for the operation completion or a timeout.*/ return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); @@ -389,7 +389,6 @@ msg_t i2c_lld_slave_transmit_timeout(I2CDriver *i2cp, sysinterval_t timeout) { i2cp->tx_buffer = txbuf; i2cp->tx_len = txbytes; - i2cp->i2c->TX_DATA = addr; /* Waits for the operation completion or a timeout.*/ return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h index 881e47d9ad..b0b11618ba 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h @@ -30,7 +30,7 @@ /*===========================================================================*/ /* Driver constants. */ /*===========================================================================*/ - +#include "sn32_i2c.h" /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ @@ -74,7 +74,7 @@ #if SN32_HAS_I2C0 #define SN32_I2C0_BASE SN_I2C0_BASE -#define SN32_I2C0 ((sn32_i2c_t *)SN_I2C_BASE) +#define SN32_I2C0 ((sn32_i2c_t *)SN_I2C0_BASE) #endif /** @@ -133,6 +133,11 @@ struct hal_i2c_driver { #endif /* End of the mandatory fields.*/ + /* @brief Thread waiting for I/O completion. */ + thread_reference_t thread; + /* @brief Current slave address without R/W bit. */ + i2caddr_t addr; + sn32_i2c_t *i2c; uint8_t *rx_buffer; uint8_t rx_len; diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/sn32_i2c.h b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/sn32_i2c.h index 2c43058d33..458c015449 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/sn32_i2c.h +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/sn32_i2c.h @@ -41,7 +41,7 @@ typedef struct { struct { uint32_t RX_DN : 1; uint32_t ACK_STAT : 1; - uint32_t NACK_STATE : 1; + uint32_t NACK_STAT : 1; uint32_t STOP_DN : 1; uint32_t START_DN : 1; uint32_t MST : 1; @@ -49,7 +49,7 @@ typedef struct { uint32_t SLV_TX_HIT : 1; uint32_t LOST_ARB : 1; uint32_t TIMEOUT : 1; - uint32_t : 5 + uint32_t : 5; uint32_t I2CIF : 1; uint32_t : 16; } STAT_b; From 3d3c2e88de92d37b56c6d8e4c9b826bd3542de86 Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Wed, 12 Apr 2023 15:07:13 +0300 Subject: [PATCH 17/22] sn32 i2c: typedefs update --- os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h index b0b11618ba..ed1a0c5852 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h @@ -139,11 +139,16 @@ struct hal_i2c_driver { i2caddr_t addr; sn32_i2c_t *i2c; + /* @brief Pointer to the buffer to put received data. */ uint8_t *rx_buffer; - uint8_t rx_len; - uint8_t *tx_buffer; - uint8_t tx_len; - uint8_t count; + /* @brief Number of bytes of data to receive. */ + size_t rx_len; + /* @brief Pointer to the buffer with data to send. */ + const uint8_t *tx_buffer; + /* @brief Number of bytes of data to send. */ + size_t tx_len; + /* @brief Current count of transmitted data. */ + size_t count; }; /* For compatibility, some LLDs could not export this.*/ From e013b998882c4e8b2a1394fcaa8543885f1d6725 Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Thu, 13 Apr 2023 09:56:54 +0300 Subject: [PATCH 18/22] sn32 i2c: fix tx routine in the handler --- os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c index a93cea9195..63929fe087 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c @@ -84,7 +84,7 @@ static inline void i2c_lld_irq_handler(I2CDriver * i2cp) { } } if (i2cp -> i2c -> STAT_b.ACK_STAT && i2cp -> tx_buffer && i2cp -> count < i2cp -> tx_len) { - i2cp -> tx_buffer[i2cp -> count++] = i2cp -> i2c -> TXDATA; + i2cp -> i2c -> TXDATA = i2cp -> tx_buffer[i2cp -> count++]; return; } } From 1700048777c5a3dd02e231aaeb19cbabfed698bc Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Thu, 20 Apr 2023 16:47:58 +0300 Subject: [PATCH 19/22] sn32 i2c: make transaction length accessible --- os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h index ed1a0c5852..db90f75e41 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h @@ -168,6 +168,22 @@ struct hal_i2c_driver { * @notapi */ #define i2c_lld_get_errors(i2cp) ((i2cp)->errors) +/** + * @brief Get rx length from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_rxbytes(i2cp) (i2cp)->rx_len +/** + * @brief Get tx length from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_txbytes(i2cp) (i2cp)->tx_len /*===========================================================================*/ /* External declarations. */ From af7b144f8e026ccd1b9c9f93ef4f9bd803881a72 Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Thu, 20 Apr 2023 16:53:57 +0300 Subject: [PATCH 20/22] sn32 i2c: make sure to reset count before transmission --- os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c index 63929fe087..596f1c369d 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c @@ -231,6 +231,7 @@ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, } i2cp->rx_buffer = rxbuf; i2cp->rx_len = rxbytes; + i2cp->count = 0; i2cp->i2c->CTRL_b.STA = true; i2cp->i2c->TXDATA = addr; @@ -295,6 +296,7 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, } i2cp->tx_buffer = txbuf; i2cp->tx_len = txbytes; + i2cp->count = 0; i2cp->i2c->CTRL_b.STA = true; i2cp->i2c->TXDATA = addr; @@ -357,6 +359,7 @@ msg_t i2c_lld_slave_receive_timeout(I2CDriver *i2cp, sysinterval_t timeout) { i2cp->rx_buffer = rxbuf; i2cp->rx_len = rxbytes; + i2cp->count = 0; /* Waits for the operation completion or a timeout.*/ return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); @@ -389,6 +392,7 @@ msg_t i2c_lld_slave_transmit_timeout(I2CDriver *i2cp, sysinterval_t timeout) { i2cp->tx_buffer = txbuf; i2cp->tx_len = txbytes; + i2cp->count = 0; /* Waits for the operation completion or a timeout.*/ return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); From 5220f75855c79ef20f6827c22a308b5c9618668a Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Mon, 29 May 2023 21:46:51 +0300 Subject: [PATCH 21/22] sn32 i2c: update the copyright notice --- os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c | 3 ++- os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h | 3 ++- os/hal/ports/SN32/LLD/SN32F2xx/I2C/sn32_i2c.h | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c index 596f1c369d..197ba3b285 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.c @@ -1,5 +1,6 @@ /* - ChibiOS - Copyright (C) 2023 1Conan + Copyright (C) 2023 1Conan + Copyright (C) 2023 Dimitris Mantzouranis Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h index db90f75e41..4c700e5b51 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/hal_i2c_lld.h @@ -1,5 +1,6 @@ /* - ChibiOS - Copyright (C) 2023 1Conan + Copyright (C) 2023 1Conan + Copyright (C) 2023 Dimitris Mantzouranis Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/sn32_i2c.h b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/sn32_i2c.h index 458c015449..9301d77bbd 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/sn32_i2c.h +++ b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/sn32_i2c.h @@ -1,5 +1,6 @@ /* - ChibiOS - Copyright (C) 2023 1Conan + Copyright (C) 2023 1Conan + Copyright (C) 2023 Dimitris Mantzouranis Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From a9e5bc680b1022206bab6bfea2116ef6a7e6a0d2 Mon Sep 17 00:00:00 2001 From: Dimitris Mantzouranis Date: Mon, 29 May 2023 21:47:39 +0300 Subject: [PATCH 22/22] sn32 i2c: remove BSP refs --- os/hal/ports/SN32/LLD/SN32F2xx/I2C/I2C.c | 368 ----------------------- os/hal/ports/SN32/LLD/SN32F2xx/I2C/I2C.h | 120 -------- 2 files changed, 488 deletions(-) delete mode 100644 os/hal/ports/SN32/LLD/SN32F2xx/I2C/I2C.c delete mode 100644 os/hal/ports/SN32/LLD/SN32F2xx/I2C/I2C.h diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/I2C.c b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/I2C.c deleted file mode 100644 index 53efe1baf1..0000000000 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/I2C.c +++ /dev/null @@ -1,368 +0,0 @@ -/******************** (C) COPYRIGHT 2017 SONiX ******************************* -* COMPANY: SONiX -* DATE: 2017/07 -* AUTHOR: SA1 -* IC: SN32F240B -* DESCRIPTION: I2C0 related functions. -*____________________________________________________________________________ -* REVISION Date User Description -* 1.0 2017/07/07 SA1 First release -* -*____________________________________________________________________________ -* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS TIME TO MARKET. -* SONiX SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL -* DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT OF SUCH SOFTWARE -* AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN -* IN CONNECTION WITH THEIR PRODUCTS. -*****************************************************************************/ - -/*_____ I N C L U D E S ____________________________________________________*/ -#include -#include -#include "I2C.h" - -/*_____ D E C L A R A T I O N S ____________________________________________*/ -uint8_t bI2C_RxFIFO[I2C_RX_FIFO_LENGTH]; -uint8_t bI2C_TxFIFO[I2C_TX_FIFO_LENGTH] = {0}; -uint8_t bI2C_RxFIFO_cnts, bI2C_Rx_cnts; -uint8_t bI2C_TxFIFO_cnts, bI2C_Tx_cnts; -uint8_t *bTX_ptr; -uint8_t EEPROM_ADR_H, EEPROM_ADR_L; -uint8_t EEPROM_WR; // 0 : write - // 1 : read -uint8_t Busy = 1, Error = 0; -uint8_t Read_Down = 0; -uint8_t Send_Address; -uint8_t temp = 0; -volatile uint8_t Timeout = 0; - - -/*_____ D E F I N I T I O N S ______________________________________________*/ - - -/*_____ M A C R O S ________________________________________________________*/ - - -/*_____ F U N C T I O N S __________________________________________________*/ -/***************************************************************************** -* Function : I2C_Init -* Description : Initialization of I2C -* Input : None -* Output : None -* Return : None -* Note : None -*****************************************************************************/ -void I2C_Init (void) -{ - SN_SYS1->AHBCLKEN_b.I2C0CLKEN = 1; //Enables HCLK for I2C0 - - //I2C speed - SN_I2C0->SCLHT = I2C0_SCLHT; - SN_I2C0->SCLLT = I2C0_SCLLT; - - SN_I2C0->CTRL_b.I2CEN = 1; //Enable I2C - - //===NVIC=== - NVIC_ClearPendingIRQ(I2C0_IRQn); - NVIC_EnableIRQ(I2C0_IRQn); -} -/***************************************************************************** -* Function : I2C_Start -* Description : transmit a START bit -* Input : None -* Output : None -* Return : None -* Note : None -*****************************************************************************/ -void I2C_Start(void) -{ - SN_I2C0->CTRL_b.STA = 1; -} -/***************************************************************************** -* Function : I2C_Stop -* Description : transmit a STOP condition in master mode -* Input : None -* Output : None -* Return : None -* Note : None -*****************************************************************************/ -void I2C_Stop(void) -{ - SN_I2C0->CTRL_b.STO = 1; -} -/***************************************************************************** -* Function : I2C_Read -* Description : read N Byte data from EEPROM -* Input : eeprom_adr - data word address -* : read_num - byte length -* Output : None -* Return : OK or Fail -* Note : None -*****************************************************************************/ -uint8_t I2C_Read(uint16_t eeprom_adr, uint8_t read_num) -{ - bI2C_Rx_cnts = 0; - - EEPROM_ADR_H = eeprom_adr >> 8; //data word address low byte - EEPROM_ADR_L = eeprom_adr & 0x00ff; //data word address high byte - - bI2C_RxFIFO_cnts = read_num; //byte length - - Busy = 1; - - EEPROM_WR = 0; //write - - I2C_Start(); //I2C start - - SysTick->CTRL = 0x7; //Enable SysTick timer and interrupt - - Send_Address = 1; //data word address setting flag - - while(Busy == 1 && Timeout == 0); - - SysTick->CTRL = 0x0; //Disable SysTick timer and interrupt - - if(Error == 1 || Timeout == 1) return FALSE; - - #if (EEPROM_less_than_32K == 0) - - SN_I2C0->TXDATA = EEPROM_ADR_H; //data word address high byte - - SysTick->CTRL = 0x7; //Enable SysTick timer and interrupt - - Busy = 1; - - while(Busy == 1 && Timeout == 0); - - SysTick->CTRL = 0x0; //Disable SysTick timer and interrupt - - if(Error == 1 || Timeout == 1) return FALSE; - - #endif - - SN_I2C0->TXDATA = EEPROM_ADR_L; //data word address low byte - - SysTick->CTRL = 0x7; //Enable SysTick timer and interrupt - - Busy = 1; - - while(Busy == 1 && Timeout == 0); - - SysTick->CTRL = 0x0; //Disable SysTick timer and interrupt - - if(Error == 1 || Timeout == 1) return FALSE; - - Read_Down = 0; - - Send_Address = 0; - - EEPROM_WR = 1; //read - - I2C_Start(); //I2C start - - SysTick->CTRL = 0x7; //Enable SysTick timer and interrupt - - while(Read_Down == 0 && Timeout == 0); - - SysTick->CTRL = 0x0; //Disable SysTick timer and interrupt - - Read_Down = 0; - - if(Error == 1 || Timeout == 1) return FALSE; - - return TRUE; -} -/***************************************************************************** -* Function : I2C_Write -* Description : write N Byte data to EEPROM -* Input : eeprom_adr - data word address -* : write_num - byte length -* Output : None -* Return : OK or Fail -* Note : None -*****************************************************************************/ -uint8_t I2C_Write(uint16_t eeprom_adr, uint8_t write_num) -{ - Timeout = 0; - - bI2C_Tx_cnts = 0; - - bTX_ptr = &bI2C_TxFIFO[0]; //write data buffer - - EEPROM_ADR_H = eeprom_adr >> 8; //data word address high byte - - EEPROM_ADR_L = eeprom_adr & 0x00ff; //data word address low byte - - bI2C_TxFIFO_cnts = write_num; //byte length - - Busy = 1; - - EEPROM_WR = 0; //write - - SysTick->CTRL = 0x7; //Enable SysTick timer and interrupt - - I2C_Start(); //I2C start - - Send_Address = 1; //data word address setting flag - - while(Busy == 1 && Timeout == 0); - - SysTick->CTRL = 0x0; //Disable SysTick timer and interrupt - - if(Error == 1 || Timeout == 1) return FALSE; - - #if (EEPROM_less_than_32K == 0) - - SN_I2C0->TXDATA = EEPROM_ADR_H; //data word address high byte - - SysTick->CTRL = 0x7; //Enable SysTick timer and interrupt - - Busy = 1; - - while(Busy == 1 && Timeout == 0); - - SysTick->CTRL = 0x0; //Disable SysTick timer and interrupt - - if(Error == 1 || Timeout == 1) return FALSE; - - #endif - - SN_I2C0->TXDATA = EEPROM_ADR_L; //data word address low byte - - SysTick->CTRL = 0x7; //Enable SysTick timer and interrupt - - Busy = 1; - - while(Busy == 1 && Timeout == 0); - - if(Error == 1 || Timeout == 1 ) return FALSE; - - SysTick->CTRL = 0x0; //Disable SysTick timer and interrupt - - Send_Address = 0; - - SN_I2C0->TXDATA = *bTX_ptr++; //write data - - SysTick->CTRL = 0x7; //Enable SysTick timer and interrupt - - Busy = 1; - - while(Busy == 1 && Timeout == 0); - - if(Error == 1 || Timeout == 1) return FALSE; - - SysTick->CTRL = 0x0; //Disable SysTick timer and interrupt - - Busy = 1; - - I2C_Stop(); - - SysTick->CTRL = 0x7; //Enable SysTick timer and interrupt - - while(Busy == 1 && Timeout == 0); - - if(Error == 1 || Timeout == 1) return FALSE; - - SysTick->CTRL = 0x0; //Disable SysTick timer and interrupt - - return TRUE; -} - -/***************************************************************************** -* Function : I2C_IRQHandler -* Description : I2C interrupt service routine -* Input : None -* Output : None -* Return : None -* Note : None -*****************************************************************************/ -__irq void I2C0_IRQHandler(void) -{ - if(((SN_I2C0->STAT) & (mskI2C_LOST_ARB_LOST_ARBITRATION)) == Lost_Arbitration) - { - SN_I2C0->STAT_b.I2CIF = 1; - SN_I2C0->CTRL_b.I2CEN = 0; //Disable I2C - SN_I2C0->CTRL_b.I2CEN = 1; //Enable I2C - I2C_Start(); //Re-start - } - - /* Stop Done */ - else if(((SN_I2C0->STAT) & (mskI2C_STA_MASTER_STA_STO)) == STOP_DONE) - { - Busy = 0; - SN_I2C0->STAT_b.I2CIF = 1; - if(EEPROM_WR == 1) - Read_Down = 1; - } - else - { - SN_I2C0->STAT_b.I2CIF = 1; - - switch (SN_I2C0->STAT) - { - case (Lost_Arbitration | mskI2C_MST_MASTER): - I2C_Start(); - break; - - /* RX with ACK/NACK transfer is down */ - case (RX_DONE | mskI2C_MST_MASTER): - bI2C_RxFIFO[bI2C_Rx_cnts++] = SN_I2C0->RXDATA; - if(bI2C_Rx_cnts < (bI2C_RxFIFO_cnts - 1)) - SN_I2C0->CTRL_b.ACK = 1; - else if(bI2C_Rx_cnts == (bI2C_RxFIFO_cnts - 1)) - SN_I2C0->CTRL_b.NACK = 1; - else if(bI2C_Rx_cnts == bI2C_RxFIFO_cnts) - I2C_Stop(); - Busy = 0; - break; - - /* SLA+W or Data has been transmitted and ACK has been received */ - case (ACK_DONE | mskI2C_MST_MASTER): - if(EEPROM_WR == 1) - { - Busy = 0; - if(bI2C_RxFIFO_cnts == 1) - SN_I2C0->CTRL_b.NACK = 1; - else - SN_I2C0->CTRL_b.ACK = 1; - } - if(EEPROM_WR == 0) - { - if(Send_Address == 0) - { - bI2C_Tx_cnts++; - if(bI2C_Tx_cnts < bI2C_TxFIFO_cnts) - SN_I2C0->TXDATA = *bTX_ptr++; - else if(bI2C_Tx_cnts == bI2C_TxFIFO_cnts) - Busy = 0; - } - else - Busy = 0; - } - break; - - /* SLA+W or Data has been transmitted and NACK has been received */ - case (NACK_DONE | mskI2C_MST_MASTER): - SN_I2C0->CTRL_b.STO = 1; - Error = 1; - break; - - /* START has been transmitted and prepare SLA+W/SLA+R */ - case (START_DONE | mskI2C_MST_MASTER): - #if (EEPROM_less_than_32K == 1) - SN_I2C0->TXDATA = Device_ADDRESS | (EEPROM_ADR_H << 1) | EEPROM_WR; - #else - SN_I2C0->TXDATA = Device_ADDRESS | EEPROM_WR; - #endif - break; - - default: - SN_I2C0->CTRL_b.I2CEN = 0; - SN_I2C0->CTRL_b.I2CEN = 1; - SN_I2C0->CTRL_b.STA = 1; - break; - } - } -} - diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/I2C.h b/os/hal/ports/SN32/LLD/SN32F2xx/I2C/I2C.h deleted file mode 100644 index 7835a05b2c..0000000000 --- a/os/hal/ports/SN32/LLD/SN32F2xx/I2C/I2C.h +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef __SN32F2XX_I2C_H -#define __SN32F2XX_I2C_H - -/*_____ I N C L U D E S ____________________________________________________*/ -#include - -/*_____ D E F I N I T I O N S ______________________________________________*/ -#define EEPROM_less_than_32K 1 // 1: for EEPROM size less than 32K bits (4096x8) - // 0: for EEPROM size more than or equal to 32K bits (4096x8) - -#define Device_ADDRESS 0xA0 -#define Lost_Arbitration 0x100 -#define SLAVE_ADDRESS_HIT_TX 0x80 -#define SLAVE_ADDRESS_HIT_RX 0x40 -#define START_DONE 0x10 -#define STOP_DONE 0x08 -#define NACK_DONE 0x04 -#define ACK_DONE 0x02 -#define RX_DONE 0x01 - -/* I2C n SCL High Time register <(I2Cn_SCLHT> (0x20) */ -#define I2C0_SCLHT 14 //[7:0], Count for SCL High Period time - //SCL High Period Time = (SCLH+1) * I2C0_PCLK cycle -#define I2C0_SCLLT 14 //[7:0], Count for SCL Low Period time - //SCL Loq Period Time = (SCLL+1) * I2C0_PCLK cycle - - -/* I2C n Status register (0x04) */ - //[0:0]RX done status -#define I2C_RX_DN_NO_HANDSHAKE 0 //No RX with ACK/NACK transfer -#define I2C_RX_DN_HANDSHAKE 1 //8-bit RX with ACK/NACK transfer is done -#define mskI2C_RX_DN_NO_HANDSHAKE (I2C_RX_DN_NO_HANDSHAKE<<0) -#define mskI2C_RX_DN_HANDSHAKE (I2C_RX_DN_HANDSHAKE<<0) - - //[1:1]ACK done status -#define I2C_ACK_STAT_NO_RECEIVED_ACK 0 //Not received an ACK -#define I2C_ACK_STAT_RECEIVED_ACK 1 //Received an ACK -#define mskI2C_ACK_STAT_NO_RECEIVED_ACK (I2C_ACK_STAT_NO_RECEIVED_ACK<<1) -#define mskI2C_ACK_STAT_RECEIVED_ACK (I2C_ACK_STAT_RECEIVED_ACK<<1) - - - //[2:2]NACK done status -#define I2C_NACK_STAT_NO_RECEIVED_NACK 0 //Not received a NACK -#define I2C_NACK_STAT_RECEIVED_NACK 1 //Received a NACK -#define mskI2C_NACK_STAT_NO_RECEIVED_NACK (I2C_NACK_STAT_NO_RECEIVED_NACK<<2) -#define mskI2C_NACK_STAT_RECEIVED_NACK (I2C_NACK_STAT_RECEIVED_NACK<<2) - - //[3:3]Stop done status -#define I2C_STOP_DN_NO_STOP 0 //No STOP bit -#define I2C_STOP_DN_STOP 1 //MASTER mode, a STOP condition was issued - //SLAVE mode, a STOP condition was received -#define mskI2C_STOP_DN_NO_STOP (I2C_STOP_DN_NO_STOP<<3) -#define mskI2C_STOP_DN_STOP (I2C_STOP_DN_STOP<<3) - - //[4:4]Start done status -#define I2C_START_DN_NO_START 0 //No START bit -#define I2C_START_DN_START 1 //MASTER mode, a START bit was issued - //SLAVE mode, a START bit was received -#define mskI2C_START_DN_NO_START (I2C_START_DN_NO_START<<4) -#define mskI2C_START_DN_START (I2C_START_DN_START<<4) - - -#define I2C_MST_SLAVE 0 //[5:5]Master/Slave status -#define I2C_MST_MASTER 1 -#define mskI2C_MST_SLAVE (I2C_MST_SLAVE<<5) -#define mskI2C_MST_MASTER (I2C_MST_MASTER<<5) - -#define mskI2C_STA_STA_STO ((I2C_START_DN_START<<4)|(I2C_STOP_DN_STOP<<3)) -#define mskI2C_STA_MASTER_STA_STO ((I2C_MST_MASTER<<5)|(I2C_START_DN_START<<4)|(I2C_STOP_DN_STOP<<3)) - - - //[6:6]Slave address check -#define I2C_SLV_RX_NO_MATCH_ADDR 0 //No matched slave address -#define I2C_SLV_RX_MATCH_ADDR 1 //Slave address hit, and is called for RX in slave mode -#define mskI2C_SLV_RX_NO_MATCH_ADDR (I2C_SLV_RX_NO_MATCH_ADDR<<6) -#define mskI2C_SLV_RX_MATCH_ADDR (I2C_SLV_RX_MATCH_ADDR<<6) - - //[7:7]Slave address check -#define I2C_SLV_TX_NO_MATCH_ADDR 0 //No matched slave address -#define I2C_SLV_TX_MATCH_ADDR 1 //Slave address hit, and is called for TX in slave mode. -#define mskI2C_SLV_TX_NO_MATCH_ADDR (I2C_SLV_TX_NO_MATCH_ADDR<<7) -#define mskI2C_SLV_TX_MATCH_ADDR (I2C_SLV_TX_MATCH_ADDR<<7) - - //[8:8]Lost arbitration -#define I2C_LOST_ARB_NO_LOST 0 //Not lost arbitration -#define I2C_LOST_ARB_LOST_ARBITRATION 1 //Lost arbitration -#define mskI2C_LOST_ARB_NO_LOST (I2C_LOST_ARB_NO_LOST<<8) -#define mskI2C_LOST_ARB_LOST_ARBITRATION (I2C_LOST_ARB_LOST_ARBITRATION<<8) - - //[9:9]Time-out status -#define I2C_TIMEOUT_NO_TIMEOUT 0 //No Timeout -#define I2C_TIMEOUT_TIMEOUT 1 //Timeout -#define mskI2C_TIMEOUT_TIMEOUT (I2C_TIMEOUT_TIMEOUT<<9) -#define mskI2C_TIMEOUT_NO_TIMEOUT (I2C_TIMEOUT_NO_TIMEOUT<<9) - - //[15:15]I2C Interrupt flag -#define I2C_I2CIF_STAUS_NO_CHANGE 0 //I2C status doesn’t change -#define I2C_I2CIF_INTERRUPT 1 //Read, I2C status changes - //Write, Clear this flag -#define mskI2C_I2CIF_STAUS_NO_CHANGE (I2C_I2CIF_STAUS_NO_CHANGE<<15) -#define mskI2C_I2CIF_INTERRUPT (I2C_I2CIF_INTERRUPT<<15) - - -//Recv FIFO -#define I2C_RX_FIFO_LENGTH 32 - -//TX FIFO -#define I2C_TX_FIFO_LENGTH 32 - -/*_____ M A C R O S ________________________________________________________*/ - - -/*_____ D E C L A R A T I O N S ____________________________________________*/ - -void I2C_Init(void); -void I2C_Start(void); -void I2C_Stop(void); -uint8_t I2C_Read(uint16_t eeprom_adr, uint8_t read_num); -uint8_t I2C_Write(uint16_t eeprom_adr, uint8_t write_num); -#endif /*__SN32F2XX_I2C_H*/