thesis_bldc_controller/Examples/SPISLAVEDMA/SPISLAVEDMA(3)/main.c

243 lines
7.9 KiB
C

/**
* \file
*
* \brief Application implement
*
* Copyright (c) 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
*
*/
/*
* Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
*/
#include <atmel_start.h>
#include "driver_examples.h"
#include "spi_slave_dma_config.h"
/* DMA channel for SPI Slave TX and RX */
#define CONF_SERCOM_6_TRANSMIT_DMA_CHANNEL 2
#define CONF_SERCOM_6_RECEIVE_DMA_CHANNEL 3
/* Buffer length to transfer/receive */
#define BUFFER_LEN (12)
/* DMA channel Descriptor */
extern DmacDescriptor _descriptor_section[DMAC_CH_NUM];
extern DmacDescriptor _write_back_section[DMAC_CH_NUM];
/* IO descriptor for SPI master */
struct io_descriptor *io_spi_master;
/* DATA transfer/reception completion flags */
volatile uint8_t spi_slave_tx_complete = 0;
volatile uint8_t spi_slave_rx_complete = 0;
volatile uint8_t spi_master_tx_complete = 0;
volatile uint8_t spi_master_rx_complete = 0;
volatile uint8_t cs_pulled_high = 0;
volatile uint8_t received_data_len = 0;
static uint8_t rx_buffer[BUFFER_LEN] = {0};
static uint8_t tx_buffer[BUFFER_LEN] = "Hello World!";
/* 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_CS, true);
spi_master_tx_complete = 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_CS, true);
spi_master_rx_complete = true;
}
/* Start SPI master data transfer */
void spi_master_tx(uint8_t *buffer, uint8_t length)
{
spi_m_dma_enable(&SPI_0);
gpio_set_pin_level(SPI_CS, false);
io_write(io_spi_master, buffer, length);
}
/* Start SPI master data Reception from Slave */
void spi_master_rx(uint8_t *buffer, uint8_t length)
{
spi_m_dma_enable(&SPI_0);
gpio_set_pin_level(SPI_CS, false);
io_read(io_spi_master, buffer, length);
}
/* SPI master IO and Callback Initialization */
void spi_master_init(void)
{
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);
}
/* SPI Slave Chip Select low to high change callback */
static void slave_select_high(void)
{
received_data_len = (_descriptor_section[CONF_SERCOM_6_RECEIVE_DMA_CHANNEL].BTCNT.reg
- _write_back_section[CONF_SERCOM_6_RECEIVE_DMA_CHANNEL].BTCNT.reg);
cs_pulled_high = true;
}
/* DMA Transfer complete callback for SPI Slave RX */
static void spi_slave_rx_complete_cb(struct _dma_resource *const resource)
{
spi_slave_rx_complete = true;
}
/* DMA Transfer complete callback for SPI Slave TX */
static void spi_slave_tx_complete_cb(struct _dma_resource *const resource)
{
spi_slave_tx_complete = true;
}
/* Register SPI Slave DMA channel callbacks */
void register_dma_spi_slave_callback(uint16_t channel, void *cb)
{
struct _dma_resource *resource_rx;
_dma_get_channel_resource(&resource_rx, channel);
resource_rx->dma_cb.transfer_done = cb;
}
/* Enable SPI slave slave select interrupt */
void spi_s_sync_enable_ss_detect(void *hw, bool state)
{
NVIC_DisableIRQ((IRQn_Type)SERCOM6_1_IRQn);
NVIC_ClearPendingIRQ((IRQn_Type)SERCOM6_1_IRQn);
NVIC_EnableIRQ((IRQn_Type)SERCOM6_1_IRQn);
if (state) {
hri_sercomspi_set_INTEN_TXC_bit(hw);
} else {
hri_sercomspi_clear_INTEN_TXC_bit(hw);
}
}
/* slave slave interrupt handler */
void SERCOM6_1_Handler()
{
hri_sercomspi_clear_INTEN_TXC_bit((SercomSpi *)(SPI_1.dev.prvt));
slave_select_high();
}
/* SERCOM SPI Slave configuration */
void spi_slave_init()
{
_dma_set_source_address(CONF_SERCOM_6_RECEIVE_DMA_CHANNEL,
(uint32_t *)&(((SercomSpi *)(SPI_1.dev.prvt))->DATA.reg));
_dma_set_destination_address(CONF_SERCOM_6_TRANSMIT_DMA_CHANNEL,
(uint32_t *)&(((SercomSpi *)(SPI_1.dev.prvt))->DATA.reg));
/* callback */
register_dma_spi_slave_callback(CONF_SERCOM_6_TRANSMIT_DMA_CHANNEL, spi_slave_tx_complete_cb);
register_dma_spi_slave_callback(CONF_SERCOM_6_RECEIVE_DMA_CHANNEL, spi_slave_rx_complete_cb);
/* Enable DMA transfer complete interrupt */
_dma_set_irq_state(CONF_SERCOM_6_RECEIVE_DMA_CHANNEL, DMA_TRANSFER_COMPLETE_CB, true);
_dma_set_irq_state(CONF_SERCOM_6_TRANSMIT_DMA_CHANNEL, DMA_TRANSFER_COMPLETE_CB, true);
spi_s_sync_enable_ss_detect((SercomSpi *)(SPI_1.dev.prvt), true);
}
/* Start SPI slave data transfer */
void spi_slave_tx(uint8_t *buffer, uint8_t length)
{
spi_s_sync_enable(&SPI_1);
_dma_set_source_address(CONF_SERCOM_6_TRANSMIT_DMA_CHANNEL, (uint32_t *)buffer);
_dma_srcinc_enable(CONF_SERCOM_6_TRANSMIT_DMA_CHANNEL, true);
_dma_set_data_amount(CONF_SERCOM_6_TRANSMIT_DMA_CHANNEL, (uint32_t)length);
_dma_enable_transaction(CONF_SERCOM_6_TRANSMIT_DMA_CHANNEL, false);
}
/* Start SPI slave data reception */
void spi_slave_rx(uint8_t *buffer, uint8_t length)
{
spi_s_sync_enable(&SPI_1);
_dma_set_destination_address(CONF_SERCOM_6_RECEIVE_DMA_CHANNEL, (uint32_t *)buffer);
_dma_set_data_amount(CONF_SERCOM_6_RECEIVE_DMA_CHANNEL, (uint32_t)length);
_dma_enable_transaction(CONF_SERCOM_6_RECEIVE_DMA_CHANNEL, false);
}
int main(void)
{
/* Initializes MCU, drivers and middleware */
atmel_start_init();
/* Initialize SPI master IO and Callback */
spi_master_init();
/* SPI Slave DMA and Callback configuration */
spi_slave_init();
/* Start SPI Slave data reception using DMA */
spi_slave_rx(rx_buffer, BUFFER_LEN);
/* Start SPI Master data transfer using DMA */
spi_master_tx(tx_buffer, BUFFER_LEN);
while (1) {
/* Check for SPI Slave is received data from SPI Master */
if (spi_slave_rx_complete) {
spi_slave_rx_complete = false;
printf("Slave Received DATA Length = %d\n\rSlave Received DATA = ", received_data_len);
/* Print Received data by SPI Slave from SPI Master on Console */
for (int i = 0; i < BUFFER_LEN; i++) {
printf("%c", rx_buffer[i]);
}
printf("\n\r");
/* Start SPI Slave data transfer using DMA */
spi_slave_tx(rx_buffer, BUFFER_LEN);
/* Start SPI Master data reception using DMA */
spi_master_rx(tx_buffer, BUFFER_LEN);
}
/* Check for SPI Master is received data from SPI Slave */
if (spi_master_rx_complete) {
spi_master_rx_complete = false;
printf("Master Received DATA Length = %d\n\rMaster Received DATA = ", received_data_len);
/* Print Received data by SPI Master from SPI Slave on Console */
for (int i = 0; i < BUFFER_LEN; i++) {
printf("%c", tx_buffer[i]);
}
printf("\n\r");
//delay_ms(500);
//spi_master_tx(tx_buffer, BUFFER_LEN);
}
delay_ms(500);
spi_slave_rx(rx_buffer, BUFFER_LEN);
spi_master_tx(tx_buffer, BUFFER_LEN);
}
}