feat: add spi.set_irq() support
This commit is contained in:
parent
54b2eb0def
commit
c3e391b190
@ -76,6 +76,17 @@ static mp_obj_t mp_machine_spi_wait_done(size_t n_args, const mp_obj_t *args)
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_wait_done_obj, 1, 2, mp_machine_spi_wait_done);
|
||||
|
||||
static mp_obj_t mp_machine_spi_set_tx_irq(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args){
|
||||
mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
|
||||
mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)MP_OBJ_TYPE_GET_SLOT(s->type, protocol);
|
||||
if (spi_p->set_tx_isr != NULL)
|
||||
{
|
||||
spi_p->set_tx_isr(s, n_args - 1, args + 1, kw_args);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
static MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_set_tx_irq_obj, 1, mp_machine_spi_set_tx_irq);
|
||||
|
||||
static mp_obj_t mp_machine_spi_read(size_t n_args, const mp_obj_t *args)
|
||||
{
|
||||
vstr_t vstr;
|
||||
@ -128,6 +139,7 @@ static const mp_rom_map_elem_t machine_spi_locals_dict_table[] = {
|
||||
{MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_machine_spi_write_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&mp_machine_spi_write_readinto_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_wait_done), MP_ROM_PTR(&mp_machine_spi_wait_done_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_set_tx_irq), MP_ROM_PTR(&machine_spi_set_tx_irq_obj)},
|
||||
|
||||
{MP_ROM_QSTR(MP_QSTR_MSB), MP_ROM_INT(MICROPY_PY_MACHINE_SPI_MSB)},
|
||||
{MP_ROM_QSTR(MP_QSTR_LSB), MP_ROM_INT(MICROPY_PY_MACHINE_SPI_LSB)},
|
||||
|
||||
@ -194,6 +194,7 @@ typedef struct _mp_machine_spi_p_t
|
||||
void (*deinit)(mp_obj_base_t *obj); // can be NULL
|
||||
void (*transfer)(mp_obj_base_t *obj, size_t len, const uint8_t *src, uint8_t *dest);
|
||||
void (*wait_done)(mp_obj_base_t *obj); // can be NULL
|
||||
void (*set_tx_isr)(mp_obj_base_t *obj, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); // can be NULL
|
||||
} mp_machine_spi_p_t;
|
||||
|
||||
// SoftSPI object.
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
make -j -C ports/rp2 BOARD=RPI_PICO USER_C_MODULES=../../user_modules/lv_binding_micropython/bindings.cmake
|
||||
|
||||
rm -rf ./ports/rp2/build-RPI_PICO/*
|
||||
|
||||
make -j -C ports/rp2 BOARD=RPI_PICO USER_C_MODULES=../../user_modules/user.cmake
|
||||
exit status=$?
|
||||
# 检查编译是否成功
|
||||
if [ $? -eq 0 ]; then
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "shared/runtime/mpirq.h"
|
||||
#include "extmod/modmachine.h"
|
||||
|
||||
#include "hardware/spi.h"
|
||||
@ -104,6 +105,8 @@ typedef struct _machine_spi_obj_t
|
||||
uint32_t baudrate;
|
||||
int chan_tx;
|
||||
int chan_rx;
|
||||
// 这里只为屏幕设置了tx中断,用来控制cs引脚和lv.disp_flush_ready()
|
||||
mp_irq_obj_t *tx_isr_obj;
|
||||
} machine_spi_obj_t;
|
||||
|
||||
static machine_spi_obj_t machine_spi_obj[] = {
|
||||
@ -122,6 +125,7 @@ static machine_spi_obj_t machine_spi_obj[] = {
|
||||
// DMA channels, -1 means not claimed
|
||||
-1,
|
||||
-1,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
{&machine_spi_type},
|
||||
@ -138,6 +142,7 @@ static machine_spi_obj_t machine_spi_obj[] = {
|
||||
// DMA channels, -1 means not claimed
|
||||
-1,
|
||||
-1,
|
||||
NULL
|
||||
},
|
||||
};
|
||||
|
||||
@ -314,6 +319,87 @@ static void machine_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj
|
||||
}
|
||||
}
|
||||
|
||||
static void machine_spi0_tx_irq_handler(void)
|
||||
{
|
||||
// currently only used for spi0
|
||||
machine_spi_obj_t *self = &machine_spi_obj[0];
|
||||
spi_hw_t *spi_hw = spi_get_hw(self->spi_inst);
|
||||
// clear the interrupt flag
|
||||
spi_hw->imsc &= ~(1 << 3);
|
||||
// 检查是否是发送FIFO中断(已屏蔽的中断)
|
||||
// if (spi_hw->mis & (1 << 3)) { // TXMIS=1
|
||||
// 确认发送真正完成:发送FIFO为空且SPI不忙
|
||||
// mp_raise_msg_varg(&mp_type_AssertionError, MP_ERROR_TEXT("IRQ triggered"));
|
||||
if ((spi_hw->sr & (1 << 0)) && !(spi_hw->sr & (1 << 4)) && dma_channel_is_busy(self->chan_tx) == false) {
|
||||
if (self->tx_isr_obj != NULL && self->tx_isr_obj->handler != mp_const_none)
|
||||
{
|
||||
mp_irq_handler(self->tx_isr_obj);
|
||||
}
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
static void machine_spi1_tx_irq_handler(void)
|
||||
{
|
||||
// currently not used
|
||||
machine_spi_obj_t *self = &machine_spi_obj[1];
|
||||
spi_hw_t *spi_hw = spi_get_hw(self->spi_inst);
|
||||
// clear the interrupt flag
|
||||
spi_hw->imsc &= ~(1 << 3);
|
||||
if (spi_hw->mis & (1 << 3)) { // TXMIS=1
|
||||
// 确认发送真正完成:发送FIFO为空且SPI不忙
|
||||
if ((spi_hw->sr & (1 << 0)) && !(spi_hw->sr & (1 << 4))) {
|
||||
if (self->tx_isr_obj != NULL && self->tx_isr_obj->handler != mp_const_none)
|
||||
{
|
||||
mp_irq_handler(self->tx_isr_obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void machine_spi_set_tx_isr(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
|
||||
{
|
||||
machine_spi_obj_t *self = (machine_spi_obj_t *)self_in;
|
||||
if (self->tx_isr_obj == NULL) {
|
||||
self->tx_isr_obj = m_new_obj(mp_irq_obj_t);
|
||||
// MP_STATE_PORT(rp2_uart_irq_obj)[self->uart_id] = self->mp_irq_obj;
|
||||
}
|
||||
enum
|
||||
{
|
||||
ARG_tx_isr,
|
||||
};
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{MP_QSTR_tx_isr, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none}},
|
||||
};
|
||||
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);
|
||||
|
||||
if (n_args < 1) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("missing tx_isr"));
|
||||
}
|
||||
mp_obj_t handler = args[ARG_tx_isr].u_obj;
|
||||
if (handler == mp_const_none || !mp_obj_is_callable(handler)) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("handler must be callable"));
|
||||
}
|
||||
if (self->tx_isr_obj == NULL) {
|
||||
// disable previous irq
|
||||
}
|
||||
irq_set_enabled(self->spi_id == 0 ? SPI0_IRQ : SPI1_IRQ, false);
|
||||
self->tx_isr_obj->handler = handler;
|
||||
// self->tx_isr_obj->base.type = &mp_type_irq;
|
||||
// self->tx_isr_obj->methods = &mp_irq_methods;
|
||||
self->tx_isr_obj->ishard = true;
|
||||
self->tx_isr_obj->parent = MP_OBJ_FROM_PTR(self);
|
||||
|
||||
irq_set_exclusive_handler(self->spi_id == 0 ? SPI0_IRQ : SPI1_IRQ, self->spi_id == 0 ? machine_spi0_tx_irq_handler : machine_spi1_tx_irq_handler);
|
||||
spi_hw_t *spi_hw = spi_get_hw(self->spi_inst);
|
||||
spi_hw->imsc |= (1 << 3);
|
||||
irq_set_enabled(self->spi_id == 0 ? SPI0_IRQ : SPI1_IRQ, true);
|
||||
|
||||
}
|
||||
|
||||
static void machine_spi_wait_done(mp_obj_base_t *self_in)
|
||||
{
|
||||
machine_spi_obj_t *self = (machine_spi_obj_t *)self_in;
|
||||
@ -332,6 +418,17 @@ static void machine_spi_wait_done(mp_obj_base_t *self_in)
|
||||
static void machine_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest)
|
||||
{
|
||||
machine_spi_obj_t *self = (machine_spi_obj_t *)self_in;
|
||||
bool write_only = dest == NULL;
|
||||
const size_t dma_min_size_threshold = 8;
|
||||
if (len <= dma_min_size_threshold){
|
||||
// Use software for small transfers
|
||||
if (write_only) {
|
||||
spi_write_blocking(self->spi_inst, src, len);
|
||||
} else {
|
||||
spi_write_read_blocking(self->spi_inst, src, dest, len);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Use DMA for large transfers if channels are available
|
||||
int chan_tx = self->chan_tx;
|
||||
int chan_rx = self->chan_rx;
|
||||
@ -340,13 +437,13 @@ static void machine_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8
|
||||
mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Error when using DMA, chan rx: %d, chan tx: %d"), chan_rx, chan_tx);
|
||||
return;
|
||||
}
|
||||
if (chan_rx >= 0)
|
||||
dma_channel_wait_for_finish_blocking(chan_rx);
|
||||
if (chan_tx >= 0)
|
||||
dma_channel_wait_for_finish_blocking(chan_tx);
|
||||
// if (chan_rx >= 0)
|
||||
// dma_channel_wait_for_finish_blocking(chan_rx);
|
||||
// if (chan_tx >= 0)
|
||||
// dma_channel_wait_for_finish_blocking(chan_tx);
|
||||
machine_spi_wait_done(self_in);
|
||||
// bool use_dma = chan_rx >= 0 && chan_tx >= 0;
|
||||
// note src is guaranteed to be non-NULL
|
||||
bool write_only = dest == NULL;
|
||||
|
||||
uint8_t dev_null;
|
||||
dma_channel_config c;
|
||||
@ -413,8 +510,11 @@ static const mp_machine_spi_p_t machine_spi_p = {
|
||||
.init = machine_spi_init,
|
||||
.transfer = machine_spi_transfer,
|
||||
.wait_done = machine_spi_wait_done,
|
||||
.set_tx_isr = machine_spi_set_tx_isr,
|
||||
};
|
||||
|
||||
|
||||
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
machine_spi_type,
|
||||
MP_QSTR_SPI,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user