openmv/lib/alif/Alif_CMSIS/Source/Driver_SPI.c
iabdalkader daf2bb30da misc: Restructure repo.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-04-13 08:28:34 +02:00

2471 lines
69 KiB
C

/* Copyright (C) 2023 Alif Semiconductor - All Rights Reserved.
* Use, distribution and modification of this code is permitted under the
* terms stated in the Alif Semiconductor Software License Agreement
*
* You should have received a copy of the Alif Semiconductor Software
* License Agreement with this file. If not, please write to:
* contact@alifsemi.com, or visit: https://alifsemi.com/license
*
*/
/**************************************************************************//**
* @file Driver_SPI.c
* @author Girish BN, Manoj A Murudi
* @email girish.bn@alifsemi.com, manoj.murudi@alifsemi.com
* @version V1.0.0
* @date 20-04-2023
* @brief CMSIS-Driver for SPI.
* @bug None.
* @Note None
******************************************************************************/
#include "Driver_SPI.h"
#include "Driver_SPI_Private.h"
#include "sys_ctrl_spi.h"
#include "spi.h"
#if !((RTE_SPI0) || (RTE_SPI1) || (RTE_SPI2) || (RTE_SPI3) || (RTE_LPSPI))
#error "SPI is not enabled in the RTE_Device.h"
#endif
#if !defined(RTE_Drivers_SPI)
#error "SPI is not enabled in the RTE_Components.h"
#endif
#define ARM_SPI_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1, 0) /* driver version */
/* Driver Version */
static const ARM_DRIVER_VERSION DriverVersion = {
ARM_SPI_API_VERSION,
ARM_SPI_DRV_VERSION
};
/* Driver Capabilities */
static const ARM_SPI_CAPABILITIES DriverCapabilities = {
0, /* Reserved (must be zero) */
0, /* TI Synchronous Serial Interface */
1, /* Microwire Interface */
0, /* Signal Mode Fault event: \ref ARM_SPI_EVENT_MODE_FAULT */
0 /* Reserved (must be zero) */
};
/**
* @fn ARM_DRIVER_VERSION ARM_SPI_GetVersion(void)
* @brief get spi version
* @note none
* @param none
* @retval driver version
*/
__STATIC_INLINE ARM_DRIVER_VERSION ARM_SPI_GetVersion(void)
{
return DriverVersion;
}
/**
* @fn ARM_SPI_CAPABILITIES ARM_SPI_GetCapabilities(void)
* @brief get spi capabilities
* @note none
* @param none
* @retval driver capabilities
*/
__STATIC_INLINE ARM_SPI_CAPABILITIES ARM_SPI_GetCapabilities(void)
{
return DriverCapabilities;
}
#if SPI_DMA_ENABLE
/**
\fn int32_t SPI_DMA_Initialize(DMA_PERIPHERAL_CONFIG *dma_periph)
\brief Initialize DMA for SPI
\param[in] dma_periph Pointer to DMA resources
\return \ref execution_status
*/
static inline int32_t SPI_DMA_Initialize(DMA_PERIPHERAL_CONFIG *dma_periph)
{
int32_t status;
ARM_DRIVER_DMA *dma_drv = dma_periph->dma_drv;
/* Initializes DMA interface */
status = dma_drv->Initialize();
if (status)
{
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
/**
\fn int32_t SPI_DMA_PowerControl(DMA_PERIPHERAL_CONFIG *dma_periph, ARM_POWER_STATE state)
\brief PowerControl DMA for SPI
\param[in] state Power state
\param[in] dma_periph Pointer to DMA resources
\return \ref execution_status
*/
static inline int32_t SPI_DMA_PowerControl(DMA_PERIPHERAL_CONFIG *dma_periph, ARM_POWER_STATE state)
{
int32_t status;
ARM_DRIVER_DMA *dma_drv = dma_periph->dma_drv;
/* Initializes DMA interface */
status = dma_drv->PowerControl(state);
if (status)
{
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
/**
\fn int32_t SPI_DMA_Allocate(DMA_PERIPHERAL_CONFIG *dma_periph)
\brief Allocate a channel for SPI
\param[in] dma_periph Pointer to DMA resources
\return \ref execution_status
*/
static inline int32_t SPI_DMA_Allocate(DMA_PERIPHERAL_CONFIG *dma_periph)
{
int32_t status;
ARM_DRIVER_DMA *dma_drv = dma_periph->dma_drv;
/* Allocate handle for peripheral */
status = dma_drv->Allocate(&dma_periph->dma_handle);
if (status)
{
return ARM_DRIVER_ERROR;
}
/* Enable the channel in the Event Router */
if (dma_periph->evtrtr_cfg.instance == 0)
{
evtrtr0_enable_dma_channel(dma_periph->evtrtr_cfg.channel,
dma_periph->evtrtr_cfg.group,
DMA_ACK_COMPLETION_PERIPHERAL);
evtrtr0_enable_dma_handshake(dma_periph->evtrtr_cfg.channel,
dma_periph->evtrtr_cfg.group);
}
else
{
evtrtrlocal_enable_dma_channel(dma_periph->evtrtr_cfg.channel,
DMA_ACK_COMPLETION_PERIPHERAL);
}
return ARM_DRIVER_OK;
}
/**
\fn int32_t SPI_DMA_DeAllocate(DMA_PERIPHERAL_CONFIG *dma_periph)
\brief De-allocate channel of SPI
\param[in] dma_periph Pointer to DMA resources
\return \ref execution_status
*/
static inline int32_t SPI_DMA_DeAllocate(DMA_PERIPHERAL_CONFIG *dma_periph)
{
int32_t status;
ARM_DRIVER_DMA *dma_drv = dma_periph->dma_drv;
/* De-Allocate handle */
status = dma_drv->DeAllocate(&dma_periph->dma_handle);
if (status)
{
return ARM_DRIVER_ERROR;
}
/* Disable the channel in the Event Router */
if (dma_periph->evtrtr_cfg.instance == 0)
{
evtrtr0_disable_dma_channel(dma_periph->evtrtr_cfg.channel);
evtrtr0_disable_dma_handshake(dma_periph->evtrtr_cfg.channel,
dma_periph->evtrtr_cfg.group);
}
else
{
evtrtrlocal_disable_dma_channel(dma_periph->evtrtr_cfg.channel);
}
return ARM_DRIVER_OK;
}
/**
\fn int32_t SPI_DMA_Start(DMA_PERIPHERAL_CONFIG *dma_periph,
ARM_DMA_PARAMS *dma_params)
\brief Start SPI DMA transfer
\param[in] dma_periph Pointer to DMA resources
\param[in] dma_params Pointer to DMA parameters
\return \ref execution_status
*/
static inline int32_t SPI_DMA_Start(DMA_PERIPHERAL_CONFIG *dma_periph, ARM_DMA_PARAMS *dma_params)
{
int32_t status;
ARM_DRIVER_DMA *dma_drv = dma_periph->dma_drv;
/* Start transfer */
status = dma_drv->Start(&dma_periph->dma_handle, dma_params);
if (status)
{
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
/**
\fn int32_t SPI_DMA_Stop(DMA_PERIPHERAL_CONFIG *dma_periph)
\brief Stop SPI DMA transfer
\param[in] dma_periph Pointer to DMA resources
\return \ref execution_status
*/
static inline int32_t SPI_DMA_Stop(DMA_PERIPHERAL_CONFIG *dma_periph)
{
int32_t status;
ARM_DRIVER_DMA *dma_drv = dma_periph->dma_drv;
/* Stop transfer */
status = dma_drv->Stop(&dma_periph->dma_handle);
if (status)
{
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
/**
\fn int32_t SPI_DMA_GetStatus(DMA_PERIPHERAL_CONFIG *dma_periph, uint32_t *count)
\brief Status of SPI DMA transfer
\param[in] dma_periph Pointer to DMA resources
\param[in] count Current transfer count
\return \ref execution_status
*/
static inline int32_t SPI_DMA_GetStatus(DMA_PERIPHERAL_CONFIG *dma_periph, uint32_t *count)
{
int32_t status;
ARM_DRIVER_DMA *dma_drv = dma_periph->dma_drv;
/* Stop transfer */
status = dma_drv->GetStatus(&dma_periph->dma_handle, count);
if (status)
{
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
#endif /* SPI_DMA_ENABLE */
#if SPI_MICROWIRE_FRF_ENABLE
/**
* @fn int32_t ARM_SPI_MicroWire_Config(SPI_RESOURCES *SPI).
* @brief Config the Microwire for communication.
* @note none.
* @param SPI : Pointer to spi resources structure.
* @retval \ref execution_status
*/
static int32_t ARM_SPI_MicroWire_Config(SPI_RESOURCES *SPI)
{
if (!((SPI->mw_config.cfs >= SPI_MW_CONTROL_FRAME_SIZE_MIN) && (SPI->mw_config.cfs <= SPI_MW_CONTROL_FRAME_SIZE_MAX)))
{
return ARM_DRIVER_ERROR_PARAMETER;
}
if (SPI->mw_config.transfer_mode == SPI_MW_TRANSFER_MODE_SEQUANTIAL)
{
spi_mw_set_sequential_mode(SPI->regs);
}
else
{
spi_mw_set_non_sequential_mode(SPI->regs);
}
if (SPI->transfer.is_master)
{
if (SPI->mw_config.handshake_enable)
{
spi_mw_enable_handshake(SPI->regs);
}
else
{
spi_mw_disable_handshake(SPI->regs);
}
}
if (SPI->drv_instance == LPSPI_INSTANCE)
{
lpspi_mw_set_cfs(SPI->regs, SPI->mw_config.cfs);
}
else
{
spi_mw_set_cfs(SPI->regs, SPI->mw_config.cfs);
}
return ARM_DRIVER_OK;
}
#endif
/**
* @fn int32_t ARM_SPI_Initialize(SPI_RESOURCES *SPI, ARM_SPI_SignalEvent_t cb_event).
* @brief Initialize the Spi for communication.
* @note none.
* @param SPI : Pointer to spi resources structure.
* @param cb_event : Pointer to user callback function.
* @retval \ref execution_status
*/
static int32_t ARM_SPI_Initialize(SPI_RESOURCES *SPI, ARM_SPI_SignalEvent_t cb_event)
{
if (SPI->state.initialized == 1)
{
return ARM_DRIVER_OK;
}
bool blocking_mode = false;
#if SPI_BLOCKING_MODE_ENABLE
if (SPI->blocking_mode)
blocking_mode = true;
#endif
if (blocking_mode == false && cb_event == NULL)
{
return ARM_DRIVER_ERROR_PARAMETER;
}
if ((SPI->tx_fifo_threshold > SPI_TX_FIFO_DEPTH) || (SPI->tx_fifo_start_level > SPI_TX_FIFO_DEPTH))
{
return ARM_DRIVER_ERROR_PARAMETER;
}
if (SPI->rx_fifo_threshold > SPI_RX_FIFO_DEPTH)
{
return ARM_DRIVER_ERROR_PARAMETER;
}
/* Reset the transfer structure for this instance */
SPI->transfer.tx_buff = NULL;
SPI->transfer.rx_buff = NULL;
SPI->transfer.tx_default_val = 0;
SPI->transfer.tx_default_enable = false;
SPI->transfer.tx_total_cnt = 0;
SPI->transfer.rx_total_cnt = 0;
SPI->transfer.tx_current_cnt = 0;
SPI->transfer.rx_current_cnt = 0;
SPI->transfer.status = SPI_TRANSFER_STATUS_NONE;
SPI->cb_event = cb_event;
#if SPI_DMA_ENABLE
if (SPI->dma_enable)
{
SPI->dma_cfg->dma_rx.dma_handle = -1;
SPI->dma_cfg->dma_tx.dma_handle = -1;
/* Initialize DMA for SPI-Tx */
if (SPI_DMA_Initialize(&SPI->dma_cfg->dma_tx) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
/* Initialize DMA for SPI-Rx */
if (SPI_DMA_Initialize(&SPI->dma_cfg->dma_rx) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
}
#endif
SPI->state.initialized = 1;
return ARM_DRIVER_OK;
}
/**
* @fn int32_t ARM_SPI_Uninitialize(SPI_RESOURCES *SPI).
* @brief Un-Initialize the Spi.
* @note none.
* @param SPI : Pointer to spi resources structure.
* @retval \ref execution_status
*/
static int32_t ARM_SPI_Uninitialize(SPI_RESOURCES *SPI)
{
if (SPI->state.initialized == 0)
{
return ARM_DRIVER_OK;
}
if (SPI->state.powered == 1)
{
return ARM_DRIVER_ERROR;
}
#if SPI_DMA_ENABLE
if (SPI->dma_enable)
{
SPI->dma_cfg->dma_rx.dma_handle = -1;
SPI->dma_cfg->dma_tx.dma_handle = -1;
}
#endif
SPI->cb_event = NULL;
SPI->transfer.tx_buff = NULL;
SPI->transfer.rx_buff = NULL;
SPI->transfer.tx_default_val = 0;
SPI->transfer.tx_default_enable = false;
SPI->transfer.tx_total_cnt = 0;
SPI->transfer.rx_total_cnt = 0;
SPI->transfer.tx_current_cnt = 0;
SPI->transfer.rx_current_cnt = 0;
SPI->transfer.status = SPI_TRANSFER_STATUS_NONE;
SPI->state.initialized = 0;
return ARM_DRIVER_OK;
}
/**
* @fn int32_t ARM_SPI_PowerControl(SPI_RESOURCES *SPI, ARM_POWER_STATE state).
* @brief Handles the spi power.
* @note none.
* @param SPI : Pointer to spi resources structure.
* @param state : power state.
* @retval \ref execution_status
*/
static int32_t ARM_SPI_PowerControl(SPI_RESOURCES *SPI, ARM_POWER_STATE state)
{
#if SPI_USE_MASTER_SS_SW
int32_t ret = ARM_DRIVER_OK;
#endif
if (SPI->state.initialized == 0)
{
return ARM_DRIVER_ERROR;
}
switch (state)
{
case ARM_POWER_OFF:
{
if (SPI->state.powered == 0)
{
return ARM_DRIVER_OK;
}
if (SPI->status.busy)
{
return ARM_DRIVER_ERROR_BUSY;
}
#if SPI_DMA_ENABLE
if (SPI->dma_enable)
{
/* Disable the TX & RX DMA interface of SPI */
spi_disable_tx_dma(SPI->regs);
spi_disable_rx_dma(SPI->regs);
/* DeAllocate DMA for SPI-Tx */
if (SPI_DMA_DeAllocate(&SPI->dma_cfg->dma_tx) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
/* DeAllocate DMA for SPI-Rx */
if (SPI_DMA_DeAllocate(&SPI->dma_cfg->dma_rx) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
/* Power Control DMA for SPI-Tx */
if (SPI_DMA_PowerControl(&SPI->dma_cfg->dma_tx, state) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
/* Power Control DMA for SPI-Rx */
if (SPI_DMA_PowerControl(&SPI->dma_cfg->dma_rx, state) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
}
#endif
#if SPI_USE_MASTER_SS_SW
if ((SPI->transfer.is_master) && (SPI->master_ss_control == SPI_SS_SW_CONTROL))
{
ret = SPI->sw_config.drvGPIO->PowerControl(SPI->sw_config.ss_pin, ARM_POWER_OFF);
if(ret != ARM_DRIVER_OK) { return ret; }
ret = SPI->sw_config.drvGPIO->Uninitialize(SPI->sw_config.ss_pin);
if(ret != ARM_DRIVER_OK) { return ret; }
}
#endif
NVIC_ClearPendingIRQ(SPI->irq);
NVIC_DisableIRQ(SPI->irq);
if (SPI->drv_instance == LPSPI_INSTANCE)
{
disable_lpspi_clk();
}
else
{
/* reset to default value */
ctrl_ss_in(SPI->drv_instance, SS_IN_IO_PIN);
}
SPI->state.powered = 0;
break;
}
case ARM_POWER_FULL:
{
if (SPI->state.powered == 1)
{
return ARM_DRIVER_OK;
}
if (SPI->drv_instance == LPSPI_INSTANCE)
{
enable_lpspi_clk();
}
spi_mask_interrupts(SPI->regs);
NVIC_ClearPendingIRQ(SPI->irq);
NVIC_SetPriority(SPI->irq, SPI->irq_priority);
NVIC_EnableIRQ(SPI->irq);
spi_set_tx_threshold(SPI->regs, SPI->tx_fifo_threshold);
if (SPI->drv_instance != LPSPI_INSTANCE)
{
spi_set_tx_fifo_start_level(SPI->regs, SPI->tx_fifo_start_level);
spi_set_rx_sample_delay(SPI->regs, SPI->rx_sample_delay);
}
#if SPI_DMA_ENABLE
if (SPI->dma_enable)
{
/* Power Control DMA for SPI-Tx */
if (SPI_DMA_PowerControl(&SPI->dma_cfg->dma_tx, state) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
/* Power Control DMA for SPI-Rx */
if (SPI_DMA_PowerControl(&SPI->dma_cfg->dma_rx, state) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
spi_set_dma_tx_level(SPI->regs, SPI->tx_fifo_threshold);
spi_set_dma_rx_level(SPI->regs, SPI->rx_fifo_threshold);
/* Try to allocate a DMA channel */
if (SPI_DMA_Allocate(&SPI->dma_cfg->dma_rx))
{
return ARM_DRIVER_ERROR;
}
if (SPI_DMA_Allocate(&SPI->dma_cfg->dma_tx))
{
return ARM_DRIVER_ERROR;
}
}
#endif
SPI->state.powered = 1;
break;
}
case ARM_POWER_LOW:
default:
{
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
}
return ARM_DRIVER_OK;
}
/**
* @fn int32_t ARM_SPI_Send(SPI_RESOURCES *SPI, const void *data, uint32_t num).
* @brief Used to send through spi.
* @note none.
* @param SPI : Pointer to spi resources structure.
* @param data : Pointer to the data to send.
* @param num : Number of data frames to send.
* @retval \ref execution_status
*/
static int32_t ARM_SPI_Send(SPI_RESOURCES *SPI, const void *data, uint32_t num)
{
if (SPI->state.powered == 0)
{
return ARM_DRIVER_ERROR;
}
#if SPI_MICROWIRE_FRF_ENABLE
if (SPI->mw_enable)
{
if (!SPI->transfer.is_master)
{
return ARM_DRIVER_ERROR;
}
}
#endif
if ((data == NULL) && (SPI->transfer.tx_default_enable == false))
{
return ARM_DRIVER_ERROR_PARAMETER;
}
if (num == 0)
{
return ARM_DRIVER_ERROR_PARAMETER;
}
if (SPI->status.busy)
{
return ARM_DRIVER_ERROR_BUSY;
}
SPI->status.busy = 1;
SPI->transfer.tx_buff = (const uint8_t *) data;
SPI->transfer.tx_total_cnt = num;
SPI->transfer.tx_current_cnt = 0;
SPI->transfer.status = SPI_TRANSFER_STATUS_NONE;
SPI->transfer.mode = SPI_TMOD_TX;
#if SPI_MICROWIRE_FRF_ENABLE
if (SPI->mw_enable)
{
if (SPI->mw_config.transfer_mode == SPI_MW_TRANSFER_MODE_SEQUANTIAL)
{
/* In master sequential mode, continuous data transfer is not available;
* therefore, the value of 'tx_total_cnt' should be set to 2. */
SPI->transfer.tx_total_cnt = 2U;
}
else
{
/* In master non-sequential mode, the value of "tx_total_cnt" should be
* twice the amount of data that needs to be sent. */
SPI->transfer.tx_total_cnt = (num << 1);
}
}
#endif
/* If the Frame size is more than 16, check if it is aligned to 4 bytes */
if ((SPI->transfer.frame_size > 16) && ((uint32_t)data & 0x3U) != 0U)
{
return ARM_DRIVER_ERROR_PARAMETER;
}
/* If the Frame size is more than 8 and less than 16, check if it is aligned to 2 bytes */
if ((SPI->transfer.frame_size > 8) && ((uint32_t)data & 0x1U) != 0U)
{
return ARM_DRIVER_ERROR_PARAMETER;
}
#if SPI_DMA_ENABLE
/* Check if DMA is enabled */
if (SPI->dma_enable)
{
ARM_DMA_PARAMS dma_params;
if (SPI->drv_instance == LPSPI_INSTANCE)
{
lpspi_dma_send(SPI->regs);
}
else
{
spi_dma_send(SPI->regs);
}
/* Start the DMA engine for sending the data to SPI */
dma_params.peri_reqno = (int8_t)SPI->dma_cfg->dma_tx.dma_periph_req;
dma_params.dir = ARM_DMA_MEM_TO_DEV;
dma_params.cb_event = SPI->dma_cb;
dma_params.src_addr = data;
dma_params.dst_addr = (void*)spi_get_data_addr(SPI->regs);
dma_params.irq_priority = SPI->dma_irq_priority;
dma_params.burst_len = SPI_TX_FIFO_DEPTH - SPI->tx_fifo_threshold;
if (SPI->transfer.frame_size > 16)
{
dma_params.num_bytes = SPI->transfer.tx_total_cnt * sizeof(uint32_t);
dma_params.burst_size = BS_BYTE_4;
}
else if (SPI->transfer.frame_size > 8)
{
dma_params.num_bytes = SPI->transfer.tx_total_cnt * sizeof(uint16_t);
dma_params.burst_size = BS_BYTE_2;
}
else
{
dma_params.num_bytes = SPI->transfer.tx_total_cnt * sizeof(uint8_t);
dma_params.burst_size = BS_BYTE_1;
}
if (SPI_DMA_Start(&SPI->dma_cfg->dma_tx, &dma_params) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
}
else
#endif
{
#if SPI_MICROWIRE_FRF_ENABLE
if (SPI->mw_enable)
{
spi_mw_transmit(SPI->regs, !(SPI->transfer.is_master));
}
else
#endif
{
if (SPI->drv_instance == LPSPI_INSTANCE)
{
#if SPI_BLOCKING_MODE_ENABLE
if (SPI->blocking_mode)
{
lpspi_send_blocking(SPI->regs, &SPI->transfer);
SPI->transfer.status = SPI_TRANSFER_STATUS_COMPLETE;
SPI->status.busy = 0;
}
else
#endif
{
lpspi_send(SPI->regs);
}
}
else
{
#if SPI_BLOCKING_MODE_ENABLE
if (SPI->blocking_mode)
{
spi_send_blocking(SPI->regs, &SPI->transfer);
SPI->transfer.status = SPI_TRANSFER_STATUS_COMPLETE;
SPI->status.busy = 0;
}
else
#endif
{
spi_send(SPI->regs);
}
}
}
}
return ARM_DRIVER_OK;
}
/**
* @fn int32_t ARM_SPI_Receive(SPI_RESOURCES *SPI, void *data, uint32_t num).
* @brief Used to receive data through spi.
* @note none.
* @param SPI : Pointer to spi resources structure.
* @param data : Pointer to the data received.
* @param num : Number of data frames to receive.
* @retval \ref execution_status
*/
static int32_t ARM_SPI_Receive(SPI_RESOURCES *SPI, void *data, uint32_t num)
{
if (SPI->state.powered == 0)
{
return ARM_DRIVER_ERROR;
}
if ((data == NULL) || (num == 0))
{
return ARM_DRIVER_ERROR_PARAMETER;
}
#if SPI_MICROWIRE_FRF_ENABLE
if (SPI->mw_enable)
{
if (SPI->transfer.is_master)
{
return ARM_DRIVER_ERROR;
}
}
#endif
if (SPI->status.busy)
{
return ARM_DRIVER_ERROR_BUSY;
}
SPI->status.busy = 1;
SPI->transfer.rx_buff = data;
SPI->transfer.rx_total_cnt = num;
SPI->transfer.rx_current_cnt = 0;
SPI->transfer.status = SPI_TRANSFER_STATUS_NONE;
SPI->transfer.mode = SPI_TMOD_RX;
spi_set_rx_threshold(SPI->regs, SPI->rx_fifo_threshold);
#if SPI_MICROWIRE_FRF_ENABLE
if (SPI->mw_enable)
{
if (SPI->mw_config.transfer_mode == SPI_MW_TRANSFER_MODE_SEQUANTIAL)
{
/* In slave sequential mode, the value of "rx_total_cnt" should be
* one greater than the number of data needs to be received. */
SPI->transfer.rx_total_cnt = (num + 1U);
}
else
{
/* In slave non-sequential mode, the value of "rx_total_cnt" should be
* twice the amount of data that needs to be received. */
SPI->transfer.rx_total_cnt = (num << 1);
}
}
#endif
/* If the Frame size is more than 16, check if it is aligned to 4 bytes */
if ((SPI->transfer.frame_size > 16) && ((uint32_t)data & 0x3U) != 0U)
{
return ARM_DRIVER_ERROR_PARAMETER;
}
/* If the Frame size is more than 8 and less than 16, check if it is aligned to 2 bytes */
if ((SPI->transfer.frame_size > 8) && ((uint32_t)data & 0x1U) != 0U)
{
return ARM_DRIVER_ERROR_PARAMETER;
}
#if SPI_DMA_ENABLE
ARM_DMA_PARAMS rx_dma_params;
/* Check if DMA is enabled for this */
if (SPI->dma_enable)
{
if (SPI->drv_instance == LPSPI_INSTANCE)
{
lpspi_dma_receive(SPI->regs, SPI->transfer.rx_total_cnt);
}
else
{
spi_dma_receive(SPI->regs, &SPI->transfer);
}
if (SPI->rx_fifo_threshold > 0)
{
SPI->rx_fifo_threshold = spi_dma_calc_rx_level(SPI->transfer.rx_total_cnt, SPI->rx_fifo_threshold);
spi_set_dma_rx_level(SPI->regs, SPI->rx_fifo_threshold);
}
/* Start the DMA engine for receive the data to SPI */
rx_dma_params.peri_reqno = (int8_t)SPI->dma_cfg->dma_rx.dma_periph_req;
rx_dma_params.dir = ARM_DMA_DEV_TO_MEM;
rx_dma_params.cb_event = SPI->dma_cb;
rx_dma_params.src_addr = (void*)spi_get_data_addr(SPI->regs);
rx_dma_params.dst_addr = data;
rx_dma_params.irq_priority = SPI->dma_irq_priority;
rx_dma_params.burst_len = SPI->rx_fifo_threshold + 1;
if (SPI->transfer.frame_size > 16)
{
rx_dma_params.num_bytes = SPI->transfer.rx_total_cnt * sizeof(uint32_t);
rx_dma_params.burst_size = BS_BYTE_4;
}
else if (SPI->transfer.frame_size > 8)
{
rx_dma_params.num_bytes = SPI->transfer.rx_total_cnt * sizeof(uint16_t);
rx_dma_params.burst_size = BS_BYTE_2;
}
else
{
rx_dma_params.num_bytes = SPI->transfer.rx_total_cnt;
rx_dma_params.burst_size = BS_BYTE_1;
}
if (SPI_DMA_Start(&SPI->dma_cfg->dma_rx, &rx_dma_params) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
}
else
#endif
{
#if SPI_MICROWIRE_FRF_ENABLE
if (SPI->mw_enable)
{
spi_mw_receive(SPI->regs, &SPI->transfer);
}
else
#endif
{
if (SPI->drv_instance == LPSPI_INSTANCE)
{
#if SPI_BLOCKING_MODE_ENABLE
if (SPI->blocking_mode)
{
lpspi_receive_blocking(SPI->regs, &SPI->transfer);
SPI->transfer.status = SPI_TRANSFER_STATUS_COMPLETE;
SPI->status.busy = 0;
}
else
#endif
{
lpspi_receive(SPI->regs, SPI->transfer.rx_total_cnt);
}
}
else
{
#if SPI_BLOCKING_MODE_ENABLE
if (SPI->blocking_mode)
{
spi_receive_blocking(SPI->regs, &SPI->transfer);
SPI->transfer.status = SPI_TRANSFER_STATUS_COMPLETE;
SPI->status.busy = 0;
}
else
#endif
{
spi_receive(SPI->regs, &SPI->transfer);
}
}
}
}
return ARM_DRIVER_OK;
}
/**
* @fn int32_t ARM_SPI_Transfer(SPI_RESOURCES *SPI, const void *data_out, void *data_in, uint32_t num).
* @brief Used to Transfer and Receive data through spi.
* @note none.
* @param SPI : Pointer to spi resources structure.
* @param data_out : Pointer to the data send.
* @param data_in : Pointer to the data received.
* @param num : Number of data frames to transfer.
* @retval \ref execution_status
*/
static int32_t ARM_SPI_Transfer(SPI_RESOURCES *SPI, const void *data_out, void *data_in, uint32_t num)
{
if (SPI->state.powered == 0)
{
return ARM_DRIVER_ERROR;
}
if ((data_out == NULL) && (SPI->transfer.tx_default_enable == false))
{
return ARM_DRIVER_ERROR_PARAMETER;
}
if ((data_out == NULL) || (data_in == NULL) || (num == 0))
{
return ARM_DRIVER_ERROR_PARAMETER;
}
if (SPI->status.busy)
{
return ARM_DRIVER_ERROR_BUSY;
}
SPI->status.busy = 1;
SPI->transfer.tx_buff = (const uint8_t *) data_out;
SPI->transfer.rx_buff = data_in;
SPI->transfer.tx_total_cnt = num;
SPI->transfer.rx_total_cnt = num;
SPI->transfer.tx_current_cnt = 0;
SPI->transfer.rx_current_cnt = 0;
SPI->transfer.status = SPI_TRANSFER_STATUS_NONE;
SPI->transfer.mode = SPI_TMOD_TX_AND_RX;
spi_set_rx_threshold(SPI->regs, SPI->rx_fifo_threshold);
#if SPI_MICROWIRE_FRF_ENABLE
if (SPI->mw_enable)
{
if (SPI->transfer.is_master && (SPI->mw_config.transfer_mode == SPI_MW_TRANSFER_MODE_SEQUANTIAL))
{
/* In master sequential mode receive, tx_total_cnt should be 1 as only one control word is sent */
SPI->transfer.tx_total_cnt = 1U;
}
if ((!SPI->transfer.is_master) && (SPI->mw_config.transfer_mode == SPI_MW_TRANSFER_MODE_SEQUANTIAL))
{
/* In slave sequential mode transmit, rx_total_cnt should be 1 as only one control word is received */
SPI->transfer.rx_total_cnt = 1U;
}
}
#endif
/* If the Frame size is more than 16, check if it is aligned to 4 bytes */
if ((SPI->transfer.frame_size > 16) && ((((uint32_t)data_in & 0x3U) != 0U) && (((uint32_t)data_out & 0x3U) != 0U)))
{
return ARM_DRIVER_ERROR_PARAMETER;
}
/* If the Frame size is more than 8 and less than 16, check if it is aligned to 2 bytes */
if ((SPI->transfer.frame_size > 8) && ((((uint32_t)data_in & 0x1U) != 0U) && (((uint32_t)data_out & 0x1U) != 0U)))
{
return ARM_DRIVER_ERROR_PARAMETER;
}
#if SPI_DMA_ENABLE
ARM_DMA_PARAMS tx_dma_params, rx_dma_params;
/* Check if DMA is enabled for this */
if (SPI->dma_enable)
{
if (SPI->drv_instance == LPSPI_INSTANCE)
{
lpspi_dma_transfer(SPI->regs);
}
else
{
spi_dma_transfer(SPI->regs);
}
if (SPI->rx_fifo_threshold > 0)
{
SPI->rx_fifo_threshold = spi_dma_calc_rx_level(SPI->transfer.rx_total_cnt, SPI->rx_fifo_threshold);
spi_set_dma_rx_level(SPI->regs, SPI->rx_fifo_threshold);
}
/* Start the DMA engine for sending the data to SPI */
tx_dma_params.peri_reqno = (int8_t)SPI->dma_cfg->dma_tx.dma_periph_req;
tx_dma_params.dir = ARM_DMA_MEM_TO_DEV;
tx_dma_params.cb_event = SPI->dma_cb;
tx_dma_params.src_addr = data_out;
tx_dma_params.dst_addr = (void*)spi_get_data_addr(SPI->regs);
tx_dma_params.irq_priority = SPI->dma_irq_priority;
tx_dma_params.burst_len = SPI_TX_FIFO_DEPTH - SPI->tx_fifo_threshold;
/* Start the DMA engine for receive the data to SPI */
rx_dma_params.peri_reqno = (int8_t)SPI->dma_cfg->dma_rx.dma_periph_req;
rx_dma_params.dir = ARM_DMA_DEV_TO_MEM;
rx_dma_params.cb_event = SPI->dma_cb;
rx_dma_params.src_addr = (void*)spi_get_data_addr(SPI->regs);
rx_dma_params.dst_addr = data_in;
rx_dma_params.irq_priority = SPI->dma_irq_priority;
rx_dma_params.burst_len = SPI->rx_fifo_threshold + 1;
if (SPI->transfer.frame_size > 16)
{
tx_dma_params.num_bytes = SPI->transfer.tx_total_cnt * sizeof(uint32_t);
rx_dma_params.num_bytes = SPI->transfer.rx_total_cnt * sizeof(uint32_t);
tx_dma_params.burst_size = BS_BYTE_4;
rx_dma_params.burst_size = BS_BYTE_4;
}
else if (SPI->transfer.frame_size > 8)
{
tx_dma_params.num_bytes = SPI->transfer.tx_total_cnt * sizeof(uint16_t);
rx_dma_params.num_bytes = SPI->transfer.rx_total_cnt * sizeof(uint16_t);
tx_dma_params.burst_size = BS_BYTE_2;
rx_dma_params.burst_size = BS_BYTE_2;
}
else
{
tx_dma_params.src_addr = (const uint8_t *)data_out;
tx_dma_params.num_bytes = SPI->transfer.tx_total_cnt * sizeof(uint8_t);
rx_dma_params.num_bytes = SPI->transfer.rx_total_cnt * sizeof(uint8_t);
tx_dma_params.burst_size = BS_BYTE_1;
rx_dma_params.burst_size = BS_BYTE_1;
}
if (SPI_DMA_Start(&SPI->dma_cfg->dma_rx, &rx_dma_params) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
if (SPI_DMA_Start(&SPI->dma_cfg->dma_tx, &tx_dma_params) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
}
else
#endif
{
#if SPI_MICROWIRE_FRF_ENABLE
if (SPI->mw_enable)
{
if (SPI->transfer.is_master)
{
spi_mw_receive(SPI->regs, &SPI->transfer);
}
else
{
spi_mw_transmit(SPI->regs, !(SPI->transfer.is_master));
}
}
else
#endif
{
if (SPI->drv_instance == LPSPI_INSTANCE)
{
#if SPI_BLOCKING_MODE_ENABLE
if (SPI->blocking_mode)
{
lpspi_transfer_blocking(SPI->regs, &SPI->transfer);
SPI->transfer.status = SPI_TRANSFER_STATUS_COMPLETE;
SPI->status.busy = 0;
}
else
#endif
{
lpspi_transfer(SPI->regs);
}
}
else
{
#if SPI_BLOCKING_MODE_ENABLE
if (SPI->blocking_mode)
{
spi_transfer_blocking(SPI->regs, &SPI->transfer);
SPI->transfer.status = SPI_TRANSFER_STATUS_COMPLETE;
SPI->status.busy = 0;
}
else
#endif
{
spi_transfer(SPI->regs);
}
}
}
}
return ARM_DRIVER_OK;
}
/**
* @fn int32_t ARM_SPI_GetDataCount(SPI_RESOURCES *SPI).
* @brief Used to get the data count on spi data transferring modes.
* @note none.
* @param SPI : Pointer to spi resources structure.
* @retval \ref data count
*/
static uint32_t ARM_SPI_GetDataCount(SPI_RESOURCES *SPI)
{
uint32_t count = 0;
SPI_TMOD tmod;
if (SPI->drv_instance == LPSPI_INSTANCE)
{
tmod = lpspi_get_tmod(SPI->regs);
}
else
{
tmod = spi_get_tmod(SPI->regs);
}
switch (tmod)
{
case SPI_TMOD_TX:
count = SPI->transfer.tx_current_cnt;
break;
case SPI_TMOD_RX:
case SPI_TMOD_TX_AND_RX:
count = SPI->transfer.rx_current_cnt;
break;
case SPI_TMOD_EEPROM_READ:
default:
break;
}
return count;
}
/**
* @fn int32_t ARM_SPI_Control(SPI_RESOURCES *SPI, uint32_t control, uint32_t arg).
* @brief Used to configure spi.
* @note none.
* @param SPI : Pointer to spi resources structure.
* @param control : control code.
* @param arg : argument.
* @retval \ref execution_status
*/
static int32_t ARM_SPI_Control(SPI_RESOURCES *SPI, uint32_t control, uint32_t arg)
{
int32_t ret = ARM_DRIVER_OK;
uint32_t clk;
if (SPI->state.powered == 0)
{
return ARM_DRIVER_ERROR;
}
if (SPI->status.busy)
{
return ARM_DRIVER_ERROR_BUSY;
}
switch (control & ARM_SPI_CONTROL_Msk)
{
case ARM_SPI_MODE_INACTIVE:
{
if (control == 0)
{
spi_disable(SPI->regs);
}
break;
}
/* SPI Master (Output on MOSI, Input on MISO); arg = Bus Speed in bps */
case ARM_SPI_MODE_MASTER:
{
if (SPI->drv_instance != LPSPI_INSTANCE)
{
ctrl_ss_in(SPI->drv_instance, SS_IN_SS_IN_VAL);
spi_mode_master(SPI->regs);
}
clk = getSpiCoreClock(SPI->drv_instance);
spi_set_bus_speed(SPI->regs, arg, clk);
SPI->transfer.is_master = 1;
break;
}
/* SPI Slave (Output on MISO, Input on MOSI) arg = Bus speed in bps */
case ARM_SPI_MODE_SLAVE:
{
if (SPI->drv_instance == LPSPI_INSTANCE)
{
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
else
{
spi_mode_slave(SPI->regs);
SPI->transfer.is_master = 0;
}
break;
}
/* SPI Slave (Output/Input on MISO) */
case ARM_SPI_SET_BUS_SPEED:
{
clk = getSpiCoreClock(SPI->drv_instance);
spi_set_bus_speed(SPI->regs, arg, clk);
break;
}
/* Get Bus Speed in bps */
case ARM_SPI_GET_BUS_SPEED:
{
clk = getSpiCoreClock(SPI->drv_instance);
return (int32_t) spi_get_bus_speed(SPI->regs, clk);
}
/* Set the default transmission value */
case ARM_SPI_SET_DEFAULT_TX_VALUE:
{
SPI->transfer.tx_default_val = arg;
SPI->transfer.tx_default_enable = true;
break;
}
/* Control the Slave Select signal */
case ARM_SPI_CONTROL_SS:
{
if (SPI->master_ss_control == SPI_SS_HW_CONTROL)
{
if (arg == 1)
{
spi_control_ss(SPI->regs, SPI->slave_select, SPI_SS_STATE_ENABLE);
}
else if (arg == 0)
{
spi_control_ss(SPI->regs, SPI->slave_select, SPI_SS_STATE_DISABLE);
}
else
{
return ARM_DRIVER_ERROR_PARAMETER;
}
}
else if (SPI->master_ss_control == SPI_SS_SW_CONTROL)
{
#if SPI_USE_MASTER_SS_SW
if (arg == 1)
{
ret = SPI->sw_config.drvGPIO->SetValue(SPI->sw_config.ss_pin, SPI->sw_config.active_polarity);
if(ret != ARM_DRIVER_OK) { return ret; }
}
else if (arg == 0)
{
ret = SPI->sw_config.drvGPIO->SetValue(SPI->sw_config.ss_pin, !(SPI->sw_config.active_polarity));
if(ret != ARM_DRIVER_OK) { return ret; }
}
else
{
return ARM_DRIVER_ERROR_PARAMETER;
}
#endif
}
return ARM_DRIVER_OK;
}
/* Abort the current data transfer */
case ARM_SPI_ABORT_TRANSFER:
{
#if SPI_DMA_ENABLE
if (SPI->dma_enable)
{
/* SEND ONLY mode */
if (SPI->transfer.mode == SPI_TMOD_TX)
{
if (SPI_DMA_Stop(&SPI->dma_cfg->dma_tx) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
}
/* RECEIVE ONLY mode */
if (SPI->transfer.mode == SPI_TMOD_RX)
{
if (SPI_DMA_Stop(&SPI->dma_cfg->dma_rx) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
if (SPI->transfer.is_master)
{
if (SPI_DMA_Stop(&SPI->dma_cfg->dma_tx) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
}
}
/* TRANSFER mode */
if (SPI->transfer.mode == SPI_TMOD_TX_AND_RX)
{
if (SPI_DMA_Stop(&SPI->dma_cfg->dma_tx) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
if (SPI_DMA_Stop(&SPI->dma_cfg->dma_rx) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
}
}
#endif
spi_mask_interrupts(SPI->regs);
SPI->transfer.tx_buff = NULL;
SPI->transfer.rx_buff = NULL;
SPI->transfer.tx_default_val = 0;
SPI->transfer.tx_default_enable = false;
SPI->transfer.tx_total_cnt = 0;
SPI->transfer.rx_total_cnt = 0;
SPI->transfer.tx_current_cnt = 0;
SPI->transfer.rx_current_cnt = 0;
SPI->status.busy = 0;
spi_disable(SPI->regs);
spi_enable(SPI->regs);
break;
}
default:
{
ret = ARM_DRIVER_ERROR_UNSUPPORTED;
break;
}
}
switch (control & ARM_SPI_FRAME_FORMAT_Msk)
{
/* SPI Mode configuration */
case ARM_SPI_CPOL0_CPHA0:
{
if (SPI->drv_instance == LPSPI_INSTANCE)
{
lpspi_set_mode(SPI->regs, SPI_MODE_0);
lpspi_set_sste(SPI->regs, SPI->sste_enable);
}
else
{
spi_set_mode(SPI->regs, SPI_MODE_0);
spi_set_sste(SPI->regs, SPI->sste_enable);
}
break;
}
case ARM_SPI_CPOL0_CPHA1:
{
if (SPI->drv_instance == LPSPI_INSTANCE)
{
lpspi_set_mode(SPI->regs, SPI_MODE_1);
}
else
{
spi_set_mode(SPI->regs, SPI_MODE_1);
}
break;
}
case ARM_SPI_CPOL1_CPHA0:
{
if (SPI->drv_instance == LPSPI_INSTANCE)
{
lpspi_set_mode(SPI->regs, SPI_MODE_2);
lpspi_set_sste(SPI->regs, SPI->sste_enable);
}
else
{
spi_set_mode(SPI->regs, SPI_MODE_2);
spi_set_sste(SPI->regs, SPI->sste_enable);
}
break;
}
case ARM_SPI_CPOL1_CPHA1:
{
if (SPI->drv_instance == LPSPI_INSTANCE)
{
lpspi_set_mode(SPI->regs, SPI_MODE_3);
}
else
{
spi_set_mode(SPI->regs, SPI_MODE_3);
}
break;
}
/* Texas Instruments Frame Format */
case ARM_SPI_TI_SSI:
{
if (SPI->drv_instance == LPSPI_INSTANCE)
{
lpspi_set_protocol(SPI->regs, SPI_PROTO_SSP);
}
else
{
spi_set_protocol(SPI->regs, SPI_PROTO_SSP);
}
break;
}
/* National Microwire Frame Format */
case ARM_SPI_MICROWIRE:
{
#if SPI_MICROWIRE_FRF_ENABLE
if (!SPI->mw_enable)
{
return ARM_DRIVER_ERROR_PARAMETER;
}
if (SPI->drv_instance == LPSPI_INSTANCE)
{
lpspi_set_protocol(SPI->regs, SPI_PROTO_MICROWIRE);
}
else
{
spi_set_protocol(SPI->regs, SPI_PROTO_MICROWIRE);
}
ret = ARM_SPI_MicroWire_Config(SPI);
if (ret != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR_PARAMETER;
}
#endif
break;
}
default:
{
ret = ARM_DRIVER_ERROR_UNSUPPORTED;
break;
}
}
/* Configure frame size */
if (control & ARM_SPI_DATA_BITS_Msk)
{
SPI->transfer.frame_size = ((control & ARM_SPI_DATA_BITS_Msk) >> ARM_SPI_DATA_BITS_Pos);
if (SPI->drv_instance == LPSPI_INSTANCE)
{
lpspi_set_dfs(SPI->regs, SPI->transfer.frame_size);
}
else
{
spi_set_dfs(SPI->regs, SPI->transfer.frame_size);
}
}
switch (control & ARM_SPI_BIT_ORDER_Msk)
{
/* SPI Bit order from MSB to LSB (default) */
case ARM_SPI_MSB_LSB:
{
break;
}
/* SPI Bit order from LSB to MSB */
case ARM_SPI_LSB_MSB:
{
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
}
if (SPI->transfer.is_master)
{
switch (control & ARM_SPI_SS_MASTER_MODE_Msk)
{
/* SPI Slave Select when Master: Not used (default) */
case ARM_SPI_SS_MASTER_UNUSED:
{
/* add dummy value to SER reg to start the data transfer. Below, setting first bit */
spi_control_ss(SPI->regs, 0x0, SPI_SS_STATE_ENABLE);
break;
}
/* SPI Slave Select when Master: Software controlled */
case ARM_SPI_SS_MASTER_SW:
{
#if SPI_USE_MASTER_SS_SW
/* add dummy value to SER reg to start the data transfer. Below, setting first bit */
spi_control_ss(SPI->regs, 0x0, SPI_SS_STATE_ENABLE);
/* GPIO setup */
ret = SPI->sw_config.drvGPIO->Initialize(SPI->sw_config.ss_pin, NULL);
if(ret != ARM_DRIVER_OK) { return ret; }
ret = SPI->sw_config.drvGPIO->PowerControl(SPI->sw_config.ss_pin, ARM_POWER_FULL);
if(ret != ARM_DRIVER_OK) { return ret; }
ret = SPI->sw_config.drvGPIO->SetDirection(SPI->sw_config.ss_pin, GPIO_PIN_DIRECTION_OUTPUT);
if(ret != ARM_DRIVER_OK) { return ret; }
ret = SPI->sw_config.drvGPIO->SetValue(SPI->sw_config.ss_pin, !(SPI->sw_config.active_polarity));
if(ret != ARM_DRIVER_OK) { return ret; }
SPI->master_ss_control = SPI_SS_SW_CONTROL;
#endif
break;
}
/* SPI Slave Select when Master: Hardware controlled Output */
case ARM_SPI_SS_MASTER_HW_OUTPUT:
{
SPI->master_ss_control = SPI_SS_HW_CONTROL;
break;
}
/* SPI Slave Select when Master: Hardware monitored Input */
case ARM_SPI_SS_MASTER_HW_INPUT:
{
//TODO: Need to Implement
break;
}
}
}
if (!(SPI->transfer.is_master))
{
switch (control & ARM_SPI_SS_SLAVE_MODE_Msk)
{
/* SPI Slave Select when Slave: Hardware monitored (default) */
case ARM_SPI_SS_SLAVE_HW:
{
/* No need to configure anything */
break;
}
/* SPI Slave Select when Slave: Software controlled */
case ARM_SPI_SS_SLAVE_SW:
{
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
}
}
return ret;
}
/**
* @fn void SPI_IRQ_Handler(SPI_RESOURCES *SPI, spi_transfer_t *transfer).
* @brief SPI IRQ handler.
* @note none.
* @param SPI : Pointer to spi resources structure.
* @param transfer : transfer structure pointer for the SPI instance
* @retval none
*/
static void SPI_IRQ_Handler(SPI_RESOURCES *SPI)
{
#if SPI_MICROWIRE_FRF_ENABLE
if (SPI->mw_enable)
{
spi_mw_irq_handler(SPI->regs, &(SPI->transfer));
}
else
#endif
{
spi_irq_handler(SPI->regs, &(SPI->transfer));
}
if (SPI->transfer.status == SPI_TRANSFER_STATUS_COMPLETE)
{
SPI->transfer.status = SPI_TRANSFER_STATUS_NONE;
SPI->status.busy = 0;
SPI->cb_event(ARM_SPI_EVENT_TRANSFER_COMPLETE);
}
if (SPI->transfer.status == SPI_TRANSFER_STATUS_OVERFLOW)
{
SPI->transfer.status = SPI_TRANSFER_STATUS_NONE;
SPI->status.data_lost = 1;
SPI->status.busy = 0;
SPI->cb_event(ARM_SPI_EVENT_DATA_LOST);
}
}
#if SPI_DMA_ENABLE
/**
* @fn void SPI_DMACallback(SPI_RESOURCES *SPI, uint32_t event, int8_t peri_num)
* @brief DMA Callback function for SPI.
* @note none.
* @param SPI : Pointer to spi resources structure.
* @param event : Event from DMA
* @param peri_num : peripheral request number
* @retval none
*/
static void SPI_DMACallback(SPI_RESOURCES *SPI, uint32_t event, int8_t peri_num)
{
if (!SPI->cb_event)
{
return;
}
/* Transfer Completed */
if (event & ARM_DMA_EVENT_COMPLETE)
{
switch(peri_num)
{
case SPI0_DMA_TX_PERIPH_REQ:
case SPI1_DMA_TX_PERIPH_REQ:
case SPI2_DMA_TX_PERIPH_REQ:
case SPI3_DMA_TX_PERIPH_REQ:
#if defined (M55_HE)
case LPSPI_DMA_TX_PERIPH_REQ:
#endif
if (SPI->transfer.mode == SPI_TMOD_TX)
{
SPI->status.busy = 0;
SPI->cb_event(ARM_SPI_EVENT_TRANSFER_COMPLETE);
}
break;
case SPI0_DMA_RX_PERIPH_REQ:
case SPI1_DMA_RX_PERIPH_REQ:
case SPI2_DMA_RX_PERIPH_REQ:
case SPI3_DMA_RX_PERIPH_REQ:
#if defined (M55_HE)
case LPSPI_DMA_RX_PERIPH_REQ:
#endif
SPI->status.busy = 0;
SPI->cb_event(ARM_SPI_EVENT_TRANSFER_COMPLETE);
break;
default:
break;
}
}
/* Abort Occurred */
if (event & ARM_DMA_EVENT_ABORT)
{
SPI->status.busy = 0;
SPI->cb_event(ARM_SPI_EVENT_DATA_LOST);
}
}
#endif
/**
* @fn ARM_SPI_STATUS ARM_SPI_GetStatus(SPI_RESOURCES *SPI)
* @brief Used to get spi status.
* @note none.
* @param SPI : Pointer to spi resources structure.
* @retval \ref spi driver status.
*/
__STATIC_INLINE ARM_SPI_STATUS ARM_SPI_GetStatus(SPI_RESOURCES *SPI)
{
return SPI->status;
}
/* SPI0 driver instance */
#if RTE_SPI0
#if RTE_SPI0_DMA_ENABLE
static void SPI0_DMACallback(uint32_t event, int8_t peri_num);
static SPI_DMA_HW_CONFIG SPI0_DMA_HW_CONFIG = {
.dma_rx =
{
.dma_drv = &ARM_Driver_DMA_(SPI0_DMA),
.dma_periph_req = SPI0_DMA_RX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = SPI0_DMA,
.group = SPI0_DMA_GROUP,
.channel = SPI0_DMA_RX_PERIPH_REQ,
.enable_handshake = SPI0_DMA_HANDSHAKE_ENABLE,
},
},
.dma_tx =
{
.dma_drv = &ARM_Driver_DMA_(SPI0_DMA),
.dma_periph_req = SPI0_DMA_TX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = SPI0_DMA,
.group = SPI0_DMA_GROUP,
.channel = SPI0_DMA_TX_PERIPH_REQ,
.enable_handshake = SPI0_DMA_HANDSHAKE_ENABLE,
},
},
};
#endif
#if RTE_SPI0_USE_MASTER_SS_SW
/* GPIO driver Instance for SPI0 SW controlled slave select */
extern ARM_DRIVER_GPIO ARM_Driver_GPIO_(RTE_SPI0_SW_SPI_PORT);
#endif
static SPI_RESOURCES SPI0_RES = {
.regs = (SPI_Type*) SPI0_BASE,
.cb_event = NULL,
.irq_priority = RTE_SPI0_IRQ_PRIORITY,
.drv_instance = SPI_INSTANCE_0,
.slave_select = RTE_SPI0_CHIP_SELECTION_PIN,
.tx_fifo_threshold = RTE_SPI0_TX_FIFO_THRESHOLD,
.tx_fifo_start_level = RTE_SPI0_TX_FIFO_LEVEL_TO_START_TRANSFER,
.rx_fifo_threshold = RTE_SPI0_RX_FIFO_THRESHOLD,
.rx_sample_delay = RTE_SPI0_RX_SAMPLE_DELAY,
.sste_enable = RTE_SPI0_SSTE_ENABLE,
.irq = SPI0_IRQ_IRQn,
#if RTE_SPI0_DMA_ENABLE
.dma_enable = RTE_SPI0_DMA_ENABLE,
.dma_irq_priority = RTE_SPI0_DMA_IRQ_PRI,
.dma_cb = SPI0_DMACallback,
.dma_cfg = &SPI0_DMA_HW_CONFIG,
#endif
#if SPI_BLOCKING_MODE_ENABLE
.blocking_mode = RTE_SPI0_BLOCKING_MODE_ENABLE,
#endif
#if RTE_SPI0_USE_MASTER_SS_SW
.sw_config =
{
.ss_port = RTE_SPI0_SW_SPI_PORT,
.ss_pin = RTE_SPI0_SW_SPI_PIN,
.active_polarity = RTE_SPI0_SW_SPI_SS_POLARITY,
.drvGPIO = (ARM_DRIVER_GPIO*) &ARM_Driver_GPIO_(RTE_SPI0_SW_SPI_PORT),
}
#endif
#if RTE_SPI0_MICROWIRE_FRF_ENABLE
.mw_enable = RTE_SPI0_MICROWIRE_FRF_ENABLE,
.mw_config =
{
#if RTE_SPI0_MW_TRANSFER_MODE
.transfer_mode = SPI_MW_TRANSFER_MODE_SEQUANTIAL,
#else
.transfer_mode = SPI_MW_TRANSFER_MODE_NON_SEQUANTIAL,
#endif
.handshake_enable = RTE_SPI0_MW_HANDSAHKE_ENABLE,
.cfs = RTE_SPI0_MW_CFS
}
#endif
};
extern void SPI0_IRQHandler(void);
void SPI0_IRQHandler(void)
{
SPI_IRQ_Handler(&SPI0_RES);
}
#if RTE_SPI0_DMA_ENABLE
void SPI0_DMACallback(uint32_t event, int8_t peri_num)
{
SPI_DMACallback(&SPI0_RES, event, peri_num);
}
#endif
static int32_t ARM_SPI0_Initialize(ARM_SPI_SignalEvent_t cb_event)
{
return ARM_SPI_Initialize(&SPI0_RES, cb_event);
}
static int32_t ARM_SPI0_Uninitialize(void)
{
return ARM_SPI_Uninitialize(&SPI0_RES);
}
static int32_t ARM_SPI0_PowerControl(ARM_POWER_STATE state)
{
return ARM_SPI_PowerControl(&SPI0_RES, state);
}
static int32_t ARM_SPI0_Send(const void *data, uint32_t num)
{
return ARM_SPI_Send(&SPI0_RES, data, num);
}
static int32_t ARM_SPI0_Receive(void *data, uint32_t num)
{
return ARM_SPI_Receive(&SPI0_RES, data, num);
}
static int32_t ARM_SPI0_Transfer(const void *data_out, void *data_in, uint32_t num)
{
return ARM_SPI_Transfer(&SPI0_RES, data_out, data_in, num);
}
static uint32_t ARM_SPI0_GetDataCount(void)
{
return ARM_SPI_GetDataCount(&SPI0_RES);
}
static int32_t ARM_SPI0_Control(uint32_t control, uint32_t arg)
{
return ARM_SPI_Control(&SPI0_RES, control, arg);
}
static ARM_SPI_STATUS ARM_SPI0_GetStatus(void)
{
return ARM_SPI_GetStatus(&SPI0_RES);
}
extern ARM_DRIVER_SPI Driver_SPI0;
ARM_DRIVER_SPI Driver_SPI0 = {
ARM_SPI_GetVersion,
ARM_SPI_GetCapabilities,
ARM_SPI0_Initialize,
ARM_SPI0_Uninitialize,
ARM_SPI0_PowerControl,
ARM_SPI0_Send,
ARM_SPI0_Receive,
ARM_SPI0_Transfer,
ARM_SPI0_GetDataCount,
ARM_SPI0_Control,
ARM_SPI0_GetStatus
};
#endif /* RTE_SPI0 */
/* SPI1 driver instance */
#if RTE_SPI1
#if RTE_SPI1_DMA_ENABLE
static void SPI1_DMACallback(uint32_t event, int8_t peri_num);
static SPI_DMA_HW_CONFIG SPI1_DMA_HW_CONFIG = {
.dma_rx =
{
.dma_drv = &ARM_Driver_DMA_(SPI1_DMA),
.dma_periph_req = SPI1_DMA_RX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = SPI1_DMA,
.group = SPI1_DMA_GROUP,
.channel = SPI1_DMA_RX_PERIPH_REQ,
.enable_handshake = SPI1_DMA_HANDSHAKE_ENABLE,
},
},
.dma_tx =
{
.dma_drv = &ARM_Driver_DMA_(SPI1_DMA),
.dma_periph_req = SPI1_DMA_TX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = SPI1_DMA,
.group = SPI1_DMA_GROUP,
.channel = SPI1_DMA_TX_PERIPH_REQ,
.enable_handshake = SPI1_DMA_HANDSHAKE_ENABLE,
},
},
};
#endif
#if RTE_SPI1_USE_MASTER_SS_SW
/* GPIO driver Instance for SPI1 SW controlled slave select */
extern ARM_DRIVER_GPIO ARM_Driver_GPIO_(RTE_SPI1_SW_SPI_PORT);
#endif
static SPI_RESOURCES SPI1_RES = {
.regs = (SPI_Type*) SPI1_BASE,
.cb_event = NULL,
.irq_priority = RTE_SPI1_IRQ_PRIORITY,
.drv_instance = SPI_INSTANCE_1,
.slave_select = RTE_SPI1_CHIP_SELECTION_PIN,
.tx_fifo_threshold = RTE_SPI1_TX_FIFO_THRESHOLD,
.tx_fifo_start_level = RTE_SPI1_TX_FIFO_LEVEL_TO_START_TRANSFER,
.rx_fifo_threshold = RTE_SPI1_RX_FIFO_THRESHOLD,
.rx_sample_delay = RTE_SPI1_RX_SAMPLE_DELAY,
.sste_enable = RTE_SPI1_SSTE_ENABLE,
.irq = SPI1_IRQ_IRQn,
#if RTE_SPI1_DMA_ENABLE
.dma_enable = RTE_SPI1_DMA_ENABLE,
.dma_irq_priority = RTE_SPI1_DMA_IRQ_PRI,
.dma_cb = SPI1_DMACallback,
.dma_cfg = &SPI1_DMA_HW_CONFIG,
#endif
#if SPI_BLOCKING_MODE_ENABLE
.blocking_mode = RTE_SPI1_BLOCKING_MODE_ENABLE,
#endif
#if RTE_SPI1_USE_MASTER_SS_SW
.sw_config =
{
.ss_port = RTE_SPI1_SW_SPI_PORT,
.ss_pin = RTE_SPI1_SW_SPI_PIN,
.active_polarity = RTE_SPI1_SW_SPI_SS_POLARITY,
.drvGPIO = (ARM_DRIVER_GPIO*) &ARM_Driver_GPIO_(RTE_SPI1_SW_SPI_PORT),
}
#endif
#if RTE_SPI1_MICROWIRE_FRF_ENABLE
.mw_enable = RTE_SPI1_MICROWIRE_FRF_ENABLE,
.mw_config =
{
#if RTE_SPI1_MW_TRANSFER_MODE
.transfer_mode = SPI_MW_TRANSFER_MODE_SEQUANTIAL,
#else
.transfer_mode = SPI_MW_TRANSFER_MODE_NON_SEQUANTIAL,
#endif
.handshake_enable = RTE_SPI1_MW_HANDSAHKE_ENABLE,
.cfs = RTE_SPI1_MW_CFS
}
#endif
};
extern void SPI1_IRQHandler(void);
void SPI1_IRQHandler(void)
{
SPI_IRQ_Handler(&SPI1_RES);
}
#if RTE_SPI1_DMA_ENABLE
void SPI1_DMACallback(uint32_t event, int8_t peri_num)
{
SPI_DMACallback(&SPI1_RES, event, peri_num);
}
#endif
static int32_t ARM_SPI1_Initialize(ARM_SPI_SignalEvent_t cb_event)
{
return ARM_SPI_Initialize(&SPI1_RES, cb_event);
}
static int32_t ARM_SPI1_Uninitialize(void)
{
return ARM_SPI_Uninitialize(&SPI1_RES);
}
static int32_t ARM_SPI1_PowerControl(ARM_POWER_STATE state)
{
return ARM_SPI_PowerControl(&SPI1_RES, state);
}
static int32_t ARM_SPI1_Send(const void *data, uint32_t num)
{
return ARM_SPI_Send(&SPI1_RES, data, num);
}
static int32_t ARM_SPI1_Receive(void *data, uint32_t num)
{
return ARM_SPI_Receive(&SPI1_RES, data, num);
}
static int32_t ARM_SPI1_Transfer(const void *data_out, void *data_in, uint32_t num)
{
return ARM_SPI_Transfer(&SPI1_RES, data_out, data_in, num);
}
static uint32_t ARM_SPI1_GetDataCount(void)
{
return ARM_SPI_GetDataCount(&SPI1_RES);
}
static int32_t ARM_SPI1_Control(uint32_t control, uint32_t arg)
{
return ARM_SPI_Control(&SPI1_RES, control, arg);
}
static ARM_SPI_STATUS ARM_SPI1_GetStatus(void)
{
return ARM_SPI_GetStatus(&SPI1_RES);
}
extern ARM_DRIVER_SPI Driver_SPI1;
ARM_DRIVER_SPI Driver_SPI1 = {
ARM_SPI_GetVersion,
ARM_SPI_GetCapabilities,
ARM_SPI1_Initialize,
ARM_SPI1_Uninitialize,
ARM_SPI1_PowerControl,
ARM_SPI1_Send,
ARM_SPI1_Receive,
ARM_SPI1_Transfer,
ARM_SPI1_GetDataCount,
ARM_SPI1_Control,
ARM_SPI1_GetStatus
};
#endif /* RTE_SPI1 */
/* SPI2 driver instance */
#if RTE_SPI2
#if RTE_SPI2_DMA_ENABLE
static void SPI2_DMACallback(uint32_t event, int8_t peri_num);
static SPI_DMA_HW_CONFIG SPI2_DMA_HW_CONFIG = {
.dma_rx =
{
.dma_drv = &ARM_Driver_DMA_(SPI2_DMA),
.dma_periph_req = SPI2_DMA_RX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = SPI2_DMA,
.group = SPI2_DMA_GROUP,
.channel = SPI2_DMA_RX_PERIPH_REQ,
.enable_handshake = SPI2_DMA_HANDSHAKE_ENABLE,
},
},
.dma_tx =
{
.dma_drv = &ARM_Driver_DMA_(SPI2_DMA),
.dma_periph_req = SPI2_DMA_TX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = SPI2_DMA,
.group = SPI2_DMA_GROUP,
.channel = SPI2_DMA_TX_PERIPH_REQ,
.enable_handshake = SPI2_DMA_HANDSHAKE_ENABLE,
},
},
};
#endif
#if RTE_SPI2_USE_MASTER_SS_SW
/* GPIO driver Instance for SPI2 SW controlled slave select */
extern ARM_DRIVER_GPIO ARM_Driver_GPIO_(RTE_SPI2_SW_SPI_PORT);
#endif
static SPI_RESOURCES SPI2_RES = {
.regs = (SPI_Type*) SPI2_BASE,
.cb_event = NULL,
.irq_priority = RTE_SPI2_IRQ_PRIORITY,
.drv_instance = SPI_INSTANCE_2,
.slave_select = RTE_SPI2_CHIP_SELECTION_PIN,
.tx_fifo_threshold = RTE_SPI2_TX_FIFO_THRESHOLD,
.tx_fifo_start_level = RTE_SPI2_TX_FIFO_LEVEL_TO_START_TRANSFER,
.rx_fifo_threshold = RTE_SPI2_RX_FIFO_THRESHOLD,
.rx_sample_delay = RTE_SPI2_RX_SAMPLE_DELAY,
.sste_enable = RTE_SPI2_SSTE_ENABLE,
.irq = SPI2_IRQ_IRQn,
#if RTE_SPI2_DMA_ENABLE
.dma_enable = RTE_SPI2_DMA_ENABLE,
.dma_irq_priority = RTE_SPI2_DMA_IRQ_PRI,
.dma_cb = SPI2_DMACallback,
.dma_cfg = &SPI2_DMA_HW_CONFIG
#endif
#if SPI_BLOCKING_MODE_ENABLE
.blocking_mode = RTE_SPI2_BLOCKING_MODE_ENABLE,
#endif
#if RTE_SPI2_USE_MASTER_SS_SW
.sw_config =
{
.ss_port = RTE_SPI2_SW_SPI_PORT,
.ss_pin = RTE_SPI2_SW_SPI_PIN,
.active_polarity = RTE_SPI2_SW_SPI_SS_POLARITY,
.drvGPIO = (ARM_DRIVER_GPIO*) &ARM_Driver_GPIO_(RTE_SPI2_SW_SPI_PORT),
}
#endif
#if RTE_SPI2_MICROWIRE_FRF_ENABLE
.mw_enable = RTE_SPI2_MICROWIRE_FRF_ENABLE,
.mw_config =
{
#if RTE_SPI2_MW_TRANSFER_MODE
.transfer_mode = SPI_MW_TRANSFER_MODE_SEQUANTIAL,
#else
.transfer_mode = SPI_MW_TRANSFER_MODE_NON_SEQUANTIAL,
#endif
.handshake_enable = RTE_SPI2_MW_HANDSAHKE_ENABLE,
.cfs = RTE_SPI2_MW_CFS
}
#endif
};
extern void SPI2_IRQHandler(void);
void SPI2_IRQHandler(void)
{
SPI_IRQ_Handler(&SPI2_RES);
}
#if RTE_SPI2_DMA_ENABLE
void SPI2_DMACallback(uint32_t event, int8_t peri_num)
{
SPI_DMACallback(&SPI2_RES, event, peri_num);
}
#endif
static int32_t ARM_SPI2_Initialize(ARM_SPI_SignalEvent_t cb_event)
{
return ARM_SPI_Initialize(&SPI2_RES, cb_event);
}
static int32_t ARM_SPI2_Uninitialize(void)
{
return ARM_SPI_Uninitialize(&SPI2_RES);
}
static int32_t ARM_SPI2_PowerControl(ARM_POWER_STATE state)
{
return ARM_SPI_PowerControl(&SPI2_RES, state);
}
static int32_t ARM_SPI2_Send(const void *data, uint32_t num)
{
return ARM_SPI_Send(&SPI2_RES, data, num);
}
static int32_t ARM_SPI2_Receive(void *data, uint32_t num)
{
return ARM_SPI_Receive(&SPI2_RES, data, num);
}
static int32_t ARM_SPI2_Transfer(const void *data_out, void *data_in, uint32_t num)
{
return ARM_SPI_Transfer(&SPI2_RES, data_out, data_in, num);
}
static uint32_t ARM_SPI2_GetDataCount(void)
{
return ARM_SPI_GetDataCount(&SPI2_RES);
}
static int32_t ARM_SPI2_Control(uint32_t control, uint32_t arg)
{
return ARM_SPI_Control(&SPI2_RES, control, arg);
}
static ARM_SPI_STATUS ARM_SPI2_GetStatus(void)
{
return ARM_SPI_GetStatus(&SPI2_RES);
}
extern ARM_DRIVER_SPI Driver_SPI2;
ARM_DRIVER_SPI Driver_SPI2 = {
ARM_SPI_GetVersion,
ARM_SPI_GetCapabilities,
ARM_SPI2_Initialize,
ARM_SPI2_Uninitialize,
ARM_SPI2_PowerControl,
ARM_SPI2_Send,
ARM_SPI2_Receive,
ARM_SPI2_Transfer,
ARM_SPI2_GetDataCount,
ARM_SPI2_Control,
ARM_SPI2_GetStatus
};
#endif /* RTE_SPI2 */
/* SPI3 driver instance */
#if RTE_SPI3
#if RTE_SPI3_DMA_ENABLE
static void SPI3_DMACallback(uint32_t event, int8_t peri_num);
static SPI_DMA_HW_CONFIG SPI3_DMA_HW_CONFIG = {
.dma_rx =
{
.dma_drv = &ARM_Driver_DMA_(SPI3_DMA),
.dma_periph_req = SPI3_DMA_RX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = SPI3_DMA,
.group = SPI3_DMA_GROUP,
.channel = SPI3_DMA_RX_PERIPH_REQ,
.enable_handshake = SPI3_DMA_HANDSHAKE_ENABLE,
},
},
.dma_tx =
{
.dma_drv = &ARM_Driver_DMA_(SPI3_DMA),
.dma_periph_req = SPI3_DMA_TX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = SPI3_DMA,
.group = SPI3_DMA_GROUP,
.channel = SPI3_DMA_TX_PERIPH_REQ,
.enable_handshake = SPI3_DMA_HANDSHAKE_ENABLE,
},
},
};
#endif
#if RTE_SPI3_USE_MASTER_SS_SW
/* GPIO driver Instance for SPI3 SW controlled slave select */
extern ARM_DRIVER_GPIO ARM_Driver_GPIO_(RTE_SPI3_SW_SPI_PORT);
#endif
static SPI_RESOURCES SPI3_RES = {
.regs = (SPI_Type*) SPI3_BASE,
.cb_event = NULL,
.irq_priority = RTE_SPI3_IRQ_PRIORITY,
.drv_instance = SPI_INSTANCE_3,
.slave_select = RTE_SPI3_CHIP_SELECTION_PIN,
.tx_fifo_threshold = RTE_SPI3_TX_FIFO_THRESHOLD,
.tx_fifo_start_level = RTE_SPI3_TX_FIFO_LEVEL_TO_START_TRANSFER,
.rx_fifo_threshold = RTE_SPI3_RX_FIFO_THRESHOLD,
.rx_sample_delay = RTE_SPI3_RX_SAMPLE_DELAY,
.sste_enable = RTE_SPI3_SSTE_ENABLE,
.irq = SPI3_IRQ_IRQn,
#if RTE_SPI3_DMA_ENABLE
.dma_enable = RTE_SPI3_DMA_ENABLE,
.dma_irq_priority = RTE_SPI3_DMA_IRQ_PRI,
.dma_cb = SPI3_DMACallback,
.dma_cfg = &SPI3_DMA_HW_CONFIG,
#endif
#if SPI_BLOCKING_MODE_ENABLE
.blocking_mode = RTE_SPI3_BLOCKING_MODE_ENABLE,
#endif
#if RTE_SPI3_USE_MASTER_SS_SW
.sw_config =
{
.ss_port = RTE_SPI3_SW_SPI_PORT,
.ss_pin = RTE_SPI3_SW_SPI_PIN,
.active_polarity = RTE_SPI3_SW_SPI_SS_POLARITY,
.drvGPIO = (ARM_DRIVER_GPIO*) &ARM_Driver_GPIO_(RTE_SPI3_SW_SPI_PORT),
}
#endif
#if RTE_SPI3_MICROWIRE_FRF_ENABLE
.mw_enable = RTE_SPI3_MICROWIRE_FRF_ENABLE,
.mw_config =
{
#if RTE_SPI3_MW_TRANSFER_MODE
.transfer_mode = SPI_MW_TRANSFER_MODE_SEQUANTIAL,
#else
.transfer_mode = SPI_MW_TRANSFER_MODE_NON_SEQUANTIAL,
#endif
.handshake_enable = RTE_SPI3_MW_HANDSAHKE_ENABLE,
.cfs = RTE_SPI3_MW_CFS
}
#endif
};
extern void SPI3_IRQHandler(void);
void SPI3_IRQHandler(void)
{
SPI_IRQ_Handler(&SPI3_RES);
}
#if RTE_SPI3_DMA_ENABLE
void SPI3_DMACallback(uint32_t event, int8_t peri_num)
{
SPI_DMACallback(&SPI3_RES, event, peri_num);
}
#endif
static int32_t ARM_SPI3_Initialize(ARM_SPI_SignalEvent_t cb_event)
{
return ARM_SPI_Initialize(&SPI3_RES, cb_event);
}
static int32_t ARM_SPI3_Uninitialize(void)
{
return ARM_SPI_Uninitialize(&SPI3_RES);
}
static int32_t ARM_SPI3_PowerControl(ARM_POWER_STATE state)
{
return ARM_SPI_PowerControl(&SPI3_RES, state);
}
static int32_t ARM_SPI3_Send(const void *data, uint32_t num)
{
return ARM_SPI_Send(&SPI3_RES, data, num);
}
static int32_t ARM_SPI3_Receive(void *data, uint32_t num)
{
return ARM_SPI_Receive(&SPI3_RES, data, num);
}
static int32_t ARM_SPI3_Transfer(const void *data_out, void *data_in, uint32_t num)
{
return ARM_SPI_Transfer(&SPI3_RES, data_out, data_in, num);
}
static uint32_t ARM_SPI3_GetDataCount(void)
{
return ARM_SPI_GetDataCount(&SPI3_RES);
}
static int32_t ARM_SPI3_Control(uint32_t control, uint32_t arg)
{
return ARM_SPI_Control(&SPI3_RES, control, arg);
}
static ARM_SPI_STATUS ARM_SPI3_GetStatus(void)
{
return ARM_SPI_GetStatus(&SPI3_RES);
}
extern ARM_DRIVER_SPI Driver_SPI3;
ARM_DRIVER_SPI Driver_SPI3 = {
ARM_SPI_GetVersion,
ARM_SPI_GetCapabilities,
ARM_SPI3_Initialize,
ARM_SPI3_Uninitialize,
ARM_SPI3_PowerControl,
ARM_SPI3_Send,
ARM_SPI3_Receive,
ARM_SPI3_Transfer,
ARM_SPI3_GetDataCount,
ARM_SPI3_Control,
ARM_SPI3_GetStatus
};
#endif /* RTE_SPI3 */
/* LPSPI driver instance */
#if RTE_LPSPI
#if RTE_LPSPI_DMA_ENABLE
static void LPSPI_DMACallback(uint32_t event, int8_t peri_num);
static SPI_DMA_HW_CONFIG LPSPI_DMA_HW_CONFIG = {
.dma_rx =
{
.dma_drv = &ARM_Driver_DMA_(LPSPI_DMA),
.dma_periph_req = LPSPI_DMA_RX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = LPSPI_DMA,
.group = LPSPI_DMA_GROUP,
.channel = LPSPI_DMA_RX_PERIPH_REQ,
.enable_handshake = LPSPI_DMA_HANDSHAKE_ENABLE,
},
},
.dma_tx =
{
.dma_drv = &ARM_Driver_DMA_(LPSPI_DMA),
.dma_periph_req = LPSPI_DMA_TX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = LPSPI_DMA,
.group = LPSPI_DMA_GROUP,
.channel = LPSPI_DMA_TX_PERIPH_REQ,
.enable_handshake = LPSPI_DMA_HANDSHAKE_ENABLE,
},
},
};
#endif
#if RTE_LPSPI_USE_MASTER_SS_SW
/* GPIO driver Instance for LPSPI SW controlled slave select */
extern ARM_DRIVER_GPIO ARM_Driver_GPIO_(RTE_LPSPI_SW_SPI_PORT);
#endif
static SPI_RESOURCES LPSPI_RES = {
.regs = (SPI_Type*) LPSPI_BASE,
.cb_event = NULL,
.irq_priority = RTE_LPSPI_IRQ_PRIORITY,
.drv_instance = LPSPI_INSTANCE,
.slave_select = RTE_LPSPI_CHIP_SELECTION_PIN,
.tx_fifo_threshold = RTE_LPSPI_TX_FIFO_THRESHOLD,
.tx_fifo_start_level = RTE_LPSPI_TX_FIFO_LEVEL_TO_START_TRANSFER,
.rx_fifo_threshold = RTE_LPSPI_RX_FIFO_THRESHOLD,
.sste_enable = RTE_LPSPI_SSTE_ENABLE,
.irq = LPSPI_IRQ_IRQn,
#if RTE_LPSPI_DMA_ENABLE
.dma_enable = RTE_LPSPI_DMA_ENABLE,
.dma_irq_priority = RTE_LPSPI_DMA_IRQ_PRI,
.dma_cb = LPSPI_DMACallback,
.dma_cfg = &LPSPI_DMA_HW_CONFIG
#endif
#if SPI_BLOCKING_MODE_ENABLE
.blocking_mode = RTE_LPSPI_BLOCKING_MODE_ENABLE,
#endif
#if RTE_LPSPI_USE_MASTER_SS_SW
.sw_config =
{
.ss_port = RTE_LPSPI_SW_SPI_PORT,
.ss_pin = RTE_LPSPI_SW_SPI_PIN,
.active_polarity = RTE_LPSPI_SW_SPI_SS_POLARITY,
.drvGPIO = (ARM_DRIVER_GPIO*) &ARM_Driver_GPIO_(RTE_LPSPI_SW_SPI_PORT),
}
#endif
#if RTE_LPSPI_MICROWIRE_FRF_ENABLE
.mw_enable = RTE_LPSPI_MICROWIRE_FRF_ENABLE,
.mw_config =
{
#if RTE_LPSPI_MW_TRANSFER_MODE
.transfer_mode = SPI_MW_TRANSFER_MODE_SEQUANTIAL,
#else
.transfer_mode = SPI_MW_TRANSFER_MODE_NON_SEQUANTIAL,
#endif
.handshake_enable = RTE_LPSPI_MW_HANDSAHKE_ENABLE,
.cfs = RTE_LPSPI_MW_CFS
}
#endif
};
extern void LPSPI_IRQHandler(void);
void LPSPI_IRQHandler(void)
{
SPI_IRQ_Handler(&LPSPI_RES);
}
#if RTE_LPSPI_DMA_ENABLE
void LPSPI_DMACallback(uint32_t event, int8_t peri_num)
{
SPI_DMACallback(&LPSPI_RES, event, peri_num);
}
#endif
static int32_t ARM_LPSPI_Initialize(ARM_SPI_SignalEvent_t cb_event)
{
return ARM_SPI_Initialize(&LPSPI_RES, cb_event);
}
static int32_t ARM_LPSPI_Uninitialize(void)
{
return ARM_SPI_Uninitialize(&LPSPI_RES);
}
static int32_t ARM_LPSPI_PowerControl(ARM_POWER_STATE state)
{
return ARM_SPI_PowerControl(&LPSPI_RES, state);
}
static int32_t ARM_LPSPI_Send(const void *data, uint32_t num)
{
return ARM_SPI_Send(&LPSPI_RES, data, num);
}
static int32_t ARM_LPSPI_Receive(void *data, uint32_t num)
{
return ARM_SPI_Receive(&LPSPI_RES, data, num);
}
static int32_t ARM_LPSPI_Transfer(const void *data_out, void *data_in, uint32_t num)
{
return ARM_SPI_Transfer(&LPSPI_RES, data_out, data_in, num);
}
static uint32_t ARM_LPSPI_GetDataCount(void)
{
return ARM_SPI_GetDataCount(&LPSPI_RES);
}
static int32_t ARM_LPSPI_Control(uint32_t control, uint32_t arg)
{
return ARM_SPI_Control(&LPSPI_RES, control, arg);
}
static ARM_SPI_STATUS ARM_LPSPI_GetStatus(void)
{
return ARM_SPI_GetStatus(&LPSPI_RES);
}
extern ARM_DRIVER_SPI Driver_SPILP;
ARM_DRIVER_SPI Driver_SPILP = {
ARM_SPI_GetVersion,
ARM_SPI_GetCapabilities,
ARM_LPSPI_Initialize,
ARM_LPSPI_Uninitialize,
ARM_LPSPI_PowerControl,
ARM_LPSPI_Send,
ARM_LPSPI_Receive,
ARM_LPSPI_Transfer,
ARM_LPSPI_GetDataCount,
ARM_LPSPI_Control,
ARM_LPSPI_GetStatus
};
#endif /* RTE_LPSPI */