merge implementation of new spitarget api
This commit is contained in:
commit
821b7f2cbf
66 changed files with 668 additions and 450 deletions
53
.github/workflows/build-rapid-0.yaml
vendored
Normal file
53
.github/workflows/build-rapid-0.yaml
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
name: Build RAPID-0 Boards
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
board: [rapid0_adcs, rapid0_cdh, rapid0_eps]
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: false
|
||||
show-progress: false
|
||||
fetch-depth: 1
|
||||
- name: Set up python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.x
|
||||
- name: Set up ports
|
||||
id: set-up-port
|
||||
uses: ./.github/actions/deps/ports
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
- name: Set up submodules
|
||||
id: set-up-submodules
|
||||
uses: ./.github/actions/deps/submodules
|
||||
with:
|
||||
action: cache
|
||||
version: true
|
||||
- name: Set up external
|
||||
uses: ./.github/actions/deps/external
|
||||
with:
|
||||
action: cache
|
||||
port: ${{ steps.set-up-port.outputs.port }}
|
||||
- name: Set up mpy-cross
|
||||
if: steps.set-up-submodules.outputs.frozen == 'True'
|
||||
uses: ./.github/actions/mpy_cross
|
||||
with:
|
||||
cp-version: ${{ steps.set-up-submodules.outputs.version }}
|
||||
download: false
|
||||
- name: Build boards
|
||||
run: make -j4 -C ports/atmel-samd BOARD=${{ matrix.board }}
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.board }}
|
||||
path: ports/atmel-samd/build-${{ matrix.board }}/firmware.*
|
||||
overwrite: true
|
||||
|
||||
18
build-rapid0-mac
Executable file
18
build-rapid0-mac
Executable file
|
|
@ -0,0 +1,18 @@
|
|||
if echo $PATH | grep "gcc-arm-none-eabi" >/dev/null; then
|
||||
true
|
||||
else
|
||||
export PATH=/Volumes/Circuit_Python_Case_Sensitive_Disk/bruinspace-circuitpython/gcc-arm-none-eabi-10-2020-q4-major/bin:$PATH
|
||||
fi
|
||||
|
||||
cd ports/atmel-samd
|
||||
make --debug -j8 BOARD=rapid0_adcs
|
||||
make --debug -j8 BOARD=rapid0_cdh
|
||||
make --debug -j8 BOARD=rapid0_eps
|
||||
cd ../..
|
||||
|
||||
echo "Compilation complete! Press ^C to confirm and exit."
|
||||
|
||||
while true; do
|
||||
afplay /System/Library/Sounds/Ping.aiff
|
||||
sleep 5s
|
||||
done
|
||||
17
build-rapid0-ubuntu
Normal file
17
build-rapid0-ubuntu
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
if echo $PATH | grep "gcc-arm-none-eabi" >/dev/null
|
||||
then
|
||||
true
|
||||
else
|
||||
export PATH=/mnt/d/Files/Documents/School/UCLA/Organizations/BruinSpace/Rapid-CDH/gcc-arm-none-eabi-10-2020-q4-major/bin:$PATH
|
||||
fi
|
||||
cd ports/atmel-samd
|
||||
make --debug -j8 BOARD=rapid0_adcs
|
||||
make --debug -j8 BOARD=rapid0_cdh
|
||||
make --debug -j8 BOARD=rapid0_eps
|
||||
cd ../..
|
||||
echo "Compilation complete! Press ^C to confirm and exit."
|
||||
while true;
|
||||
do
|
||||
paplay /usr/share/sounds/freedesktop/stereo/complete.oga
|
||||
sleep 5s
|
||||
done
|
||||
|
|
@ -72,6 +72,7 @@ as a natural "TODO" list. An example minimal build list is shown below:
|
|||
CIRCUITPY_FRAMEBUFFERIO = 0
|
||||
CIRCUITPY_FREQUENCYIO = 0
|
||||
CIRCUITPY_I2CTARGET = 0
|
||||
CIRCUITPY_SPITARGET = 0
|
||||
# Requires SPI, PulseIO (stub ok):
|
||||
CIRCUITPY_DISPLAYIO = 0
|
||||
|
||||
|
|
|
|||
|
|
@ -1055,10 +1055,6 @@ msgstr ""
|
|||
msgid "Hard fault: memory access or instruction error."
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/busio/SPI.c
|
||||
msgid "Hardware SS pin only supported for slave mode"
|
||||
msgstr ""
|
||||
|
||||
#: ports/mimxrt10xx/common-hal/busio/SPI.c
|
||||
#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/I2C.c
|
||||
#: ports/stm/common-hal/busio/SPI.c ports/stm/common-hal/busio/UART.c
|
||||
|
|
@ -1343,10 +1339,6 @@ msgstr ""
|
|||
msgid "Must provide MISO or MOSI pin"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/busio/SPI.c
|
||||
msgid "Must provide SS pin to operate in slave mode"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/rgbmatrix/RGBMatrix.c
|
||||
#, c-format
|
||||
msgid "Must use a multiple of 6 rgb pins, not %d"
|
||||
|
|
@ -1891,12 +1883,6 @@ msgstr ""
|
|||
msgid "Size not supported"
|
||||
msgstr ""
|
||||
|
||||
#: ports/cxd56/common-hal/busio/SPI.c ports/espressif/common-hal/busio/SPI.c
|
||||
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/nrf/common-hal/busio/SPI.c
|
||||
#: ports/raspberrypi/common-hal/busio/SPI.c ports/stm/common-hal/busio/SPI.c
|
||||
msgid "Slave mode SPI is not implemented"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/alarm/SleepMemory.c shared-bindings/memorymap/AddressRange.c
|
||||
#: shared-bindings/nvm/ByteArray.c
|
||||
msgid "Slice and value different lengths."
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_PA01, &pin_PA00, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_PA01, &pin_PA00, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_PA13, &pin_PA12, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_PA13, &pin_PA12, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ uint8_t refresh_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_PB13, &pin_PB15, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_PB13, &pin_PB15, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_PA23, &pin_PA22, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_PA23, &pin_PA22, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_PA13, &pin_PA15, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_PA13, &pin_PA15, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_PB13, &pin_PB15, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_PB13, &pin_PB15, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_PB13, &pin_PB15, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_PB13, &pin_PB15, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_PB20, &pin_PB19, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_PB20, &pin_PB19, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -37,14 +37,13 @@
|
|||
|
||||
#include "hal/include/hal_gpio.h"
|
||||
#include "hal/include/hal_spi_m_sync.h"
|
||||
#include "hal/include/hpl_spi_m_sync.h"
|
||||
|
||||
#include "samd/dma.h"
|
||||
#include "samd/sercom.h"
|
||||
|
||||
void common_hal_busio_spi_construct(busio_spi_obj_t *self,
|
||||
const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi,
|
||||
const mcu_pin_obj_t *miso, const mcu_pin_obj_t *ss, bool half_duplex, bool slave_mode) {
|
||||
const mcu_pin_obj_t *miso, bool half_duplex) {
|
||||
Sercom *sercom = NULL;
|
||||
uint8_t sercom_index;
|
||||
uint32_t clock_pinmux = 0;
|
||||
|
|
@ -52,7 +51,6 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
|
|||
bool miso_none = miso == NULL;
|
||||
uint32_t mosi_pinmux = 0;
|
||||
uint32_t miso_pinmux = 0;
|
||||
uint32_t ss_pinmux = 0;
|
||||
uint8_t clock_pad = 0;
|
||||
uint8_t mosi_pad = 0;
|
||||
uint8_t miso_pad = 0;
|
||||
|
|
@ -97,87 +95,36 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
|
|||
if (!samd_peripherals_valid_spi_clock_pad(clock_pad)) {
|
||||
continue;
|
||||
}
|
||||
if (slave_mode) {
|
||||
// find miso_pad first, since it corresponds to dopo which takes limited values
|
||||
for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) {
|
||||
if (!miso_none) {
|
||||
if (sercom_index == miso->sercom[j].index) {
|
||||
miso_pinmux = PINMUX(miso->number, (j == 0) ? MUX_C : MUX_D);
|
||||
miso_pad = miso->sercom[j].pad;
|
||||
dopo = samd_peripherals_get_spi_dopo(clock_pad, miso_pad);
|
||||
if (dopo > 0x3) {
|
||||
continue; // pad combination not possible
|
||||
}
|
||||
if (mosi_none) {
|
||||
for (int m = 0; m < NUM_SERCOMS_PER_PIN; m++) {
|
||||
if (sercom_index == ss->sercom[m].index) {
|
||||
ss_pinmux = PINMUX(ss->number, (m == 0) ? MUX_C : MUX_D);
|
||||
sercom = potential_sercom;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sercom != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
// find mosi_pad first, since it corresponds to dopo which takes limited values
|
||||
for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) {
|
||||
if (!mosi_none) {
|
||||
if (sercom_index == mosi->sercom[j].index) {
|
||||
mosi_pinmux = PINMUX(mosi->number, (j == 0) ? MUX_C : MUX_D);
|
||||
mosi_pad = mosi->sercom[j].pad;
|
||||
dopo = samd_peripherals_get_spi_dopo(clock_pad, mosi_pad);
|
||||
if (dopo > 0x3) {
|
||||
continue; // pad combination not possible
|
||||
}
|
||||
}
|
||||
if (!mosi_none) {
|
||||
for (int k = 0; k < NUM_SERCOMS_PER_PIN; k++) {
|
||||
if (sercom_index == mosi->sercom[k].index) {
|
||||
mosi_pinmux = PINMUX(mosi->number, (k == 0) ? MUX_C : MUX_D);
|
||||
mosi_pad = mosi->sercom[k].pad;
|
||||
for (int m = 0; m < NUM_SERCOMS_PER_PIN; m++) {
|
||||
if (sercom_index == ss->sercom[m].index) {
|
||||
ss_pinmux = PINMUX(ss->number, (m == 0) ? MUX_C : MUX_D);
|
||||
sercom = potential_sercom;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sercom != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (miso_none) {
|
||||
sercom = potential_sercom;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sercom != NULL) {
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// find mosi_pad first, since it corresponds to dopo which takes limited values
|
||||
for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) {
|
||||
if (!mosi_none) {
|
||||
if (sercom_index == mosi->sercom[j].index) {
|
||||
mosi_pinmux = PINMUX(mosi->number, (j == 0) ? MUX_C : MUX_D);
|
||||
mosi_pad = mosi->sercom[j].pad;
|
||||
dopo = samd_peripherals_get_spi_dopo(clock_pad, mosi_pad);
|
||||
if (dopo > 0x3) {
|
||||
continue; // pad combination not possible
|
||||
}
|
||||
if (miso_none) {
|
||||
sercom = potential_sercom;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
if (!miso_none) {
|
||||
for (int k = 0; k < NUM_SERCOMS_PER_PIN; k++) {
|
||||
if (sercom_index == miso->sercom[k].index) {
|
||||
miso_pinmux = PINMUX(miso->number, (k == 0) ? MUX_C : MUX_D);
|
||||
miso_pad = miso->sercom[k].pad;
|
||||
sercom = potential_sercom;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!miso_none) {
|
||||
for (int k = 0; k < NUM_SERCOMS_PER_PIN; k++) {
|
||||
if (sercom_index == miso->sercom[k].index) {
|
||||
miso_pinmux = PINMUX(miso->number, (k == 0) ? MUX_C : MUX_D);
|
||||
miso_pad = miso->sercom[k].pad;
|
||||
sercom = potential_sercom;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sercom != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sercom != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sercom != NULL) {
|
||||
|
|
@ -199,11 +146,9 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
|
|||
// Pads must be set after spi_m_sync_init(), which uses default values from
|
||||
// the prototypical SERCOM.
|
||||
|
||||
hri_sercomspi_write_CTRLA_MODE_bf(sercom, slave_mode ? 2 : 3);
|
||||
self->slave_mode = slave_mode;
|
||||
hri_sercomspi_write_CTRLA_MODE_bf(sercom, 3);
|
||||
hri_sercomspi_write_CTRLA_DOPO_bf(sercom, dopo);
|
||||
hri_sercomspi_write_CTRLA_DIPO_bf(sercom, slave_mode ? mosi_pad : miso_pad);
|
||||
hri_sercomspi_write_CTRLB_PLOADEN_bit(sercom, slave_mode);
|
||||
hri_sercomspi_write_CTRLA_DIPO_bf(sercom, miso_pad);
|
||||
|
||||
// Always start at 250khz which is what SD cards need. They are sensitive to
|
||||
// SPI bus noise before they are put into SPI mode.
|
||||
|
|
@ -214,7 +159,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
|
|||
mp_raise_OSError(MP_EIO);
|
||||
}
|
||||
|
||||
gpio_set_pin_direction(clock->number, slave_mode ? GPIO_DIRECTION_IN : GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_direction(clock->number, GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_pull_mode(clock->number, GPIO_PULL_OFF);
|
||||
gpio_set_pin_function(clock->number, clock_pinmux);
|
||||
claim_pin(clock);
|
||||
|
|
@ -224,7 +169,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
|
|||
if (mosi_none) {
|
||||
self->MOSI_pin = NO_PIN;
|
||||
} else {
|
||||
gpio_set_pin_direction(mosi->number, slave_mode ? GPIO_DIRECTION_IN : GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_direction(mosi->number, GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_pull_mode(mosi->number, GPIO_PULL_OFF);
|
||||
gpio_set_pin_function(mosi->number, mosi_pinmux);
|
||||
self->MOSI_pin = mosi->number;
|
||||
|
|
@ -235,7 +180,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
|
|||
if (miso_none) {
|
||||
self->MISO_pin = NO_PIN;
|
||||
} else {
|
||||
gpio_set_pin_direction(miso->number, slave_mode ? GPIO_DIRECTION_OUT : GPIO_DIRECTION_IN);
|
||||
gpio_set_pin_direction(miso->number, GPIO_DIRECTION_IN);
|
||||
gpio_set_pin_pull_mode(miso->number, GPIO_PULL_OFF);
|
||||
gpio_set_pin_function(miso->number, miso_pinmux);
|
||||
self->MISO_pin = miso->number;
|
||||
|
|
@ -243,17 +188,6 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
|
|||
hri_port_set_PINCFG_DRVSTR_bit(PORT, (enum gpio_port)GPIO_PORT(miso->number), GPIO_PIN(miso->number));
|
||||
}
|
||||
|
||||
if (slave_mode) {
|
||||
gpio_set_pin_direction(ss->number, slave_mode ? GPIO_DIRECTION_OUT : GPIO_DIRECTION_IN);
|
||||
gpio_set_pin_pull_mode(ss->number, GPIO_PULL_OFF);
|
||||
gpio_set_pin_function(ss->number, ss_pinmux);
|
||||
self->SS_pin = ss->number;
|
||||
claim_pin(ss);
|
||||
hri_port_set_PINCFG_DRVSTR_bit(PORT, (enum gpio_port)GPIO_PORT(ss->number), GPIO_PIN(ss->number));
|
||||
}
|
||||
|
||||
self->running_dma.failure = 1; // not started
|
||||
|
||||
spi_m_sync_enable(&self->spi_desc);
|
||||
}
|
||||
|
||||
|
|
@ -336,9 +270,6 @@ bool common_hal_busio_spi_write(busio_spi_obj_t *self,
|
|||
if (len == 0) {
|
||||
return true;
|
||||
}
|
||||
if (self->running_dma.failure != 1) {
|
||||
mp_raise_RuntimeError(MP_ERROR_TEXT("Async SPI transfer in progress on this bus, keep awaiting."));
|
||||
}
|
||||
int32_t status;
|
||||
if (len >= 16) {
|
||||
size_t bytes_remaining = len;
|
||||
|
|
@ -369,9 +300,6 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self,
|
|||
if (len == 0) {
|
||||
return true;
|
||||
}
|
||||
if (self->running_dma.failure != 1) {
|
||||
mp_raise_RuntimeError(MP_ERROR_TEXT("Async SPI transfer in progress on this bus, keep awaiting."));
|
||||
}
|
||||
int32_t status;
|
||||
if (len >= 16) {
|
||||
status = sercom_dma_read(self->spi_desc.dev.prvt, data, len, write_value);
|
||||
|
|
@ -390,9 +318,6 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, const uint8_t *data_ou
|
|||
if (len == 0) {
|
||||
return true;
|
||||
}
|
||||
if (self->running_dma.failure != 1) {
|
||||
mp_raise_RuntimeError(MP_ERROR_TEXT("Async SPI transfer in progress on this bus, keep awaiting."));
|
||||
}
|
||||
int32_t status;
|
||||
if (len >= 16) {
|
||||
status = sercom_dma_transfer(self->spi_desc.dev.prvt, data_out, data_in, len);
|
||||
|
|
@ -406,62 +331,6 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, const uint8_t *data_ou
|
|||
return status >= 0; // Status is number of chars read or an error code < 0.
|
||||
}
|
||||
|
||||
void common_hal_busio_spi_transfer_async_start(busio_spi_obj_t *self, const uint8_t *data_out, uint8_t *data_in, size_t len) {
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
if (self->running_dma.failure != 1) {
|
||||
mp_raise_RuntimeError(MP_ERROR_TEXT("Async SPI transfer in progress on this bus, keep awaiting."));
|
||||
}
|
||||
Sercom* sercom = self->spi_desc.dev.prvt;
|
||||
self->running_dma = shared_dma_transfer_start(sercom, data_out, &sercom->SPI.DATA.reg, &sercom->SPI.DATA.reg, data_in, len, 0);
|
||||
|
||||
// There is an issue where if an unexpected SPI transfer is received before the user calls "end" for the in-progress, expected
|
||||
// transfer, the SERCOM has an error and gets confused. This can be detected from INTFLAG.ERROR. I think the code in
|
||||
// ports/atmel-samd/peripherals/samd/dma.c at line 277 (as of this commit; it's the part that reads s->SPI.INTFLAG.bit.RXC and
|
||||
// s->SPI.DATA.reg) is supposed to fix this, but experimentation seems to show that it does not in fact fix anything. Anyways, if
|
||||
// the ERROR bit is set, let's just reset the peripheral and then setup the transfer again -- that seems to work.
|
||||
if (hri_sercomspi_get_INTFLAG_ERROR_bit(sercom)) {
|
||||
shared_dma_transfer_close(self->running_dma);
|
||||
|
||||
// disable the sercom
|
||||
spi_m_sync_disable(&self->spi_desc);
|
||||
hri_sercomspi_wait_for_sync(sercom, SERCOM_SPI_SYNCBUSY_MASK);
|
||||
|
||||
// save configurations
|
||||
hri_sercomspi_ctrla_reg_t ctrla_saved_val = hri_sercomspi_get_CTRLA_reg(sercom, -1); // -1 mask is all ones: save all bits
|
||||
hri_sercomspi_ctrlb_reg_t ctrlb_saved_val = hri_sercomspi_get_CTRLB_reg(sercom, -1); // -1 mask is all ones: save all bits
|
||||
hri_sercomspi_baud_reg_t baud_saved_val = hri_sercomspi_get_BAUD_reg(sercom, -1); // -1 mask is all ones: save all bits
|
||||
// reset
|
||||
hri_sercomspi_set_CTRLA_SWRST_bit(sercom);
|
||||
hri_sercomspi_wait_for_sync(sercom, SERCOM_SPI_SYNCBUSY_MASK);
|
||||
// re-write configurations
|
||||
hri_sercomspi_write_CTRLA_reg(sercom, ctrla_saved_val);
|
||||
hri_sercomspi_write_CTRLB_reg(sercom, ctrlb_saved_val);
|
||||
hri_sercomspi_write_BAUD_reg (sercom, baud_saved_val);
|
||||
hri_sercomspi_wait_for_sync(sercom, SERCOM_SPI_SYNCBUSY_MASK);
|
||||
|
||||
// re-enable the sercom
|
||||
spi_m_sync_enable(&self->spi_desc);
|
||||
hri_sercomspi_wait_for_sync(sercom, SERCOM_SPI_SYNCBUSY_MASK);
|
||||
|
||||
self->running_dma = shared_dma_transfer_start(sercom, data_out, &sercom->SPI.DATA.reg, &sercom->SPI.DATA.reg, data_in, len, 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool common_hal_busio_spi_transfer_async_check(busio_spi_obj_t *self) {
|
||||
return self->running_dma.failure == 1 || shared_dma_transfer_finished(self->running_dma);
|
||||
}
|
||||
|
||||
int common_hal_busio_spi_transfer_async_end(busio_spi_obj_t *self) {
|
||||
if (self->running_dma.failure == 1) {
|
||||
return 0;
|
||||
}
|
||||
int res = shared_dma_transfer_close(self->running_dma);
|
||||
self->running_dma.failure = 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t *self) {
|
||||
return samd_peripherals_spi_baud_reg_value_to_baudrate(hri_sercomspi_read_BAUD_reg(self->spi_desc.dev.prvt));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,9 +40,6 @@ typedef struct {
|
|||
uint8_t clock_pin;
|
||||
uint8_t MOSI_pin;
|
||||
uint8_t MISO_pin;
|
||||
uint8_t SS_pin;
|
||||
bool slave_mode;
|
||||
dma_descr_t running_dma;
|
||||
} busio_spi_obj_t;
|
||||
|
||||
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_BUSIO_SPI_H
|
||||
|
|
|
|||
235
ports/atmel-samd/common-hal/spitarget/SPITarget.c
Normal file
235
ports/atmel-samd/common-hal/spitarget/SPITarget.c
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
#include "common-hal/spitarget/SPITarget.h"
|
||||
#include "common-hal/busio/__init__.h"
|
||||
|
||||
#include "shared-bindings/spitarget/SPITarget.h"
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#include "hpl_sercom_config.h"
|
||||
#include "peripheral_clk_config.h"
|
||||
|
||||
#include "hal/include/hal_gpio.h"
|
||||
#include "hal/include/hal_spi_m_sync.h"
|
||||
|
||||
#include "hpl_sercom_config.h"
|
||||
#include "samd/sercom.h"
|
||||
|
||||
void common_hal_spitarget_spi_target_construct(spitarget_spi_target_obj_t *self,
|
||||
const mcu_pin_obj_t *sck, const mcu_pin_obj_t *mosi,
|
||||
const mcu_pin_obj_t *miso, const mcu_pin_obj_t *ss) {
|
||||
Sercom *sercom = NULL;
|
||||
uint8_t sercom_index;
|
||||
uint32_t clock_pinmux = 0;
|
||||
uint32_t mosi_pinmux = 0;
|
||||
uint32_t miso_pinmux = 0;
|
||||
uint32_t ss_pinmux = 0;
|
||||
uint8_t clock_pad = 0;
|
||||
uint8_t mosi_pad = 0;
|
||||
uint8_t miso_pad = 0;
|
||||
uint8_t dopo = 255;
|
||||
|
||||
// Ensure the object starts in its deinit state.
|
||||
self->clock_pin = NO_PIN;
|
||||
|
||||
// Special case for SAMR21 boards. (feather_radiofruit_zigbee)
|
||||
#if defined(PIN_PC19F_SERCOM4_PAD0)
|
||||
if (miso == &pin_PC19) {
|
||||
if (mosi == &pin_PB30 && sck == &pin_PC18) {
|
||||
sercom = SERCOM4;
|
||||
sercom_index = 4;
|
||||
clock_pinmux = MUX_F;
|
||||
mosi_pinmux = MUX_F;
|
||||
miso_pinmux = MUX_F;
|
||||
clock_pad = 3;
|
||||
mosi_pad = 2;
|
||||
miso_pad = 0;
|
||||
dopo = samd_peripherals_get_spi_dopo(clock_pad, mosi_pad);
|
||||
}
|
||||
// Error, leave SERCOM unset to throw an exception later.
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
for (int i = 0; i < NUM_SERCOMS_PER_PIN; i++) {
|
||||
sercom_index = sck->sercom[i].index; // 2 for SERCOM2, etc.
|
||||
if (sercom_index >= SERCOM_INST_NUM) {
|
||||
continue;
|
||||
}
|
||||
Sercom *potential_sercom = sercom_insts[sercom_index];
|
||||
if (potential_sercom->SPI.CTRLA.bit.ENABLE != 0) {
|
||||
continue;
|
||||
}
|
||||
clock_pinmux = PINMUX(sck->number, (i == 0) ? MUX_C : MUX_D);
|
||||
clock_pad = sck->sercom[i].pad;
|
||||
if (!samd_peripherals_valid_spi_clock_pad(clock_pad)) {
|
||||
continue;
|
||||
}
|
||||
// find miso_pad first, since it corresponds to dopo which takes limited values
|
||||
for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) {
|
||||
if (sercom_index == miso->sercom[j].index) {
|
||||
miso_pinmux = PINMUX(miso->number, (j == 0) ? MUX_C : MUX_D);
|
||||
miso_pad = miso->sercom[j].pad;
|
||||
dopo = samd_peripherals_get_spi_dopo(clock_pad, miso_pad);
|
||||
if (dopo > 0x3) {
|
||||
continue; // pad combination not possible
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
for (int k = 0; k < NUM_SERCOMS_PER_PIN; k++) {
|
||||
if (sercom_index == mosi->sercom[k].index) {
|
||||
mosi_pinmux = PINMUX(mosi->number, (k == 0) ? MUX_C : MUX_D);
|
||||
mosi_pad = mosi->sercom[k].pad;
|
||||
for (int m = 0; m < NUM_SERCOMS_PER_PIN; m++) {
|
||||
if (sercom_index == ss->sercom[m].index) {
|
||||
ss_pinmux = PINMUX(ss->number, (m == 0) ? MUX_C : MUX_D);
|
||||
sercom = potential_sercom;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sercom != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sercom != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sercom != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sercom == NULL) {
|
||||
raise_ValueError_invalid_pins();
|
||||
}
|
||||
|
||||
// Set up SPI clocks on SERCOM.
|
||||
samd_peripherals_sercom_clock_init(sercom, sercom_index);
|
||||
|
||||
if (spi_m_sync_init(&self->spi_desc, sercom) != ERR_NONE) {
|
||||
mp_raise_OSError(MP_EIO);
|
||||
}
|
||||
|
||||
// Pads must be set after spi_m_sync_init(), which uses default values from
|
||||
// the prototypical SERCOM.
|
||||
|
||||
hri_sercomspi_write_CTRLA_MODE_bf(sercom, 2);
|
||||
hri_sercomspi_write_CTRLA_DOPO_bf(sercom, dopo);
|
||||
hri_sercomspi_write_CTRLA_DIPO_bf(sercom, mosi_pad);
|
||||
hri_sercomspi_write_CTRLB_PLOADEN_bit(sercom, 1);
|
||||
|
||||
// Always start at 250khz which is what SD cards need. They are sensitive to
|
||||
// SPI bus noise before they are put into SPI mode.
|
||||
uint8_t baud_value = samd_peripherals_spi_baudrate_to_baud_reg_value(250000);
|
||||
if (spi_m_sync_set_baudrate(&self->spi_desc, baud_value) != ERR_NONE) {
|
||||
// spi_m_sync_set_baudrate does not check for validity, just whether the device is
|
||||
// busy or not
|
||||
mp_raise_OSError(MP_EIO);
|
||||
}
|
||||
|
||||
gpio_set_pin_direction(sck->number, GPIO_DIRECTION_IN);
|
||||
gpio_set_pin_pull_mode(sck->number, GPIO_PULL_OFF);
|
||||
gpio_set_pin_function(sck->number, clock_pinmux);
|
||||
claim_pin(sck);
|
||||
self->clock_pin = sck->number;
|
||||
|
||||
gpio_set_pin_direction(mosi->number, GPIO_DIRECTION_IN);
|
||||
gpio_set_pin_pull_mode(mosi->number, GPIO_PULL_OFF);
|
||||
gpio_set_pin_function(mosi->number, mosi_pinmux);
|
||||
self->MOSI_pin = mosi->number;
|
||||
claim_pin(mosi);
|
||||
|
||||
gpio_set_pin_direction(miso->number, GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_pull_mode(miso->number, GPIO_PULL_OFF);
|
||||
gpio_set_pin_function(miso->number, miso_pinmux);
|
||||
self->MISO_pin = miso->number;
|
||||
claim_pin(miso);
|
||||
|
||||
gpio_set_pin_direction(ss->number, GPIO_DIRECTION_IN);
|
||||
gpio_set_pin_pull_mode(ss->number, GPIO_PULL_OFF);
|
||||
gpio_set_pin_function(ss->number, ss_pinmux);
|
||||
self->SS_pin = ss->number;
|
||||
claim_pin(ss);
|
||||
|
||||
self->running_dma.failure = 1; // not started
|
||||
|
||||
spi_m_sync_enable(&self->spi_desc);
|
||||
}
|
||||
|
||||
bool common_hal_spitarget_spi_target_deinited(spitarget_spi_target_obj_t *self) {
|
||||
return self->clock_pin == NO_PIN;
|
||||
}
|
||||
|
||||
void common_hal_spitarget_spi_target_deinit(spitarget_spi_target_obj_t *self) {
|
||||
if (common_hal_spitarget_spi_target_deinited(self)) {
|
||||
return;
|
||||
}
|
||||
allow_reset_sercom(self->spi_desc.dev.prvt);
|
||||
|
||||
spi_m_sync_disable(&self->spi_desc);
|
||||
spi_m_sync_deinit(&self->spi_desc);
|
||||
reset_pin_number(self->clock_pin);
|
||||
reset_pin_number(self->MOSI_pin);
|
||||
reset_pin_number(self->MISO_pin);
|
||||
reset_pin_number(self->SS_pin);
|
||||
self->clock_pin = NO_PIN;
|
||||
}
|
||||
|
||||
void common_hal_spitarget_spi_target_transfer_start(spitarget_spi_target_obj_t *self,
|
||||
uint8_t *mosi_packet, const uint8_t *miso_packet, size_t len) {
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
if (self->running_dma.failure != 1) {
|
||||
mp_raise_RuntimeError(MP_ERROR_TEXT("Async SPI transfer in progress on this bus, keep awaiting."));
|
||||
}
|
||||
Sercom* sercom = self->spi_desc.dev.prvt;
|
||||
self->running_dma = shared_dma_transfer_start(sercom, miso_packet, &sercom->SPI.DATA.reg, &sercom->SPI.DATA.reg, mosi_packet, len, 0);
|
||||
|
||||
// There is an issue where if an unexpected SPI transfer is received before the user calls "end" for the in-progress, expected
|
||||
// transfer, the SERCOM has an error and gets confused. This can be detected from INTFLAG.ERROR. I think the code in
|
||||
// ports/atmel-samd/peripherals/samd/dma.c at line 277 (as of this commit; it's the part that reads s->SPI.INTFLAG.bit.RXC and
|
||||
// s->SPI.DATA.reg) is supposed to fix this, but experimentation seems to show that it does not in fact fix anything. Anyways, if
|
||||
// the ERROR bit is set, let's just reset the peripheral and then setup the transfer again -- that seems to work.
|
||||
if (hri_sercomspi_get_INTFLAG_ERROR_bit(sercom)) {
|
||||
shared_dma_transfer_close(self->running_dma);
|
||||
|
||||
// disable the sercom
|
||||
spi_m_sync_disable(&self->spi_desc);
|
||||
hri_sercomspi_wait_for_sync(sercom, SERCOM_SPI_SYNCBUSY_MASK);
|
||||
|
||||
// save configurations
|
||||
hri_sercomspi_ctrla_reg_t ctrla_saved_val = hri_sercomspi_get_CTRLA_reg(sercom, -1); // -1 mask is all ones: save all bits
|
||||
hri_sercomspi_ctrlb_reg_t ctrlb_saved_val = hri_sercomspi_get_CTRLB_reg(sercom, -1); // -1 mask is all ones: save all bits
|
||||
hri_sercomspi_baud_reg_t baud_saved_val = hri_sercomspi_get_BAUD_reg(sercom, -1); // -1 mask is all ones: save all bits
|
||||
// reset
|
||||
hri_sercomspi_set_CTRLA_SWRST_bit(sercom);
|
||||
hri_sercomspi_wait_for_sync(sercom, SERCOM_SPI_SYNCBUSY_MASK);
|
||||
// re-write configurations
|
||||
hri_sercomspi_write_CTRLA_reg(sercom, ctrla_saved_val);
|
||||
hri_sercomspi_write_CTRLB_reg(sercom, ctrlb_saved_val);
|
||||
hri_sercomspi_write_BAUD_reg (sercom, baud_saved_val);
|
||||
hri_sercomspi_wait_for_sync(sercom, SERCOM_SPI_SYNCBUSY_MASK);
|
||||
|
||||
// re-enable the sercom
|
||||
spi_m_sync_enable(&self->spi_desc);
|
||||
hri_sercomspi_wait_for_sync(sercom, SERCOM_SPI_SYNCBUSY_MASK);
|
||||
|
||||
self->running_dma = shared_dma_transfer_start(sercom, miso_packet, &sercom->SPI.DATA.reg, &sercom->SPI.DATA.reg, mosi_packet, len, 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool common_hal_spitarget_spi_target_transfer_is_finished(spitarget_spi_target_obj_t *self) {
|
||||
return self->running_dma.failure == 1 || shared_dma_transfer_finished(self->running_dma);
|
||||
}
|
||||
|
||||
int common_hal_spitarget_spi_target_transfer_close(spitarget_spi_target_obj_t *self) {
|
||||
if (self->running_dma.failure == 1) {
|
||||
return 0;
|
||||
}
|
||||
int res = shared_dma_transfer_close(self->running_dma);
|
||||
self->running_dma.failure = 1;
|
||||
return res;
|
||||
}
|
||||
21
ports/atmel-samd/common-hal/spitarget/SPITarget.h
Normal file
21
ports/atmel-samd/common-hal/spitarget/SPITarget.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_BUSIO_SPI_TARGET_H
|
||||
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_BUSIO_SPI_TARGET_H
|
||||
|
||||
#include "common-hal/microcontroller/Pin.h"
|
||||
#include "hal/include/hal_spi_m_sync.h"
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
|
||||
struct spi_m_sync_descriptor spi_desc;
|
||||
|
||||
uint8_t clock_pin;
|
||||
uint8_t MOSI_pin;
|
||||
uint8_t MISO_pin;
|
||||
uint8_t SS_pin;
|
||||
|
||||
dma_descr_t running_dma;
|
||||
} spitarget_spi_target_obj_t;
|
||||
|
||||
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_BUSIO_SPI_TARGET_H
|
||||
1
ports/atmel-samd/common-hal/spitarget/__init__.c
Normal file
1
ports/atmel-samd/common-hal/spitarget/__init__.c
Normal file
|
|
@ -0,0 +1 @@
|
|||
// No spitarget module functions.
|
||||
|
|
@ -46,6 +46,7 @@ CIRCUITPY_OS_GETENV ?= 0
|
|||
CIRCUITPY_PIXELMAP ?= 0
|
||||
CIRCUITPY_RE ?= 0
|
||||
CIRCUITPY_SDCARDIO ?= 0
|
||||
CIRCUITPY_SPITARGET ?= 0
|
||||
CIRCUITPY_SYNTHIO ?= 0
|
||||
CIRCUITPY_TOUCHIO_USE_NATIVE ?= 1
|
||||
CIRCUITPY_TRACEBACK ?= 0
|
||||
|
|
@ -105,6 +106,7 @@ CIRCUITPY_FRAMEBUFFERIO ?= $(CIRCUITPY_FULL_BUILD)
|
|||
CIRCUITPY_PS2IO ?= 1
|
||||
CIRCUITPY_RGBMATRIX ?= $(CIRCUITPY_FRAMEBUFFERIO)
|
||||
CIRCUITPY_SAMD ?= 1
|
||||
CIRCUITPY_SPITARGET ?= 1
|
||||
CIRCUITPY_SYNTHIO_MAX_CHANNELS = 12
|
||||
CIRCUITPY_ULAB_OPTIMIZE_SIZE ?= 1
|
||||
CIRCUITPY_WATCHDOG ?= 1
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ void reset_spi(void) {
|
|||
|
||||
void common_hal_busio_spi_construct(busio_spi_obj_t *self,
|
||||
const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi,
|
||||
const mcu_pin_obj_t *miso, const mcu_pin_obj_t *ss, bool half_duplex, bool slave_mode) {
|
||||
const mcu_pin_obj_t *miso, bool half_duplex) {
|
||||
size_t instance_index = NUM_SPI;
|
||||
BP_Function_Enum clock_alt = 0;
|
||||
BP_Function_Enum mosi_alt = 0;
|
||||
|
|
@ -86,9 +86,6 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
|
|||
if (half_duplex) {
|
||||
mp_raise_NotImplementedError(MP_ERROR_TEXT("Half duplex SPI is not implemented"));
|
||||
}
|
||||
if (slave_mode) {
|
||||
mp_raise_NotImplementedError(MP_ERROR_TEXT("Slave mode SPI is not implemented"));
|
||||
}
|
||||
|
||||
// BCM_VERSION != 2711 have 3 SPI but as listed in peripherals/gen/pins.c two are on
|
||||
// index 0, once one index 0 SPI is found the other will throw an invalid_pins error.
|
||||
|
|
|
|||
|
|
@ -36,15 +36,12 @@
|
|||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
|
||||
void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t *clock,
|
||||
const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, const mcu_pin_obj_t *ss, bool half_duplex, bool slave_mode) {
|
||||
const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, bool half_duplex) {
|
||||
int port = -1;
|
||||
|
||||
if (half_duplex) {
|
||||
mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_half_duplex);
|
||||
}
|
||||
if (slave_mode) {
|
||||
mp_raise_NotImplementedError(MP_ERROR_TEXT("Slave mode SPI is not implemented"));
|
||||
}
|
||||
|
||||
if (clock->number == PIN_SPI4_SCK &&
|
||||
(mosi == NULL || mosi->number == PIN_SPI4_MOSI) &&
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO36, &pin_GPIO35, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO36, &pin_GPIO35, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ const uint8_t refresh_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO36, &pin_GPIO35, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO36, &pin_GPIO35, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO7, &pin_GPIO6, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO7, &pin_GPIO6, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO7, &pin_GPIO6, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO7, &pin_GPIO6, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO6, &pin_GPIO7, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO6, &pin_GPIO7, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO18, &pin_GPIO23, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO18, &pin_GPIO23, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -73,10 +73,7 @@ static void display_init(void) {
|
|||
&pin_GPIO34, // CLK
|
||||
&pin_GPIO33, // MOSI
|
||||
NULL, // MISO not connected
|
||||
NULL, // SS not connected
|
||||
false, // Not half-duplex
|
||||
false // operate SPI bus as master
|
||||
);
|
||||
false); // Not half-duplex
|
||||
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO12, &pin_GPIO11, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO12, &pin_GPIO11, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -73,10 +73,7 @@ static void display_init(void) {
|
|||
&pin_GPIO36, // CLK
|
||||
&pin_GPIO35, // MOSI
|
||||
NULL, // MISO not connected
|
||||
NULL, // SS not connected
|
||||
false, // Not half-duplex
|
||||
false // operate SPI bus as master
|
||||
);
|
||||
false); // Not half-duplex
|
||||
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
|
|
|
|||
|
|
@ -53,10 +53,7 @@ static void display_init(void) {
|
|||
&pin_GPIO18, // CLK
|
||||
&pin_GPIO19, // MOSI
|
||||
NULL, // MISO not connected
|
||||
NULL, // SS not connected
|
||||
false, // Not half-duplex
|
||||
false // operate SPI bus as master
|
||||
);
|
||||
false); // Not half-duplex
|
||||
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
|
|
|
|||
|
|
@ -56,9 +56,7 @@ static void display_init(void) {
|
|||
&pin_GPIO18, // CLK
|
||||
&pin_GPIO19, // MOSI
|
||||
NULL, // MISO not connected
|
||||
NULL, // SS not connected
|
||||
false, // Not half-duplex
|
||||
false // operate SPI bus as master
|
||||
false // Not half-duplex
|
||||
);
|
||||
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ void board_init(void) {
|
|||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
// busio_spi_obj_t *spi = common_hal_board_create_spi(0);
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO17, &pin_GPIO21, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO17, &pin_GPIO21, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ static bool pmic_init(busio_i2c_obj_t *i2c) {
|
|||
static bool display_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO13, &pin_GPIO15, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO13, &pin_GPIO15, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ static bool pmic_init(busio_i2c_obj_t *i2c) {
|
|||
static bool display_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO13, &pin_GPIO15, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO13, &pin_GPIO15, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -149,10 +149,7 @@ void board_init(void) {
|
|||
&pin_GPIO12, // CLK
|
||||
&pin_GPIO11, // MOSI
|
||||
NULL, // MISO not connected
|
||||
NULL, // SS not connected
|
||||
false, // Not half-duplex
|
||||
false // operate SPI bus as master
|
||||
);
|
||||
false); // Not half-duplex
|
||||
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
|
|
|
|||
|
|
@ -72,10 +72,7 @@ static void display_init(void) {
|
|||
&pin_GPIO10, // CLK
|
||||
&pin_GPIO11, // MOSI
|
||||
NULL, // MISO not connected
|
||||
NULL, // SS not connected
|
||||
false, // Not half-duplex
|
||||
false // operate SPI bus as master
|
||||
);
|
||||
false); // Not half-duplex
|
||||
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ static void set_spi_config(busio_spi_obj_t *self,
|
|||
|
||||
void common_hal_busio_spi_construct(busio_spi_obj_t *self,
|
||||
const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi,
|
||||
const mcu_pin_obj_t *miso, const mcu_pin_obj_t *ss, bool half_duplex, bool slave_mode) {
|
||||
const mcu_pin_obj_t *miso, bool half_duplex) {
|
||||
|
||||
const spi_bus_config_t bus_config = {
|
||||
.mosi_io_num = mosi != NULL ? mosi->number : -1,
|
||||
|
|
@ -90,9 +90,6 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
|
|||
if (half_duplex) {
|
||||
mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_half_duplex);
|
||||
}
|
||||
if (slave_mode) {
|
||||
mp_raise_NotImplementedError(MP_ERROR_TEXT("Slave mode SPI is not implemented"));
|
||||
}
|
||||
|
||||
for (spi_host_device_t host_id = SPI2_HOST; host_id < SOC_SPI_PERIPH_NUM; host_id++) {
|
||||
if (spi_bus_is_free(host_id)) {
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ void spi_reset(void) {
|
|||
|
||||
void common_hal_busio_spi_construct(busio_spi_obj_t *self,
|
||||
const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi,
|
||||
const mcu_pin_obj_t *miso, const mcu_pin_obj_t *ss, bool half_duplex, bool slave_mode) {
|
||||
const mcu_pin_obj_t *miso, bool half_duplex) {
|
||||
|
||||
const uint32_t sck_count = MP_ARRAY_SIZE(mcu_spi_sck_list);
|
||||
const uint32_t miso_count = MP_ARRAY_SIZE(mcu_spi_sdi_list);
|
||||
|
|
@ -101,9 +101,6 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
|
|||
if (half_duplex) {
|
||||
mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_half_duplex);
|
||||
}
|
||||
if (slave_mode) {
|
||||
mp_raise_NotImplementedError(MP_ERROR_TEXT("Slave mode SPI is not implemented"));
|
||||
}
|
||||
|
||||
for (uint i = 0; i < sck_count; i++) {
|
||||
if (mcu_spi_sck_list[i].pin != clock) {
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_P0_14, &pin_P0_15, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_P0_14, &pin_P0_15, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ void board_init(void) {
|
|||
fb->base.type = &sharpdisplay_framebuffer_type;
|
||||
|
||||
busio_spi_obj_t *spi = &fb->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_P0_26, &pin_P0_27, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_P0_26, &pin_P0_27, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
common_hal_sharpdisplay_framebuffer_construct(fb, spi, &pin_P0_05, 500000, 176, 176, true);
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_P0_07, &pin_P1_08, NULL, NULL, false, false); // SCK, MOSI, MISO, not half-duplex
|
||||
common_hal_busio_spi_construct(spi, &pin_P0_07, &pin_P1_08, NULL, false); // SCK, MOSI, MISO, not half-duplex
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_P0_11, &pin_P0_12, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_P0_11, &pin_P0_12, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_P0_11, &pin_P0_12, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_P0_11, &pin_P0_12, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -143,14 +143,11 @@ static nrf_spim_frequency_t baudrate_to_spim_frequency(const uint32_t baudrate)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, const mcu_pin_obj_t *ss, bool half_duplex, bool slave_mode) {
|
||||
void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, bool half_duplex) {
|
||||
|
||||
if (half_duplex) {
|
||||
mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_half_duplex);
|
||||
}
|
||||
if (slave_mode) {
|
||||
mp_raise_NotImplementedError(MP_ERROR_TEXT("Slave mode SPI is not implemented"));
|
||||
}
|
||||
|
||||
// Find a free instance, with most desirable (highest freq and not shared) allocated first.
|
||||
self->spim_peripheral = NULL;
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO26, &pin_GPIO27, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO26, &pin_GPIO27, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO18, &pin_GPIO19, &pin_GPIO16, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO18, &pin_GPIO19, &pin_GPIO16, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -74,10 +74,7 @@ static void display_init(void) {
|
|||
&pin_GPIO2, // CLK
|
||||
&pin_GPIO3, // MOSI
|
||||
NULL, // MISO not connected
|
||||
NULL, // SS not connected
|
||||
false, // Not half-duplex
|
||||
false // operate SPI bus as master
|
||||
);
|
||||
false); // Not half-duplex
|
||||
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO18, &pin_GPIO19, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO18, &pin_GPIO19, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ void board_init(void) {
|
|||
// Set up the SPI object used to control the display
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO18, &pin_GPIO19, &pin_GPIO16, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO18, &pin_GPIO19, &pin_GPIO16, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
// Set up the DisplayIO pin object
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO6, &pin_GPIO7, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO6, &pin_GPIO7, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ uint8_t display_init_sequence[] = {
|
|||
void board_init(void) {
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
busio_spi_obj_t *spi = &bus->inline_bus;
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO2, &pin_GPIO3, NULL, NULL, false, false);
|
||||
common_hal_busio_spi_construct(spi, &pin_GPIO2, &pin_GPIO3, NULL, false);
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
|
|
|||
|
|
@ -70,9 +70,7 @@ static void display_init(void) {
|
|||
&pin_GPIO10, // CLK
|
||||
&pin_GPIO11, // MOSI
|
||||
NULL, // MISO not connected
|
||||
NULL, // SS not connected
|
||||
false, // Not half-duplex
|
||||
false // operate SPI bus as master
|
||||
false // Not half-duplex
|
||||
);
|
||||
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
|
|
|||
|
|
@ -54,15 +54,12 @@ void reset_spi(void) {
|
|||
|
||||
void common_hal_busio_spi_construct(busio_spi_obj_t *self,
|
||||
const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi,
|
||||
const mcu_pin_obj_t *miso, const mcu_pin_obj_t *ss, bool half_duplex, bool slave_mode) {
|
||||
const mcu_pin_obj_t *miso, bool half_duplex) {
|
||||
size_t instance_index = NO_INSTANCE;
|
||||
|
||||
if (half_duplex) {
|
||||
mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_half_duplex);
|
||||
}
|
||||
if (slave_mode) {
|
||||
mp_raise_NotImplementedError(MP_ERROR_TEXT("Slave mode SPI is not implemented"));
|
||||
}
|
||||
|
||||
if (clock->number % 4 == 2) {
|
||||
instance_index = (clock->number / 8) % 2;
|
||||
|
|
|
|||
|
|
@ -53,17 +53,13 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
|
|||
const mcu_pin_obj_t *sck,
|
||||
const mcu_pin_obj_t *mosi,
|
||||
const mcu_pin_obj_t *miso,
|
||||
const mcu_pin_obj_t *ss,
|
||||
bool half_duplex, bool slave_mode) {
|
||||
bool half_duplex) {
|
||||
Ecode_t sc = ECODE_OK;
|
||||
|
||||
if (half_duplex) {
|
||||
mp_raise_NotImplementedError(
|
||||
MP_ERROR_TEXT("Half duplex SPI is not implemented"));
|
||||
}
|
||||
if (slave_mode) {
|
||||
mp_raise_NotImplementedError(MP_ERROR_TEXT("Slave mode SPI is not implemented"));
|
||||
}
|
||||
|
||||
if ((sck != NULL) && (mosi != NULL) && (miso != NULL)) {
|
||||
if (sck->function_list[FN_EUSART1_SCLK] == 1
|
||||
|
|
|
|||
|
|
@ -167,10 +167,7 @@ STATIC int check_pins(busio_spi_obj_t *self,
|
|||
|
||||
void common_hal_busio_spi_construct(busio_spi_obj_t *self,
|
||||
const mcu_pin_obj_t *sck, const mcu_pin_obj_t *mosi,
|
||||
const mcu_pin_obj_t *miso, const mcu_pin_obj_t *ss, bool half_duplex, bool slave_mode) {
|
||||
if (slave_mode) {
|
||||
mp_raise_NotImplementedError(MP_ERROR_TEXT("Slave mode SPI is not implemented"));
|
||||
}
|
||||
const mcu_pin_obj_t *miso, bool half_duplex) {
|
||||
|
||||
int periph_index = check_pins(self, sck, mosi, miso);
|
||||
SPI_TypeDef *SPIx = mcu_spi_banks[periph_index - 1];
|
||||
|
|
|
|||
|
|
@ -351,6 +351,9 @@ endif
|
|||
ifeq ($(CIRCUITPY_SOCKETPOOL),1)
|
||||
SRC_PATTERNS += socketpool/%
|
||||
endif
|
||||
ifeq ($(CIRCUITPY_SPITARGET),1)
|
||||
SRC_PATTERNS += spitarget/%
|
||||
endif
|
||||
ifeq ($(CIRCUITPY_SSL),1)
|
||||
SRC_PATTERNS += ssl/%
|
||||
endif
|
||||
|
|
@ -516,6 +519,8 @@ SRC_COMMON_HAL_ALL = \
|
|||
socketpool/__init__.c \
|
||||
socketpool/SocketPool.c \
|
||||
socketpool/Socket.c \
|
||||
spitarget/SPITarget.c \
|
||||
spitarget/__init__.c \
|
||||
supervisor/Runtime.c \
|
||||
supervisor/__init__.c \
|
||||
usb_host/__init__.c \
|
||||
|
|
|
|||
|
|
@ -476,6 +476,9 @@ CFLAGS += -DCIRCUITPY_SKIP_SAFE_MODE_WAIT=$(CIRCUITPY_SKIP_SAFE_MODE_WAIT)
|
|||
CIRCUITPY_SOCKETPOOL ?= $(CIRCUITPY_WIFI)
|
||||
CFLAGS += -DCIRCUITPY_SOCKETPOOL=$(CIRCUITPY_SOCKETPOOL)
|
||||
|
||||
CIRCUITPY_SPITARGET ?= 0
|
||||
CFLAGS += -DCIRCUITPY_SPITARGET=$(CIRCUITPY_SPITARGET)
|
||||
|
||||
CIRCUITPY_SSL ?= $(CIRCUITPY_WIFI)
|
||||
CFLAGS += -DCIRCUITPY_SSL=$(CIRCUITPY_SSL)
|
||||
|
||||
|
|
|
|||
|
|
@ -73,9 +73,7 @@
|
|||
//| clock: microcontroller.Pin,
|
||||
//| MOSI: Optional[microcontroller.Pin] = None,
|
||||
//| MISO: Optional[microcontroller.Pin] = None,
|
||||
//| SS: Optional[microcontroller.Pin] = None,
|
||||
//| half_duplex: bool = False,
|
||||
//| slave_mode: bool = False,
|
||||
//| half_duplex: bool = False
|
||||
//| ) -> None:
|
||||
//| """Construct an SPI object on the given pins.
|
||||
//|
|
||||
|
|
@ -98,10 +96,8 @@
|
|||
//| :param ~microcontroller.Pin MOSI: the Main Out Selected In pin.
|
||||
//| :param ~microcontroller.Pin MISO: the Main In Selected Out pin.
|
||||
//| :param bool half_duplex: True when MOSI is used for bidirectional data. False when SPI is full-duplex or simplex.
|
||||
//| :param-bool slave_mode: True when the chip is operating as a slave. False when the chip is operating as a master.
|
||||
//|
|
||||
//| **Limitations:** ``half_duplex`` is available only on STM; other chips do not have the hardware support.
|
||||
//| **Limitations:** ``slave_mode`` is available only on SAMD51; other chips do not have the firmware support.
|
||||
//| """
|
||||
//| ...
|
||||
|
||||
|
|
@ -110,14 +106,12 @@
|
|||
STATIC mp_obj_t busio_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
#if CIRCUITPY_BUSIO_SPI
|
||||
busio_spi_obj_t *self = mp_obj_malloc(busio_spi_obj_t, &busio_spi_type);
|
||||
enum { ARG_clock, ARG_MOSI, ARG_MISO, ARG_SS, ARG_half_duplex, ARG_slave_mode };
|
||||
enum { ARG_clock, ARG_MOSI, ARG_MISO, ARG_half_duplex };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_clock, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_MOSI, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_MISO, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_SS, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_half_duplex, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
|
||||
{ MP_QSTR_slave_mode, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
|
||||
};
|
||||
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);
|
||||
|
|
@ -125,19 +119,12 @@ STATIC mp_obj_t busio_spi_make_new(const mp_obj_type_t *type, size_t n_args, siz
|
|||
const mcu_pin_obj_t *clock = validate_obj_is_free_pin(args[ARG_clock].u_obj, MP_QSTR_clock);
|
||||
const mcu_pin_obj_t *mosi = validate_obj_is_free_pin_or_none(args[ARG_MOSI].u_obj, MP_QSTR_mosi);
|
||||
const mcu_pin_obj_t *miso = validate_obj_is_free_pin_or_none(args[ARG_MISO].u_obj, MP_QSTR_miso);
|
||||
const mcu_pin_obj_t *ss = validate_obj_is_free_pin_or_none(args[ARG_SS].u_obj, MP_QSTR_ss);
|
||||
|
||||
if (!miso && !mosi) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("Must provide MISO or MOSI pin"));
|
||||
}
|
||||
if (args[ARG_slave_mode].u_bool && !ss) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("Must provide SS pin to operate in slave mode"));
|
||||
}
|
||||
if (!args[ARG_slave_mode].u_bool && ss) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("Hardware SS pin only supported for slave mode"));
|
||||
}
|
||||
|
||||
common_hal_busio_spi_construct(self, clock, mosi, miso, ss, args[ARG_half_duplex].u_bool, args[ARG_slave_mode].u_bool);
|
||||
common_hal_busio_spi_construct(self, clock, mosi, miso, args[ARG_half_duplex].u_bool);
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
#else
|
||||
raise_ValueError_invalid_pins();
|
||||
|
|
@ -482,145 +469,6 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_get_frequency_obj, busio_spi_obj_get_frequen
|
|||
MP_PROPERTY_GETTER(busio_spi_frequency_obj,
|
||||
(mp_obj_t)&busio_spi_get_frequency_obj);
|
||||
|
||||
#if CIRCUITPY_SAMD
|
||||
|
||||
//| import sys
|
||||
//| def async_transfer_start(
|
||||
//| self,
|
||||
//| out_buffer: ReadableBuffer,
|
||||
//| in_buffer: WriteableBuffer,
|
||||
//| *,
|
||||
//| out_start: int = 0,
|
||||
//| out_end: int = sys.maxsize,
|
||||
//| in_start: int = 0,
|
||||
//| in_end: int = sys.maxsize
|
||||
//| ) -> None:
|
||||
//| """Write out the data in ``out_buffer`` while simultaneously reading data into ``in_buffer``.
|
||||
//| The SPI object must be locked. Note: this method returns immediately, and the data will not
|
||||
//| actually be transferred until some time has passed. Use `async_transfer_finished` and
|
||||
//| `async_transfer_end` to check on the status of the transfer and close out its resources.
|
||||
//|
|
||||
//| If ``out_start`` or ``out_end`` is provided, then the buffer will be sliced
|
||||
//| as if ``out_buffer[out_start:out_end]`` were passed, but without copying the data.
|
||||
//| The number of bytes written will be the length of ``out_buffer[out_start:out_end]``.
|
||||
//|
|
||||
//| If ``in_start`` or ``in_end`` is provided, then the input buffer will be sliced
|
||||
//| as if ``in_buffer[in_start:in_end]`` were passed,
|
||||
//| The number of bytes read will be the length of ``out_buffer[in_start:in_end]``.
|
||||
//|
|
||||
//| The lengths of the slices defined by ``out_buffer[out_start:out_end]``
|
||||
//| and ``in_buffer[in_start:in_end]`` must be equal.
|
||||
//| If buffer slice lengths are both 0, nothing happens.
|
||||
//|
|
||||
//| Note: This method is currently only available on atmel-samd` ports of CircuitPython.
|
||||
//|
|
||||
//| :param ReadableBuffer out_buffer: write out bytes from this buffer
|
||||
//| :param WriteableBuffer in_buffer: read bytes into this buffer
|
||||
//| :param int out_start: beginning of ``out_buffer`` slice
|
||||
//| :param int out_end: end of ``out_buffer`` slice; if not specified, use ``len(out_buffer)``
|
||||
//| :param int in_start: beginning of ``in_buffer`` slice
|
||||
//| :param int in_end: end of ``in_buffer slice``; if not specified, use ``len(in_buffer)``
|
||||
//| """
|
||||
//| ...
|
||||
|
||||
STATIC mp_obj_t busio_spi_start_async_transfer(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_out_buffer, ARG_in_buffer, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_out_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_in_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_out_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_out_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
|
||||
{ MP_QSTR_in_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_in_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
|
||||
};
|
||||
busio_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
check_for_deinit(self);
|
||||
check_lock(self);
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
mp_buffer_info_t buf_out_info;
|
||||
mp_get_buffer_raise(args[ARG_out_buffer].u_obj, &buf_out_info, MP_BUFFER_READ);
|
||||
int out_stride_in_bytes = mp_binary_get_size('@', buf_out_info.typecode, NULL);
|
||||
int32_t out_start = args[ARG_out_start].u_int;
|
||||
size_t out_length = buf_out_info.len / out_stride_in_bytes;
|
||||
normalize_buffer_bounds(&out_start, args[ARG_out_end].u_int, &out_length);
|
||||
|
||||
mp_buffer_info_t buf_in_info;
|
||||
mp_get_buffer_raise(args[ARG_in_buffer].u_obj, &buf_in_info, MP_BUFFER_WRITE);
|
||||
int in_stride_in_bytes = mp_binary_get_size('@', buf_in_info.typecode, NULL);
|
||||
int32_t in_start = args[ARG_in_start].u_int;
|
||||
size_t in_length = buf_in_info.len / in_stride_in_bytes;
|
||||
normalize_buffer_bounds(&in_start, args[ARG_in_end].u_int, &in_length);
|
||||
|
||||
// Treat start and length in terms of bytes from now on.
|
||||
out_start *= out_stride_in_bytes;
|
||||
out_length *= out_stride_in_bytes;
|
||||
in_start *= in_stride_in_bytes;
|
||||
in_length *= in_stride_in_bytes;
|
||||
|
||||
if (out_length != in_length) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("buffer slices must be of equal length"));
|
||||
}
|
||||
|
||||
common_hal_busio_spi_transfer_async_start(self,
|
||||
((uint8_t *)buf_out_info.buf) + out_start,
|
||||
((uint8_t *)buf_in_info.buf) + in_start,
|
||||
out_length);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_start_transfer_obj, 1, busio_spi_start_async_transfer);
|
||||
|
||||
//| import sys
|
||||
//| def async_transfer_finished(
|
||||
//| self
|
||||
//| ) -> None:
|
||||
//| """Check whether or not the last async transfer started on this SPI object has finished. If
|
||||
//| no transfer was started, this method behaves as though the most recent transfer has finished
|
||||
//| and returns `True`. Otherwise, it returns `False`.
|
||||
//|
|
||||
//| Note: This method is currently only available on atmel-samd` ports of CircuitPython.
|
||||
//| """
|
||||
//| ...
|
||||
STATIC mp_obj_t busio_spi_obj_check_async_transfer(mp_obj_t self_in) {
|
||||
busio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
return common_hal_busio_spi_transfer_async_check(self) ? mp_const_true : mp_const_false;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_check_transfer_obj, busio_spi_obj_check_async_transfer);
|
||||
|
||||
//| import sys
|
||||
//| def async_transfer_end(
|
||||
//| self
|
||||
//| ) -> None:
|
||||
//| """Return the status code with which the last async transfer on this SPI object completed. This
|
||||
//| method MUST be called for all transfers, regardless of user interest in status code. The resources
|
||||
//| for the transfer will be left open until this method is called. Once this method is called, the
|
||||
//| peripheral resets and is ready for another transfer. The return code of this method also resets to
|
||||
//| its pre-transfer state: repeated calls to this method may produce different codes.
|
||||
//|
|
||||
//| Return code 0: No transfer has occured, either because `start_async_transfer` was never called, or because
|
||||
//| it was called with zero-length buffers.
|
||||
//| Return code -1: The transfer failed because no DMA channels are available.
|
||||
//| Return code -2: The transfer executed, but the DMA controller indicates that either some data is
|
||||
//| untransferred, that a software issue prevented the data transfer from completing, or that some other error
|
||||
//| has occured within the DMA controller.
|
||||
//| Return code -3: An unaligned buffer was passed to the QSPI peripheral, which prevents the DMA controller from
|
||||
//| appropriately chunking the transfer.
|
||||
//| Return code n>0: A transfer of `n` bytes in each direction has succeeded.
|
||||
//|
|
||||
//| Note: This method is currently only available on atmel-samd` ports of CircuitPython.
|
||||
//| """
|
||||
//| ...
|
||||
STATIC mp_obj_t busio_spi_obj_end_async_transfer(mp_obj_t self_in) {
|
||||
busio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
return MP_OBJ_NEW_SMALL_INT(common_hal_busio_spi_transfer_async_end(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_end_transfer_obj, busio_spi_obj_end_async_transfer);
|
||||
|
||||
#endif // CIRCUITPY_SAMD
|
||||
|
||||
#endif // CIRCUITPY_BUSIO_SPI
|
||||
|
||||
|
||||
|
|
@ -639,13 +487,6 @@ STATIC const mp_rom_map_elem_t busio_spi_locals_dict_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&busio_spi_write_readinto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&busio_spi_frequency_obj) }
|
||||
|
||||
#if CIRCUITPY_SAMD
|
||||
,
|
||||
{ MP_ROM_QSTR(MP_QSTR_async_transfer_start), MP_ROM_PTR(&busio_spi_start_transfer_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_async_transfer_finished), MP_ROM_PTR(&busio_spi_check_transfer_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_async_transfer_end), MP_ROM_PTR(&busio_spi_end_transfer_obj) }
|
||||
#endif // CIRCUITPY_SAMD
|
||||
|
||||
#endif // CIRCUITPY_BUSIO_SPI
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(busio_spi_locals_dict, busio_spi_locals_dict_table);
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ extern const mp_obj_type_t busio_spi_type;
|
|||
// Construct an underlying SPI object.
|
||||
extern void common_hal_busio_spi_construct(busio_spi_obj_t *self,
|
||||
const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi,
|
||||
const mcu_pin_obj_t *miso, const mcu_pin_obj_t *ss, bool half_duplex, bool slave_mode);
|
||||
const mcu_pin_obj_t *miso, bool half_duplex);
|
||||
|
||||
extern void common_hal_busio_spi_deinit(busio_spi_obj_t *self);
|
||||
extern bool common_hal_busio_spi_deinited(busio_spi_obj_t *self);
|
||||
|
|
@ -58,19 +58,6 @@ extern bool common_hal_busio_spi_read(busio_spi_obj_t *self, uint8_t *data, size
|
|||
// Reads and write len bytes simultaneously.
|
||||
extern bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, const uint8_t *data_out, uint8_t *data_in, size_t len);
|
||||
|
||||
#if CIRCUITPY_SAMD
|
||||
|
||||
// Initiates a transfer that reads and write len bytes simultaneously
|
||||
extern void common_hal_busio_spi_transfer_async_start(busio_spi_obj_t *self, const uint8_t *data_out, uint8_t *data_in, size_t len);
|
||||
|
||||
// Reads the state of the in-progress transfer
|
||||
extern bool common_hal_busio_spi_transfer_async_check(busio_spi_obj_t *self);
|
||||
|
||||
// Cleans up the completed transfer and returns any error code produced by the transfer
|
||||
extern int common_hal_busio_spi_transfer_async_end(busio_spi_obj_t *self);
|
||||
|
||||
#endif // CIRCUITPY_SAMD
|
||||
|
||||
// Return actual SPI bus frequency.
|
||||
uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t *self);
|
||||
|
||||
|
|
|
|||
182
shared-bindings/spitarget/SPITarget.c
Normal file
182
shared-bindings/spitarget/SPITarget.c
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
#include "shared-bindings/spitarget/SPITarget.h"
|
||||
#include "shared-bindings/time/__init__.h"
|
||||
#include "shared-bindings/util.h"
|
||||
|
||||
#include "shared/runtime/buffer_helper.h"
|
||||
#include "shared/runtime/context_manager_helpers.h"
|
||||
#include "shared/runtime/interrupt_char.h"
|
||||
|
||||
#include "py/mperrno.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/objproperty.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
//| class SPITarget:
|
||||
//| """Serial Peripheral Interface protocol target"""
|
||||
//|
|
||||
//| def __init__(
|
||||
//| self,
|
||||
//| sck: microcontroller.Pin,
|
||||
//| mosi: microcontroller.Pin,
|
||||
//| miso: microcontroller.Pin,
|
||||
//| ss: microcontroller.Pin
|
||||
//| ) -> None:
|
||||
//| """SPI is a four-wire protocol for communicating between devices.
|
||||
//| This implements the secondary (aka target or peripheral) side.
|
||||
//|
|
||||
//| :param ~microcontroller.Pin sck: The SPI clock pin
|
||||
//| :param ~microcontroller.Pin mosi: The pin transferring data from the main to the secondary
|
||||
//| :param ~microcontroller.Pin miso: The pin transferring data from the secondary to the main
|
||||
//| :param ~microcontroller.Pin ss: The secondary selection pin"""
|
||||
//| ...
|
||||
STATIC mp_obj_t spitarget_spi_target_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
spitarget_spi_target_obj_t *self = mp_obj_malloc(spitarget_spi_target_obj_t, &spitarget_spi_target_type);
|
||||
enum { ARG_sck, ARG_mosi, ARG_miso, ARG_ss };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_sck, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_mosi, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_miso, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_ss, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
};
|
||||
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);
|
||||
|
||||
const mcu_pin_obj_t *sck = validate_obj_is_free_pin(args[ARG_sck].u_obj, MP_QSTR_sck);
|
||||
const mcu_pin_obj_t *mosi = validate_obj_is_free_pin(args[ARG_mosi].u_obj, MP_QSTR_mosi);
|
||||
const mcu_pin_obj_t *miso = validate_obj_is_free_pin(args[ARG_miso].u_obj, MP_QSTR_miso);
|
||||
const mcu_pin_obj_t *ss = validate_obj_is_free_pin(args[ARG_ss].u_obj, MP_QSTR_ss);
|
||||
|
||||
common_hal_spitarget_spi_target_construct(self, sck, mosi, miso, ss);
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
//| def deinit(self) -> None:
|
||||
//| """Releases control of the underlying hardware so other classes can use it."""
|
||||
//| ...
|
||||
STATIC mp_obj_t spitarget_spi_target_obj_deinit(mp_obj_t self_in) {
|
||||
mp_check_self(mp_obj_is_type(self_in, &spitarget_spi_target_type));
|
||||
spitarget_spi_target_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
common_hal_spitarget_spi_target_deinit(self);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(spitarget_spi_target_deinit_obj, spitarget_spi_target_obj_deinit);
|
||||
|
||||
//| def __enter__(self) -> SPITarget:
|
||||
//| """No-op used in Context Managers."""
|
||||
//| ...
|
||||
// Provided by context manager helper.
|
||||
|
||||
//| def __exit__(self) -> None:
|
||||
//| """Automatically deinitializes the hardware on context exit. See
|
||||
//| :ref:`lifetime-and-contextmanagers` for more info."""
|
||||
//| ...
|
||||
STATIC mp_obj_t spitarget_spi_target_obj___exit__(size_t n_args, const mp_obj_t *args) {
|
||||
mp_check_self(mp_obj_is_type(args[0], &spitarget_spi_target_target_type));
|
||||
spitarget_spi_target_obj_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
common_hal_spitarget_spi_target_deinit(self);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(spitarget_spi_target___exit___obj, 4, 4, spitarget_spi_target_obj___exit__);
|
||||
|
||||
//| def load_packet(self, mosi_packet: bytearray, miso_packet: bytearray) -> None:
|
||||
//| """Queue data for the next SPI transfer from the main device.
|
||||
//| If a packet has already been queued for this SPI bus but has not yet been transferred, an error will be raised.
|
||||
//|
|
||||
//| :param bytearray miso_packet: Packet data to be sent from secondary to main on next request."""
|
||||
//|
|
||||
STATIC mp_obj_t spitarget_spi_target_load_packet(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
mp_check_self(mp_obj_is_type(pos_args[0], &spitarget_spi_target_type));
|
||||
spitarget_spi_target_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
if (common_hal_spitarget_spi_target_deinited(self)) {
|
||||
raise_deinited_error();
|
||||
}
|
||||
enum { ARG_mosi_packet, ARG_miso_packet };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_mosi_packet, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_miso_packet, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
};
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
mp_buffer_info_t mosi_bufinfo;
|
||||
mp_get_buffer_raise(args[ARG_mosi_packet].u_obj, &mosi_bufinfo, MP_BUFFER_WRITE);
|
||||
|
||||
mp_buffer_info_t miso_bufinfo;
|
||||
mp_get_buffer_raise(args[ARG_miso_packet].u_obj, &miso_bufinfo, MP_BUFFER_READ);
|
||||
|
||||
if (miso_bufinfo.len != mosi_bufinfo.len) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("Packet buffers for an SPI transfer must have the same length."));
|
||||
}
|
||||
|
||||
common_hal_spitarget_spi_target_transfer_start(self, ((uint8_t *)mosi_bufinfo.buf), ((uint8_t *)miso_bufinfo.buf), mosi_bufinfo.len);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(spitarget_spi_target_load_packet_obj, 1, spitarget_spi_target_load_packet);
|
||||
|
||||
//| def try_transfer(self, *, timeout: float = -1) -> bool:
|
||||
//| """Wait for an SPI transfer from the main device.
|
||||
//|
|
||||
//| :param float timeout: Timeout in seconds. Zero means wait forever, a negative value means check once
|
||||
//| :return: True if the transfer is complete, or False if no response received before the timeout
|
||||
//| :rtype: ~bool"""
|
||||
//|
|
||||
STATIC mp_obj_t spitarget_spi_target_try_transfer(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
mp_check_self(mp_obj_is_type(pos_args[0], &spitarget_spi_target_type));
|
||||
spitarget_spi_target_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
if (common_hal_spitarget_spi_target_deinited(self)) {
|
||||
raise_deinited_error();
|
||||
}
|
||||
enum { ARG_timeout };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(-1)} },
|
||||
};
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
float f = mp_obj_get_float(args[ARG_timeout].u_obj) * 1000;
|
||||
int timeout_ms = (int)f;
|
||||
#else
|
||||
int timeout_ms = mp_obj_get_int(args[ARG_timeout].u_obj) * 1000;
|
||||
#endif
|
||||
|
||||
bool forever = false;
|
||||
uint64_t timeout_end = 0;
|
||||
if (timeout_ms == 0) {
|
||||
forever = true;
|
||||
} else if (timeout_ms > 0) {
|
||||
timeout_end = common_hal_time_monotonic_ms() + timeout_ms;
|
||||
}
|
||||
|
||||
do {
|
||||
if (common_hal_spitarget_spi_target_transfer_is_finished(self)) {
|
||||
common_hal_spitarget_spi_target_transfer_close(self); // implicitly discards error indicator code
|
||||
return mp_const_true;
|
||||
}
|
||||
mp_hal_delay_us(10);
|
||||
} while (forever || common_hal_time_monotonic_ms() < timeout_end);
|
||||
|
||||
return mp_const_false;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(spitarget_spi_target_try_transfer_obj, 1, spitarget_spi_target_try_transfer);
|
||||
|
||||
STATIC const mp_rom_map_elem_t spitarget_spi_target_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&spitarget_spi_target_deinit_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&spitarget_spi_target___exit___obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_load_packet), MP_ROM_PTR(&spitarget_spi_target_load_packet_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_try_transfer), MP_ROM_PTR(&spitarget_spi_target_try_transfer_obj) },
|
||||
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(spitarget_spi_target_locals_dict, spitarget_spi_target_locals_dict_table);
|
||||
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
spitarget_spi_target_type,
|
||||
MP_QSTR_SPITarget,
|
||||
MP_TYPE_FLAG_NONE,
|
||||
make_new, spitarget_spi_target_make_new,
|
||||
locals_dict, &spitarget_spi_target_locals_dict
|
||||
);
|
||||
21
shared-bindings/spitarget/SPITarget.h
Normal file
21
shared-bindings/spitarget/SPITarget.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SPI_TARGET_H
|
||||
#define MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SPI_TARGET_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
#include "common-hal/microcontroller/Pin.h"
|
||||
#include "common-hal/spitarget/SPITarget.h"
|
||||
|
||||
extern const mp_obj_type_t spitarget_spi_target_type;
|
||||
|
||||
extern void common_hal_spitarget_spi_target_construct(spitarget_spi_target_obj_t *self,
|
||||
const mcu_pin_obj_t *sck, const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, const mcu_pin_obj_t *ss);
|
||||
extern void common_hal_spitarget_spi_target_deinit(spitarget_spi_target_obj_t *self);
|
||||
extern bool common_hal_spitarget_spi_target_deinited(spitarget_spi_target_obj_t *self);
|
||||
|
||||
extern void common_hal_spitarget_spi_target_transfer_start(spitarget_spi_target_obj_t *self,
|
||||
uint8_t *mosi_packet, const uint8_t *miso_packet, size_t len);
|
||||
extern bool common_hal_spitarget_spi_target_transfer_is_finished(spitarget_spi_target_obj_t *self);
|
||||
extern int common_hal_spitarget_spi_target_transfer_close(spitarget_spi_target_obj_t *self);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SPI_TARGET_H
|
||||
28
shared-bindings/spitarget/__init__.c
Normal file
28
shared-bindings/spitarget/__init__.c
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
#include "shared-bindings/spitarget/SPITarget.h"
|
||||
|
||||
#include "py/runtime.h"
|
||||
|
||||
//| """Serial Peripheral Interface protocol target
|
||||
//|
|
||||
//| The `spitarget` module contains classes to support an SPI target.
|
||||
|
||||
|
||||
STATIC const mp_rom_map_elem_t spitarget_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_spitarget) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_SPITarget), MP_ROM_PTR(&spitarget_spi_target_type) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(spitarget_module_globals, spitarget_module_globals_table);
|
||||
|
||||
const mp_obj_module_t spitarget_module = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&spitarget_module_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_spitarget, spitarget_module);
|
||||
|
|
@ -130,7 +130,7 @@ mp_obj_t common_hal_board_create_spi(const mp_int_t instance) {
|
|||
assert_pin_free(spi_pin[instance].mosi);
|
||||
assert_pin_free(spi_pin[instance].miso);
|
||||
|
||||
common_hal_busio_spi_construct(self, spi_pin[instance].clock, spi_pin[instance].mosi, spi_pin[instance].miso, NULL, false, false);
|
||||
common_hal_busio_spi_construct(self, spi_pin[instance].clock, spi_pin[instance].mosi, spi_pin[instance].miso, false);
|
||||
|
||||
spi_obj_created[instance] = true;
|
||||
return &spi_obj[instance];
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ void spi_flash_init(void) {
|
|||
common_hal_digitalio_digitalinout_never_reset(&cs_pin);
|
||||
|
||||
supervisor_flash_spi_bus.base.type = &busio_spi_type;
|
||||
common_hal_busio_spi_construct(&supervisor_flash_spi_bus, SPI_FLASH_SCK_PIN, SPI_FLASH_MOSI_PIN, SPI_FLASH_MISO_PIN, NULL, false, false);
|
||||
common_hal_busio_spi_construct(&supervisor_flash_spi_bus, SPI_FLASH_SCK_PIN, SPI_FLASH_MOSI_PIN, SPI_FLASH_MISO_PIN, false);
|
||||
common_hal_busio_spi_never_reset(&supervisor_flash_spi_bus);
|
||||
common_hal_busio_spi_configure(&supervisor_flash_spi_bus, SPI_FLASH_MAX_BAUDRATE, 0, 0, 8);
|
||||
|
||||
|
|
|
|||
|
|
@ -164,8 +164,6 @@ void status_led_init() {
|
|||
MICROPY_HW_APA102_SCK,
|
||||
MICROPY_HW_APA102_MOSI,
|
||||
NULL,
|
||||
NULL,
|
||||
false,
|
||||
false);
|
||||
#endif
|
||||
#if CIRCUITPY_BITBANG_APA102
|
||||
|
|
|
|||
Loading…
Reference in a new issue