commiting examples

This commit is contained in:
Nicolas Trimborn
2021-07-26 10:32:22 +02:00
parent 76cd702edc
commit 312768d2cf
589 changed files with 464854 additions and 446 deletions

View File

@@ -50,7 +50,7 @@
<description>Atmel Start Framework</description>
<RTE_Components_h>#define ATMEL_START</RTE_Components_h>
<files>
<file category="doc" condition="ARMCC, GCC, IAR" name="hal/documentation/spi_master_sync.rst"/>
<file category="doc" condition="ARMCC, GCC, IAR" name="hal/documentation/spi_master_dma.rst"/>
<file category="doc" condition="ARMCC, GCC, IAR" name="hal/documentation/usart_sync.rst"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_atomic.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_cache.h"/>
@@ -59,7 +59,7 @@
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_init.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_io.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_sleep.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_spi_m_sync.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_spi_m_dma.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_cmcc.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_core.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_delay.h"/>
@@ -161,7 +161,7 @@
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_spi_s_sync.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_usart_async.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_usart_sync.h"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/src/hal_spi_m_sync.c"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/src/hal_spi_m_dma.c"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/src/hal_usart_sync.c"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/utils/include/parts.h"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hpl/cmcc/hpl_cmcc.c"/>

View File

@@ -146,7 +146,7 @@ drivers:
the transaction
dmac_blockact_9: Channel will be disabled if it is the last block transfer in
the transaction
dmac_channel_0_settings: false
dmac_channel_0_settings: true
dmac_channel_10_settings: false
dmac_channel_11_settings: false
dmac_channel_12_settings: false
@@ -157,7 +157,7 @@ drivers:
dmac_channel_17_settings: false
dmac_channel_18_settings: false
dmac_channel_19_settings: false
dmac_channel_1_settings: false
dmac_channel_1_settings: true
dmac_channel_20_settings: false
dmac_channel_21_settings: false
dmac_channel_22_settings: false
@@ -179,7 +179,7 @@ drivers:
dmac_channel_8_settings: false
dmac_channel_9_settings: false
dmac_dbgrun: false
dmac_dstinc_0: false
dmac_dstinc_0: true
dmac_dstinc_1: false
dmac_dstinc_10: false
dmac_dstinc_11: false
@@ -211,7 +211,7 @@ drivers:
dmac_dstinc_7: false
dmac_dstinc_8: false
dmac_dstinc_9: false
dmac_enable: false
dmac_enable: true
dmac_evact_0: No action
dmac_evact_1: No action
dmac_evact_10: No action
@@ -417,7 +417,7 @@ drivers:
dmac_runstdby_8: false
dmac_runstdby_9: false
dmac_srcinc_0: false
dmac_srcinc_1: false
dmac_srcinc_1: true
dmac_srcinc_10: false
dmac_srcinc_11: false
dmac_srcinc_12: false
@@ -449,7 +449,7 @@ drivers:
dmac_srcinc_8: false
dmac_srcinc_9: false
dmac_stepsel_0: Step size settings apply to the destination address
dmac_stepsel_1: Step size settings apply to the destination address
dmac_stepsel_1: Step size settings apply to the source address
dmac_stepsel_10: Step size settings apply to the destination address
dmac_stepsel_11: Step size settings apply to the destination address
dmac_stepsel_12: Step size settings apply to the destination address
@@ -512,8 +512,8 @@ drivers:
dmac_stepsize_7: Next ADDR = ADDR + (BEATSIZE + 1) * 1
dmac_stepsize_8: Next ADDR = ADDR + (BEATSIZE + 1) * 1
dmac_stepsize_9: Next ADDR = ADDR + (BEATSIZE + 1) * 1
dmac_trifsrc_0: Only software/event triggers
dmac_trifsrc_1: Only software/event triggers
dmac_trifsrc_0: SERCOM4 RX Trigger
dmac_trifsrc_1: SERCOM4 TX Trigger
dmac_trifsrc_10: Only software/event triggers
dmac_trifsrc_11: Only software/event triggers
dmac_trifsrc_12: Only software/event triggers
@@ -544,8 +544,8 @@ drivers:
dmac_trifsrc_7: Only software/event triggers
dmac_trifsrc_8: Only software/event triggers
dmac_trifsrc_9: Only software/event triggers
dmac_trigact_0: One trigger required for each block transfer
dmac_trigact_1: One trigger required for each block transfer
dmac_trigact_0: One trigger required for each beat transfer
dmac_trigact_1: One trigger required for each beat transfer
dmac_trigact_10: One trigger required for each block transfer
dmac_trigact_11: One trigger required for each block transfer
dmac_trigact_12: One trigger required for each block transfer
@@ -1000,12 +1000,12 @@ drivers:
slow_gclk_selection: Generic clock generator 3
SPI_0:
user_label: SPI_0
definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::SERCOM4::driver_config_definition::SPI.Master::HAL:Driver:SPI.Master.Sync
definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::SERCOM4::driver_config_definition::SPI.Master::HAL:Driver:SPI.Master.DMA
functionality: SPI
api: HAL:Driver:SPI_Master_Sync
api: HAL:Driver:SPI_Master_DMA
configuration:
spi_master_advanced: false
spi_master_arch_cpha: Sample input on leading edge
spi_master_advanced: true
spi_master_arch_cpha: Sample input on trailing edge
spi_master_arch_cpol: SCK is low when idle
spi_master_arch_dbgstop: Keep running
spi_master_arch_dord: MSB first
@@ -1013,7 +1013,10 @@ drivers:
spi_master_arch_runstdby: false
spi_master_baud_rate: 1000000
spi_master_character_size: 8 bits
spi_master_dma_rx_channel: 0
spi_master_dma_tx_channel: 1
spi_master_dummybyte: 511
spi_master_rx_channel: true
spi_master_rx_enable: true
optional_signals: []
variant:

View File

@@ -50,8 +50,7 @@ uint8_t spiCalcEvenParity(uint16_t value){
uint16_t read(uint16_t registerAddress)
{
uint8_t dummy_packet[2] = {0xC0,0x00};
union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } t;
uint8_t in_buf[2], out_buf[2];
volatile uint16_t command = 0b0100000000000000; // PAR=0 R/W=R
@@ -72,7 +71,7 @@ uint16_t read(uint16_t registerAddress)
/* Send Command */
gpio_set_pin_level(AS5048A_CS, false);
//io_write(io, &out_buf, 2);
spi_m_sync_transfer(&SPI_0, &xfer);
gpio_set_pin_level(AS5048A_CS, true);
// spi_m_sync_transfer(&SPI_0, &xfer);

View File

@@ -0,0 +1,167 @@
/*
* AS5048A_dma.c
*
* Created: 18/07/2021 14:38:25
* Author: Nick-XMG
*/
#include "AS5048A_dma.h"
#include "atmel_start_pins.h"
static uint8_t AS5048A_rx_buffer[2] = {0};
static uint8_t AS5048A_tx_buffer[2] = {0};
void spi_master_tx_complete_cb(struct _dma_resource *const resource)
{
//DMAC->Channel[CONF_SERCOM_6_TRANSMIT_DMA_CHANNEL].CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE;
delay_us(10);
gpio_set_pin_level(SPI_SS, true);
}
void spi_master_rx_complete_cb(struct _dma_resource *const resource)
{
//DMAC->Channel[CONF_SERCOM_6_RECEIVE_DMA_CHANNEL].CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE;
gpio_set_pin_level(SPI_SS, true);
}
void as5048a_init(void)
{
spi_m_dma_enable(&SPI_0);
/* tx_descriptor */
DmacDescriptor tx_descriptor;
tx_descriptor.DSTADDR.reg = (uint32_t)&AS5048A_SPI->SPI.DATA.reg; // destination address is SPI DATA register
tx_descriptor.SRCADDR.reg = (uint32_t)(AS5048A_tx_buffer + sizeof AS5048A_tx_buffer); // source address is the DMA buffer
tx_descriptor.DESCADDR.reg = 0; // only one transfer descriptor
tx_descriptor.BTCTRL.bit.BEATSIZE = DMAC_BTCTRL_BEATSIZE_BYTE_Val; // beat size is one byte
tx_descriptor.BTCTRL.bit.DSTINC = 0; // destination address increment disabled
tx_descriptor.BTCTRL.bit.SRCINC = 1; // source address increment enabled
tx_descriptor.BTCTRL.bit.STEPSEL = DMAC_BTCTRL_STEPSEL_SRC_Val; // flexible source address increment size
tx_descriptor.BTCTRL.bit.STEPSIZE = DMAC_BTCTRL_STEPSIZE_X1_Val; // source address increment is one byte
tx_descriptor.BTCTRL.bit.BLOCKACT = DMAC_BTCTRL_BLOCKACT_NOACT_Val; // request interrupt at end of block transfer
tx_descriptor.BTCNT.reg = sizeof AS5048A_tx_buffer; // beat count
tx_descriptor.BTCTRL.bit.VALID = 1;
//DMA_add_channel(0x0D, tx_descriptor, 1);
/* Register Callback */
spi_m_dma_register_callback(&SPI_0, SPI_M_DMA_CB_TX_DONE, spi_master_tx_complete_cb);
//struct _dma_resource *resource_tx;
//_dma_get_channel_resource(&resource_tx, CONF_SERCOM_6_TRANSMIT_DMA_CHANNEL);
//resource_tx->dma_cb.transfer_done = DMAC_Handler_tx_cb;
/* rx_descriptor */
DmacDescriptor rx_descriptor;
rx_descriptor.DSTADDR.reg = (uint32_t)(AS5048A_rx_buffer + sizeof AS5048A_rx_buffer); // destination address is SPI DATA register
rx_descriptor.SRCADDR.reg = (uint32_t)&AS5048A_SPI->SPI.DATA.reg; // source address is the DMA buffer
rx_descriptor.DESCADDR.reg = 0; // only one transfer descriptor
rx_descriptor.BTCTRL.bit.BEATSIZE = DMAC_BTCTRL_BEATSIZE_BYTE_Val; // beat size is one byte
rx_descriptor.BTCTRL.bit.DSTINC = 0; // destination address increment disabled
rx_descriptor.BTCTRL.bit.SRCINC = 1; // source address increment enabled
rx_descriptor.BTCTRL.bit.STEPSEL = DMAC_BTCTRL_STEPSEL_SRC_Val; // flexible source address increment size
rx_descriptor.BTCTRL.bit.STEPSIZE = DMAC_BTCTRL_STEPSIZE_X1_Val; // source address increment is one byte
rx_descriptor.BTCTRL.bit.BLOCKACT = DMAC_BTCTRL_BLOCKACT_NOACT_Val; // request interrupt at end of block transfer
rx_descriptor.BTCNT.reg = sizeof AS5048A_rx_buffer; // beat count
rx_descriptor.BTCTRL.bit.VALID = 1;
//DMA_add_channel(0x0C, rx_descriptor, 0);
/* Register Callback */
spi_m_dma_register_callback(&SPI_0, SPI_M_DMA_CB_RX_DONE, spi_master_rx_complete_cb);
//struct _dma_resource *resource_rx;
//_dma_get_channel_resource(&resource_tx, CONF_SERCOM_6_RECEIVE_DMA_CHANNEL);
//resource_tx->dma_cb.transfer_done = DMAC_Handler_rx_cb;
//DMA_enable();
}
uint16_t as5048a_read(uint16_t registerAddress)
{
uint8_t in_buf[2], out_buf[2];
volatile uint16_t command = 0b0100000000000000; // PAR=0 R/W=R
command = command | registerAddress;
//Add a parity bit on the the MSB
command |= ((uint16_t)spiCalcEvenParity(command)<<15);
//Split the command into two bytes
AS5048A_tx_buffer[1] = command & 0xFF;
AS5048A_tx_buffer[0] = ( command >> 8 ) & 0xFF;
gpio_set_pin_level(SPI_SS, false);
spi_m_dma_transfer(&SPI_0, AS5048A_tx_buffer, AS5048A_rx_buffer, sizeof AS5048A_tx_buffer );
//gpio_set_pin_level(SPI_SS, false);
//_dma_enable_transaction(0,false);
//_dma_enable_transaction(1,false);
if (AS5048A_rx_buffer[1] & 0x40) {
int i = 0;
//as5048a.errorFlag = 1;
} else {
//as5048a.errorFlag = 0;
}
return (( ( AS5048A_rx_buffer[1] & 0xFF ) << 8 ) | ( AS5048A_rx_buffer[0] & 0xFF )) & ~0xC000;
}
void as5048a_write(void)
{
}
uint8_t calcEvenParity(uint16_t value)
{
uint8_t cnt = 0;
uint8_t i;
for (i = 0; i < 16; i++)
{
if (value & 0x1)
{
cnt++;
}
value >>= 1;
}
return cnt & 0x1;
}
void DMA_add_channel(const int trigger_source, DmacDescriptor descriptor, const uint8_t channel)
{
/* disable DMA if enabled */
if (DMAC->CTRL.bit.DMAENABLE)
DMAC->CTRL.bit.DMAENABLE = 0;
while (DMAC->CTRL.bit.DMAENABLE);
_dma_set_descriptor(channel, descriptor);
/* add transfer descriptor to transfer descriptor section (before enabling channel!) */
//memcpy(descriptor_section + channel * sizeof(DmacDescriptor) , descriptor, sizeof(DmacDescriptor));
/* configure and enable first least significant free channel */
// use first free channel
DMAC->Channel[channel].CHPRILVL.bit.PRILVL = 0x00; // channel priority level 0
DMAC->Channel[channel].CHCTRLA.bit.TRIGACT = 0x02; // one trigger each beat transfer
DMAC->Channel[channel].CHCTRLA.bit.TRIGSRC = trigger_source; // select trigger source
DMAC->Channel[channel].CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE; // enable channel
/* enable DMA block transfer complete interrupt */
DMAC->Channel[channel].CHINTENSET.bit.TCMPL = 1; // enable DMA block transfer complete interrupt
NVIC_EnableIRQ(DMAC_1_IRQn);
}
void DMA_enable(void)
{
/* enable DMA controller */
DMAC->CTRL.bit.DMAENABLE = 1;
}

View File

@@ -0,0 +1,43 @@
/*
* AS5048A_dma.h
*
* Created: 18/07/2021 14:38:15
* Author: Nick-XMG
*/
#ifndef AS5048A_DMA_H_
#define AS5048A_DMA_H_
#include <atmel_start.h>
#include <hpl_dma.h>
/* AS5048 Registers */
#define AS5048A_CMD_NOP 0x0000
#define AS5048A_READ 0x4000
#define AS5048A_CLEAR_ERROR_FLAG 0x0001
#define AS5048A_PROGRAMMING_CONTROL 0x0003
#define AS5048A_OTP_REGISTER_ZERO_POS_HIGH 0x0016
#define AS5048A_OTP_REGISTER_ZERO_POS_LOW 0x0017
#define AS5048A_DIAG_AGC 0x3FFD
#define AS5048A_MAGNITUDE 0x3FFE
#define AS5048A_ANGLE 0x3FFF
/* AS5048 parameters */
#define AS5048A_MAX_VALUE 8191.0f
/* DMA channel for SPI Master TX and RX */
#define CONF_SERCOM_6_TRANSMIT_DMA_CHANNEL 0
#define CONF_SERCOM_6_RECEIVE_DMA_CHANNEL 1
#define AS5048A_SPI SERCOM4
void as5048a_init(void);
uint16_t as5048a_read(uint16_t registerAddress);
void as5048a_write(void);
uint8_t calcEvenParity(uint16_t value);
void DMA_add_channel(const int trigger_source, DmacDescriptor descriptor, const uint8_t channel);
void DMA_enable(void);
#endif /* AS5048A_DMA_H_ */

View File

@@ -58,7 +58,7 @@
<AcmeProjectActionInfo Action="File" Source="hal/include/hal_init.h" IsConfig="false" Hash="OrYSVpF3YA5XrOBImWpdSg" />
<AcmeProjectActionInfo Action="File" Source="hal/include/hal_io.h" IsConfig="false" Hash="XZRSabc39WU/0MFBLYGLvQ" />
<AcmeProjectActionInfo Action="File" Source="hal/include/hal_sleep.h" IsConfig="false" Hash="KuZDwgrLdU+fuMG82ZFTqg" />
<AcmeProjectActionInfo Action="File" Source="hal/include/hal_spi_m_sync.h" IsConfig="false" Hash="2oma6hRMCcowUy2wVveqMg" />
<AcmeProjectActionInfo Action="File" Source="hal/include/hal_spi_m_dma.h" IsConfig="false" Hash="MRP9iaBaY97VrZIf+yI+nQ" />
<AcmeProjectActionInfo Action="File" Source="hal/include/hpl_cmcc.h" IsConfig="false" Hash="mDAHEzTxsniAe2HtqO43oA" />
<AcmeProjectActionInfo Action="File" Source="hal/include/hpl_core.h" IsConfig="false" Hash="XeEtUlBSwXUmLA41hFYYWg" />
<AcmeProjectActionInfo Action="File" Source="hal/include/hpl_delay.h" IsConfig="false" Hash="3tgjyGPrs0ePCewpMUQPbQ" />
@@ -144,11 +144,11 @@
<AcmeProjectActionInfo Action="File" Source="stdio_redirect/stdio_io.c" IsConfig="false" Hash="Nx8PfIAymK/f5AjLql/CyQ" />
<AcmeProjectActionInfo Action="File" Source="stdio_redirect/stdio_io.h" IsConfig="false" Hash="4X02f8UL8cjBHeGJM3BnHw" />
<AcmeProjectActionInfo Action="File" Source="main.c" IsConfig="false" Hash="k0AH7j+BrmdFhBPzCCMptA" />
<AcmeProjectActionInfo Action="File" Source="driver_init.c" IsConfig="false" Hash="YY6vPpiyDxSIT1+YpzM7Kw" />
<AcmeProjectActionInfo Action="File" Source="driver_init.h" IsConfig="false" Hash="HHGaPRA14zpRrZmWNf1CpA" />
<AcmeProjectActionInfo Action="File" Source="driver_init.c" IsConfig="false" Hash="PLbWLP8oINvN7KOAwvpoMw" />
<AcmeProjectActionInfo Action="File" Source="driver_init.h" IsConfig="false" Hash="KySSAkcWv9PPl3bgQY8WRg" />
<AcmeProjectActionInfo Action="File" Source="atmel_start_pins.h" IsConfig="false" Hash="M5pyeMRZyoPpiWeIh6Kfwg" />
<AcmeProjectActionInfo Action="File" Source="examples/driver_examples.h" IsConfig="false" Hash="Rmw7b009Kyb5JTTerAW1RA" />
<AcmeProjectActionInfo Action="File" Source="examples/driver_examples.c" IsConfig="false" Hash="UJMLSdu355whTkvhArrZiQ" />
<AcmeProjectActionInfo Action="File" Source="examples/driver_examples.h" IsConfig="false" Hash="dkK05IW/Rlgtb0Wi2Od/sA" />
<AcmeProjectActionInfo Action="File" Source="examples/driver_examples.c" IsConfig="false" Hash="lGVC3kcjrnpxt217aSMKlw" />
<AcmeProjectActionInfo Action="File" Source="hal/include/hal_usart_sync.h" IsConfig="false" Hash="ZzIGSRyjZuxRzFAtNNt7sw" />
<AcmeProjectActionInfo Action="File" Source="hal/include/hpl_missing_features.h" IsConfig="false" Hash="XsAvpgfutzkw0Y5SydYFaw" />
<AcmeProjectActionInfo Action="File" Source="hal/include/hpl_reset.h" IsConfig="false" Hash="WwLFRlBtuZ/qnD1JuDKnRQ" />
@@ -159,14 +159,14 @@
<AcmeProjectActionInfo Action="File" Source="hal/include/hpl_spi_s_sync.h" IsConfig="false" Hash="gEGr6GqKbsOQvxQYz2fotA" />
<AcmeProjectActionInfo Action="File" Source="hal/include/hpl_usart_async.h" IsConfig="false" Hash="tBfmk3BN3Q1WbYVoWDbsJw" />
<AcmeProjectActionInfo Action="File" Source="hal/include/hpl_usart_sync.h" IsConfig="false" Hash="Yj+PoPxG2CqDOy5XoIWkwg" />
<AcmeProjectActionInfo Action="File" Source="hal/src/hal_spi_m_sync.c" IsConfig="false" Hash="Q0IudnTEWeoIkfQIoYIqxA" />
<AcmeProjectActionInfo Action="File" Source="hal/src/hal_spi_m_dma.c" IsConfig="false" Hash="KMrinO/3xx7qWxy2PsJB7g" />
<AcmeProjectActionInfo Action="File" Source="hal/src/hal_usart_sync.c" IsConfig="false" Hash="VBVlAmBFEYTTUMHeIRFSxg" />
<AcmeProjectActionInfo Action="File" Source="hal/utils/include/parts.h" IsConfig="false" Hash="THMC0T2wU10PzPgIVGK93g" />
<AcmeProjectActionInfo Action="File" Source="hpl/cmcc/hpl_cmcc.c" IsConfig="false" Hash="xrdKSj3ppVwQWgZ3zrlaRg" />
<AcmeProjectActionInfo Action="File" Source="hpl/core/hpl_core_m4.c" IsConfig="false" Hash="VG4QALndju794J3HSKhsEQ" />
<AcmeProjectActionInfo Action="File" Source="hpl/core/hpl_core_port.h" IsConfig="false" Hash="RXrDMMracCeflR1F9jWiGg" />
<AcmeProjectActionInfo Action="File" Source="hpl/core/hpl_init.c" IsConfig="false" Hash="/W7xK3rVKLxPEwN+aiJq8Q" />
<AcmeProjectActionInfo Action="File" Source="hpl/dmac/hpl_dmac.c" IsConfig="false" Hash="RW/GgakK2RoVdDBtrCxYaA" />
<AcmeProjectActionInfo Action="File" Source="hpl/dmac/hpl_dmac.c" IsConfig="false" Hash="hfo1VP6av1KthYmILu3PCg" />
<AcmeProjectActionInfo Action="File" Source="hpl/gclk/hpl_gclk.c" IsConfig="false" Hash="5XO/19EedZQ0lq6yB8UTWQ" />
<AcmeProjectActionInfo Action="File" Source="hpl/gclk/hpl_gclk_base.h" IsConfig="false" Hash="VnaHvu/VnbGvOxrehrp2mQ" />
<AcmeProjectActionInfo Action="File" Source="hpl/mclk/hpl_mclk.c" IsConfig="false" Hash="XNSKHdNpSWfkSJUMnJUASA" />
@@ -176,19 +176,19 @@
<AcmeProjectActionInfo Action="File" Source="hpl/pm/hpl_pm_base.h" IsConfig="false" Hash="KOec1StxUZxY/RKBDbMkpg" />
<AcmeProjectActionInfo Action="File" Source="hpl/port/hpl_gpio_base.h" IsConfig="false" Hash="tEjgvZ4kvfccSWnEgilG5Q" />
<AcmeProjectActionInfo Action="File" Source="hpl/ramecc/hpl_ramecc.c" IsConfig="false" Hash="pMdmwVWBg16VG8HOwA3DPw" />
<AcmeProjectActionInfo Action="File" Source="hpl/sercom/hpl_sercom.c" IsConfig="false" Hash="CjIu1Ksl4k1CotxZpVcqMA" />
<AcmeProjectActionInfo Action="File" Source="hpl/sercom/hpl_sercom.c" IsConfig="false" Hash="hcMq5dgdlyb9xXr1YOQnMQ" />
<AcmeProjectActionInfo Action="File" Source="stdio_start.c" IsConfig="false" Hash="WtwT7ld+0j4cPDj52v3y1A" />
<AcmeProjectActionInfo Action="File" Source="stdio_start.h" IsConfig="false" Hash="5j2k69zdoQpbzluEyr/rHQ" />
<AcmeProjectActionInfo Action="File" Source="atmel_start.h" IsConfig="false" Hash="TNU9VszFRFbDuMJ3vToUzg" />
<AcmeProjectActionInfo Action="File" Source="atmel_start.c" IsConfig="false" Hash="lom1/YOY9m/TDACgnyb3yA" />
<AcmeProjectActionInfo Action="File" Source="config/hpl_cmcc_config.h" IsConfig="true" Hash="bmtxQ8rLloaRtAo2HeXZRQ" />
<AcmeProjectActionInfo Action="File" Source="config/hpl_dmac_config.h" IsConfig="true" Hash="mNec32O7w53e4vDmQlvjCA" />
<AcmeProjectActionInfo Action="File" Source="config/hpl_dmac_config.h" IsConfig="true" Hash="ns3tY+WWZKF5xxMvthvqEQ" />
<AcmeProjectActionInfo Action="File" Source="config/hpl_gclk_config.h" IsConfig="true" Hash="qFfXbIiu7Skw/l5fYsEt7Q" />
<AcmeProjectActionInfo Action="File" Source="config/hpl_mclk_config.h" IsConfig="true" Hash="pxBzoQXTG66x4dbzVzxteg" />
<AcmeProjectActionInfo Action="File" Source="config/hpl_osc32kctrl_config.h" IsConfig="true" Hash="HgvzEqDUH4jq/syjj/+G+Q" />
<AcmeProjectActionInfo Action="File" Source="config/hpl_oscctrl_config.h" IsConfig="true" Hash="uzEpFoaBTLlpyWknL/fmxg" />
<AcmeProjectActionInfo Action="File" Source="config/hpl_port_config.h" IsConfig="true" Hash="5iQ/eeupKkHFkYA/g43bXQ" />
<AcmeProjectActionInfo Action="File" Source="config/hpl_sercom_config.h" IsConfig="true" Hash="4cR+7kwM1FGXaHKzMryPIw" />
<AcmeProjectActionInfo Action="File" Source="config/hpl_sercom_config.h" IsConfig="true" Hash="YlSwcGH0BPsqcwA8k4enSA" />
<AcmeProjectActionInfo Action="File" Source="config/peripheral_clk_config.h" IsConfig="true" Hash="zg2vMh4Usy8Jbwc/RH3Ljg" />
<AcmeProjectActionInfo Action="File" Source="config/stdio_redirect_config.h" IsConfig="true" Hash="CKmkBk12sfr7mb+HRQBuzg" />
</AcmeActionInfos>
@@ -343,6 +343,7 @@
<armgcc.compiler.optimization.DebugLevel>Maximum (-g3)</armgcc.compiler.optimization.DebugLevel>
<armgcc.compiler.warnings.AllWarnings>True</armgcc.compiler.warnings.AllWarnings>
<armgcc.compiler.miscellaneous.OtherFlags>-std=gnu99 -mfloat-abi=softfp -mfpu=fpv4-sp-d16</armgcc.compiler.miscellaneous.OtherFlags>
<armgcc.linker.general.UseNewlibNano>True</armgcc.linker.general.UseNewlibNano>
<armgcc.linker.libraries.Libraries>
<ListValues>
<Value>libm</Value>
@@ -416,6 +417,12 @@
<Compile Include="AS5048A.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="AS5048A_dma.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="AS5048A_dma.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="atmel_start.c">
<SubType>compile</SubType>
</Compile>
@@ -497,7 +504,7 @@
<Compile Include="hal\include\hal_sleep.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="hal\include\hal_spi_m_sync.h">
<Compile Include="hal\include\hal_spi_m_dma.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="hal\include\hal_usart_sync.h">
@@ -605,7 +612,7 @@
<Compile Include="hal\src\hal_sleep.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="hal\src\hal_spi_m_sync.c">
<Compile Include="hal\src\hal_spi_m_dma.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="hal\src\hal_usart_sync.c">
@@ -875,7 +882,7 @@
<None Include="documentation\stdio.rst">
<SubType>compile</SubType>
</None>
<None Include="hal\documentation\spi_master_sync.rst">
<None Include="hal\documentation\spi_master_dma.rst">
<SubType>compile</SubType>
</None>
<None Include="hal\documentation\usart_sync.rst">

View File

@@ -8,7 +8,7 @@
// <i> Indicates whether dmac is enabled or not
// <id> dmac_enable
#ifndef CONF_DMAC_ENABLE
#define CONF_DMAC_ENABLE 0
#define CONF_DMAC_ENABLE 1
#endif
// <q> Priority Level 0
@@ -105,7 +105,7 @@
// <e> Channel 0 settings
// <id> dmac_channel_0_settings
#ifndef CONF_DMAC_CHANNEL_0_SETTINGS
#define CONF_DMAC_CHANNEL_0_SETTINGS 0
#define CONF_DMAC_CHANNEL_0_SETTINGS 1
#endif
// <q> Channel Run in Standby
@@ -122,7 +122,7 @@
// <i> Defines the trigger action used for a transfer
// <id> dmac_trigact_0
#ifndef CONF_DMAC_TRIGACT_0
#define CONF_DMAC_TRIGACT_0 0
#define CONF_DMAC_TRIGACT_0 2
#endif
// <o> Trigger source
@@ -214,7 +214,7 @@
// <i> Defines the peripheral trigger which is source of the transfer
// <id> dmac_trifsrc_0
#ifndef CONF_DMAC_TRIGSRC_0
#define CONF_DMAC_TRIGSRC_0 0
#define CONF_DMAC_TRIGSRC_0 12
#endif
// <o> Channel Arbitration Level
@@ -291,7 +291,7 @@
// <i> Indicates whether the destination address incrementation is enabled or not
// <id> dmac_dstinc_0
#ifndef CONF_DMAC_DSTINC_0
#define CONF_DMAC_DSTINC_0 0
#define CONF_DMAC_DSTINC_0 1
#endif
// <o> Beat Size
@@ -329,7 +329,7 @@
// <e> Channel 1 settings
// <id> dmac_channel_1_settings
#ifndef CONF_DMAC_CHANNEL_1_SETTINGS
#define CONF_DMAC_CHANNEL_1_SETTINGS 0
#define CONF_DMAC_CHANNEL_1_SETTINGS 1
#endif
// <q> Channel Run in Standby
@@ -346,7 +346,7 @@
// <i> Defines the trigger action used for a transfer
// <id> dmac_trigact_1
#ifndef CONF_DMAC_TRIGACT_1
#define CONF_DMAC_TRIGACT_1 0
#define CONF_DMAC_TRIGACT_1 2
#endif
// <o> Trigger source
@@ -438,7 +438,7 @@
// <i> Defines the peripheral trigger which is source of the transfer
// <id> dmac_trifsrc_1
#ifndef CONF_DMAC_TRIGSRC_1
#define CONF_DMAC_TRIGSRC_1 0
#define CONF_DMAC_TRIGSRC_1 13
#endif
// <o> Channel Arbitration Level
@@ -501,14 +501,14 @@
// <i> Defines whether source or destination addresses are using the step size settings
// <id> dmac_stepsel_1
#ifndef CONF_DMAC_STEPSEL_1
#define CONF_DMAC_STEPSEL_1 0
#define CONF_DMAC_STEPSEL_1 1
#endif
// <q> Source Address Increment
// <i> Indicates whether the source address incrementation is enabled or not
// <id> dmac_srcinc_1
#ifndef CONF_DMAC_SRCINC_1
#define CONF_DMAC_SRCINC_1 0
#define CONF_DMAC_SRCINC_1 1
#endif
// <q> Destination Address Increment

View File

@@ -280,6 +280,28 @@
#define CONF_SERCOM_4_SPI_ENABLE 1
#endif
//<o> SPI DMA TX Channel <0-32>
//<i> This defines DMA channel to be used
//<id> spi_master_dma_tx_channel
#ifndef CONF_SERCOM_4_SPI_M_DMA_TX_CHANNEL
#define CONF_SERCOM_4_SPI_M_DMA_TX_CHANNEL 1
#endif
// <e> SPI RX Channel Enable
// <id> spi_master_rx_channel
#ifndef CONF_SERCOM_4_SPI_RX_CHANNEL
#define CONF_SERCOM_4_SPI_RX_CHANNEL 1
#endif
//<o> DMA Channel <0-32>
//<i> This defines DMA channel to be used
//<id> spi_master_dma_rx_channel
#ifndef CONF_SERCOM_4_SPI_M_DMA_RX_CHANNEL
#define CONF_SERCOM_4_SPI_M_DMA_RX_CHANNEL 0
#endif
// </e>
// Set module in SPI Master mode
#ifndef CONF_SERCOM_4_SPI_MODE
#define CONF_SERCOM_4_SPI_MODE 0x03
@@ -314,7 +336,7 @@
// <e> Advanced Configuration
// <id> spi_master_advanced
#ifndef CONF_SERCOM_4_SPI_ADVANCED
#define CONF_SERCOM_4_SPI_ADVANCED 0
#define CONF_SERCOM_4_SPI_ADVANCED 1
#endif
// <o> Dummy byte <0x00-0x1ff>
@@ -348,7 +370,7 @@
// <i> Determines if input data is sampled on leading or trailing SCK edge. (CPHA)
// <id> spi_master_arch_cpha
#ifndef CONF_SERCOM_4_SPI_CPHA
#define CONF_SERCOM_4_SPI_CPHA 0x0
#define CONF_SERCOM_4_SPI_CPHA 0x1
#endif
// <o> Immediate Buffer Overflow Notification

View File

@@ -11,10 +11,10 @@
#include <utils.h>
#include <hal_init.h>
struct spi_m_sync_descriptor SPI_0;
struct usart_sync_descriptor TARGET_IO;
struct spi_m_dma_descriptor SPI_0;
void TARGET_IO_PORT_init(void)
{
@@ -90,7 +90,7 @@ void SPI_0_CLOCK_init(void)
void SPI_0_init(void)
{
SPI_0_CLOCK_init();
spi_m_sync_init(&SPI_0, SERCOM4);
spi_m_dma_init(&SPI_0, SERCOM4);
SPI_0_PORT_init();
}

View File

@@ -22,10 +22,12 @@ extern "C" {
#include <hal_sleep.h>
#include <hal_usart_sync.h>
#include <hal_spi_m_sync.h>
#include <hal_spi_m_dma.h>
extern struct usart_sync_descriptor TARGET_IO;
extern struct spi_m_sync_descriptor SPI_0;
extern struct spi_m_dma_descriptor SPI_0;
void TARGET_IO_PORT_init(void);
void TARGET_IO_CLOCK_init(void);

View File

@@ -24,14 +24,26 @@ void TARGET_IO_example(void)
/**
* Example of using SPI_0 to write "Hello World" using the IO abstraction.
*
* Since the driver is asynchronous we need to use statically allocated memory for string
* because driver initiates transfer and then returns before the transmission is completed.
*
* Once transfer has been completed the tx_cb function will be called.
*/
static uint8_t example_SPI_0[12] = "Hello World!";
static void tx_complete_cb_SPI_0(struct _dma_resource *resource)
{
/* Transfer completed */
}
void SPI_0_example(void)
{
struct io_descriptor *io;
spi_m_sync_get_io_descriptor(&SPI_0, &io);
spi_m_dma_get_io_descriptor(&SPI_0, &io);
spi_m_sync_enable(&SPI_0);
spi_m_dma_register_callback(&SPI_0, SPI_M_DMA_CB_TX_DONE, tx_complete_cb_SPI_0);
spi_m_dma_enable(&SPI_0);
io_write(io, example_SPI_0, 12);
}

View File

@@ -14,6 +14,8 @@ extern "C" {
void TARGET_IO_example(void);
void SPI_0_example(void);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,56 @@
The SPI Master DMA Driver
==================================
The serial peripheral interface (SPI) is a DMA serial communication
interface.
The SPI Master DMA driver uses DMA system to transfer data from
a memory buffer to SPI (Memory to Peripheral), and receive data
from SPI to a memory buffer (Peripheral to Memory).User must configure
DMA system driver accordingly. A callback is called when all the data
is transfered or all the data is received, if it is registered via
spi_m_dma_register_callback function.
Features
--------
* Initialization/de-initialization
* Enabling/disabling
* Control of the following settings:
* Baudrate
* SPI mode
* Character size
* Data order
* Data transfer: transmission, reception and full-duplex
* Notifications about transfer completion and errors via callbacks
Applications
------------
Send/receive/exchange data with a SPI slave device. E.g., serial flash, SD card,
LCD controller, etc.
Dependencies
------------
SPI master capable hardware and DMA hardware, with data sent/received.
Concurrency
-----------
N/A
Limitations
-----------
When only uses DMA channel to receive data, the transfer channel must enable to
send dummy data to the slave.
While read/write/transfer is in progress, the data buffer used must be kept
unchanged.
Known issues and workarounds
----------------------------
N/A

View File

@@ -1,51 +0,0 @@
The SPI Master Synchronous Driver
=================================
The serial peripheral interface (SPI) is a synchronous serial communication
interface.
SPI devices communicate in full duplex mode using a master-slave
architecture with a single master. The master device originates the frame for
reading and writing. Multiple slave devices are supported through selection
with individual slave select (SS) lines.
Features
--------
* Initialization/de-initialization
* Enabling/disabling
* Control of the following settings:
* Baudrate
* SPI mode
* Character size
* Data order
* Data transfer: transmission, reception and full-duplex
Applications
------------
Send/receive/exchange data with a SPI slave device. E.g., serial flash, SD card,
LCD controller, etc.
Dependencies
------------
SPI master capable hardware
Concurrency
-----------
N/A
Limitations
-----------
The slave select (SS) is not automatically inserted during read/write/transfer,
user must use I/O to control the devices' SS.
Known issues and workarounds
----------------------------
N/A

View File

@@ -0,0 +1,257 @@
/**
* \file
*
* \brief SPI DMA related functionality declaration.
*
* Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#ifndef _HAL_SPI_M_DMA_H_INCLUDED
#define _HAL_SPI_M_DMA_H_INCLUDED
#include <hal_io.h>
#include <hpl_spi_m_dma.h>
/**
* \addtogroup doc_driver_hal_spi_master_dma
*
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/* Forward declaration of spi_descriptor. */
struct spi_m_dma_descriptor;
/** The callback types */
enum spi_m_dma_cb_type {
/** Callback type for DMA transfer buffer done */
SPI_M_DMA_CB_TX_DONE,
/** Callback type for DMA receive buffer done */
SPI_M_DMA_CB_RX_DONE,
/** Callback type for DMA errors */
SPI_M_DMA_CB_ERROR,
SPI_M_DMA_CB_N
};
/**
* \brief SPI Master DMA callback type
*/
typedef void (*spi_m_dma_cb_t)(struct _dma_resource *resource);
/** \brief SPI HAL driver struct for DMA access
*/
struct spi_m_dma_descriptor {
struct _spi_m_dma_hpl_interface *func;
/** Pointer to SPI device instance */
struct _spi_m_dma_dev dev;
/** I/O read/write */
struct io_descriptor io;
/** DMA resource */
struct _dma_resource *resource;
};
/** \brief Set the SPI HAL instance function pointer for HPL APIs.
*
* Set SPI HAL instance function pointer for HPL APIs.
*
* \param[in] spi Pointer to the HAL SPI instance.
* \param[in] func Pointer to the HPL api structure.
*
*/
void spi_m_dma_set_func_ptr(struct spi_m_dma_descriptor *spi, void *const func);
/** \brief Initialize the SPI HAL instance and hardware for DMA mode
*
* Initialize SPI HAL with dma mode.
*
* \param[in] spi Pointer to the HAL SPI instance.
* \param[in] hw Pointer to the hardware base.
*
* \return Operation status.
* \retval ERR_NONE Success.
* \retval ERR_INVALID_DATA Error, initialized.
*/
int32_t spi_m_dma_init(struct spi_m_dma_descriptor *spi, void *const hw);
/** \brief Deinitialize the SPI HAL instance
*
* Abort transfer, disable and reset SPI, de-init software.
*
* \param[in] spi Pointer to the HAL SPI instance.
*
* \return Operation status.
* \retval ERR_NONE Success.
* \retval <0 Error code.
*/
void spi_m_dma_deinit(struct spi_m_dma_descriptor *spi);
/** \brief Enable SPI
*
* \param[in] spi Pointer to the HAL SPI instance.
*
* \return Operation status.
* \retval ERR_NONE Success.
* \retval <0 Error code.
*/
void spi_m_dma_enable(struct spi_m_dma_descriptor *spi);
/** \brief Disable SPI
*
* \param[in] spi Pointer to the HAL SPI instance.
*
* \return Operation status.
* \retval ERR_NONE Success.
* \retval <0 Error code.
*/
void spi_m_dma_disable(struct spi_m_dma_descriptor *spi);
/** \brief Set SPI baudrate
*
* Works if SPI is initialized as master.
* In the function a sanity check is used to confirm it's called in the correct mode.
*
* \param[in] spi Pointer to the HAL SPI instance.
* \param[in] baud_val The target baudrate value
* (See "baudrate calculation" for calculating the value).
*
* \return Operation status.
* \retval ERR_NONE Success.
* \retval ERR_BUSY Busy.
*
* note: This api should be used to write the baudrate register with the given baud_val
* paramter, the user has to calculate the baud_val for required baud rate and pass it as
* argument(baud_val) to this api
*/
int32_t spi_m_dma_set_baudrate(struct spi_m_dma_descriptor *spi, const uint32_t baud_val);
/** \brief Set SPI mode
*
* Set SPI transfer mode (\ref spi_transfer_mode),
* which controls clock polarity and clock phase:
* - Mode 0: leading edge is rising edge, data sample on leading edge.
* - Mode 1: leading edge is rising edge, data sample on trailing edge.
* - Mode 2: leading edge is falling edge, data sample on leading edge.
* - Mode 3: leading edge is falling edge, data sample on trailing edge.
*
* \param[in] spi Pointer to the HAL SPI instance.
* \param[in] mode The mode (\ref spi_transfer_mode).
*
* \return Operation status.
* \retval ERR_NONE Success.
* \retval ERR_BUSY Busy, CS activated.
*/
int32_t spi_m_dma_set_mode(struct spi_m_dma_descriptor *spi, const enum spi_transfer_mode mode);
/** \brief Set the SPI transfer character size in number of bits
*
* The character size (\ref spi_char_size) influence the way the data is
* sent/received.
* For char size <= 8-bit, data is stored byte by byte.
* For char size between 9-bit ~ 16-bit, data is stored in 2-byte length.
* Note that the default and recommended char size is 8-bit since it's
* supported by all system.
*
* \param[in] spi Pointer to the HAL SPI instance.
* \param[in] char_size The char size (\ref spi_char_size).
*
* \return Operation status.
* \retval ERR_NONE Success.
* \retval ERR_BUSY Busy, CS activated.
* \retval ERR_INVALID_ARG The char size is not supported.
*/
int32_t spi_m_dma_set_char_size(struct spi_m_dma_descriptor *spi, const enum spi_char_size char_size);
/** \brief Set SPI transfer data order
*
* \param[in] spi Pointer to the HAL SPI instance.
* \param[in] dord The data order: send LSB/MSB first.
*
* \return Operation status.
* \retval ERR_NONE Success.
* \retval ERR_BUSY Busy, CS activated.
* \retval ERR_INVALID The data order is not supported.
*/
int32_t spi_m_dma_set_data_order(struct spi_m_dma_descriptor *spi, const enum spi_data_order dord);
/** \brief Perform the SPI data transfer (TX and RX) with the DMA
*
* \param[in] spi Pointer to the HAL SPI instance.
* \param[in] txbuf Pointer to the transfer information.
* \param[out] rxbuf Pointer to the receiver information.
* \param[in] length SPI transfer data length.
*
* \return Operation status.
* \retval ERR_NONE Success.
* \retval ERR_BUSY Busy.
*/
int32_t spi_m_dma_transfer(struct spi_m_dma_descriptor *spi, uint8_t const *txbuf, uint8_t *const rxbuf,
const uint16_t length);
/** \brief Register a function as an SPI transfer completion callback
*
* Register a callback function specified by its \c type.
* - SPI_CB_COMPLETE: set the function that will be called on the SPI transfer
* completion including deactivating the CS.
* - SPI_CB_XFER: set the function that will be called on the SPI buffer transfer
* completion.
* Register a NULL function to not use the callback.
*
* \param[in] spi Pointer to the HAL SPI instance.
* \param[in] type Callback type (\ref spi_m_dma_cb_type).
* \param[in] func Pointer to callback function.
*/
void spi_m_dma_register_callback(struct spi_m_dma_descriptor *spi, const enum spi_m_dma_cb_type type,
spi_m_dma_cb_t func);
/**
* \brief Return I/O descriptor for this SPI instance
*
* This function will return an I/O instance for this SPI driver instance
*
* \param[in] spi An SPI master descriptor, which is used to communicate through
* SPI
* \param[in, out] io A pointer to an I/O descriptor pointer type
*
* \retval ERR_NONE
*/
int32_t spi_m_dma_get_io_descriptor(struct spi_m_dma_descriptor *const spi, struct io_descriptor **io);
/** \brief Retrieve the current driver version
*
* \return Current driver version.
*/
uint32_t spi_m_dma_get_version(void);
#ifdef __cplusplus
}
#endif
/**@}*/
#endif /* ifndef _HAL_SPI_M_DMA_H_INCLUDED */

View File

@@ -1,221 +0,0 @@
/**
* \file
*
* \brief SPI related functionality declaration.
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#ifndef _HAL_SPI_M_SYNC_H_INCLUDED
#define _HAL_SPI_M_SYNC_H_INCLUDED
#include <hal_io.h>
#include <hpl_spi_m_sync.h>
/**
* \addtogroup doc_driver_hal_spi_master_sync
*
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/** \brief SPI HAL driver struct for polling mode
*
*/
struct spi_m_sync_descriptor {
struct _spi_m_sync_hpl_interface *func;
/** SPI device instance */
struct _spi_sync_dev dev;
/** I/O read/write */
struct io_descriptor io;
/** Flags for HAL driver */
uint16_t flags;
};
/** \brief Set the SPI HAL instance function pointer for HPL APIs.
*
* Set SPI HAL instance function pointer for HPL APIs.
*
* \param[in] spi Pointer to the HAL SPI instance.
* \param[in] func Pointer to the HPL api structure.
*
*/
void spi_m_sync_set_func_ptr(struct spi_m_sync_descriptor *spi, void *const func);
/** \brief Initialize SPI HAL instance and hardware for polling mode
*
* Initialize SPI HAL with polling mode.
*
* \param[in] spi Pointer to the HAL SPI instance.
* \param[in] hw Pointer to the hardware base.
*
* \return Operation status.
* \retval ERR_NONE Success.
* \retval ERR_INVALID_DATA Error, initialized.
*/
int32_t spi_m_sync_init(struct spi_m_sync_descriptor *spi, void *const hw);
/** \brief Deinitialize the SPI HAL instance and hardware
*
* Abort transfer, disable and reset SPI, deinit software.
*
* \param[in] spi Pointer to the HAL SPI instance.
*
* \return Operation status.
* \retval ERR_NONE Success.
* \retval <0 Error code.
*/
void spi_m_sync_deinit(struct spi_m_sync_descriptor *spi);
/** \brief Enable SPI
*
* \param[in] spi Pointer to the HAL SPI instance.
*
* \return Operation status.
* \retval ERR_NONE Success.
* \retval <0 Error code.
*/
void spi_m_sync_enable(struct spi_m_sync_descriptor *spi);
/** \brief Disable SPI
*
* \param[in] spi Pointer to the HAL SPI instance.
*
* \return Operation status.
* \retval ERR_NONE Success.
* \retval <0 Error code.
*/
void spi_m_sync_disable(struct spi_m_sync_descriptor *spi);
/** \brief Set SPI baudrate
*
* Works if SPI is initialized as master, it sets the baudrate.
*
* \param[in] spi Pointer to the HAL SPI instance.
* \param[in] baud_val The target baudrate value
* (see "baudrate calculation" for calculating the value).
*
* \return Operation status.
* \retval ERR_NONE Success.
* \retval ERR_BUSY Busy
* \retval ERR_INVALID_ARG The baudrate is not supported.
*/
int32_t spi_m_sync_set_baudrate(struct spi_m_sync_descriptor *spi, const uint32_t baud_val);
/** \brief Set SPI mode
*
* Set the SPI transfer mode (\ref spi_transfer_mode),
* which controls the clock polarity and clock phase:
* - Mode 0: leading edge is rising edge, data sample on leading edge.
* - Mode 1: leading edge is rising edge, data sample on trailing edge.
* - Mode 2: leading edge is falling edge, data sample on leading edge.
* - Mode 3: leading edge is falling edge, data sample on trailing edge.
*
* \param[in] spi Pointer to the HAL SPI instance.
* \param[in] mode The mode (0~3).
*
* \return Operation status.
* \retval ERR_NONE Success.
* \retval ERR_BUSY Busy
* \retval ERR_INVALID_ARG The mode is not supported.
*/
int32_t spi_m_sync_set_mode(struct spi_m_sync_descriptor *spi, const enum spi_transfer_mode mode);
/** \brief Set SPI transfer character size in number of bits
*
* The character size (\ref spi_char_size) influence the way the data is
* sent/received.
* For char size <= 8-bit, data is stored byte by byte.
* For char size between 9-bit ~ 16-bit, data is stored in 2-byte length.
* Note that the default and recommended char size is 8-bit since it's
* supported by all system.
*
* \param[in] spi Pointer to the HAL SPI instance.
* \param[in] char_size The char size (~16, recommended 8).
*
* \return Operation status.
* \retval ERR_NONE Success.
* \retval ERR_BUSY Busy
* \retval ERR_INVALID_ARG The char size is not supported.
*/
int32_t spi_m_sync_set_char_size(struct spi_m_sync_descriptor *spi, const enum spi_char_size char_size);
/** \brief Set SPI transfer data order
*
* \param[in] spi Pointer to the HAL SPI instance.
* \param[in] dord The data order: send LSB/MSB first.
*
* \return Operation status.
* \retval ERR_NONE Success.
* \retval ERR_BUSY Busy
* \retval ERR_INVALID_ARG The data order is not supported.
*/
int32_t spi_m_sync_set_data_order(struct spi_m_sync_descriptor *spi, const enum spi_data_order dord);
/** \brief Perform the SPI data transfer (TX and RX) in polling way
*
* Activate CS, do TX and RX and deactivate CS. It blocks.
*
* \param[in, out] spi Pointer to the HAL SPI instance.
* \param[in] xfer Pointer to the transfer information (\ref spi_xfer).
*
* \retval size Success.
* \retval >=0 Timeout, with number of characters transferred.
* \retval ERR_BUSY SPI is busy
*/
int32_t spi_m_sync_transfer(struct spi_m_sync_descriptor *spi, const struct spi_xfer *xfer);
/**
* \brief Return the I/O descriptor for this SPI instance
*
* This function will return an I/O instance for this SPI driver instance.
*
* \param[in] spi An SPI master descriptor, which is used to communicate through
* SPI
* \param[in, out] io A pointer to an I/O descriptor pointer type
*
* \retval ERR_NONE
*/
int32_t spi_m_sync_get_io_descriptor(struct spi_m_sync_descriptor *const spi, struct io_descriptor **io);
/** \brief Retrieve the current driver version
*
* \return Current driver version.
*/
uint32_t spi_m_sync_get_version(void);
/**@}*/
#ifdef __cplusplus
}
#endif
#endif /* ifndef _HAL_SPI_M_SYNC_H_INCLUDED */

View File

@@ -0,0 +1,183 @@
/**
* \file
*
* \brief I/O SPI DMA related functionality implementation.
*
* Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#include "hal_atomic.h"
#include "hal_spi_m_dma.h"
#include <utils_assert.h>
#include <utils.h>
/**
* \brief Driver version
*/
#define SPI_DRIVER_VERSION 0x00000001u
static int32_t _spi_m_dma_io_write(struct io_descriptor *const io, const uint8_t *const buf, const uint16_t length);
static int32_t _spi_m_dma_io_read(struct io_descriptor *const io, uint8_t *const buf, const uint16_t length);
/**
* \brief Initialize the SPI HAL instance function pointer for HPL APIs.
*/
void spi_m_dma_set_func_ptr(struct spi_m_dma_descriptor *spi, void *const func)
{
ASSERT(spi);
spi->func = (struct _spi_m_dma_hpl_interface *)func;
}
int32_t spi_m_dma_init(struct spi_m_dma_descriptor *spi, void *const hw)
{
int32_t rc = 0;
ASSERT(spi && hw);
spi->dev.prvt = (void *)hw;
rc = _spi_m_dma_init(&spi->dev, hw);
if (rc) {
return rc;
}
spi->io.read = _spi_m_dma_io_read;
spi->io.write = _spi_m_dma_io_write;
return ERR_NONE;
}
void spi_m_dma_deinit(struct spi_m_dma_descriptor *spi)
{
ASSERT(spi);
_spi_m_dma_deinit(&spi->dev);
}
void spi_m_dma_enable(struct spi_m_dma_descriptor *spi)
{
ASSERT(spi);
_spi_m_dma_enable(&spi->dev);
}
void spi_m_dma_disable(struct spi_m_dma_descriptor *spi)
{
ASSERT(spi);
_spi_m_dma_disable(&spi->dev);
}
int32_t spi_m_dma_set_baudrate(struct spi_m_dma_descriptor *spi, const uint32_t baud_val)
{
ASSERT(spi);
return _spi_m_dma_set_baudrate(&spi->dev, baud_val);
}
int32_t spi_m_dma_set_mode(struct spi_m_dma_descriptor *spi, const enum spi_transfer_mode mode)
{
ASSERT(spi);
return _spi_m_dma_set_mode(&spi->dev, mode);
}
int32_t spi_m_dma_set_char_size(struct spi_m_dma_descriptor *spi, const enum spi_char_size char_size)
{
ASSERT(spi);
return _spi_m_dma_set_char_size(&spi->dev, char_size);
}
int32_t spi_m_dma_set_data_order(struct spi_m_dma_descriptor *spi, const enum spi_data_order dord)
{
ASSERT(spi);
return _spi_m_dma_set_data_order(&spi->dev, dord);
}
/** \brief Do SPI read in background
*
* It never blocks and return quickly, user check status or set callback to
* know when data is ready to process.
*
* \param[in, out] spi Pointer to the HAL SPI instance.
* \param[out] p_buf Pointer to the buffer to store read data.
* \param[in] size Size of the data in number of characters.
* \return ERR_NONE on success, or an error code on failure.
* \retval ERR_NONE Success, transfer started.
* \retval ERR_BUSY Busy.
*/
static int32_t _spi_m_dma_io_read(struct io_descriptor *io, uint8_t *const buf, const uint16_t length)
{
ASSERT(io);
struct spi_m_dma_descriptor *spi = CONTAINER_OF(io, struct spi_m_dma_descriptor, io);
return _spi_m_dma_transfer(&spi->dev, NULL, buf, length);
}
/** \brief Do SPI data write in background
*
* The data read back is discarded.
*
* It never blocks and return quickly, user check status or set callback to
* know when data is sent.
*
* \param[in, out] spi Pointer to the HAL SPI instance.
* \param[in] p_buf Pointer to the buffer to store data to write.
* \param[in] size Size of the data in number of characters.
*
* \return ERR_NONE on success, or an error code on failure.
* \retval ERR_NONE Success, transfer started.
* \retval ERR_BUSY Busy.
*/
static int32_t _spi_m_dma_io_write(struct io_descriptor *io, const uint8_t *const buf, const uint16_t length)
{
ASSERT(io);
struct spi_m_dma_descriptor *spi = CONTAINER_OF(io, struct spi_m_dma_descriptor, io);
return _spi_m_dma_transfer(&spi->dev, buf, NULL, length);
}
int32_t spi_m_dma_transfer(struct spi_m_dma_descriptor *spi, uint8_t const *txbuf, uint8_t *const rxbuf,
const uint16_t length)
{
ASSERT(spi);
return _spi_m_dma_transfer(&spi->dev, txbuf, rxbuf, length);
}
void spi_m_dma_register_callback(struct spi_m_dma_descriptor *spi, const enum spi_m_dma_cb_type type,
spi_m_dma_cb_t func)
{
ASSERT(spi);
_spi_m_dma_register_callback(&spi->dev, (enum _spi_dma_dev_cb_type)type, func);
}
int32_t spi_m_dma_get_io_descriptor(struct spi_m_dma_descriptor *const spi, struct io_descriptor **io)
{
ASSERT(spi && io);
*io = &spi->io;
return 0;
}
uint32_t spi_m_dma_get_version(void)
{
return SPI_DRIVER_VERSION;
}

View File

@@ -1,201 +0,0 @@
/**
* \file
*
* \brief I/O SPI related functionality implementation.
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#include "hal_spi_m_sync.h"
#include <utils_assert.h>
#include <utils.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Driver version
*/
#define SPI_M_SYNC_DRIVER_VERSION 0x00000001u
#define SPI_DEACTIVATE_NEXT 0x8000
static int32_t _spi_m_sync_io_write(struct io_descriptor *const io, const uint8_t *const buf, const uint16_t length);
static int32_t _spi_m_sync_io_read(struct io_descriptor *const io, uint8_t *const buf, const uint16_t length);
/**
* \brief Initialize the SPI HAL instance function pointer for HPL APIs.
*/
void spi_m_sync_set_func_ptr(struct spi_m_sync_descriptor *spi, void *const func)
{
ASSERT(spi);
spi->func = (struct _spi_m_sync_hpl_interface *)func;
}
int32_t spi_m_sync_init(struct spi_m_sync_descriptor *spi, void *const hw)
{
int32_t rc = 0;
ASSERT(spi && hw);
spi->dev.prvt = (void *)hw;
rc = _spi_m_sync_init(&spi->dev, hw);
if (rc < 0) {
return rc;
}
spi->flags = SPI_DEACTIVATE_NEXT;
spi->io.read = _spi_m_sync_io_read;
spi->io.write = _spi_m_sync_io_write;
return ERR_NONE;
}
void spi_m_sync_deinit(struct spi_m_sync_descriptor *spi)
{
ASSERT(spi);
_spi_m_sync_deinit(&spi->dev);
}
void spi_m_sync_enable(struct spi_m_sync_descriptor *spi)
{
ASSERT(spi);
_spi_m_sync_enable(&spi->dev);
}
void spi_m_sync_disable(struct spi_m_sync_descriptor *spi)
{
ASSERT(spi);
_spi_m_sync_disable(&spi->dev);
}
int32_t spi_m_sync_set_baudrate(struct spi_m_sync_descriptor *spi, const uint32_t baud_val)
{
ASSERT(spi);
return _spi_m_sync_set_baudrate(&spi->dev, baud_val);
}
int32_t spi_m_sync_set_mode(struct spi_m_sync_descriptor *spi, const enum spi_transfer_mode mode)
{
ASSERT(spi);
return _spi_m_sync_set_mode(&spi->dev, mode);
}
int32_t spi_m_sync_set_char_size(struct spi_m_sync_descriptor *spi, const enum spi_char_size char_size)
{
ASSERT(spi);
return _spi_m_sync_set_char_size(&spi->dev, char_size);
}
int32_t spi_m_sync_set_data_order(struct spi_m_sync_descriptor *spi, const enum spi_data_order dord)
{
ASSERT(spi);
return _spi_m_sync_set_data_order(&spi->dev, dord);
}
/** \brief Do SPI read in polling way
* For SPI master, activate CS, do send 0xFFs and read data, deactivate CS.
*
* It blocks until all data read or error.
*
* \param[in, out] spi Pointer to the HAL SPI instance.
* \param[out] buf Pointer to the buffer to store read data.
* \param[in] size Size of the data in number of characters.
* \return Operation status.
* \retval size Success.
* \retval >=0 Time out, with number of characters read.
*/
static int32_t _spi_m_sync_io_read(struct io_descriptor *io, uint8_t *buf, const uint16_t length)
{
ASSERT(io);
struct spi_m_sync_descriptor *spi = CONTAINER_OF(io, struct spi_m_sync_descriptor, io);
struct spi_xfer xfer;
xfer.rxbuf = buf;
xfer.txbuf = 0;
xfer.size = length;
return spi_m_sync_transfer(spi, &xfer);
}
/** \brief Do SPI data write in polling way
* For SPI master, activate CS, do buffer send and deactivate CS. The data back
* is discarded.
*
* The data read back is discarded.
*
* It blocks until all data sent or error.
*
* \param[in, out] spi Pointer to the HAL SPI instance.
* \param[in] p_xfer Pointer to the transfer information (\ref spi_transfer).
* \return Operation status.
* \retval size Success.
* \retval >=0 Timeout, with number of characters transferred.
*/
static int32_t _spi_m_sync_io_write(struct io_descriptor *const io, const uint8_t *const buf, const uint16_t length)
{
ASSERT(io);
struct spi_m_sync_descriptor *spi = CONTAINER_OF(io, struct spi_m_sync_descriptor, io);
struct spi_xfer xfer;
xfer.rxbuf = 0;
xfer.txbuf = (uint8_t *)buf;
xfer.size = length;
return spi_m_sync_transfer(spi, &xfer);
}
int32_t spi_m_sync_transfer(struct spi_m_sync_descriptor *spi, const struct spi_xfer *p_xfer)
{
struct spi_msg msg;
ASSERT(spi && p_xfer);
msg.txbuf = p_xfer->txbuf;
msg.rxbuf = p_xfer->rxbuf;
msg.size = p_xfer->size;
return _spi_m_sync_trans(&spi->dev, &msg);
}
int32_t spi_m_sync_get_io_descriptor(struct spi_m_sync_descriptor *const spi, struct io_descriptor **io)
{
ASSERT(spi && io);
*io = &spi->io;
return 0;
}
uint32_t spi_m_sync_get_version(void)
{
return SPI_M_SYNC_DRIVER_VERSION;
}
#ifdef __cplusplus
}
#endif

View File

@@ -37,7 +37,6 @@
#include <hpl_dmac_config.h>
#include <utils_repeat_macro.h>
#if CONF_DMAC_ENABLE
/* Section containing first descriptors for all DMAC channels */
COMPILER_ALIGNED(16)
DmacDescriptor _descriptor_section[DMAC_CH_NUM];
@@ -75,6 +74,15 @@ struct dmac_channel_cfg {
/* DMAC channel configurations */
const static struct dmac_channel_cfg _cfgs[] = {REPEAT_MACRO(DMAC_CHANNEL_CFG, i, DMAC_CH_NUM)};
// ADDED
int32_t _dma_set_descriptor(const uint8_t channel, const DmacDescriptor descriptor)
{
_descriptor_section[channel] = descriptor;
return ERR_NONE;
}
/**
* \brief Initialize DMAC
*/
@@ -259,5 +267,3 @@ void DMAC_4_Handler(void)
{
_dmac_handler();
}
#endif /* CONF_DMAC_ENABLE */

View File

@@ -31,6 +31,7 @@
* \asf_license_stop
*
*/
#include <hpl_spi_m_dma.h>
#include <hpl_dma.h>
#include <hpl_i2c_m_async.h>
#include <hpl_i2c_m_sync.h>
@@ -2957,3 +2958,428 @@ void _spi_s_async_set_irq_state(struct _spi_async_dev *const device, const enum
{
_spi_m_async_set_irq_state(device, type, state);
}
#ifndef CONF_SERCOM_0_SPI_M_DMA_TX_CHANNEL
#define CONF_SERCOM_0_SPI_M_DMA_TX_CHANNEL 0
#endif
#ifndef CONF_SERCOM_0_SPI_M_DMA_RX_CHANNEL
#define CONF_SERCOM_0_SPI_M_DMA_RX_CHANNEL 1
#endif
#ifndef CONF_SERCOM_1_SPI_M_DMA_TX_CHANNEL
#define CONF_SERCOM_1_SPI_M_DMA_TX_CHANNEL 0
#endif
#ifndef CONF_SERCOM_1_SPI_M_DMA_RX_CHANNEL
#define CONF_SERCOM_1_SPI_M_DMA_RX_CHANNEL 1
#endif
#ifndef CONF_SERCOM_2_SPI_M_DMA_TX_CHANNEL
#define CONF_SERCOM_2_SPI_M_DMA_TX_CHANNEL 0
#endif
#ifndef CONF_SERCOM_2_SPI_M_DMA_RX_CHANNEL
#define CONF_SERCOM_2_SPI_M_DMA_RX_CHANNEL 1
#endif
#ifndef CONF_SERCOM_3_SPI_M_DMA_TX_CHANNEL
#define CONF_SERCOM_3_SPI_M_DMA_TX_CHANNEL 0
#endif
#ifndef CONF_SERCOM_3_SPI_M_DMA_RX_CHANNEL
#define CONF_SERCOM_3_SPI_M_DMA_RX_CHANNEL 1
#endif
#ifndef CONF_SERCOM_4_SPI_M_DMA_TX_CHANNEL
#define CONF_SERCOM_4_SPI_M_DMA_TX_CHANNEL 0
#endif
#ifndef CONF_SERCOM_4_SPI_M_DMA_RX_CHANNEL
#define CONF_SERCOM_4_SPI_M_DMA_RX_CHANNEL 1
#endif
#ifndef CONF_SERCOM_5_SPI_M_DMA_TX_CHANNEL
#define CONF_SERCOM_5_SPI_M_DMA_TX_CHANNEL 0
#endif
#ifndef CONF_SERCOM_5_SPI_M_DMA_RX_CHANNEL
#define CONF_SERCOM_5_SPI_M_DMA_RX_CHANNEL 1
#endif
#ifndef CONF_SERCOM_6_SPI_M_DMA_TX_CHANNEL
#define CONF_SERCOM_6_SPI_M_DMA_TX_CHANNEL 0
#endif
#ifndef CONF_SERCOM_6_SPI_M_DMA_RX_CHANNEL
#define CONF_SERCOM_6_SPI_M_DMA_RX_CHANNEL 1
#endif
#ifndef CONF_SERCOM_7_SPI_M_DMA_TX_CHANNEL
#define CONF_SERCOM_7_SPI_M_DMA_TX_CHANNEL 0
#endif
#ifndef CONF_SERCOM_7_SPI_M_DMA_RX_CHANNEL
#define CONF_SERCOM_7_SPI_M_DMA_RX_CHANNEL 1
#endif
#ifndef CONF_SERCOM_0_SPI_RX_CHANNEL
#define CONF_SERCOM_0_SPI_RX_CHANNEL 0
#endif
#ifndef CONF_SERCOM_1_SPI_RX_CHANNEL
#define CONF_SERCOM_1_SPI_RX_CHANNEL 0
#endif
#ifndef CONF_SERCOM_2_SPI_RX_CHANNEL
#define CONF_SERCOM_2_SPI_RX_CHANNEL 0
#endif
#ifndef CONF_SERCOM_3_SPI_RX_CHANNEL
#define CONF_SERCOM_3_SPI_RX_CHANNEL 0
#endif
#ifndef CONF_SERCOM_4_SPI_RX_CHANNEL
#define CONF_SERCOM_4_SPI_RX_CHANNEL 0
#endif
#ifndef CONF_SERCOM_5_SPI_RX_CHANNEL
#define CONF_SERCOM_5_SPI_RX_CHANNEL 0
#endif
#ifndef CONF_SERCOM_6_SPI_RX_CHANNEL
#define CONF_SERCOM_6_SPI_RX_CHANNEL 0
#endif
#ifndef CONF_SERCOM_7_SPI_RX_CHANNEL
#define CONF_SERCOM_7_SPI_RX_CHANNEL 0
#endif
/** \internal Enable SERCOM SPI RX
*
* \param[in] hw Pointer to the hardware register base.
*
* \return Enabling status
*/
static int32_t _spi_sync_rx_enable(void *const hw)
{
if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_CTRLB)) {
return ERR_BUSY;
}
hri_sercomspi_set_CTRLB_RXEN_bit(hw);
return ERR_NONE;
}
/** \internal Disable SERCOM SPI RX
*
* \param[in] hw Pointer to the hardware register base.
*
* \return Disabling status
*/
static int32_t _spi_sync_rx_disable(void *const hw)
{
if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_CTRLB)) {
return ERR_BUSY;
}
hri_sercomspi_clear_CTRLB_RXEN_bit(hw);
return ERR_NONE;
}
static int32_t _spi_m_dma_rx_enable(struct _spi_m_dma_dev *dev)
{
ASSERT(dev && dev->prvt);
return _spi_sync_rx_enable(dev->prvt);
}
static int32_t _spi_m_dma_rx_disable(struct _spi_m_dma_dev *dev)
{
ASSERT(dev && dev->prvt);
return _spi_sync_rx_disable(dev->prvt);
}
/**
* \brief Get the spi source address for DMA
* \param[in] dev Pointer to the SPI device instance
*
* \return The spi source address
*/
static uint32_t _spi_m_get_source_for_dma(void *const hw)
{
return (uint32_t) & (((Sercom *)hw)->SPI.DATA);
}
/**
* \brief Get the spi destination address for DMA
* \param[in] dev Pointer to the SPI device instance
*
* \return The spi destination address
*/
static uint32_t _spi_m_get_destination_for_dma(void *const hw)
{
return (uint32_t) & (((Sercom *)hw)->SPI.DATA);
}
/**
* \brief Return the SPI TX DMA channel index
* \param[in] hw_addr The hardware register base address
*
* \return SPI TX DMA channel index.
*/
static uint8_t _spi_get_tx_dma_channel(const void *const hw)
{
uint8_t index = _sercom_get_hardware_index(hw);
switch (index) {
case 0:
return CONF_SERCOM_0_SPI_M_DMA_TX_CHANNEL;
case 1:
return CONF_SERCOM_1_SPI_M_DMA_TX_CHANNEL;
case 2:
return CONF_SERCOM_2_SPI_M_DMA_TX_CHANNEL;
case 3:
return CONF_SERCOM_3_SPI_M_DMA_TX_CHANNEL;
case 4:
return CONF_SERCOM_4_SPI_M_DMA_TX_CHANNEL;
case 5:
return CONF_SERCOM_5_SPI_M_DMA_TX_CHANNEL;
case 6:
return CONF_SERCOM_6_SPI_M_DMA_TX_CHANNEL;
case 7:
return CONF_SERCOM_7_SPI_M_DMA_TX_CHANNEL;
default:
return CONF_SERCOM_0_SPI_M_DMA_TX_CHANNEL;
}
}
/**
* \brief Return whether SPI RX DMA channel is enabled or not
* \param[in] hw_addr The hardware register base address
*
* \return one if enabled.
*/
static uint8_t _spi_is_rx_dma_channel_enabled(const void *const hw)
{
uint8_t index = _sercom_get_hardware_index(hw);
switch (index) {
case 0:
return CONF_SERCOM_0_SPI_RX_CHANNEL;
case 1:
return CONF_SERCOM_1_SPI_RX_CHANNEL;
case 2:
return CONF_SERCOM_2_SPI_RX_CHANNEL;
case 3:
return CONF_SERCOM_3_SPI_RX_CHANNEL;
case 4:
return CONF_SERCOM_4_SPI_RX_CHANNEL;
case 5:
return CONF_SERCOM_5_SPI_RX_CHANNEL;
case 6:
return CONF_SERCOM_6_SPI_RX_CHANNEL;
case 7:
return CONF_SERCOM_7_SPI_RX_CHANNEL;
default:
return false;
}
}
/**
* \brief Return the SPI RX DMA channel index
* \param[in] hw_addr The hardware register base address
*
* \return SPI RX DMA channel index.
*/
static uint8_t _spi_get_rx_dma_channel(const void *const hw)
{
uint8_t index = _sercom_get_hardware_index(hw);
switch (index) {
case 0:
return CONF_SERCOM_0_SPI_M_DMA_RX_CHANNEL;
case 1:
return CONF_SERCOM_1_SPI_M_DMA_RX_CHANNEL;
case 2:
return CONF_SERCOM_2_SPI_M_DMA_RX_CHANNEL;
case 3:
return CONF_SERCOM_3_SPI_M_DMA_RX_CHANNEL;
case 4:
return CONF_SERCOM_4_SPI_M_DMA_RX_CHANNEL;
case 5:
return CONF_SERCOM_5_SPI_M_DMA_RX_CHANNEL;
case 6:
return CONF_SERCOM_6_SPI_M_DMA_RX_CHANNEL;
case 7:
return CONF_SERCOM_7_SPI_M_DMA_RX_CHANNEL;
default:
return CONF_SERCOM_0_SPI_M_DMA_TX_CHANNEL;
}
}
/**
* \brief Callback for RX
* \param[in, out] dev Pointer to the DMA resource.
*/
static void _spi_dma_rx_complete(struct _dma_resource *resource)
{
struct _spi_m_dma_dev *dev = (struct _spi_m_dma_dev *)resource->back;
if (dev->callbacks.rx) {
dev->callbacks.rx(resource);
}
}
/**
* \brief Callback for TX
* \param[in, out] dev Pointer to the DMA resource.
*/
static void _spi_dma_tx_complete(struct _dma_resource *resource)
{
struct _spi_m_dma_dev *dev = (struct _spi_m_dma_dev *)resource->back;
if (dev->callbacks.tx) {
dev->callbacks.tx(resource);
}
}
/**
* \brief Callback for ERROR
* \param[in, out] dev Pointer to the DMA resource.
*/
static void _spi_dma_error_occured(struct _dma_resource *resource)
{
struct _spi_m_dma_dev *dev = (struct _spi_m_dma_dev *)resource->back;
if (dev->callbacks.error) {
dev->callbacks.error(resource);
}
}
int32_t _spi_m_dma_init(struct _spi_m_dma_dev *dev, void *const hw)
{
const struct sercomspi_regs_cfg *regs = _spi_get_regs((uint32_t)hw);
ASSERT(dev && hw);
if (regs == NULL) {
return ERR_INVALID_ARG;
}
if (!hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST)) {
uint32_t mode = regs->ctrla & SERCOM_SPI_CTRLA_MODE_Msk;
if (hri_sercomspi_get_CTRLA_reg(hw, SERCOM_SPI_CTRLA_ENABLE)) {
hri_sercomspi_clear_CTRLA_ENABLE_bit(hw);
hri_sercomspi_wait_for_sync(hw, SERCOM_SPI_SYNCBUSY_ENABLE);
}
hri_sercomspi_write_CTRLA_reg(hw, SERCOM_SPI_CTRLA_SWRST | mode);
}
hri_sercomspi_wait_for_sync(hw, SERCOM_SPI_SYNCBUSY_SWRST);
dev->prvt = hw;
_spi_load_regs_master(hw, regs);
/* If enabled, initialize DMA rx channel */
if (_spi_is_rx_dma_channel_enabled(hw)) {
_dma_get_channel_resource(&dev->resource, _spi_get_rx_dma_channel(hw));
dev->resource->back = dev;
dev->resource->dma_cb.transfer_done = _spi_dma_rx_complete;
dev->resource->dma_cb.error = _spi_dma_error_occured;
}
/* Initialize DMA tx channel */
_dma_get_channel_resource(&dev->resource, _spi_get_tx_dma_channel(hw));
dev->resource->back = dev;
dev->resource->dma_cb.transfer_done = _spi_dma_tx_complete;
dev->resource->dma_cb.error = _spi_dma_error_occured;
return ERR_NONE;
}
int32_t _spi_m_dma_deinit(struct _spi_m_dma_dev *dev)
{
return _spi_deinit(dev->prvt);
}
int32_t _spi_m_dma_enable(struct _spi_m_dma_dev *dev)
{
ASSERT(dev && dev->prvt);
return _spi_sync_enable(dev->prvt);
}
int32_t _spi_m_dma_disable(struct _spi_m_dma_dev *dev)
{
ASSERT(dev && dev->prvt);
return _spi_sync_disable(dev->prvt);
}
int32_t _spi_m_dma_set_mode(struct _spi_m_dma_dev *dev, const enum spi_transfer_mode mode)
{
ASSERT(dev && dev->prvt);
return _spi_set_mode(dev->prvt, mode);
}
int32_t _spi_m_dma_set_baudrate(struct _spi_m_dma_dev *dev, const uint32_t baud_val)
{
ASSERT(dev && dev->prvt);
return _spi_set_baudrate(dev->prvt, baud_val);
}
int32_t _spi_m_dma_set_data_order(struct _spi_m_dma_dev *dev, const enum spi_data_order dord)
{
ASSERT(dev && dev->prvt);
return _spi_set_data_order(dev->prvt, dord);
}
int32_t _spi_m_dma_set_char_size(struct _spi_m_dma_dev *dev, const enum spi_char_size char_size)
{
uint8_t size;
ASSERT(dev && dev->prvt);
_spi_set_char_size(dev->prvt, char_size, &size);
return size;
}
void _spi_m_dma_register_callback(struct _spi_m_dma_dev *dev, enum _spi_dma_dev_cb_type type, _spi_dma_cb_t func)
{
switch (type) {
case SPI_DEV_CB_DMA_TX:
dev->callbacks.tx = func;
_dma_set_irq_state(_spi_get_tx_dma_channel(dev->prvt), DMA_TRANSFER_COMPLETE_CB, func != NULL);
break;
case SPI_DEV_CB_DMA_RX:
dev->callbacks.rx = func;
_dma_set_irq_state(_spi_get_rx_dma_channel(dev->prvt), DMA_TRANSFER_COMPLETE_CB, func != NULL);
break;
case SPI_DEV_CB_DMA_ERROR:
dev->callbacks.error = func;
_dma_set_irq_state(_spi_get_rx_dma_channel(dev->prvt), DMA_TRANSFER_ERROR_CB, func != NULL);
_dma_set_irq_state(_spi_get_tx_dma_channel(dev->prvt), DMA_TRANSFER_ERROR_CB, func != NULL);
break;
case SPI_DEV_CB_DMA_N:
break;
}
}
int32_t _spi_m_dma_transfer(struct _spi_m_dma_dev *dev, uint8_t const *txbuf, uint8_t *const rxbuf,
const uint16_t length)
{
const struct sercomspi_regs_cfg *regs = _spi_get_regs((uint32_t)dev->prvt);
uint8_t rx_ch = _spi_get_rx_dma_channel(dev->prvt);
uint8_t tx_ch = _spi_get_tx_dma_channel(dev->prvt);
if (rxbuf) {
/* Enable spi rx */
_spi_m_dma_rx_enable(dev);
_dma_set_source_address(rx_ch, (void *)_spi_m_get_source_for_dma(dev->prvt));
_dma_set_destination_address(rx_ch, rxbuf);
_dma_set_data_amount(rx_ch, length);
_dma_enable_transaction(rx_ch, false);
} else {
/* Disable spi rx */
_spi_m_dma_rx_disable(dev);
}
if (txbuf) {
/* Enable spi tx */
_dma_set_source_address(tx_ch, txbuf);
_dma_set_destination_address(tx_ch, (void *)_spi_m_get_destination_for_dma(dev->prvt));
_dma_srcinc_enable(tx_ch, true);
_dma_set_data_amount(tx_ch, length);
} else {
_dma_set_source_address(tx_ch, &regs->dummy_byte);
_dma_set_destination_address(tx_ch, (void *)_spi_m_get_destination_for_dma(dev->prvt));
_dma_srcinc_enable(tx_ch, false);
_dma_set_data_amount(tx_ch, length);
}
_dma_enable_transaction(tx_ch, false);
return ERR_NONE;
}

View File

@@ -1,29 +1,76 @@
#include <atmel_start.h>
#include "AS5048A.h"
#include "AS5048A_dma.h"
#define CONF_DELAY_US 10
#define BUFFER_LEN (6)
static uint8_t rx_buffer[BUFFER_LEN] = {0};
static uint8_t tx_buffer[BUFFER_LEN] = "Hello";
/* DMA Transfer complete callback for SPI master TX */
static void spi_master_tx_complete_cb(struct _dma_resource *resource)
{
/* Transfer completed */
delay_us(CONF_DELAY_US);
gpio_set_pin_level(SPI_SS, true);
}
/* DMA Transfer complete callback for SPI master RX */
static void spi_master_rx_complete_cb(struct _dma_resource *resource)
{
/* Transfer completed */
gpio_set_pin_level(SPI_SS, true);
}
/* IO descriptor for SPI master */
struct io_descriptor *io_spi_master;
/* SPI master IO and Callback Initialization */
void spi_master_init(void)
{
spi_m_dma_enable(&SPI_0);
spi_m_dma_get_io_descriptor(&SPI_0, &io_spi_master);
spi_m_dma_register_callback(&SPI_0, SPI_M_DMA_CB_TX_DONE, spi_master_tx_complete_cb);
spi_m_dma_register_callback(&SPI_0, SPI_M_DMA_CB_RX_DONE, spi_master_rx_complete_cb);
}
int main(void)
{
/* Initializes MCU, drivers and middleware */
atmel_start_init();
if(AS5048A_init())
printf("Init Complete\n");
else
printf("Init failed\n");
//spi_master_init();
as5048a_init();
//spi_m_dma_enable(&SPI_0);
//io_write(io_spi_master, tx_buffer, BUFFER_LEN );
/* Replace with your application code */
as5048a_read(AS5048A_CLEAR_ERROR_FLAG);
while (1) {
delay_ms(1000);
// gpio_set_pin_level(SPI_SS, false);
// spi_m_dma_transfer(&SPI_0, tx_buffer, rx_buffer, BUFFER_LEN );
//printf("%u\r\n", getRawRotation());
//volatile float angle = getRotationInDegrees();
//read(AS5048A_ANGLE);
read(AS5048A_CLEAR_ERROR_FLAG);
delay_ms(500);
read(AS5048A_CMD_NOP);
delay_ms(500);
read(AS5048A_CMD_NOP);
delay_ms(500);
//volatile float angle = getRotationInDegrees();
//printf("%f\r\n", angle);
}
}
//as5048a_read(AS5048A_CLEAR_ERROR_FLAG);
//delay_ms(100);
//as5048a_read(AS5048A_CMD_NOP);
//uint16_t raw_angle = (( ( in_buf[1] & 0xFF ) << 8 ) | ( in_buf[0] & 0xFF )) & ~0xC000);
printf("%u\n\r", as5048a_read(AS5048A_ANGLE));
//printf("%i\n\r", as5048a_read(AS5048A_ANGLE));
//delay_ms(100);
//as5048a_read(AS5048A_CMD_NOP);
}
}