-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
New port for Infineon PSoC6 controllers #16705
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
The following modules are enabled: - machine.ADC - machine.ADCBlock - machine.I2C - machine.I2S - machine.Pin - machine.PWM - machine.RTC - machine.SDCard - machine.SPI - machine.Timer - machine.UART - machine.WDT - network.WLAN - os.vfs (LFS2 and FAT) Evaluation boards initially integrated in the port: - CY8CPROTO-062-4343W - CY8CPROTO-063-BLE - CY8CKIT-062S2-AI Signed-off-by: enriquezgarc <enriquezgarcia.external@infineon.com>
Signed-off-by: enriquezgarc <enriquezgarcia.external@infineon.com>
Signed-off-by: enriquezgarc <enriquezgarcia.external@infineon.com>
Signed-off-by: enriquezgarc <enriquezgarcia.external@infineon.com>
Signed-off-by: enriquezgarc <enriquezgarcia.external@infineon.com>
Signed-off-by: enriquezgarc <enriquezgarcia.external@infineon.com>
Signed-off-by: enriquezgarc <enriquezgarcia.external@infineon.com>
Signed-off-by: enriquezgarc <enriquezgarcia.external@infineon.com>
Signed-off-by: enriquezgarc <enriquezgarcia.external@infineon.com>
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #16705 +/- ##
==========================================
- Coverage 98.59% 98.53% -0.06%
==========================================
Files 167 169 +2
Lines 21599 21822 +223
==========================================
+ Hits 21295 21502 +207
- Misses 304 320 +16 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Code size report:
|
Great work. Modify Try to check code formatting by |
Thanks for you review @IhorNehrutsa ! You mean to add the psoc port and boards to that tests no? That we can do. With the code formatting you mean after modifying the test? |
ports/psoc6/machine_pwm.c
Outdated
|
||
static void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { | ||
machine_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); | ||
mp_printf(print, "frequency=%u duty_cycle=%f", self->fz, (double)self->duty); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mp_printf(print, "PWM(Pin(%s),freq=%u, duty_u16=%f", self->pin, self->fz, (double)self->duty);
As a test code something like:
>>> pwm = PWM(Pin(XXX), freq=5000, duty_u16=3272)
>>> pwm2 = eval(str(pwm))
>>> pwm
PWM(Pin(XXX), freq=5000, duty_u16=3272)
>>> pwm2
PWM(Pin(XXX), freq=5000, duty_u16=3272)
EDIT: Use similar test codes for other objects. Pin, ADC, UART etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a requirement/standard for machine classes that the human readable string representation of an object needs to match its constructor call?
In our case, this would use string pin labels (i.e. "P12_6") instead of pin objects (Pin(x)):
Virtual File System: mounted at '/' with LFS2 format in internal flash.
MicroPython 104dbf82c-dirty on 2025-02-06; CY8CPROTO-063-BLE with PSoC63
Type "help()" for more information.
>>> from machine import PWM
>>> pwm_string= "PWM(\"P12_6\", freq=5000, duty_u16=3272)"
>>> pwm =eval(str(pwm_string))
>>> pwm
PWM("P12_6",freq=5000, duty_u16=3272.000000)
>>>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please take a look at the discussion in #4379.
Is this a requirement/standard for machine classes that the human-readable string representation of an object needs to match its constructor call?
IMHO: Yes. This allows save/restore, send/receive the objects.
Also:
PWM(Pin("P12_6"), freq=5000, duty_u16=3272) - is preferred.
PWM("P12_6", freq=5000, duty_u16=3272) - is possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understood. Then we have to review all the rest of machine classes, if we want to be consistent.
Regarding the Pin() vs label. We will stick to "the possible" as long as possible 😜, as the the Pin()
object creation as in our port was rather artificial... due to the GPIO handling of the underlying PSOC6 apis for the different hw (machine) peripherals.
We thought on the impact in portability (across ports), but at the end of the day, for each port, the pin definition is specific... Therefore, we did not see the benefit on making our port code more intricated.
If this is a requirement then we have to refactor and redesign the machine classes... If we could skip that, at least for now, it would be great 🤞
Yes, add. |
Perfect. We will start working on those changes. @IhorNehrutsa is your review completed? Or just have started from the PWM module? |
ports/psoc6/machine_wdt.c
Outdated
void mod_wdt_deinit() { | ||
cyhal_wdt_stop(&psoc6_wdt); | ||
cyhal_wdt_free(&psoc6_wdt); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wdt_deinit
was rejected here :
ESP32/machine_wdt.c: Add WDT.deinit() method. #6631
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The deinit is not exposed at user API level.
This function is called once the device is gets out of the REPL loop in the main.c (usually upon soft-reset):
https://github.com/Infineon/micropython/blob/ports-psoc6-pr-new/ports/psoc6/main.c#L225
As part of the macro MICROPY_PORT_DEINIT_FUNC
:
https://github.com/Infineon/micropython/blob/ports-psoc6-pr-new/ports/psoc6/mpconfigport.h#L207-L208
Which calls them machine_deinit()
:
https://github.com/Infineon/micropython/blob/ports-psoc6-pr-new/ports/psoc6/modmachine.c#L124-L139
Its removal will prevent having a cleaned up post-reset operating system for the users, in which the watchdog could only be disabled through hard-reset.
I would need to understand how this is handled at other ports better, and the overall implications, before just getting rid of it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't rush to delete; may wait for maintainers.
IMHO, okay. I have reviewed PWM and WDT. |
ports/psoc6/machine_pwm.c
Outdated
self->duty_type = DUTY_U16; | ||
} | ||
|
||
if (args[ARG_duty_ns].u_int != VALUE_NOT_SET) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
else if (args[ARG_duty_ns].u_int != VALUE_NOT_SET) {
HERE
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I go it :)
I tried, but we would need to implement Anyway, we have our own ci test for pmw: In the long run I assume the goal is to generalize and reuse as much the common tests for all ports. If this is a must for the PR to be approved, we can/should implement it. It should be rather quick unless we fail to achieve the pwm and time_pulse_us performance required for that test. |
Are all 183 files needed in PR? |
I would say so. We could argue about a few of them, but they are all used. For example, the "mtb-libs" is used for integration of the toolchain and the dependencies of the PSOC6. We could make that a submodule, but it needs to be retrieved (initialized and updated as submodule) to build the port. The tests are all running under our CI HIL (hardware-in-the-loop). But of course, they aren´t needed for building the PSOC6 MicroPython binary. Some files under "tools/psoc6" might be only used by our fork ci hardware-in-the-loop workflow. If some of those are bothering, we could keep them in our fork only... |
Signed-off-by: enriquezgarc <enriquezgarcia.external@infineon.com>
I won´t yet push to this branch until you consider the first review iteration done. |
ports/psoc6/machine_pwm.c
Outdated
static cy_rslt_t pwm_freq_duty_set(cyhal_pwm_t *pwm_obj, uint32_t fz, float duty_cycle) { | ||
return cyhal_pwm_set_duty_cycle(pwm_obj, duty_cycle * 100, fz); // duty_cycle in percentage | ||
} | ||
|
||
static inline cy_rslt_t pwm_duty_set_ns(cyhal_pwm_t *pwm_obj, uint32_t fz, uint32_t pulse_width) { | ||
return cyhal_pwm_set_period(pwm_obj, 1000000 / fz, pulse_width / 1000); // !# * --> / | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may be more convenient to choose one of these functions cyhal_pwm_set_duty_cycle
or cyhal_pwm_set_period
and use only that one in both cases.
Also, it is possible to recalculate a duty at the last minute before calling cyhal_pwm_set_XXX
and remove float
and double
in other places.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understand it might be a bit confusing. But, taking reference from here: https://ifx-micropython.readthedocs.io/en/latest/library/machine.PWM.html#machine.PWM
- When duty_u16 is set, it is set as raw value and
cyhal_pwm_set_duty_cycle
allows to pass duty_cycle as percentage. - When duty_ns is set, it is set as time in ns and
cyhal_pwm_set_period
allows to directly pass time.
It helps to reuse the low-level API's as much as intended functionality is provided through them. Does that explains?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
Anyhow, I think as long as possible is a good idea to restrict the conversion to one place. @IhorNehrutsa let us check if we can refactor without breaking any functionality :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned in the other comment:
Infineon@3c14c39
I have kept the 2 ways of setting freq/duty. But now abstracted and encapsulated under pwm_config()
.
There was a big discussion about what to do when |
Actually that is the common and intended behavior: not PWM signal unless both freq and duty cycle have been specified. There are no reasonable default values. The ESP32 does not yet meet that rule. |
I have no restriction about the
You may merge |
You may interested in #16743 |
In the PR feedback changes we are currently making mandatory that
Any issue with this approach? Something like in the esp32 port: |
Yes, let us put that in our backlog but with less prio. |
If you approve the changes in Infineon@3c14c39 |
Signed-off-by: enriquezgarc <enriquezgarcia.external@infineon.com>
Signed-off-by: enriquezgarc <enriquezgarcia.external@infineon.com>
Feedback changes discussed merged now. |
Difficult to review due to the large number of files |
Hi @mattytrentini @dpgeorge,
We have kept working on further enabling the PSoC6 controller in MPY. This pull request deprecates #15642.
Here a list of the features enabled:
machine
classes:ADC
ADCBlock
I2C
. Master and slave mode.I2S
Pin
PWM
RTC
SDCard
SPI
. Master and slave mode.Timer
UART
WDT
Additional modules:
network.WLAN
PSoC6 evaluation boards available:
CY8CPROTO-062-4343W
CY8CPROTO-063-BLE
CY8CKIT-062S2-AI
Tests running in a hardware in the loop setup under ci/cd are provided for (at least) the main API functionalities of the enabled classes.
Looking forward to discuss the next steps regarding this PR with our teams.