From 9e2d585ad5f6835b237ddebe7bd519dfddd7e3cc Mon Sep 17 00:00:00 2001 From: IFX-Anusha Date: Tue, 27 Jun 2023 11:39:03 +0530 Subject: [PATCH 1/3] ports/psoc6: Timer Module. Signed-off-by: IFX-Anusha ports/psoc6: Timer Module. Signed-off-by: IFX-Anusha ports/psoc6/modules/machine/machine_timer.c: Removed print in isr. Signed-off-by: enriquezgarc --- ports/psoc6/Makefile | 1 + ports/psoc6/modules/machine/machine_timer.c | 155 ++++++++++++++++++++ ports/psoc6/modules/machine/modmachine.c | 1 + ports/psoc6/modules/machine/modmachine.h | 1 + 4 files changed, 158 insertions(+) create mode 100644 ports/psoc6/modules/machine/machine_timer.c diff --git a/ports/psoc6/Makefile b/ports/psoc6/Makefile index 13bdab91b3c6..1a1d72258c6d 100644 --- a/ports/psoc6/Makefile +++ b/ports/psoc6/Makefile @@ -140,6 +140,7 @@ MOD_SRC_C += $(addprefix modules/,\ machine/machine_rtc.c \ machine/machine_spi.c \ machine/pins.c \ + machine/machine_timer.c \ \ psoc6/modpsoc6.c \ psoc6/psoc6_fatfs.c \ diff --git a/ports/psoc6/modules/machine/machine_timer.c b/ports/psoc6/modules/machine/machine_timer.c new file mode 100644 index 000000000000..d5d87a31021e --- /dev/null +++ b/ports/psoc6/modules/machine/machine_timer.c @@ -0,0 +1,155 @@ +// mpy includes +#include "py/runtime.h" +#include "py/mphal.h" + + +// MTB includes +#include "cybsp.h" +#include "cyhal.h" + + +#define TIMER_MODE_ONE_SHOT (0) +#define TIMER_MODE_PERIODIC (1) + +typedef struct _machine_timer_obj_t { + mp_obj_base_t base; + cyhal_timer_t timer_obj; + uint32_t mode; + uint32_t period; + uint32_t freq; + mp_obj_t callback; +} machine_timer_obj_t; + +const mp_obj_type_t machine_timer_type; + +static void isr_timer(void *callback_arg, cyhal_timer_event_t event) { + machine_timer_obj_t *self = callback_arg; + mp_sched_schedule(self->callback, MP_OBJ_FROM_PTR(self)); +} + + +STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in); + qstr mode = self->mode == TIMER_MODE_ONE_SHOT ? MP_QSTR_ONE_SHOT : MP_QSTR_PERIODIC; + mp_printf(print, "Timer(mode=%q, period=%u, tick_hz=1000)", mode, self->period); +} + +STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_mode, ARG_callback, ARG_period, ARG_freq, }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = TIMER_MODE_PERIODIC} }, + { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 9999u} }, + { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 10000u} }, + }; + // Parse args + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + self->mode = args[ARG_mode].u_int; + self->freq = args[ARG_freq].u_int; + self->period = args[ARG_period].u_int; + + if (args[ARG_callback].u_obj != mp_const_none) { + self->callback = args[ARG_callback].u_obj; + } + + // Timer initialisation of port + cy_rslt_t rslt; + + const cyhal_timer_cfg_t timer_cfg = + { + .compare_value = 0, /* Timer compare value, not used */ + .period = self->period, /* Defines the timer period */ + .direction = CYHAL_TIMER_DIR_UP, /* Timer counts up */ + .is_compare = false, /* Don't use compare mode */ + .is_continuous = self->mode, /* Run the timer */ + .value = 0 /* Initial value of counter */ + }; + + /* Initialize the timer object. Does not use pin output ('pin' is NC) and + * does not use a pre-configured clock source ('clk' is NULL). */ + + rslt = cyhal_timer_init(&self->timer_obj, NC, NULL); + CY_ASSERT(CY_RSLT_SUCCESS == rslt); + + /* Apply timer configuration such as period, count direction, run mode, etc. */ + rslt = cyhal_timer_configure(&self->timer_obj, &timer_cfg); + + /* Set the frequency of timer to Defined frequency */ + rslt = cyhal_timer_set_frequency(&self->timer_obj, self->freq); + + /* Assign the ISR to execute on timer interrupt */ + cyhal_timer_register_callback(&self->timer_obj, isr_timer, self); + + /* Set the event on which timer interrupt occurs and enable it */ + cyhal_timer_enable_event(&self->timer_obj, CYHAL_TIMER_IRQ_TERMINAL_COUNT, 3, true); + + /* Start the timer with the configured settings */ + rslt = cyhal_timer_start(&self->timer_obj); + + CY_ASSERT(CY_RSLT_SUCCESS == rslt); + + return mp_const_none; +} + +STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + machine_timer_obj_t *self = mp_obj_malloc(machine_timer_obj_t, &machine_timer_type); + + self->base.type = &machine_timer_type; + + mp_int_t id = 0; + if (n_args > 0) { + id = mp_obj_get_int(args[0]); + --n_args; + ++args; + } + // Get timer id + if (id != 0) { + mp_raise_ValueError(MP_ERROR_TEXT("Specified Timer doesn't exist. Currently only id 0 is comfigured")); + } + + if (n_args > 0 || n_kw > 0) { + // Start the timer + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + machine_timer_init_helper(self, n_args, args, &kw_args); + } + + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t machine_timer_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + machine_timer_obj_t *self = MP_OBJ_TO_PTR(args[0]); + return machine_timer_init_helper(self, n_args - 1, args + 1, kw_args); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_init_obj, 1, machine_timer_init); + +STATIC mp_obj_t machine_timer_deinit(mp_obj_t self_in) { + machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in); + cyhal_timer_free(&self->timer_obj); + return mp_const_none; +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_deinit_obj, machine_timer_deinit); + +STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_timer_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_timer_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_timer_deinit_obj) }, + + { MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(TIMER_MODE_ONE_SHOT) }, + { MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(TIMER_MODE_PERIODIC) }, +}; + +STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + machine_timer_type, + MP_QSTR_Timer, + MP_TYPE_FLAG_NONE, + make_new, machine_timer_make_new, + print, machine_timer_print, + locals_dict, &machine_timer_locals_dict + ); diff --git a/ports/psoc6/modules/machine/modmachine.c b/ports/psoc6/modules/machine/modmachine.c index 0fe8877ed964..ef5b71e7a363 100644 --- a/ports/psoc6/modules/machine/modmachine.c +++ b/ports/psoc6/modules/machine/modmachine.c @@ -262,6 +262,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) }, { MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) }, + { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, }; STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); diff --git a/ports/psoc6/modules/machine/modmachine.h b/ports/psoc6/modules/machine/modmachine.h index 6def0227f738..c4dfc139dcfc 100644 --- a/ports/psoc6/modules/machine/modmachine.h +++ b/ports/psoc6/modules/machine/modmachine.h @@ -11,6 +11,7 @@ extern const mp_obj_type_t machine_pin_type; extern const mp_obj_type_t machine_rtc_type; extern const mp_obj_type_t machine_pwm_type; extern const mp_obj_type_t machine_spi_type; +extern const mp_obj_type_t machine_timer_type; /* Note: the static functions' prototypes in the .c file cannot be declared here since they are static. The static type in those functions come from MPY hence From b0bcc24ba8078eeda24b2cb56db55dc2a1ead368 Mon Sep 17 00:00:00 2001 From: enriquezgarc Date: Thu, 13 Jul 2023 16:40:30 +0200 Subject: [PATCH 2/3] test/psoc6/timer.py: Added basic timer test. Signed-off-by: enriquezgarc --- tests/psoc6/timer.py | 6 ++++++ tests/psoc6/timer.py.exp | 1 + 2 files changed, 7 insertions(+) create mode 100644 tests/psoc6/timer.py create mode 100644 tests/psoc6/timer.py.exp diff --git a/tests/psoc6/timer.py b/tests/psoc6/timer.py new file mode 100644 index 000000000000..7acef9376b0d --- /dev/null +++ b/tests/psoc6/timer.py @@ -0,0 +1,6 @@ +import time +from machine import Timer + +t = Timer(0) +t.init(period=2000, mode=Timer.ONE_SHOT, callback=lambda t: print("hello")) +time.sleep_ms(3000) diff --git a/tests/psoc6/timer.py.exp b/tests/psoc6/timer.py.exp new file mode 100644 index 000000000000..ce013625030b --- /dev/null +++ b/tests/psoc6/timer.py.exp @@ -0,0 +1 @@ +hello From 240048e2b0348604e59e7562c88e07eae05f4ce1 Mon Sep 17 00:00:00 2001 From: IFX-Anusha Date: Fri, 28 Jul 2023 11:54:45 +0530 Subject: [PATCH 3/3] ports/psoc6: Timer Documentation. Signed-off-by: IFX-Anusha --- docs/psoc6/feature_list.rst | 6 ++++++ docs/psoc6/quickref.rst | 15 +++++++++++++++ ports/psoc6/modules/machine/machine_timer.c | 4 ++-- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/docs/psoc6/feature_list.rst b/docs/psoc6/feature_list.rst index a333971ec50d..d43d048c9d41 100644 --- a/docs/psoc6/feature_list.rst +++ b/docs/psoc6/feature_list.rst @@ -38,6 +38,10 @@ Enabled modules * I2C * RTC * SoftI2C + * SPI + * SoftSPI + * PWM + * Timer * micropython * ucryptolib * uctypes @@ -117,6 +121,8 @@ Table :ref:`configuration details ` below lists specifi +-----------------+----------------------------------------------------------------------------------------------------------------------+ | machine.SoftSPI | Option ``MICROPY_PY_MACHINE_SOFTSPI`` enabled. | +-----------------+----------------------------------------------------------------------------------------------------------------------+ +| machine.Timer | mode = Timer.PERIODIC is not supported | ++-----------------+----------------------------------------------------------------------------------------------------------------------+ | machine.SPI | Option ``MICROPY_PY_MACHINE_SPI``, ``MICROPY_PY_MACHINE_SPI_MSB`` , ``MICROPY_PY_MACHINE_SPI_MSB`` enabled. | +-----------------+----------------------------------------------------------------------------------------------------------------------+ | psoc6 | Option to enable the external instead of the internal flash: ``MICROPY_ENABLE_EXT_QSPI_FLASH``. | diff --git a/docs/psoc6/quickref.rst b/docs/psoc6/quickref.rst index c008bb692479..3efdde24b95d 100644 --- a/docs/psoc6/quickref.rst +++ b/docs/psoc6/quickref.rst @@ -447,4 +447,19 @@ Methods ^^^^^^^ All the methods(functions) given in :ref:`machine.SPI ` class have been implemented in this port +Timers +------ + +Hardware timer is supported. + +Use the :mod:`machine.Timer` class:: + + from machine import Timer + import time + tim = Timer(0) #Default assignment: period=9999, frequency=10000 + tim.init(period=2000, mode=Timer.ONE_SHOT, callback=lambda t:print(2)) + time.sleep_ms(100) + +Here id=0 should be passed mandatorily. +.. note:: Here mode=Timer.PERIODIC is not currently supported diff --git a/ports/psoc6/modules/machine/machine_timer.c b/ports/psoc6/modules/machine/machine_timer.c index d5d87a31021e..d1a9b5d4dac0 100644 --- a/ports/psoc6/modules/machine/machine_timer.c +++ b/ports/psoc6/modules/machine/machine_timer.c @@ -31,13 +31,13 @@ static void isr_timer(void *callback_arg, cyhal_timer_event_t event) { STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in); qstr mode = self->mode == TIMER_MODE_ONE_SHOT ? MP_QSTR_ONE_SHOT : MP_QSTR_PERIODIC; - mp_printf(print, "Timer(mode=%q, period=%u, tick_hz=1000)", mode, self->period); + mp_printf(print, "Timer(mode=%q, period=%u, tick_hz=%u)", mode, self->period, self->freq); } STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_mode, ARG_callback, ARG_period, ARG_freq, }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = TIMER_MODE_PERIODIC} }, + { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = TIMER_MODE_ONE_SHOT} }, { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 9999u} }, { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 10000u} },