arch/arm/src/stm32/stm32_i2cslave_v2.c: add STM32 I2C Slave support for the v2 ip core

This commit adds the lowerhalf driver support for the I2C Slave.
While not currently ideal, it is compatible with the upperhalf i2c slave driver.
A workqueue can be used to delegate the isr work to the upperhalf driver.
But keep in mind wq introduces a lot of delay and in certain scenarios,
it is better to write your own better upperhalf driver.

Signed-off-by: Stepan Pressl <pressl.stepan@gmail.com>
This commit is contained in:
Pressl, Stepan
2025-07-02 01:59:46 +08:00
committed by Xiang Xiao
parent 3d37e85b13
commit 55bef681e1
6 changed files with 934 additions and 5 deletions
@@ -2,7 +2,7 @@
I2C Device Drivers
==================
- ``include/nuttx/i2c/i2c_master.h`` and ``include/nuttx/i2c/i2c_slave.h``.
- ``include/nuttx/i2c/i2c_master.h``
All structures and APIs needed to work with I2C drivers are provided in
this header file.
@@ -22,10 +22,59 @@ I2C Device Drivers
- **Examples**: ``arch/z80/src/ez80/ez80_i2c.c``,
``arch/z80/src/z8/z8_i2c.c``, etc.
- ``struct i2c_slaveops_s``. Each I2C slave device driver must implement
========================
I2C Slave Device Drivers
========================
- ``include/nuttx/i2c/i2c_slave.h``
Declaration of all macros and ops and ``int i2c_slave_register``,
used to bind the lowerhalf driver to the upper one and register an
I2C slave device.
- **Binding I2C Slave Drivers**. Use ``int i2c_slave_register`` in your BSP
to register your slave device. Before that, you need to get the instance
of ``struct i2c_slave_s`` from the hardware-specific I2C Slave driver.
- **Using I2C Slave in your Application**. I2C slave drivers are normally directly
accessed by user code, We can read and write to device nodes using posix
interfaces. The device is registered as ``/dev/i2cslv%d``, where ``%d``
is a number provided in the BSP initialization phase.
- **BSP initialization example (STM32 I2C Slave)**:
.. code-block:: c
int stm32_i2cs_setup(void)
{
i2cs = stm32_i2cbus_slaveinitialize(1);
if (i2cs != NULL)
{
return -ENOENT;
}
return i2c_slave_register(i2cs, 1, 0x01, 7);
}
I2C Slave Driver API
--------------------
.. c:function:: int i2c_slave_register(FAR struct i2c_slave_s *dev, int bus, int addr, int nbit);
Bind the lowerhalf ``dev`` driver to the upperhalf driver and register
a device. The name of the device is ``/dev/i2cslv%d``, where ``%d`` is
bus. The address the I2C slave is specified in ``addr``.
``nbit`` is either 7 or 10 and it specifies the address format.
- ``struct i2c_slaveops_s``. Each I2C slave lowerhalf driver must implement
an instance of ``struct i2c_slaveops_s``. That structure defines a call
table with the following methods:
- **Binding I2C Slave Drivers**. I2C slave drivers are normally directly
accessed by user code, We can read and write to device nodes using posix
interfaces.
- ``setownaddress``: the address the slave responds to,
- ``write``: sets the tx buffer pointer,
- ``read``: sets the rx buffer pointer,
- ``registercallback``: registers the callback function which should
be called from a service routine. Signals the received or fully transferred
I2C packet.
- ``setup``: initializes the peripheral,
- ``shutdown``: shutdowns the peripheral.
+3
View File
@@ -82,6 +82,9 @@ if(CONFIG_STM32_HAVE_IP_I2C_V1)
endif()
elseif(CONFIG_STM32_HAVE_IP_I2C_V2)
list(APPEND SRCS stm32_i2c_v2.c)
if(CONFIG_STM32_I2C_SLAVE)
list(APPEND SRCS stm32_i2cslave_v2.c)
endif()
endif()
if(CONFIG_USBDEV)
+47
View File
@@ -3024,6 +3024,24 @@ config STM32_I2C3
depends on STM32_HAVE_I2C3
select STM32_I2C
config STM32_I2C1_SLAVE
bool "I2C1 Slave"
default n
depends on !STM32_I2C1 && I2C_SLAVE
select STM32_I2C_SLAVE
config STM32_I2C2_SLAVE
bool "I2C2 Slave"
default n
depends on STM32_HAVE_I2C2 && !STM32_I2C2 && I2C_SLAVE
select STM32_I2C_SLAVE
config STM32_I2C3_SLAVE
bool "I2C3 Slave"
default n
depends on STM32_HAVE_I2C3 && !STM32_I2C3 && I2C_SLAVE
select STM32_I2C_SLAVE
config STM32_LPTIM1
bool "LPTIM1"
default n
@@ -3421,6 +3439,10 @@ config STM32_I2C
bool
default n
config STM32_I2C_SLAVE
bool
default n
config STM32_CAN
bool
default n
@@ -10720,6 +10742,31 @@ config STM32_I2C_DMA
endmenu
menu "I2C Slave Configuration"
depends on STM32_I2C_SLAVE
config STM32_I2C_SLAVE_DEFAULT_TX
hex "Default TX byte to be sent when the TX buffer is empty"
default 0xFF
config STM32_I2C_SLAVE_USEWQ
bool "Use work queue to delegate the isr completion status"
default n
---help---
With the current upperhalf I2C slave driver implementation, the user
should delegate the callback completion status using a work queue.
However, work queues introduce a delay, so in certain scenarios
it is better to use a custom driver without using a work queue.
config STM32_I2C_SLAVE_RETRANSFER
bool "The frame is retransferred when stop is issued beforehand"
default n
---help---
If stop is issued before the whole frame is transferred,
the tx pointer is reset to 0.
endmenu
menu "SDIO Configuration"
depends on STM32_SDIO
+3
View File
@@ -65,6 +65,9 @@ CHIP_CSRCS += stm32_i2c.c
endif
else ifeq ($(CONFIG_STM32_HAVE_IP_I2C_V2),y)
CHIP_CSRCS += stm32_i2c_v2.c
ifeq ($(CONFIG_STM32_I2C_SLAVE),y)
CHIP_CSRCS += stm32_i2cslave_v2.c
endif
endif
ifeq ($(CONFIG_USBDEV),y)
+34
View File
@@ -88,4 +88,38 @@ struct i2c_master_s *stm32_i2cbus_initialize(int port);
int stm32_i2cbus_uninitialize(struct i2c_master_s *dev);
/****************************************************************************
* Name: stm32_i2cbus_slaveinitialize
*
* Description:
* Initialize the selected I2C port as a slave. Return an unique
* instance of struct i2c_slave_s.
*
* Input Parameters:
* Port number (for hardware that has multiple I2C interfaces)
*
* Returned Value:
* Valid I2C device structure reference on success; a NULL on failure
*
****************************************************************************/
struct i2c_slave_s *stm32_i2cbus_slaveinitialize(int port);
/****************************************************************************
* Name: stm32_i2cbus_uninitialize
*
* Description:
* De-initialize the selected I2C port, and power down the device.
*
* Input Parameters:
* Device structure as returned by the stm32_i2cbus_initialize()
*
* Returned Value:
* OK on success, ERROR when internal reference count mismatch or dev
* points to invalid hardware device.
*
****************************************************************************/
int stm32_i2cbus_uninitialize(struct i2c_master_s *dev);
#endif /* __ARCH_ARM_SRC_STM32_STM32_I2C_H */
File diff suppressed because it is too large Load Diff