Skip to content

Conversation

@LinjingZhang
Copy link

@LinjingZhang LinjingZhang commented Dec 16, 2025

Summary

Implement i2c target (slave) based on mpy extmod.momachine
Only 0 address is supported!

TODO:
8 bit/16 bit Memory Access mode:
https://jirard.intra.infineon.com/browse/MICROPY-82
Explore mpy ROM level feature
https://jirard.intra.infineon.com/browse/MICROPY-83

Testing

Using example in micropython doc:
Target - PSoC edge:

from machine import I2CTarget

# Define an IRQ handler, for I2C events.
def irq_handler(i2c_target):
    flags = i2c_target.irq().flags()
    if flags & I2CTarget.IRQ_END_READ:
        print("controller read target at addr", i2c_target.memaddr)
    if flags & I2CTarget.IRQ_END_WRITE:
        print("controller wrote target at addr", i2c_target.memaddr)

# Create the I2C target and register to receive default events.
mem = bytearray(8)
i2c = I2CTarget(addr=67, mem=mem)
i2c.irq(irq_handler)
image

Controller - PSoC 6:

from machine import I2C
scl_slave_pin = "P0_2"
sda_slave_pin = "P0_3"

i2c = I2C(scl=scl_slave_pin, sda=sda_slave_pin, freq=400000)


devices = i2c.scan()
print("Found devices:", [hex(d) for d in devices])

i2c.writeto(0x43, b'Hello')


data = i2c.readfrom(0x43, 8)
print("Read:", data)
image

Verify with logic analyzer:
image

Trade-offs and Alternatives

I've added a few modules/functions, but these are the minimum I need to use extmod I2CTarget.

Signed-off-by: zhanglinjing <Linjing.Zhang@infineon.com>
Signed-off-by: zhanglinjing <Linjing.Zhang@infineon.com>
Signed-off-by: zhanglinjing <Linjing.Zhang@infineon.com>
Signed-off-by: zhanglinjing <Linjing.Zhang@infineon.com>
Signed-off-by: zhanglinjing <Linjing.Zhang@infineon.com>
@LinjingZhang LinjingZhang marked this pull request as ready for review December 17, 2025 10:00
Copy link
Member

@jaenrig-ifx jaenrig-ifx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quite a lot of progress :) Well done, looks quite good as far as I can judge.
Some questions and minor discussion or things we can polish before merging to main.


LDFLAGS += -Wl,-Map,$(BUILD)/$(MPY_APP_NAME).map

# Ensure assembly file is compiled with correct flags
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain this contribution regarding the assembler flags?

#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "KIT_PSE84_AI"

#define MICROPY_GC_HEAP_SIZE (315 * 1024) // 315 KB
#define MICROPY_GC_HEAP_SIZE (32 * 1024) // TODO: 315 was too big for non-secure RAM?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this relates to the I2C ?

return 0;
}

#if MICROPY_ENABLE_GC
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain this enablement of the garbage collector?

#define MICROPY_PY_BUILTINS_SLICE (1)

// Disable optional modules, only use bytearray
#define MICROPY_PY_ARRAY (0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are all these macros related to the I2C enablement?
Please remove all the defines that are not related to what you are working on, and you are not aware of what they control.
Usually by default, they have default values in "py/mpconfig.h" which should be consciously overwritten.


// Forward declare MAX_I2C from mpconfigboard.h
#ifndef MAX_I2C
#define MAX_I2C MICROPY_HW_MAX_I2C
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no default definition of MICROPY_HW_MAX_I2C or? If not MAX_I2C is defined this will not compile.

In file included from ../../extmod/machine_i2c_target.c:240:
../../ports/psoc-edge/machine_i2c_target.c:59:17: error: 'MICROPY_HW_MAX_I2C' undeclared here (not in a function); did you mean 'MICROPY_HW_MCU_NAME'?
   59 | #define MAX_I2C MICROPY_HW_MAX_I2C
      |                 ^~~~~~~~~~~~~~~~~~
../../ports/psoc-edge/machine_i2c_target.c:62:56: note: in expansion of macro 'MAX_I2C'
   62 | static machine_i2c_target_obj_t machine_i2c_target_obj[MAX_I2C];
      |                                                        ^~~~~~~
../../ports/psoc-edge/machine_i2c_target.c:62:33: error: 'machine_i2c_target_obj' defined but not used [-Werror=unused-variable]
   62 | static machine_i2c_target_obj_t machine_i2c_target_obj[MAX_I2C];
      |                                 ^~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
-e See https://github.com/micropython/micropython/wiki/Build-Troubleshooting
make: *** [../../py/mkrules.mk:101: build-KIT_PSE84_AI/extmod/machine_i2c_target.o] Error 1

.useRxFifo = false, // PDL recommends false for slave to avoid side effects
.useTxFifo = true,
.slaveAddress = addr,
.slaveAddressMask = (addrsize == 7) ? 0xFEU : 0xFCU, // Mask for 7-bit or 10-bit
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mmm is that mask right? if addrsize is 7 the mask is 0b11111110 and if not 0b11111100. How does this work?

}

static void mp_machine_i2c_target_irq_config(machine_i2c_target_obj_t *self, unsigned int trigger) {
// IRQ configuration already handled in init
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is not needed? How is the passed trigger by the user updated in the pdl interrupt handler?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants