From 77ff64950a5f8cee933711a83c04bd5940e571e4 Mon Sep 17 00:00:00 2001 From: NikhitaR-IFX Date: Fri, 12 Apr 2024 12:54:19 +0530 Subject: [PATCH] ports/psoc6: SPI enhanvements and test. Signed-off-by: NikhitaR-IFX --- docs/psoc6/quickref.rst | 12 +- ports/psoc6/machine_spi.c | 358 +++++++++++++------------------------ tests/psoc6/hw_ext/spi.exp | 27 +++ tests/psoc6/hw_ext/spi.py | 189 ++++++++++++++++++++ 4 files changed, 341 insertions(+), 245 deletions(-) create mode 100644 tests/psoc6/hw_ext/spi.exp create mode 100644 tests/psoc6/hw_ext/spi.py diff --git a/docs/psoc6/quickref.rst b/docs/psoc6/quickref.rst index 3f49f3d97d0f8..65064c629d625 100644 --- a/docs/psoc6/quickref.rst +++ b/docs/psoc6/quickref.rst @@ -522,16 +522,6 @@ Software SPI (using bit-banging) works on all pins, and is accessed via the Hardware SPI bus ---------------- -Hardware SPI works on the following listed pair of SPI pins. - -===== =========== ============ ============ -\ Default -===== =========== ============ ============ -MOSI P9_0 P6_0 P10_0 -MISO P9_1 P6_1 P10_1 -SCK P9_2 P6_2 P10_2 -===== =========== ============ ============ - .. TODO: This is only applicable to the CY8CPROTO-062-4343W. This does not belong here. TODO: Define approach on how the user gets to know the pinout diagram, alternate function of each board @@ -540,7 +530,7 @@ SCK P9_2 P6_2 P10_2 - To create a pinout diagram? Refer `PSoC 6 MCU: CY8C62x8, CY8C62xA Datasheet `_ -for additional details regarding all the SPI capable pins. The pins ``sck``, ``mosi`` and ``miso`` *must* be specified when +for details regarding all the SPI capable pins. The pins ``sck``, ``mosi`` and ``miso`` *must* be specified when initialising Software SPI. The driver is accessed via :ref:`machine.SPI ` diff --git a/ports/psoc6/machine_spi.c b/ports/psoc6/machine_spi.c index b4fc74ded2ed3..4eb446306fc0b 100644 --- a/ports/psoc6/machine_spi.c +++ b/ports/psoc6/machine_spi.c @@ -25,15 +25,23 @@ #define DEFAULT_SPI_BITS (8) #define DEFAULT_SPI_FIRSTBIT (0) // msb +#define spi_assert_raise_val(msg, ret) if (ret != CY_RSLT_SUCCESS) { \ + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT(msg), ret); \ +} + +#define spi_alloc_msg(pin_name, pin_obj, msg) if (pin_obj == NULL) { \ + size_t slen; \ + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT(msg), mp_obj_str_get_data(pin_name, &slen)); \ +} typedef struct _machine_spi_obj_t { mp_obj_base_t base; cyhal_spi_t spi_obj; - uint8_t spi_id; uint8_t polarity; uint8_t phase; uint8_t bits; uint8_t firstbit; + machine_pin_phy_obj_t *ssel; machine_pin_phy_obj_t *sck; machine_pin_phy_obj_t *mosi; machine_pin_phy_obj_t *miso; @@ -42,6 +50,42 @@ typedef struct _machine_spi_obj_t { machine_spi_obj_t *spi_obj[MAX_SPI] = { NULL }; +// Function to select the mode +static cyhal_spi_mode_t spi_mode_select(uint8_t firstbit, uint8_t polarity, uint8_t phase) { + + cyhal_spi_mode_t mode; + if (firstbit == 1) { + if (polarity == 0) { + if (phase == 0) { + mode = CYHAL_SPI_MODE_00_LSB; + } else { + mode = CYHAL_SPI_MODE_01_LSB; + } + } else { + if (phase == 0) { + mode = CYHAL_SPI_MODE_10_LSB; + } else { + mode = CYHAL_SPI_MODE_11_LSB; + } + } + } else { + if (polarity == 0) { + if (phase == 0) { + mode = CYHAL_SPI_MODE_00_MSB; + } else { + mode = CYHAL_SPI_MODE_01_MSB; + } + } else { + if (phase == 0) { + mode = CYHAL_SPI_MODE_10_MSB; + } else { + mode = CYHAL_SPI_MODE_11_MSB; + } + } + } + return mode; +} + static inline machine_spi_obj_t *spi_obj_alloc(bool is_slave) { for (uint8_t i = 0; i < MAX_SPI; i++) { @@ -72,122 +116,86 @@ static inline void spi_obj_free(machine_spi_obj_t *spi_obj_ptr) { static inline void spi_sck_alloc(machine_spi_obj_t *spi_obj, mp_obj_t pin_name) { machine_pin_phy_obj_t *sck = pin_phy_realloc(pin_name, PIN_PHY_FUNC_SPI); - - if (sck == NULL) { - size_t slen; - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("SCK pin (%s) not found !"), mp_obj_str_get_data(pin_name, &slen)); - } - + spi_alloc_msg(pin_name, sck, "SCK pin (%s) not found !"); spi_obj->sck = sck; } -static inline void spi_sck_free(machine_spi_obj_t *spi_obj) { - pin_phy_free(spi_obj->sck); +static inline void spi_ssel_alloc(machine_spi_obj_t *spi_obj, mp_obj_t pin_name) { + machine_pin_phy_obj_t *ssel = pin_phy_realloc(pin_name, PIN_PHY_FUNC_SPI); + spi_alloc_msg(pin_name, ssel, "SSEL pin (%s) not found !"); + spi_obj->ssel = ssel; } static inline void spi_mosi_alloc(machine_spi_obj_t *spi_obj, mp_obj_t pin_name) { machine_pin_phy_obj_t *mosi = pin_phy_realloc(pin_name, PIN_PHY_FUNC_SPI); - - if (mosi == NULL) { - size_t slen; - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("MOSI pin (%s) not found !"), mp_obj_str_get_data(pin_name, &slen)); - } - + spi_alloc_msg(pin_name, mosi, "MOSI pin (%s) not found !"); spi_obj->mosi = mosi; } -static inline void spi_mosi_free(machine_spi_obj_t *spi_obj) { - pin_phy_free(spi_obj->mosi); -} - static inline void spi_miso_alloc(machine_spi_obj_t *spi_obj, mp_obj_t pin_name) { machine_pin_phy_obj_t *miso = pin_phy_realloc(pin_name, PIN_PHY_FUNC_SPI); - - if (miso == NULL) { - size_t slen; - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("MISO pin (%s) not found !"), mp_obj_str_get_data(pin_name, &slen)); - } - + spi_alloc_msg(pin_name, miso, "MISO pin (%s) not found !"); spi_obj->miso = miso; } +static inline void spi_sck_free(machine_spi_obj_t *spi_obj) { + pin_phy_free(spi_obj->sck); +} + +static inline void spi_mosi_free(machine_spi_obj_t *spi_obj) { + pin_phy_free(spi_obj->mosi); +} static inline void spi_miso_free(machine_spi_obj_t *spi_obj) { pin_phy_free(spi_obj->miso); } -// Function to select the mode -static cyhal_spi_mode_t mode_select(uint8_t firstbit, uint8_t polarity, uint8_t phase) { - - cyhal_spi_mode_t mode; - if (firstbit == 1) { - if (polarity == 0) { - if (phase == 0) { - mode = CYHAL_SPI_MODE_00_LSB; - } else { - mode = CYHAL_SPI_MODE_01_LSB; - } - } else { - if (phase == 0) { - mode = CYHAL_SPI_MODE_10_LSB; - } else { - mode = CYHAL_SPI_MODE_11_LSB; - } - } - } else { - if (polarity == 0) { - if (phase == 0) { - mode = CYHAL_SPI_MODE_00_MSB; - } else { - mode = CYHAL_SPI_MODE_01_MSB; - } - } else { - if (phase == 0) { - mode = CYHAL_SPI_MODE_10_MSB; - } else { - mode = CYHAL_SPI_MODE_11_MSB; - } - } - } - return mode; +static inline void spi_init(machine_spi_obj_t *machine_spi_obj, int spi_mode) { + cyhal_spi_mode_t mode = spi_mode_select(machine_spi_obj->firstbit, machine_spi_obj->polarity, machine_spi_obj->phase); + // set the baudrate + cyhal_spi_set_frequency(&machine_spi_obj->spi_obj, machine_spi_obj->baudrate); + // Initialise the SPI peripheral if any arguments given, or it was not initialised previously. + cy_rslt_t result = cyhal_spi_init(&machine_spi_obj->spi_obj, machine_spi_obj->mosi->addr, machine_spi_obj->miso->addr, machine_spi_obj->sck->addr, machine_spi_obj->ssel->addr, NULL, machine_spi_obj->bits, mode, spi_mode); + spi_assert_raise_val("SPI initialisation failed with return code %x !", result); } static void machine_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "SPI(id=%u, baudrate=%u, polarity=%u, phase=%u, bits=%u, firstbit=%u, sck=%d, mosi=%d, miso=%d)", - self->spi_id, self->baudrate, self->polarity, + mp_printf(print, "SPI(baudrate=%u, polarity=%u, phase=%u, bits=%u, firstbit=%u, ssel=%d, sck=%d, mosi=%d, miso=%d)", + self->baudrate, self->polarity, self->phase, self->bits, self->firstbit, - self->sck->addr, self->mosi->addr, self->miso->addr); + self->ssel->addr, self->sck->addr, self->mosi->addr, self->miso->addr); } -mp_obj_t machine_spi_master_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - enum { ARG_id, ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit, ARG_sck, ARG_mosi, ARG_miso }; + +static void machine_spi_slave_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "SPISlave(baudrate=%u, polarity=%u, phase=%u, bits=%u, firstbit=%u, ssel=%d, sck=%d, mosi=%d, miso=%d)", + self->baudrate, self->polarity, + self->phase, self->bits, self->firstbit, + self->ssel->addr, self->sck->addr, self->mosi->addr, self->miso->addr); +} + +mp_obj_t machine_spi_init_helper(machine_spi_obj_t *self, int spi_mode, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit, ARG_ssel, ARG_sck, ARG_mosi, ARG_miso }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = DEFAULT_SPI_BAUDRATE} }, { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_SPI_POLARITY} }, { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_SPI_PHASE} }, { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_SPI_BITS} }, { MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_SPI_FIRSTBIT} }, + { MP_QSTR_ssel, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, }; - // Parse the arguments. mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - // Get the SPI bus id. - // There are no separate spi blocks. Now id is used to identify the master mode - int spi_id = mp_obj_get_int(args[ARG_id].u_obj); - - if (spi_id != 0) { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("SPI should be configured in master mode!")); + if (spi_mode < 0 || spi_mode > 1) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("SPI should be configured in master or slave mode!")); } - // Get static peripheral object. - machine_spi_obj_t *self = spi_obj_alloc(false); - // set baudrate if provided if (args[ARG_baudrate].u_int != -1) { self->baudrate = args[ARG_baudrate].u_int; @@ -213,7 +221,13 @@ mp_obj_t machine_spi_master_make_new(const mp_obj_type_t *type, size_t n_args, s self->firstbit = args[ARG_firstbit].u_int; } - // Set SCK/MOSI/MISO pins if configured. + // Set SSEL/SCK/MOSI/MISO pins if configured. + if (args[ARG_ssel].u_obj != mp_const_none) { + spi_ssel_alloc(self, args[ARG_ssel].u_obj); + } else { + mp_raise_TypeError(MP_ERROR_TEXT("SSEL pin must be provided")); + } + if (args[ARG_sck].u_obj != mp_const_none) { spi_sck_alloc(self, args[ARG_sck].u_obj); } else { @@ -233,150 +247,33 @@ mp_obj_t machine_spi_master_make_new(const mp_obj_type_t *type, size_t n_args, s } if (n_args > 1 || n_kw > 0) { - cyhal_spi_mode_t mode = mode_select(self->firstbit, self->polarity, self->phase); - // set the baudrate - cyhal_spi_set_frequency(&self->spi_obj, self->baudrate); - // Initialise the SPI peripheral if any arguments given, or it was not initialised previously. - cy_rslt_t result = cyhal_spi_init(&self->spi_obj, self->mosi->addr, self->miso->addr, self->sck->addr, NC, NULL, self->bits, mode, false); - if (result != CY_RSLT_SUCCESS) { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("SPI initialisation failed with return code %lx !"), result); - } + spi_init(self, spi_mode); } return MP_OBJ_FROM_PTR(self); } -mp_obj_t machine_spi_slave_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - enum { ARG_id, ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit, ARG_sck, ARG_mosi, ARG_miso }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = DEFAULT_SPI_BAUDRATE} }, - { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_SPI_POLARITY} }, - { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_SPI_PHASE} }, - { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_SPI_BITS} }, - { MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_SPI_FIRSTBIT} }, - { MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, - { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, - { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, - }; - - // Parse the arguments. - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - // Get the SPI bus id. - // There are no separate spi blocks. Now id is used to identify the master mode - int spi_id = mp_obj_get_int(args[ARG_id].u_obj); - - if (spi_id != 1) { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("SPI should be configured in slave mode!")); - } - - // Get static peripheral object. - machine_spi_obj_t *self = spi_obj_alloc(true); - - // set baudrate if provided - if (args[ARG_baudrate].u_int != -1) { - self->baudrate = args[ARG_baudrate].u_int; - } - - // set polarity(CPOL) if provided - if (args[ARG_polarity].u_int != -1) { - self->polarity = args[ARG_polarity].u_int; - } - - // set phase(CPHA) if provided - if (args[ARG_phase].u_int != -1) { - self->phase = args[ARG_phase].u_int; - } - - // set bits if provided - if (args[ARG_bits].u_int != -1) { - self->bits = args[ARG_bits].u_int; - } - - // set firstbit if provided(LSB or MSB first) - if (args[ARG_firstbit].u_int != -1) { - self->firstbit = args[ARG_firstbit].u_int; - } - - // Set SCK/MOSI/MISO pins if configured. - if (args[ARG_sck].u_obj != mp_const_none) { - spi_sck_alloc(self, args[ARG_sck].u_obj); - } else { - mp_raise_TypeError(MP_ERROR_TEXT("SCK pin must be provided")); - } - - if (args[ARG_mosi].u_obj != mp_const_none) { - spi_mosi_alloc(self, args[ARG_mosi].u_obj); +mp_obj_t machine_spi_master_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + machine_spi_obj_t *self = spi_obj_alloc(false); + if (n_kw > 1) { + machine_spi_init_helper(self, 0, n_args, n_kw, all_args); } else { - mp_raise_TypeError(MP_ERROR_TEXT("MOSI pin must be provided")); + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("Init failed as all required arguments not passed!")); } + return MP_OBJ_FROM_PTR(self); +} - if (args[ARG_miso].u_obj != mp_const_none) { - spi_miso_alloc(self, args[ARG_miso].u_obj); +mp_obj_t machine_spi_slave_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + machine_spi_obj_t *self = spi_obj_alloc(true); + if (n_kw > 1) { + machine_spi_init_helper(self, 1, n_args, n_kw, all_args); } else { - mp_raise_TypeError(MP_ERROR_TEXT("MISO pin must be provided")); - } - - if (n_args > 1 || n_kw > 0) { - cyhal_spi_mode_t mode = mode_select(self->firstbit, self->polarity, self->phase); - // set the baudrate - cyhal_spi_set_frequency(&self->spi_obj, self->baudrate); - // Initialise the SPI peripheral if any arguments given, or it was not initialised previously. - cy_rslt_t result = cyhal_spi_init(&self->spi_obj, self->mosi->addr, self->miso->addr, self->sck->addr, NC, NULL, self->bits, mode, true); - if (result != CY_RSLT_SUCCESS) { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("SPI initialisation failed with return code %lx !"), result); - } + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("Init failed as all required arguments not passed!")); } return MP_OBJ_FROM_PTR(self); } static void machine_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - }; - - // Parse the arguments. - machine_spi_obj_t *self = (machine_spi_obj_t *)self_in; - 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); - - // Reconfigure the baudrate if requested. - if (args[ARG_baudrate].u_int != -1) { - self->baudrate = args[ARG_baudrate].u_int; - cyhal_spi_set_frequency(&self->spi_obj, self->baudrate); - } - - if (args[ARG_polarity].u_int != -1) { - self->polarity = args[ARG_polarity].u_int; - } - - if (args[ARG_phase].u_int != -1) { - self->phase = args[ARG_phase].u_int; - } - - if (args[ARG_bits].u_int != -1) { - self->bits = args[ARG_bits].u_int; - } - - if (args[ARG_firstbit].u_int != -1) { - self->firstbit = args[ARG_firstbit].u_int; - } - - cyhal_spi_mode_t mode = mode_select(self->firstbit, self->polarity, self->phase); - - // since it's reinitialising, first it should be deinitialised & initilased with new parameters - cyhal_spi_free(&self->spi_obj); - - cy_rslt_t result = cyhal_spi_init(&self->spi_obj, self->mosi->addr, self->miso->addr, self->sck->addr, NC, NULL, self->bits, mode, false); - if (result != CY_RSLT_SUCCESS) { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("SPI initialisation failed with return code %lx !"), result); - } + mp_raise_NotImplementedError(MP_ERROR_TEXT("Init not supported. Use the constructor to initialize.\n")); } static void machine_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) { @@ -387,27 +284,22 @@ static void machine_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8 for (int i = 0; i < len; i++) { result = cyhal_spi_send(&self->spi_obj, src[i]); - if (result != CY_RSLT_SUCCESS) { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("cyhal_spi_send failed with return code %lx !"), result); - } + spi_assert_raise_val("SPI initialisation failed with return code %lx !", result); } } else if (src == NULL) { for (int i = 0; i < len; i++) { result = cyhal_spi_recv(&self->spi_obj, (uint32_t *)(dest + i)); - if (result != CY_RSLT_SUCCESS) { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("cyhal_spi_recv failed with return code %lx !"), result); - } + spi_assert_raise_val("SPI initialisation failed with return code %lx !", result); } } else { result = cyhal_spi_transfer(&self->spi_obj, src, len, dest, len, 0xFF); - if (result != CY_RSLT_SUCCESS) { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("cyhal_spi_transf failed with return code %lx !"), result); - } + spi_assert_raise_val("SPI initialisation failed with return code %lx !", result); } } + static void machine_spi_deinit(mp_obj_base_t *self_in) { machine_spi_obj_t *self = (machine_spi_obj_t *)self_in; cyhal_spi_free(&self->spi_obj); @@ -442,36 +334,34 @@ static mp_obj_t machine_spi_slave_deinit(mp_obj_t self_in) { } MP_DEFINE_CONST_FUN_OBJ_1(machine_spi_slave_deinit_obj, machine_spi_slave_deinit); -static mp_obj_t machine_spi_slave_configure_receive_buffer(mp_obj_t self_in, mp_obj_t buf_in) { - /*machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); +static mp_obj_t machine_spi_slave_read(mp_obj_t self_in, mp_obj_t buf_in) { + machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); - - cy_rslt_t result = cyhal_spi_slave_config_write_buffer(&self->i2c_obj, bufinfo.buf, bufinfo.len); - i2c_assert_raise_val("I2C Slave configure receive buffer failed with return code %lx !", result);*/ - + uint16_t len = bufinfo.len; + cy_rslt_t result = cyhal_spi_slave_read(&self->spi_obj, bufinfo.buf, &len, 0); + spi_assert_raise_val("SPI slave read failed with return code %lx !", result); return mp_const_none; } -static MP_DEFINE_CONST_FUN_OBJ_2(machine_spi_slave_conf_rx_buffer_obj, machine_spi_slave_configure_receive_buffer); +static MP_DEFINE_CONST_FUN_OBJ_2(machine_spi_slave_read_obj, machine_spi_slave_read); -static mp_obj_t machine_spi_slave_configure_transmit_buffer(mp_obj_t self_in, mp_obj_t buf_in) { - /*machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); +static mp_obj_t machine_spi_slave_write(mp_obj_t self_in, mp_obj_t buf_in) { + machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); - - cy_rslt_t result = cyhal_spi_slave_config_read_buffer(&self->i2c_obj, bufinfo.buf, bufinfo.len); - i2c_assert_raise_val("I2C Slave configure receive buffer failed with return code %lx !", result); - */ + uint16_t len = bufinfo.len; + cy_rslt_t result = cyhal_spi_slave_write(&self->spi_obj, bufinfo.buf, &len, 0); + spi_assert_raise_val("SPI slave write failed with return code %lx !", result); return mp_const_none; } -static MP_DEFINE_CONST_FUN_OBJ_2(machine_spi_slave_conf_tx_buffer_obj, machine_spi_slave_configure_transmit_buffer); +static MP_DEFINE_CONST_FUN_OBJ_2(machine_spi_slave_write_obj, machine_spi_slave_write); static const mp_rom_map_elem_t machine_spi_slave_locals_dict_table[] = { // Functions - { MP_ROM_QSTR(MP_QSTR_conf_receive_buffer), MP_ROM_PTR(&machine_spi_slave_conf_rx_buffer_obj) }, - { MP_ROM_QSTR(MP_QSTR_conf_transmit_buffer), MP_ROM_PTR(&machine_spi_slave_conf_tx_buffer_obj) }, - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_spi_slave_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_spi_slave_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_spi_slave_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_spi_slave_deinit_obj) }, }; static MP_DEFINE_CONST_DICT(machine_spi_slave_locals_dict, machine_spi_slave_locals_dict_table); @@ -481,7 +371,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_SPISlave, MP_TYPE_FLAG_NONE, make_new, machine_spi_slave_make_new, - print, machine_spi_print, + print, machine_spi_slave_print, locals_dict, &machine_spi_slave_locals_dict ); diff --git a/tests/psoc6/hw_ext/spi.exp b/tests/psoc6/hw_ext/spi.exp new file mode 100644 index 0000000000000..1a799612edfe6 --- /dev/null +++ b/tests/psoc6/hw_ext/spi.exp @@ -0,0 +1,27 @@ +SPI Hardware Test + +Init failed as all required arguments not passed! +Init failed as all required arguments not passed! +must specify all of sck/mosi/miso +must specify all of sck/mosi/miso + + SPI(baudrate=1000000, polarity=0, phase=0, bits=8, firstbit=0, ssel=51, sck=50, mosi=48, miso=49) +SPISlave(baudrate=1000000, polarity=0, phase=0, bits=8, firstbit=0, ssel=107, sck=106, mosi=104, miso=105) + +Writing 4-bytes data from master to slave +transffered data: b'\x88\x88\x11\x11' +received data: bytearray(b'\x88\x88\x11\x11') +data transfer is successful: True + +Writing 8-bytes data from slave to master +transffered data: b'\x11\x11\x88\x88\x11\x11\x88\x88' +received data by master: b'\x11\x11\x88\x88\x11\x11\x88\x88' +data transfer is successful: True + + SPI(baudrate=1000000, polarity=0, phase=0, bits=8, firstbit=0, ssel=51, sck=50, mosi=48, miso=49) +SPISlave(baudrate=1000000, polarity=0, phase=0, bits=8, firstbit=1, ssel=107, sck=106, mosi=104, miso=105) + +Writing data from master to slave with firstbit as MSB (master) and LSB(slave) +transffered data: b'\x11\x11\x88\x88\x11\x11\x88\x88' +received data: bytearray(b'\x88\x88\x11\x11\x88\x88\x11\x11') +data transfer is successful: True diff --git a/tests/psoc6/hw_ext/spi.py b/tests/psoc6/hw_ext/spi.py new file mode 100644 index 0000000000000..6fa85f65668fc --- /dev/null +++ b/tests/psoc6/hw_ext/spi.py @@ -0,0 +1,189 @@ +### SPI + +from machine import SPI, SPISlave, SoftSPI +import binascii +import time +import os + +# Allocate pin based on board +machine = os.uname().machine +if "CY8CPROTO-062-4343W" in machine: + sck_master_pin = "P6_2" + mosi_master_pin = "P6_0" + miso_master_pin = "P6_1" + ssel_master_pin = "P6_3" + sck_slave_pin = "P13_2" + mosi_slave_pin = "P13_0" + miso_slave_pin = "P13_1" + ssel_slave_pin = "P13_3" +elif "CY8CPROTO-063-BLE" in machine: + sck_master_pin = "P6_2" + mosi_master_pin = "P6_0" + miso_master_pin = "P6_1" + ssel_master_pin = "P6_3" + sck_slave_pin = "P13_2" + mosi_slave_pin = "P13_0" + miso_slave_pin = "P13_1" + ssel_slave_pin = "P13_3" + +master_to_slave_write = 0 +master_to_slave_write_read = 1 +slave_to_master_write = 2 + +# Test hardware setup +#################################################### +# The SCK, MOSI, MISO and SSEL pins from master +# should be connected to SCK, MISO, MOSI and SSEL +# pins of slave respectively where master and slave +# are two boards of same type. + +# 0. Error missing arguments in constructors +#################################################### +print("SPI Hardware Test\n") +try: + spi = SPI(ssel=ssel_master_pin) +except Exception as e: + print(e) + +try: + spi = SPISlave(sck=sck_master_pin) +except Exception as e: + print(e) + +try: + spi = SoftSPI(mosi=mosi_master_pin) +except Exception as e: + print(e) + +try: + spi = SoftSPI(miso=miso_master_pin) +except Exception as e: + print(e) + + +def _validate_data(exp_rx_data, act_rx_data): + print("data transfer is successful: ", act_rx_data == exp_rx_data) + + +def transfer_data_and_validate(tx_buf, rx_buf, exp_recv_data, data_transfer_dir): + print("transffered data: ", tx_buf) + if data_transfer_dir == master_to_slave_write: + spi_master.write(tx_buf) + spi_slave.read(rx_buf) + print("received data: ", rx_buf) + _validate_data(exp_recv_data, rx_buf) + + elif data_transfer_dir == master_to_slave_write_read: + tx_slave_buf = b"\x00\x11\x00\x11\x00\x11\x00\x11" + rx_slave_buf = bytearray(8) + spi_slave.write(tx_slave_buf) + print("slave writes: ", tx_slave_buf) + spi_master.write_readinto(tx_buf, rx_buf) + print("master received: ", rx_buf) + # spi_slave.read(rx_slave_buf) + print("slave recvd: ", rx_slave_buf) + print("Validate slave to master data transfer") + _validate_data(tx_slave_buf, rx_buf) + # print("Validate master to slave data transfer") + # _validate_data(tx_buf,rx_slave_buf) + + elif data_transfer_dir == slave_to_master_write: + spi_slave.write(tx_buf) + rx_buf = spi_master.read(len(rx_buf)) + print("received data by master: ", rx_buf) + _validate_data(exp_recv_data, rx_buf) + + else: + print("Wrong data transfer direction!") + + +# 1. Construct master and slave instances +########################################## +spi_master = SPI( + baudrate=1000000, + polarity=0, + phase=0, + bits=8, + firstbit=SPI.MSB, + ssel=ssel_master_pin, + sck=sck_master_pin, + mosi=mosi_master_pin, + miso=miso_master_pin, +) +print("\n", spi_master) +spi_slave = SPISlave( + baudrate=1000000, + polarity=0, + phase=0, + bits=8, + firstbit=SPI.MSB, + ssel=ssel_slave_pin, + sck=sck_slave_pin, + mosi=mosi_slave_pin, + miso=miso_slave_pin, +) +print(spi_slave) +# spi_soft_master = SoftSPI(sck=sck_master_pin, mosi=mosi_master_pin, miso=miso_master_pin) +# print(spi_soft_master) + + +# 3. Master to slave 4-bytes data transfer +########################################### +tx_buf = b"\x88\x88\x11\x11" +rx_buf = bytearray(4) +print("\nWriting 4-bytes data from master to slave") +transfer_data_and_validate(tx_buf, rx_buf, tx_buf, master_to_slave_write) + +# 4. Slave to master 8-bytes data transfer +########################################### +tx_buf = b"\x11\x11\x88\x88\x11\x11\x88\x88" +rx_buf = bytearray(8) +print("\nWriting 8-bytes data from slave to master") +transfer_data_and_validate(tx_buf, rx_buf, tx_buf, slave_to_master_write) + +# 5. Deinit SPI modules +########################## +spi_master.deinit() +spi_slave.deinit() + +# 6. Reconfigure firstbit and transfer data from master to slave +################################################################# +spi_master = SPI( + baudrate=1000000, + polarity=0, + phase=0, + bits=8, + firstbit=SPI.MSB, + ssel=ssel_master_pin, + sck=sck_master_pin, + mosi=mosi_master_pin, + miso=miso_master_pin, +) +print("\n", spi_master) +spi_slave = SPISlave( + baudrate=1000000, + polarity=0, + phase=0, + bits=8, + firstbit=SPI.LSB, + ssel=ssel_slave_pin, + sck=sck_slave_pin, + mosi=mosi_slave_pin, + miso=miso_slave_pin, +) +print(spi_slave) +tx_buf = b"\x11\x11\x88\x88\x11\x11\x88\x88" +rx_buf = bytearray(8) +tx_exp_buf = b"\x88\x88\x11\x11\x88\x88\x11\x11" +print("\nWriting data from master to slave with firstbit as MSB (master) and LSB(slave)") +transfer_data_and_validate(tx_buf, rx_buf, tx_exp_buf, master_to_slave_write) + +# 7. Write from master to slave and read concurrently +###################################################### + +"""spi_master = SPI(baudrate=1000000, polarity=0, phase=0, bits=8, firstbit=SPI.LSB,ssel=ssel_master_pin, sck=sck_master_pin, mosi=mosi_master_pin, miso=miso_master_pin) +print(spi_master) +spi_slave = SPISlave(baudrate=1000000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, ssel=ssel_slave_pin, sck=sck_slave_pin, mosi=mosi_slave_pin, miso=miso_slave_pin) +print(spi_slave) +transfer_data() +#validate_data()"""