Skip to content
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

Machine spi deinit #98

Merged
merged 4 commits into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ports/psoc6/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ extern void mod_pin_deinit(void);
extern void mod_adc_block_deinit(void);
extern void mod_i2c_deinit(void);
extern void mod_pwm_deinit(void);
extern void mod_spi_deinit(void);

void mpy_task(void *arg);

Expand Down Expand Up @@ -183,6 +184,7 @@ void mpy_task(void *arg) {
mod_adc_block_deinit();
mod_i2c_deinit();
mod_pwm_deinit();
mod_spi_deinit();
mod_pin_phy_deinit();
Copy link
Member

Choose a reason for hiding this comment

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

I have the same concern here. If mod_spi_deinit ihas already deinited the physical pin, then what consequences would mod_pin_phy_deinit has if internally it is not checking a deinit operation was already done from module side.

Copy link
Member Author

Choose a reason for hiding this comment

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

As before, that pin_phy_deinit() can be called several times without unexpected behavior, if deinited already, then it has no unsafe effect.

#if MICROPY_PY_NETWORK
mod_network_deinit();
Expand Down
133 changes: 95 additions & 38 deletions ports/psoc6/modules/machine/machine_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,10 @@

// port-specific includes
#include "modmachine.h"
#include "machine_pin_phy.h"
#include "mplogger.h"

#define MICROPY_HW_SPI_SCK P9_2
#define MICROPY_HW_SPI_MOSI P9_0
#define MICROPY_HW_SPI_MISO P9_1

#define MAX_SPI 10 // TODO: Change as per bsp?

#define DEFAULT_SPI_BAUDRATE (1000000)
#define DEFAULT_SPI_POLARITY (0)
Expand All @@ -38,12 +36,80 @@ typedef struct _machine_spi_obj_t {
uint8_t phase;
uint8_t bits;
uint8_t firstbit;
uint8_t sck;
uint8_t mosi;
uint8_t miso;
machine_pin_phy_obj_t *sck;
machine_pin_phy_obj_t *mosi;
machine_pin_phy_obj_t *miso;
uint32_t baudrate;
} machine_spi_obj_t;

machine_spi_obj_t *spi_obj[MAX_SPI] = { NULL };

static inline machine_spi_obj_t *spi_obj_alloc() {
for (uint8_t i = 0; i < MAX_SPI; i++)
{
if (spi_obj[i] == NULL) {
spi_obj[i] = mp_obj_malloc(machine_spi_obj_t, &machine_spi_type);
return spi_obj[i];
}
}

return NULL;
}

static inline void spi_obj_free(machine_spi_obj_t *spi_obj_ptr) {
for (uint8_t i = 0; i < MAX_SPI; i++)
{
if (spi_obj[i] == spi_obj_ptr) {
spi_obj[i] = NULL;
}
}
}

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_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_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_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_obj->miso = miso;
}

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) {

Expand Down Expand Up @@ -85,10 +151,9 @@ STATIC void machine_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_prin
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,
self->phase, self->bits, self->firstbit,
self->sck, self->mosi, self->miso);
self->sck->addr, self->mosi->addr, self->miso->addr);
}


mp_obj_t machine_spi_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[] = {
Expand Down Expand Up @@ -116,7 +181,7 @@ mp_obj_t machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n
}

// Get static peripheral object.
machine_spi_obj_t *self = mp_obj_malloc(machine_spi_obj_t, &machine_spi_type);
machine_spi_obj_t *self = spi_obj_alloc();

// set baudrate if provided
if (args[ARG_baudrate].u_int != -1) {
Expand Down Expand Up @@ -145,54 +210,34 @@ mp_obj_t machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n

// Set SCK/MOSI/MISO pins if configured.
if (args[ARG_sck].u_obj != mp_const_none) {
int sck = mp_hal_get_pin_obj(args[ARG_sck].u_obj);

if (self->sck == -1) {
size_t slen;
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("SCK pin (%s) not found !"), mp_obj_str_get_data(args[ARG_sck].u_obj, &slen));
}
self->sck = sck;
spi_sck_alloc(self, args[ARG_sck].u_obj);
} else {
self->sck = MICROPY_HW_SPI_SCK;
mp_raise_TypeError(MP_ERROR_TEXT("SCK pin must be provided"));
}

if (args[ARG_mosi].u_obj != mp_const_none) {
int mosi = mp_hal_get_pin_obj(args[ARG_mosi].u_obj);

if (self->mosi == -1) {
size_t slen;
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("MOSI pin (%s) not found !"), mp_obj_str_get_data(args[ARG_mosi].u_obj, &slen));
}
self->mosi = mosi;
spi_mosi_alloc(self, args[ARG_mosi].u_obj);
} else {
self->mosi = MICROPY_HW_SPI_MOSI;
mp_raise_TypeError(MP_ERROR_TEXT("MOSI pin must be provided"));
}

if (args[ARG_miso].u_obj != mp_const_none) {
int miso = mp_hal_get_pin_obj(args[ARG_miso].u_obj);

if (self->miso == -1) {
size_t slen;
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("MISO pin (%s) not found !"), mp_obj_str_get_data(args[ARG_miso].u_obj, &slen));
}
self->miso = miso;
spi_miso_alloc(self, args[ARG_miso].u_obj);
} else {
self->miso = MICROPY_HW_SPI_MISO;

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, self->miso, self->sck, NC, NULL, self->bits, mode, false);
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);
}
}
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) {
Expand Down Expand Up @@ -237,7 +282,7 @@ STATIC void machine_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj
// 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, self->miso, self->sck, NC, NULL, self->bits, mode, false);
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);
}
Expand Down Expand Up @@ -275,6 +320,10 @@ STATIC void machine_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8
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);
spi_sck_free(self);
spi_mosi_free(self);
spi_miso_free(self);
spi_obj_free(self);
}

STATIC const mp_machine_spi_p_t machine_spi_p = {
Expand All @@ -292,3 +341,11 @@ MP_DEFINE_CONST_OBJ_TYPE(
protocol, &machine_spi_p,
locals_dict, &mp_machine_spi_locals_dict
);

void mod_spi_deinit() {
for (uint8_t i = 0; i < MAX_SPI; i++) {
if (spi_obj[i] != NULL) {
machine_spi_deinit((mp_obj_base_t *)(spi_obj[i]));
}
}
}
2 changes: 1 addition & 1 deletion tests/psoc6/spi_hard.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from machine import SPI

spi = SPI(0)
spi = SPI(0, sck="P9_2", mosi="P9_0", miso="P9_1")
print(spi)
Loading