forked from micropython/micropython
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
SAMD51 SPI Secondary Mode #9385
Open
Randall-Scharpf
wants to merge
44
commits into
adafruit:main
Choose a base branch
from
Bruin-Spacecraft-Group:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
44 commits
Select commit
Hold shift + click to select a range
639fed2
Add slave_mode parameter to the SPI bus constructor
Randall-Scharpf b459802
Update SPI construction usages
Randall-Scharpf 58e1ee7
Attempt to change MODE to peripheral
Randall-Scharpf 8444193
fix inversion bitmath error
Randall-Scharpf b98ff01
add build script
Randall-Scharpf c969a64
working edits to spi and can attempts
Randall-Scharpf 82a6f95
SPI responds to clock with this change, data transfer still ununcerta…
Randall-Scharpf 9c8401b
build interpreter (mac version)
anniexiang01 8a552f1
potential fix for busio SPI parameters
anniexiang01 b983bf9
add SS pin and fix DIPO/DOPO assignment
Randall-Scharpf 1728222
Merge branch '9.0.x' of https://github.com/adafruit/circuitpython int…
Randall-Scharpf 09d2c66
Merge branch 'adafruit-9.0.x' into main
Randall-Scharpf c06f9e1
hey wait we dont need a crystal
Randall-Scharpf bd10666
update dma code to use new allocation interface
Randall-Scharpf 5490a82
add async spi interface
Randall-Scharpf cfa4425
enable preloading data register
Randall-Scharpf 5c21495
update samd-peripherals submodule to point to a bruinspace-owned fork
Randall-Scharpf 4d151a0
update reference submodule commit hash
Randall-Scharpf 26e838b
added board configurations for RAPID-0 CDH, ADCS, and EPS boards. rev…
anniexiang01 0ae5be8
corrected board family on rapid0_adcs mpconfigboard.mk file
anniexiang01 a73df58
Updated USB VID, PID, and PRODUCT to reflect sublicense given by Micr…
anniexiang01 d4df61e
updated adcs board files to be based on the bdmicro vina d51, new bui…
anniexiang01 dcc97d7
fixed rapid0-cdh pin error
anniexiang01 14136fc
restore metro_m4_express configuration
Randall-Scharpf 555f1a3
remove extraneous build files
Randall-Scharpf d048667
remove extraneous build files
Randall-Scharpf 4696d07
set SPI drive strength to high
Randall-Scharpf 1fc4d72
haha! adcs works now
Randall-Scharpf 2ba0b56
add annie's new rapid-0 firmware build workflow
Randall-Scharpf a7b3de4
add SPITarget interface (HAL still unimplemented)
Randall-Scharpf 289f420
implement the spitarget methods
Randall-Scharpf 616ec37
fix the type of self within spitarget
Randall-Scharpf 114d49e
fix import errors and transfer_close return typing
Randall-Scharpf 5657f8a
fix typing and naming mismatches
Randall-Scharpf 1aad399
ok this is the one
Randall-Scharpf ff2fb90
fix function name mismatch between call and declaration
Randall-Scharpf dd7056b
return none from bound functions
Randall-Scharpf 1875e70
fix buffer mishandling in spitarget bindings
Randall-Scharpf 0a68f43
remove busio.SPI
Randall-Scharpf ea344c3
repair constructors referencing old API
Randall-Scharpf 100a045
remove asynchronous interface under busio.SPI
Randall-Scharpf 821b7f2
merge implementation of new spitarget api
Randall-Scharpf 022e191
add missing files not found by wildcard
Randall-Scharpf d059736
push samd-peripherals to merge commit in adafruit repository
Randall-Scharpf File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
// No spitarget module functions. |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you'll want to store the buffer objects here while a transfer is in progress. If you don't the garbage collector may clean them up while a transfer is in progress.