Compare commits
4 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae3d233b56 | ||
|
|
a278034831 | ||
|
|
703c6dd497 | ||
|
|
16567c4af4 |
14 changed files with 503 additions and 24 deletions
|
|
@ -337,23 +337,115 @@ bool SERCOM::isDataRegisterEmptySPI()
|
||||||
return sercom->SPI.INTFLAG.bit.DRE;
|
return sercom->SPI.INTFLAG.bit.DRE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//bool SERCOM::isTransmitCompleteSPI()
|
bool SERCOM::isTransmitCompleteSPI()
|
||||||
//{
|
{
|
||||||
// //TXC : Transmit complete
|
//TXC : Transmit complete
|
||||||
// return sercom->SPI.INTFLAG.bit.TXC;
|
return sercom->SPI.INTFLAG.bit.TXC;
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//bool SERCOM::isReceiveCompleteSPI()
|
bool SERCOM::isReceiveCompleteSPI()
|
||||||
//{
|
{
|
||||||
// //RXC : Receive complete
|
//RXC : Receive complete
|
||||||
// return sercom->SPI.INTFLAG.bit.RXC;
|
return sercom->SPI.INTFLAG.bit.RXC;
|
||||||
//}
|
}
|
||||||
|
|
||||||
uint8_t SERCOM::calculateBaudrateSynchronous(uint32_t baudrate)
|
uint8_t SERCOM::calculateBaudrateSynchronous(uint32_t baudrate)
|
||||||
{
|
{
|
||||||
return SERCOM_FREQ_REF / (2 * baudrate) - 1;
|
return SERCOM_FREQ_REF / (2 * baudrate) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SERCOM::initSPIDMA( uint8_t channelRx, uint8_t channelTx, DmacDescriptor *descrx, DmacDescriptor *desctx )
|
||||||
|
{
|
||||||
|
descrx->SRCADDR.reg = (uint32_t)(&sercom->SPI.DATA.reg);
|
||||||
|
desctx->DSTADDR.reg = (uint32_t)(&sercom->SPI.DATA.reg);
|
||||||
|
|
||||||
|
#ifdef __SAMD51__
|
||||||
|
if(sercom == SERCOM0)
|
||||||
|
{
|
||||||
|
DMAC->Channel[channelRx].CHCTRLA.bit.TRIGSRC = SERCOM0_DMAC_ID_RX;
|
||||||
|
DMAC->Channel[channelTx].CHCTRLA.bit.TRIGSRC = SERCOM0_DMAC_ID_TX;
|
||||||
|
}
|
||||||
|
else if(sercom == SERCOM1)
|
||||||
|
{
|
||||||
|
DMAC->Channel[channelRx].CHCTRLA.bit.TRIGSRC = SERCOM1_DMAC_ID_RX;
|
||||||
|
DMAC->Channel[channelTx].CHCTRLA.bit.TRIGSRC = SERCOM1_DMAC_ID_TX;
|
||||||
|
}
|
||||||
|
else if(sercom == SERCOM2)
|
||||||
|
{
|
||||||
|
DMAC->Channel[channelRx].CHCTRLA.bit.TRIGSRC = SERCOM2_DMAC_ID_RX;
|
||||||
|
DMAC->Channel[channelTx].CHCTRLA.bit.TRIGSRC = SERCOM2_DMAC_ID_TX;
|
||||||
|
}
|
||||||
|
else if(sercom == SERCOM3)
|
||||||
|
{
|
||||||
|
DMAC->Channel[channelRx].CHCTRLA.bit.TRIGSRC = SERCOM3_DMAC_ID_RX;
|
||||||
|
DMAC->Channel[channelTx].CHCTRLA.bit.TRIGSRC = SERCOM3_DMAC_ID_TX;
|
||||||
|
}
|
||||||
|
else if(sercom == SERCOM4)
|
||||||
|
{
|
||||||
|
DMAC->Channel[channelRx].CHCTRLA.bit.TRIGSRC = SERCOM4_DMAC_ID_RX;
|
||||||
|
DMAC->Channel[channelTx].CHCTRLA.bit.TRIGSRC = SERCOM4_DMAC_ID_TX;
|
||||||
|
}
|
||||||
|
else if(sercom == SERCOM5)
|
||||||
|
{
|
||||||
|
DMAC->Channel[channelRx].CHCTRLA.bit.TRIGSRC = SERCOM5_DMAC_ID_RX;
|
||||||
|
DMAC->Channel[channelTx].CHCTRLA.bit.TRIGSRC = SERCOM5_DMAC_ID_TX;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if(sercom == SERCOM0)
|
||||||
|
{
|
||||||
|
DMAC->CHID.bit.ID = channelRx;
|
||||||
|
DMAC->CHCTRLB.bit.TRIGSRC = SERCOM0_DMAC_ID_RX;
|
||||||
|
|
||||||
|
DMAC->CHID.bit.ID = channelTx;
|
||||||
|
DMAC->CHCTRLB.bit.TRIGSRC = SERCOM0_DMAC_ID_TX;
|
||||||
|
}
|
||||||
|
else if(sercom == SERCOM1)
|
||||||
|
{
|
||||||
|
DMAC->CHID.bit.ID = channelRx;
|
||||||
|
DMAC->CHCTRLB.bit.TRIGSRC = SERCOM1_DMAC_ID_RX;
|
||||||
|
|
||||||
|
DMAC->CHID.bit.ID = channelTx;
|
||||||
|
DMAC->CHCTRLB.bit.TRIGSRC = SERCOM1_DMAC_ID_TX;
|
||||||
|
}
|
||||||
|
else if(sercom == SERCOM2)
|
||||||
|
{
|
||||||
|
DMAC->CHID.bit.ID = channelRx;
|
||||||
|
DMAC->CHCTRLB.bit.TRIGSRC = SERCOM2_DMAC_ID_RX;
|
||||||
|
|
||||||
|
DMAC->CHID.bit.ID = channelTx;
|
||||||
|
DMAC->CHCTRLB.bit.TRIGSRC = SERCOM2_DMAC_ID_TX;
|
||||||
|
}
|
||||||
|
else if(sercom == SERCOM3)
|
||||||
|
{
|
||||||
|
DMAC->CHID.bit.ID = channelRx;
|
||||||
|
DMAC->CHCTRLB.bit.TRIGSRC = SERCOM3_DMAC_ID_RX;
|
||||||
|
|
||||||
|
DMAC->CHID.bit.ID = channelTx;
|
||||||
|
DMAC->CHCTRLB.bit.TRIGSRC = SERCOM3_DMAC_ID_TX;
|
||||||
|
}
|
||||||
|
#if defined(SERCOM4)
|
||||||
|
else if(sercom == SERCOM4)
|
||||||
|
{
|
||||||
|
DMAC->CHID.bit.ID = channelRx;
|
||||||
|
DMAC->CHCTRLB.bit.TRIGSRC = SERCOM4_DMAC_ID_RX;
|
||||||
|
|
||||||
|
DMAC->CHID.bit.ID = channelTx;
|
||||||
|
DMAC->CHCTRLB.bit.TRIGSRC = SERCOM4_DMAC_ID_TX;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(SERCOM5)
|
||||||
|
else if(sercom == SERCOM5)
|
||||||
|
{
|
||||||
|
DMAC->CHID.bit.ID = channelRx;
|
||||||
|
DMAC->CHCTRLB.bit.TRIGSRC = SERCOM5_DMAC_ID_RX;
|
||||||
|
|
||||||
|
DMAC->CHID.bit.ID = channelTx;
|
||||||
|
DMAC->CHCTRLB.bit.TRIGSRC = SERCOM5_DMAC_ID_TX;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
* ===== Sercom WIRE
|
* ===== Sercom WIRE
|
||||||
|
|
@ -374,7 +466,7 @@ void SERCOM::enableWIRE()
|
||||||
{
|
{
|
||||||
// I2C Master and Slave modes share the ENABLE bit function.
|
// I2C Master and Slave modes share the ENABLE bit function.
|
||||||
|
|
||||||
// Enable the I²C master mode
|
// Enable the I<EFBFBD>C master mode
|
||||||
sercom->I2CM.CTRLA.bit.ENABLE = 1 ;
|
sercom->I2CM.CTRLA.bit.ENABLE = 1 ;
|
||||||
|
|
||||||
while ( sercom->I2CM.SYNCBUSY.bit.ENABLE != 0 )
|
while ( sercom->I2CM.SYNCBUSY.bit.ENABLE != 0 )
|
||||||
|
|
@ -395,7 +487,7 @@ void SERCOM::disableWIRE()
|
||||||
{
|
{
|
||||||
// I2C Master and Slave modes share the ENABLE bit function.
|
// I2C Master and Slave modes share the ENABLE bit function.
|
||||||
|
|
||||||
// Enable the I²C master mode
|
// Enable the I<EFBFBD>C master mode
|
||||||
sercom->I2CM.CTRLA.bit.ENABLE = 0 ;
|
sercom->I2CM.CTRLA.bit.ENABLE = 0 ;
|
||||||
|
|
||||||
while ( sercom->I2CM.SYNCBUSY.bit.ENABLE != 0 )
|
while ( sercom->I2CM.SYNCBUSY.bit.ENABLE != 0 )
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
#define _SERCOM_CLASS_
|
#define _SERCOM_CLASS_
|
||||||
|
|
||||||
#include "sam.h"
|
#include "sam.h"
|
||||||
|
#include "dma.h"
|
||||||
|
|
||||||
#define SERCOM_FREQ_REF 48000000ul
|
#define SERCOM_FREQ_REF 48000000ul
|
||||||
|
|
||||||
|
|
@ -180,6 +181,7 @@ class SERCOM
|
||||||
bool isDataRegisterEmptySPI( void ) ;
|
bool isDataRegisterEmptySPI( void ) ;
|
||||||
bool isTransmitCompleteSPI( void ) ;
|
bool isTransmitCompleteSPI( void ) ;
|
||||||
bool isReceiveCompleteSPI( void ) ;
|
bool isReceiveCompleteSPI( void ) ;
|
||||||
|
void initSPIDMA( uint8_t channelRx, uint8_t channelTx, DmacDescriptor *descrx, DmacDescriptor *desctx ) ;
|
||||||
|
|
||||||
/* ========== WIRE ========== */
|
/* ========== WIRE ========== */
|
||||||
void initSlaveWIRE(uint8_t address) ;
|
void initSlaveWIRE(uint8_t address) ;
|
||||||
|
|
|
||||||
141
cores/arduino/dma.h
Normal file
141
cores/arduino/dma.h
Normal file
|
|
@ -0,0 +1,141 @@
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
*
|
||||||
|
* \brief SAM Direct Memory Access Controller Driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014-2015 Atmel Corporation. All rights reserved.
|
||||||
|
*
|
||||||
|
* \asf_license_start
|
||||||
|
*
|
||||||
|
* \page License
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* 4. This software may only be redistributed and used in connection with an
|
||||||
|
* Atmel microcontroller product.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||||
|
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* \asf_license_stop
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||||
|
*/
|
||||||
|
#ifndef DMA_H_INCLUDED
|
||||||
|
#define DMA_H_INCLUDED
|
||||||
|
|
||||||
|
// THIS IS A PARED-DOWN VERSION OF DMA.H FROM ATMEL ASFCORE 3.
|
||||||
|
// Please keep original copyright and license intact!
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern DmacDescriptor // 128 bit alignment
|
||||||
|
_descriptor[DMAC_CH_NUM],
|
||||||
|
_writeback[DMAC_CH_NUM];
|
||||||
|
|
||||||
|
#if (SAML21) || (SAML22) || (SAMC20) || (SAMC21) || defined(__DOXYGEN__) || defined(__SAMD51__)
|
||||||
|
#define FEATURE_DMA_CHANNEL_STANDBY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum dma_transfer_trigger_action{
|
||||||
|
#ifdef __SAMD51__
|
||||||
|
// SAMD51 has a 'burst' transfer which can be set to one
|
||||||
|
// beat to accomplish same idea as SAMD21's 'beat' transfer.
|
||||||
|
// Trigger name is ACTON_BEAT for backward compatibility.
|
||||||
|
DMA_TRIGGER_ACTON_BLOCK = DMAC_CHCTRLA_TRIGACT_BLOCK_Val,
|
||||||
|
DMA_TRIGGER_ACTON_BEAT = DMAC_CHCTRLA_TRIGACT_BURST_Val,
|
||||||
|
DMA_TRIGGER_ACTON_TRANSACTION = DMAC_CHCTRLA_TRIGACT_TRANSACTION_Val,
|
||||||
|
#else
|
||||||
|
DMA_TRIGGER_ACTON_BLOCK = DMAC_CHCTRLB_TRIGACT_BLOCK_Val,
|
||||||
|
DMA_TRIGGER_ACTON_BEAT = DMAC_CHCTRLB_TRIGACT_BEAT_Val,
|
||||||
|
DMA_TRIGGER_ACTON_TRANSACTION = DMAC_CHCTRLB_TRIGACT_TRANSACTION_Val,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
enum dma_callback_type {
|
||||||
|
// First item here is for any transfer errors. A transfer error is
|
||||||
|
// flagged if a bus error is detected during an AHB access or when
|
||||||
|
// the DMAC fetches an invalid descriptor
|
||||||
|
DMA_CALLBACK_TRANSFER_ERROR,
|
||||||
|
DMA_CALLBACK_TRANSFER_DONE,
|
||||||
|
DMA_CALLBACK_CHANNEL_SUSPEND,
|
||||||
|
DMA_CALLBACK_N, // Number of available callbacks
|
||||||
|
};
|
||||||
|
|
||||||
|
enum dma_beat_size {
|
||||||
|
DMA_BEAT_SIZE_BYTE = 0, // 8-bit
|
||||||
|
DMA_BEAT_SIZE_HWORD, // 16-bit
|
||||||
|
DMA_BEAT_SIZE_WORD, // 32-bit
|
||||||
|
};
|
||||||
|
|
||||||
|
enum dma_event_output_selection {
|
||||||
|
DMA_EVENT_OUTPUT_DISABLE = 0, // Disable event generation
|
||||||
|
DMA_EVENT_OUTPUT_BLOCK, // Event strobe when block xfer complete
|
||||||
|
DMA_EVENT_OUTPUT_RESERVED,
|
||||||
|
DMA_EVENT_OUTPUT_BEAT, // Event strobe when beat xfer complete
|
||||||
|
};
|
||||||
|
|
||||||
|
enum dma_block_action {
|
||||||
|
DMA_BLOCK_ACTION_NOACT = 0,
|
||||||
|
// Channel in normal operation and sets transfer complete interrupt
|
||||||
|
// flag after block transfer
|
||||||
|
DMA_BLOCK_ACTION_INT,
|
||||||
|
// Trigger channel suspend after block transfer and sets channel
|
||||||
|
// suspend interrupt flag once the channel is suspended
|
||||||
|
DMA_BLOCK_ACTION_SUSPEND,
|
||||||
|
// Sets transfer complete interrupt flag after a block transfer and
|
||||||
|
// trigger channel suspend. The channel suspend interrupt flag will
|
||||||
|
// be set once the channel is suspended.
|
||||||
|
DMA_BLOCK_ACTION_BOTH,
|
||||||
|
};
|
||||||
|
|
||||||
|
// DMA step selection. This bit determines whether the step size setting
|
||||||
|
// is applied to source or destination address.
|
||||||
|
enum dma_step_selection {
|
||||||
|
DMA_STEPSEL_DST = 0,
|
||||||
|
DMA_STEPSEL_SRC,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Address increment step size. These bits select the address increment step
|
||||||
|
// size. The setting apply to source or destination address, depending on
|
||||||
|
// STEPSEL setting.
|
||||||
|
enum dma_address_increment_stepsize {
|
||||||
|
DMA_ADDRESS_INCREMENT_STEP_SIZE_1 = 0, // beat size * 1
|
||||||
|
DMA_ADDRESS_INCREMENT_STEP_SIZE_2, // beat size * 2
|
||||||
|
DMA_ADDRESS_INCREMENT_STEP_SIZE_4, // beat size * 4
|
||||||
|
DMA_ADDRESS_INCREMENT_STEP_SIZE_8, // etc...
|
||||||
|
DMA_ADDRESS_INCREMENT_STEP_SIZE_16,
|
||||||
|
DMA_ADDRESS_INCREMENT_STEP_SIZE_32,
|
||||||
|
DMA_ADDRESS_INCREMENT_STEP_SIZE_64,
|
||||||
|
DMA_ADDRESS_INCREMENT_STEP_SIZE_128,
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // DMA_H_INCLUDED
|
||||||
|
|
@ -62,6 +62,12 @@ void calibrateADC()
|
||||||
* - Watchdog is disabled by default, unless someone plays with NVM User page
|
* - Watchdog is disabled by default, unless someone plays with NVM User page
|
||||||
* - During reset, all PORT lines are configured as inputs with input buffers, output buffers and pull disabled.
|
* - During reset, all PORT lines are configured as inputs with input buffers, output buffers and pull disabled.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// DMA descriptor list entry point (and writeback buffer) per channel
|
||||||
|
__attribute__((__aligned__(16))) DmacDescriptor // 128 bit alignment
|
||||||
|
_descriptor[DMAC_CH_NUM] SECTION_DMAC_DESCRIPTOR,
|
||||||
|
_writeback[DMAC_CH_NUM] SECTION_DMAC_DESCRIPTOR;
|
||||||
|
|
||||||
void init( void )
|
void init( void )
|
||||||
{
|
{
|
||||||
// Set Systick to 1ms interval, common to all Cortex-M variants
|
// Set Systick to 1ms interval, common to all Cortex-M variants
|
||||||
|
|
@ -185,6 +191,26 @@ void init( void )
|
||||||
|
|
||||||
|
|
||||||
#endif //SAMD51
|
#endif //SAMD51
|
||||||
|
|
||||||
|
//init DMAC
|
||||||
|
#if (SAML21) || (SAML22) || (SAMC20) || (SAMC21)
|
||||||
|
PM->AHBMASK.bit.DMAC_ = 1;
|
||||||
|
#elif defined(__SAMD51__)
|
||||||
|
MCLK->AHBMASK.bit.DMAC_ = 1; // Initialize DMA clocks
|
||||||
|
#else
|
||||||
|
PM->AHBMASK.bit.DMAC_ = 1; // Initialize DMA clocks
|
||||||
|
PM->APBBMASK.bit.DMAC_ = 1;
|
||||||
|
#endif
|
||||||
|
DMAC->CTRL.bit.DMAENABLE = 0; // Disable DMA controller
|
||||||
|
DMAC->CTRL.bit.SWRST = 1; // Perform software reset
|
||||||
|
|
||||||
|
// Initialize descriptor list addresses
|
||||||
|
DMAC->BASEADDR.bit.BASEADDR = (uint32_t)_descriptor;
|
||||||
|
DMAC->WRBADDR.bit.WRBADDR = (uint32_t)_writeback;
|
||||||
|
memset(_descriptor, 0, sizeof(_descriptor));
|
||||||
|
memset(_writeback , 0, sizeof(_writeback));
|
||||||
|
|
||||||
|
DMAC->CTRL.reg = DMAC_CTRL_DMAENABLE | DMAC_CTRL_LVLEN(0xF);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,8 @@
|
||||||
|
|
||||||
const SPISettings DEFAULT_SPI_SETTINGS = SPISettings();
|
const SPISettings DEFAULT_SPI_SETTINGS = SPISettings();
|
||||||
|
|
||||||
SPIClass::SPIClass(SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI, SercomSpiTXPad PadTx, SercomRXPad PadRx)
|
SPIClass::SPIClass(SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI,
|
||||||
|
SercomSpiTXPad PadTx, SercomRXPad PadRx, int8_t dmaChannelRx, int8_t dmaChannelTx)
|
||||||
{
|
{
|
||||||
initialized = false;
|
initialized = false;
|
||||||
assert(p_sercom != NULL);
|
assert(p_sercom != NULL);
|
||||||
|
|
@ -39,6 +40,9 @@ SPIClass::SPIClass(SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint
|
||||||
_uc_pinSCK = uc_pinSCK;
|
_uc_pinSCK = uc_pinSCK;
|
||||||
_uc_pinMosi = uc_pinMOSI;
|
_uc_pinMosi = uc_pinMOSI;
|
||||||
|
|
||||||
|
_dmaChannelRx = dmaChannelRx;
|
||||||
|
_dmaChannelTx = dmaChannelTx;
|
||||||
|
|
||||||
// SERCOM pads
|
// SERCOM pads
|
||||||
_padTx=PadTx;
|
_padTx=PadTx;
|
||||||
_padRx=PadRx;
|
_padRx=PadRx;
|
||||||
|
|
@ -53,6 +57,64 @@ void SPIClass::begin()
|
||||||
pinPeripheral(_uc_pinSCK, g_APinDescription[_uc_pinSCK].ulPinType);
|
pinPeripheral(_uc_pinSCK, g_APinDescription[_uc_pinSCK].ulPinType);
|
||||||
pinPeripheral(_uc_pinMosi, g_APinDescription[_uc_pinMosi].ulPinType);
|
pinPeripheral(_uc_pinMosi, g_APinDescription[_uc_pinMosi].ulPinType);
|
||||||
|
|
||||||
|
if(_dmaChannelRx > -1 && _dmaChannelTx > -1){
|
||||||
|
descrx = &_descriptor[_dmaChannelRx];
|
||||||
|
desctx = &_descriptor[_dmaChannelTx];
|
||||||
|
descrx->BTCTRL.bit.VALID = true;
|
||||||
|
descrx->BTCTRL.bit.EVOSEL = DMA_EVENT_OUTPUT_DISABLE;
|
||||||
|
descrx->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_NOACT;
|
||||||
|
descrx->BTCTRL.bit.BEATSIZE = DMA_BEAT_SIZE_BYTE;
|
||||||
|
descrx->BTCTRL.bit.SRCINC = false;
|
||||||
|
descrx->BTCTRL.bit.DSTINC = true;
|
||||||
|
descrx->BTCTRL.bit.STEPSEL = DMA_STEPSEL_DST;
|
||||||
|
descrx->BTCTRL.bit.STEPSIZE = DMA_ADDRESS_INCREMENT_STEP_SIZE_1;
|
||||||
|
descrx->BTCNT.reg = 0;
|
||||||
|
descrx->SRCADDR.reg = (uint32_t)0;
|
||||||
|
|
||||||
|
desctx->BTCTRL.bit.VALID = true;
|
||||||
|
desctx->BTCTRL.bit.EVOSEL = DMA_EVENT_OUTPUT_DISABLE;
|
||||||
|
desctx->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_NOACT;
|
||||||
|
desctx->BTCTRL.bit.BEATSIZE = DMA_BEAT_SIZE_BYTE;
|
||||||
|
desctx->BTCTRL.bit.SRCINC = true;
|
||||||
|
desctx->BTCTRL.bit.DSTINC = false;
|
||||||
|
desctx->BTCTRL.bit.STEPSEL = DMA_STEPSEL_DST;
|
||||||
|
desctx->BTCTRL.bit.STEPSIZE = DMA_ADDRESS_INCREMENT_STEP_SIZE_1;
|
||||||
|
desctx->BTCNT.reg = 0;
|
||||||
|
desctx->SRCADDR.reg = (uint32_t)0;
|
||||||
|
|
||||||
|
#ifdef __SAMD51__
|
||||||
|
DMAC->Channel[_dmaChannelRx].CHCTRLA.bit.ENABLE = 0;
|
||||||
|
DMAC->Channel[_dmaChannelRx].CHCTRLA.bit.SWRST = 1;
|
||||||
|
DMAC->Channel[_dmaChannelTx].CHCTRLA.bit.ENABLE = 0;
|
||||||
|
DMAC->Channel[_dmaChannelTx].CHCTRLA.bit.SWRST = 1;
|
||||||
|
|
||||||
|
DMAC->Channel[_dmaChannelRx].CHPRILVL.bit.PRILVL = 0;
|
||||||
|
DMAC->Channel[_dmaChannelRx].CHCTRLA.bit.TRIGACT = DMA_TRIGGER_ACTON_BEAT;
|
||||||
|
DMAC->Channel[_dmaChannelRx].CHCTRLA.bit.BURSTLEN = DMAC_CHCTRLA_BURSTLEN_SINGLE_Val; // Single-beat burst length
|
||||||
|
|
||||||
|
DMAC->Channel[_dmaChannelTx].CHPRILVL.bit.PRILVL = 0;
|
||||||
|
DMAC->Channel[_dmaChannelTx].CHCTRLA.bit.TRIGACT = DMA_TRIGGER_ACTON_BEAT;
|
||||||
|
DMAC->Channel[_dmaChannelTx].CHCTRLA.bit.BURSTLEN = DMAC_CHCTRLA_BURSTLEN_SINGLE_Val; // Single-beat burst length
|
||||||
|
|
||||||
|
DMAC->SWTRIGCTRL.reg &= ~(1UL << _dmaChannelTx);
|
||||||
|
DMAC->SWTRIGCTRL.reg &= ~(1UL << _dmaChannelRx);
|
||||||
|
#else
|
||||||
|
DMAC->CHID.bit.ID = _dmaChannelRx;
|
||||||
|
DMAC->CHCTRLA.bit.ENABLE = 0;
|
||||||
|
DMAC->CHCTRLA.bit.SWRST = 1;
|
||||||
|
DMAC->CHCTRLB.bit.LVL = 0;
|
||||||
|
DMAC->CHCTRLB.bit.TRIGACT = DMA_TRIGGER_ACTON_BEAT;
|
||||||
|
|
||||||
|
DMAC->CHID.bit.ID = _dmaChannelTx;
|
||||||
|
DMAC->CHCTRLA.bit.ENABLE = 0;
|
||||||
|
DMAC->CHCTRLA.bit.SWRST = 1;
|
||||||
|
DMAC->CHCTRLB.bit.LVL = 0;
|
||||||
|
DMAC->CHCTRLB.bit.TRIGACT = DMA_TRIGGER_ACTON_BEAT;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_p_sercom->initSPIDMA(_dmaChannelRx, _dmaChannelTx, descrx, desctx);
|
||||||
|
}
|
||||||
|
|
||||||
config(DEFAULT_SPI_SETTINGS);
|
config(DEFAULT_SPI_SETTINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -206,13 +268,82 @@ uint16_t SPIClass::transfer16(uint16_t data) {
|
||||||
return t.val;
|
return t.val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPIClass::transfer(void *buf, size_t count)
|
void SPIClass::transfer(void *rx, void *tx, size_t count)
|
||||||
{
|
{
|
||||||
uint8_t *buffer = reinterpret_cast<uint8_t *>(buf);
|
if(count > 2 && count < 65536 && _dmaChannelRx > -1 && _dmaChannelTx > -1){
|
||||||
for (size_t i=0; i<count; i++) {
|
//use a synchronous DMA transfer
|
||||||
*buffer = transfer(*buffer);
|
descrx->BTCTRL.bit.VALID = true;
|
||||||
buffer++;
|
descrx->DSTADDR.reg = (uint32_t)rx + count;
|
||||||
|
descrx->BTCNT.reg = count;
|
||||||
|
|
||||||
|
desctx->BTCTRL.bit.VALID = true;
|
||||||
|
desctx->SRCADDR.reg = (uint32_t)tx + count;
|
||||||
|
desctx->BTCNT.reg = count;
|
||||||
|
|
||||||
|
#ifdef __SAMD51__
|
||||||
|
DMAC->Channel[_dmaChannelTx].CHCTRLA.bit.ENABLE = 1;
|
||||||
|
if(rx != NULL)
|
||||||
|
DMAC->Channel[_dmaChannelRx].CHCTRLA.bit.ENABLE = 1;
|
||||||
|
#else
|
||||||
|
DMAC->CHID.bit.ID = _dmaChannelTx;
|
||||||
|
DMAC->CHCTRLA.bit.ENABLE = 1;
|
||||||
|
|
||||||
|
DMAC->CHID.bit.ID = _dmaChannelRx;
|
||||||
|
DMAC->CHCTRLA.bit.ENABLE = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//wait for the transfer to finish
|
||||||
|
while(_writeback[_dmaChannelTx].BTCTRL.bit.VALID || !_p_sercom->isDataRegisterEmptySPI());
|
||||||
|
while(!_p_sercom->isTransmitCompleteSPI());
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
|
//use a normal transfer
|
||||||
|
uint8_t *rxBuffer = reinterpret_cast<uint8_t *>(rx);
|
||||||
|
uint8_t *txBuffer = reinterpret_cast<uint8_t *>(tx);
|
||||||
|
for (size_t i=0; i<count; i++) {
|
||||||
|
*rxBuffer++ = transfer(*txBuffer++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//returns true if the transfer could be started, false otherwise
|
||||||
|
bool SPIClass::transferNonBlocking(void *rx, void *tx, size_t count)
|
||||||
|
{
|
||||||
|
if(count < 65536 && _dmaChannelRx > -1 && _dmaChannelTx > -1){
|
||||||
|
//previous transfer has not finished
|
||||||
|
if(_writeback[_dmaChannelTx].BTCTRL.bit.VALID || !_p_sercom->isDataRegisterEmptySPI() ||
|
||||||
|
!_p_sercom->isTransmitCompleteSPI()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//use a synchronous DMA transfer
|
||||||
|
descrx->BTCTRL.bit.VALID = true;
|
||||||
|
descrx->DSTADDR.reg = (uint32_t)rx + count;
|
||||||
|
descrx->BTCNT.reg = count;
|
||||||
|
|
||||||
|
desctx->BTCTRL.bit.VALID = true;
|
||||||
|
desctx->SRCADDR.reg = (uint32_t)tx + count;
|
||||||
|
desctx->BTCNT.reg = count;
|
||||||
|
|
||||||
|
#ifdef __SAMD51__
|
||||||
|
DMAC->Channel[_dmaChannelTx].CHCTRLA.bit.ENABLE = 1;
|
||||||
|
if(rx != NULL)
|
||||||
|
DMAC->Channel[_dmaChannelRx].CHCTRLA.bit.ENABLE = 1;
|
||||||
|
#else
|
||||||
|
DMAC->CHID.bit.ID = _dmaChannelTx;
|
||||||
|
DMAC->CHCTRLA.bit.ENABLE = 1;
|
||||||
|
|
||||||
|
DMAC->CHID.bit.ID = _dmaChannelRx;
|
||||||
|
DMAC->CHCTRLA.bit.ENABLE = 1;
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPIClass::transfer(void *buf, size_t count){
|
||||||
|
transfer(buf, buf, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPIClass::attachInterrupt() {
|
void SPIClass::attachInterrupt() {
|
||||||
|
|
@ -233,26 +364,51 @@ void SPIClass::detachInterrupt() {
|
||||||
* - SercomSpiTXPad
|
* - SercomSpiTXPad
|
||||||
* - SercomRXPad
|
* - SercomRXPad
|
||||||
*/
|
*/
|
||||||
#ifndef PERIPH_SPI
|
#ifndef PERIPH_SPI
|
||||||
#define PERIPH_SPI sercom4
|
#define PERIPH_SPI sercom4
|
||||||
#define PAD_SPI_TX SPI_PAD_2_SCK_3
|
#define PAD_SPI_TX SPI_PAD_2_SCK_3
|
||||||
#define PAD_SPI_RX SERCOM_RX_PAD_0
|
#define PAD_SPI_RX SERCOM_RX_PAD_0
|
||||||
#endif // PERIPH_SPI
|
#endif // PERIPH_SPI
|
||||||
|
|
||||||
|
#ifdef SPI_HAS_DMA
|
||||||
|
SPIClass SPI (&PERIPH_SPI, PIN_SPI_MISO, PIN_SPI_SCK, PIN_SPI_MOSI, PAD_SPI_TX, PAD_SPI_RX, SPI_DMA_CHANNEL_RX, SPI_DMA_CHANNEL_TX);
|
||||||
|
#else
|
||||||
SPIClass SPI (&PERIPH_SPI, PIN_SPI_MISO, PIN_SPI_SCK, PIN_SPI_MOSI, PAD_SPI_TX, PAD_SPI_RX);
|
SPIClass SPI (&PERIPH_SPI, PIN_SPI_MISO, PIN_SPI_SCK, PIN_SPI_MOSI, PAD_SPI_TX, PAD_SPI_RX);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#if SPI_INTERFACES_COUNT > 1
|
#if SPI_INTERFACES_COUNT > 1
|
||||||
|
#ifdef SPI1_HAS_DMA
|
||||||
|
SPIClass SPI1(&PERIPH_SPI1, PIN_SPI1_MISO, PIN_SPI1_SCK, PIN_SPI1_MOSI, PAD_SPI1_TX, PAD_SPI1_RX, SPI1_DMA_CHANNEL_RX, SPI1_DMA_CHANNEL_TX);
|
||||||
|
#else
|
||||||
SPIClass SPI1(&PERIPH_SPI1, PIN_SPI1_MISO, PIN_SPI1_SCK, PIN_SPI1_MOSI, PAD_SPI1_TX, PAD_SPI1_RX);
|
SPIClass SPI1(&PERIPH_SPI1, PIN_SPI1_MISO, PIN_SPI1_SCK, PIN_SPI1_MOSI, PAD_SPI1_TX, PAD_SPI1_RX);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#if SPI_INTERFACES_COUNT > 2
|
#if SPI_INTERFACES_COUNT > 2
|
||||||
SPIClass SPI2(&PERIPH_SPI2, PIN_SPI2_MISO, PIN_SPI2_SCK, PIN_SPI2_MOSI, PAD_SPI2_TX, PAD_SPI2_RX);
|
#ifdef SPI2_HAS_DMA
|
||||||
|
SPIClass SPI2(&PERIPH_SPI2, PIN_SPI2_MISO, PIN_SPI2_SCK, PIN_SPI2_MOSI, PAD_SPI2_TX, PAD_SPI2_RX, SPI2_DMA_CHANNEL_RX, SPI2_DMA_CHANNEL_TX);
|
||||||
|
#else
|
||||||
|
SPIClass SPI2(&PERIPH_SPI2, PIN_SPI1_MISO, PIN_SPI2_SCK, PIN_SPI2_MOSI, PAD_SPI2_TX, PAD_SPI2_RX);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if SPI_INTERFACES_COUNT > 3
|
#if SPI_INTERFACES_COUNT > 3
|
||||||
|
#ifdef SPI3_HAS_DMA
|
||||||
|
SPIClass SPI3(&PERIPH_SPI3, PIN_SPI3_MISO, PIN_SPI3_SCK, PIN_SPI3_MOSI, PAD_SPI3_TX, PAD_SPI3_RX, SPI3_DMA_CHANNEL_RX, SPI3_DMA_CHANNEL_TX);
|
||||||
|
#else
|
||||||
SPIClass SPI3(&PERIPH_SPI3, PIN_SPI3_MISO, PIN_SPI3_SCK, PIN_SPI3_MOSI, PAD_SPI3_TX, PAD_SPI3_RX);
|
SPIClass SPI3(&PERIPH_SPI3, PIN_SPI3_MISO, PIN_SPI3_SCK, PIN_SPI3_MOSI, PAD_SPI3_TX, PAD_SPI3_RX);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#if SPI_INTERFACES_COUNT > 4
|
#if SPI_INTERFACES_COUNT > 4
|
||||||
|
#ifdef SPI4_HAS_DMA
|
||||||
|
SPIClass SPI4(&PERIPH_SPI4, PIN_SPI4_MISO, PIN_SPI4_SCK, PIN_SPI4_MOSI, PAD_SPI4_TX, PAD_SPI4_RX, SPI4_DMA_CHANNEL_RX, SPI4_DMA_CHANNEL_TX);
|
||||||
|
#else
|
||||||
SPIClass SPI4(&PERIPH_SPI4, PIN_SPI4_MISO, PIN_SPI4_SCK, PIN_SPI4_MOSI, PAD_SPI4_TX, PAD_SPI4_RX);
|
SPIClass SPI4(&PERIPH_SPI4, PIN_SPI4_MISO, PIN_SPI4_SCK, PIN_SPI4_MOSI, PAD_SPI4_TX, PAD_SPI4_RX);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#if SPI_INTERFACES_COUNT > 5
|
#if SPI_INTERFACES_COUNT > 5
|
||||||
|
#ifdef SPI5_HAS_DMA
|
||||||
|
SPIClass SPI5(&PERIPH_SPI5, PIN_SPI5_MISO, PIN_SPI5_SCK, PIN_SPI5_MOSI, PAD_SPI5_TX, PAD_SPI5_RX, SPI5_DMA_CHANNEL_RX, SPI5_DMA_CHANNEL_TX);
|
||||||
|
#else
|
||||||
SPIClass SPI5(&PERIPH_SPI5, PIN_SPI5_MISO, PIN_SPI5_SCK, PIN_SPI5_MOSI, PAD_SPI5_TX, PAD_SPI5_RX);
|
SPIClass SPI5(&PERIPH_SPI5, PIN_SPI5_MISO, PIN_SPI5_SCK, PIN_SPI5_MOSI, PAD_SPI5_TX, PAD_SPI5_RX);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#define _SPI_H_INCLUDED
|
#define _SPI_H_INCLUDED
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include "dma.h"
|
||||||
|
|
||||||
// SPI_HAS_TRANSACTION means SPI has
|
// SPI_HAS_TRANSACTION means SPI has
|
||||||
// - beginTransaction()
|
// - beginTransaction()
|
||||||
|
|
@ -91,12 +92,14 @@ class SPISettings {
|
||||||
|
|
||||||
class SPIClass {
|
class SPIClass {
|
||||||
public:
|
public:
|
||||||
SPIClass(SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI, SercomSpiTXPad, SercomRXPad);
|
SPIClass(SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI, SercomSpiTXPad PadTx, SercomRXPad PadRx, int8_t dmaChannelRx=-1, int8_t dmaChannelTx=-1);
|
||||||
|
|
||||||
|
|
||||||
byte transfer(uint8_t data);
|
byte transfer(uint8_t data);
|
||||||
uint16_t transfer16(uint16_t data);
|
uint16_t transfer16(uint16_t data);
|
||||||
void transfer(void *buf, size_t count);
|
void transfer(void *buf, size_t count);
|
||||||
|
void transfer(void *rx, void *tx, size_t count);
|
||||||
|
bool transferNonBlocking(void *rx, void *tx, size_t count);
|
||||||
|
|
||||||
// Transaction Functions
|
// Transaction Functions
|
||||||
void usingInterrupt(int interruptNumber);
|
void usingInterrupt(int interruptNumber);
|
||||||
|
|
@ -122,6 +125,10 @@ class SPIClass {
|
||||||
uint8_t _uc_pinMiso;
|
uint8_t _uc_pinMiso;
|
||||||
uint8_t _uc_pinMosi;
|
uint8_t _uc_pinMosi;
|
||||||
uint8_t _uc_pinSCK;
|
uint8_t _uc_pinSCK;
|
||||||
|
DmacDescriptor *descrx;
|
||||||
|
DmacDescriptor *desctx;
|
||||||
|
int8_t _dmaChannelRx;
|
||||||
|
int8_t _dmaChannelTx;
|
||||||
|
|
||||||
SercomSpiTXPad _padTx;
|
SercomSpiTXPad _padTx;
|
||||||
SercomRXPad _padRx;
|
SercomRXPad _padRx;
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,13 @@ static const uint8_t MOSI = PIN_SPI_MOSI ;
|
||||||
static const uint8_t MISO = PIN_SPI_MISO ;
|
static const uint8_t MISO = PIN_SPI_MISO ;
|
||||||
static const uint8_t SCK = PIN_SPI_SCK ;
|
static const uint8_t SCK = PIN_SPI_SCK ;
|
||||||
|
|
||||||
|
#define SPI_HAS_DMA
|
||||||
|
#define SPI_DMA_CHANNEL_RX (DMAC_CH_NUM-2)
|
||||||
|
#define SPI_DMA_CHANNEL_TX (DMAC_CH_NUM-1)
|
||||||
|
|
||||||
|
#define DMAC_RESERVED_CHANNELS ((1UL << SPI_DMA_CHANNEL_RX) | \
|
||||||
|
(1UL << SPI_DMA_CHANNEL_TX))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wire Interfaces
|
* Wire Interfaces
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,13 @@ static const uint8_t MOSI = PIN_SPI_MOSI ;
|
||||||
static const uint8_t MISO = PIN_SPI_MISO ;
|
static const uint8_t MISO = PIN_SPI_MISO ;
|
||||||
static const uint8_t SCK = PIN_SPI_SCK ;
|
static const uint8_t SCK = PIN_SPI_SCK ;
|
||||||
|
|
||||||
|
#define SPI_HAS_DMA
|
||||||
|
#define SPI_DMA_CHANNEL_RX (DMAC_CH_NUM-2)
|
||||||
|
#define SPI_DMA_CHANNEL_TX (DMAC_CH_NUM-1)
|
||||||
|
|
||||||
|
#define DMAC_RESERVED_CHANNELS ((1UL << SPI_DMA_CHANNEL_RX) | \
|
||||||
|
(1UL << SPI_DMA_CHANNEL_TX))
|
||||||
|
|
||||||
|
|
||||||
#define PIN_SPI1_MISO (36u)
|
#define PIN_SPI1_MISO (36u)
|
||||||
#define PIN_SPI1_MOSI (37u)
|
#define PIN_SPI1_MOSI (37u)
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,13 @@ static const uint8_t MOSI = PIN_SPI_MOSI ;
|
||||||
static const uint8_t MISO = PIN_SPI_MISO ;
|
static const uint8_t MISO = PIN_SPI_MISO ;
|
||||||
static const uint8_t SCK = PIN_SPI_SCK ;
|
static const uint8_t SCK = PIN_SPI_SCK ;
|
||||||
|
|
||||||
|
#define SPI_HAS_DMA
|
||||||
|
#define SPI_DMA_CHANNEL_RX (DMAC_CH_NUM-2)
|
||||||
|
#define SPI_DMA_CHANNEL_TX (DMAC_CH_NUM-1)
|
||||||
|
|
||||||
|
#define DMAC_RESERVED_CHANNELS ((1UL << SPI_DMA_CHANNEL_RX) | \
|
||||||
|
(1UL << SPI_DMA_CHANNEL_TX))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wire Interfaces
|
* Wire Interfaces
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -130,6 +130,13 @@ static const uint8_t MOSI = PIN_SPI_MOSI ;
|
||||||
static const uint8_t MISO = PIN_SPI_MISO ;
|
static const uint8_t MISO = PIN_SPI_MISO ;
|
||||||
static const uint8_t SCK = PIN_SPI_SCK ;
|
static const uint8_t SCK = PIN_SPI_SCK ;
|
||||||
|
|
||||||
|
#define SPI_HAS_DMA
|
||||||
|
#define SPI_DMA_CHANNEL_RX (DMAC_CH_NUM-2)
|
||||||
|
#define SPI_DMA_CHANNEL_TX (DMAC_CH_NUM-1)
|
||||||
|
|
||||||
|
#define DMAC_RESERVED_CHANNELS ((1UL << SPI_DMA_CHANNEL_RX) | \
|
||||||
|
(1UL << SPI_DMA_CHANNEL_TX))
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wire Interfaces
|
* Wire Interfaces
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,13 @@ static const uint8_t MOSI = PIN_SPI_MOSI ;
|
||||||
static const uint8_t MISO = PIN_SPI_MISO ;
|
static const uint8_t MISO = PIN_SPI_MISO ;
|
||||||
static const uint8_t SCK = PIN_SPI_SCK ;
|
static const uint8_t SCK = PIN_SPI_SCK ;
|
||||||
|
|
||||||
|
#define SPI_HAS_DMA
|
||||||
|
#define SPI_DMA_CHANNEL_RX (DMAC_CH_NUM-2)
|
||||||
|
#define SPI_DMA_CHANNEL_TX (DMAC_CH_NUM-1)
|
||||||
|
|
||||||
|
#define DMAC_RESERVED_CHANNELS ((1UL << SPI_DMA_CHANNEL_RX) | \
|
||||||
|
(1UL << SPI_DMA_CHANNEL_TX))
|
||||||
|
|
||||||
|
|
||||||
#define PIN_SPI1_MISO (36u)
|
#define PIN_SPI1_MISO (36u)
|
||||||
#define PIN_SPI1_MOSI (37u)
|
#define PIN_SPI1_MOSI (37u)
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,13 @@ static const uint8_t MOSI = PIN_SPI_MOSI ;
|
||||||
static const uint8_t MISO = PIN_SPI_MISO ;
|
static const uint8_t MISO = PIN_SPI_MISO ;
|
||||||
static const uint8_t SCK = PIN_SPI_SCK ;
|
static const uint8_t SCK = PIN_SPI_SCK ;
|
||||||
|
|
||||||
|
#define SPI_HAS_DMA
|
||||||
|
#define SPI_DMA_CHANNEL_RX (DMAC_CH_NUM-2)
|
||||||
|
#define SPI_DMA_CHANNEL_TX (DMAC_CH_NUM-1)
|
||||||
|
|
||||||
|
#define DMAC_RESERVED_CHANNELS ((1UL << SPI_DMA_CHANNEL_RX) | \
|
||||||
|
(1UL << SPI_DMA_CHANNEL_TX))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wire Interfaces
|
* Wire Interfaces
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,12 @@ static const uint8_t MOSI = PIN_SPI_MOSI ;
|
||||||
static const uint8_t MISO = PIN_SPI_MISO ;
|
static const uint8_t MISO = PIN_SPI_MISO ;
|
||||||
static const uint8_t SCK = PIN_SPI_SCK ;
|
static const uint8_t SCK = PIN_SPI_SCK ;
|
||||||
|
|
||||||
|
#define SPI_HAS_DMA
|
||||||
|
#define SPI_DMA_CHANNEL_RX (DMAC_CH_NUM-2)
|
||||||
|
#define SPI_DMA_CHANNEL_TX (DMAC_CH_NUM-1)
|
||||||
|
|
||||||
|
#define DMAC_RESERVED_CHANNELS ((1UL << SPI_DMA_CHANNEL_RX) | \
|
||||||
|
(1UL << SPI_DMA_CHANNEL_TX))
|
||||||
|
|
||||||
#define PIN_SPI1_MISO (36u)
|
#define PIN_SPI1_MISO (36u)
|
||||||
#define PIN_SPI1_MOSI (37u)
|
#define PIN_SPI1_MOSI (37u)
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,13 @@ static const uint8_t ATN = PIN_ATN;
|
||||||
#define PAD_SPI_TX SPI_PAD_0_SCK_1
|
#define PAD_SPI_TX SPI_PAD_0_SCK_1
|
||||||
#define PAD_SPI_RX SERCOM_RX_PAD_2
|
#define PAD_SPI_RX SERCOM_RX_PAD_2
|
||||||
|
|
||||||
|
#define SPI_HAS_DMA
|
||||||
|
#define SPI_DMA_CHANNEL_RX (DMAC_CH_NUM-2)
|
||||||
|
#define SPI_DMA_CHANNEL_TX (DMAC_CH_NUM-1)
|
||||||
|
|
||||||
|
#define DMAC_RESERVED_CHANNELS ((1UL << SPI_DMA_CHANNEL_RX) | \
|
||||||
|
(1UL << SPI_DMA_CHANNEL_TX))
|
||||||
|
|
||||||
static const uint8_t SS = PIN_A2 ;
|
static const uint8_t SS = PIN_A2 ;
|
||||||
static const uint8_t MOSI = PIN_SPI_MOSI ;
|
static const uint8_t MOSI = PIN_SPI_MOSI ;
|
||||||
static const uint8_t MISO = PIN_SPI_MISO ;
|
static const uint8_t MISO = PIN_SPI_MISO ;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue