| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034 |
- /* --------------------------------------------------------------------------
- * Copyright (c) 2013-2016 ARM Limited. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the License); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * $Date: 13. March 2016
- * $Revision: V2.8
- *
- * Driver: Driver_SPI0, Driver_SPI1
- * Configured: via RTE_Device.h configuration file
- * Project: SPI (SSP used for SPI) Driver for NXP LPC18xx
- * --------------------------------------------------------------------------
- * Use the following configuration settings in the middleware component
- * to connect to this driver.
- *
- * Configuration Setting Value SPI Interface
- * --------------------- ----- -------------
- * Connect to hardware via Driver_SPI# = 0 use SPI0 (SSP0)
- * Connect to hardware via Driver_SPI# = 1 use SPI1 (SSP1)
- * -------------------------------------------------------------------------- */
- /* History:
- * Version 2.8
- * - Corrected Pin Configuration and Unconfiguration
- * Version 2.7
- * - Driver update to work with GPDMA_LPC18xx ver.: 1.3
- * Version 2.6
- * - Corrected Bus Speed configuration
- * - Corrected PowerControl function for conditional Power full (driver must be initialized)
- * Version 2.5
- * - PowerControl for Power OFF and Uninitialize functions made unconditional.
- * - Corrected status bit-field handling, to prevent race conditions.
- * - Corrected ARM_SPI_EVENT_DATA_LOST event handling in slave mode
- * Version 2.4
- * - Corrected ssp->info->mode and pin handling
- * Version 2.3
- * - Updated Control functions
- * - GPDMA initialization and uninitialization
- * Version 2.2
- * - Updated Send and Receive functions to avoid stack corruption
- * Version 2.1
- * - Added DMA support
- * Version 2.0
- * - Initial CMSIS Driver API V2.00 release
- */
- #include <string.h>
- #include "SCU_LPC18xx.h"
- #include "GPIO_LPC18xx.h"
- #include "GPDMA_LPC18xx.h"
- #include "SSP_LPC18xx.h"
- #include "Driver_SPI.h"
- #include "RTE_Device.h"
- #include "RTE_Components.h"
- extern uint32_t GetClockFreq (uint32_t clk_src);
- void SSP0_GPDMA_Tx_SignalEvent (uint32_t event);
- void SSP0_GPDMA_Rx_SignalEvent (uint32_t event);
- void SSP1_GPDMA_Tx_SignalEvent (uint32_t event);
- void SSP1_GPDMA_Rx_SignalEvent (uint32_t event);
- #define ARM_SPI_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(2,8) // driver version
- #if ((defined(RTE_Drivers_SPI0) || defined(RTE_Drivers_SPI1)) && (!RTE_SSP0) && (!RTE_SSP1))
- #error "SSP not configured in RTE_Device.h!"
- #endif
- #if ((RTE_SSP0) && \
- ((RTE_SSP0_DMA_TX_EN && !RTE_SSP0_DMA_RX_EN) || \
- (RTE_SSP0_DMA_RX_EN && !RTE_SSP0_DMA_TX_EN)))
- #error "Both Tx and Rx DMA for SSP0 have to be enabled or disabled in RTE_Device.h!"
- #endif
- #if ((RTE_SSP1) && \
- ((RTE_SSP1_DMA_TX_EN && !RTE_SSP1_DMA_RX_EN) || \
- (RTE_SSP1_DMA_RX_EN && !RTE_SSP1_DMA_TX_EN)))
- #error "Both Tx and Rx DMA for SSP1 have to be enabled or disabled in RTE_Device.h!"
- #endif
- // 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, // Simplex Mode (Master and Slave)
- 1, // TI Synchronous Serial Interface
- 1, // Microwire Interface
- 0 // Signal Mode Fault event: \ref ARM_SPI_EVENT_MODE_FAULT
- };
- #if (RTE_SSP0)
- static SSP_INFO SSP0_Info = { 0 };
- static SSP_TRANSFER_INFO SSP0_Xfer;
- static PIN_ID SSP0_pin_sck = { RTE_SSP0_SCK_PORT, RTE_SSP0_SCK_BIT, RTE_SSP0_SCK_FUNC };
- static PIN_ID SSP0_pin_miso = { RTE_SSP0_MISO_PORT, RTE_SSP0_MISO_BIT, RTE_SSP0_MISO_FUNC};
- static PIN_ID SSP0_pin_mosi = { RTE_SSP0_MOSI_PORT, RTE_SSP0_MOSI_BIT, RTE_SSP0_MOSI_FUNC};
- #if (RTE_SSP0_SSEL_PIN_EN == 1U)
- static PIN_ID SSP0_pin_ssel = { RTE_SSP0_SSEL_PORT, RTE_SSP0_SSEL_BIT, RTE_SSP0_SSEL_FUNC };
- static GPIO_ID SSP0_gpio_ssel = { RTE_SSP0_SSEL_GPIO_PORT, RTE_SSP0_SSEL_GPIO_BIT};
- #endif
- static SSP_RESOURCES SSP0_Resources = {
- LPC_SSP0,
- { &SSP0_pin_sck,
- &SSP0_pin_miso,
- &SSP0_pin_mosi,
- #if (RTE_SSP0_SSEL_PIN_EN == 1U)
- &SSP0_pin_ssel,
- &SSP0_gpio_ssel,
- RTE_SSP0_SSEL_GPIO_FUNC,
- #else
- NULL,
- NULL,
- 0,
- #endif
- },
- { CGU_BASE_SSPx_CLK_AUTOBLOCK | ((CLK_SRC_PLL1 << 24) & CGU_BASE_SSPx_CLK_CLK_SEL),
- &(LPC_CGU->BASE_SSP0_CLK),
- CCU1_CLK_M3_SSPx_CFG_AUTO | CCU1_CLK_M3_SSPx_CFG_RUN,
- &(LPC_CCU1->CLK_M3_SSP0_CFG),
- CCU1_CLK_M3_SSPx_STAT_RUN,
- &(LPC_CCU1->CLK_M3_SSP0_STAT) },
- { RGU_RESET_CTRL1_SSP0_RST,
- &(LPC_RGU->RESET_CTRL1),
- RGU_RESET_ACTIVE_STATUS1_SSP0_RST,
- &(LPC_RGU->RESET_ACTIVE_STATUS1) },
- { RTE_SSP0_DMA_TX_EN,
- RTE_SSP0_DMA_TX_CH,
- RTE_SSP0_DMA_TX_PERI,
- RTE_SSP0_DMA_TX_PERI_SEL,
- SSP0_GPDMA_Tx_SignalEvent,
- RTE_SSP0_DMA_RX_EN,
- RTE_SSP0_DMA_RX_CH,
- RTE_SSP0_DMA_RX_PERI,
- RTE_SSP0_DMA_RX_PERI_SEL,
- SSP0_GPDMA_Rx_SignalEvent },
- SSP0_IRQn,
- &SSP0_Info,
- &SSP0_Xfer
- };
- #endif
- #if (RTE_SSP1)
- static SSP_INFO SSP1_Info = { 0 };
- static SSP_TRANSFER_INFO SSP1_Xfer;
- static PIN_ID SSP1_pin_sck = { RTE_SSP1_SCK_PORT, RTE_SSP1_SCK_BIT, RTE_SSP1_SCK_FUNC };
- static PIN_ID SSP1_pin_miso = { RTE_SSP1_MISO_PORT, RTE_SSP1_MISO_BIT, RTE_SSP1_MISO_FUNC};
- static PIN_ID SSP1_pin_mosi = { RTE_SSP1_MOSI_PORT, RTE_SSP1_MOSI_BIT, RTE_SSP1_MOSI_FUNC};
- #if (RTE_SSP1_SSEL_PIN_EN == 1U)
- static PIN_ID SSP1_pin_ssel = { RTE_SSP1_SSEL_PORT, RTE_SSP1_SSEL_BIT, RTE_SSP1_SSEL_FUNC };
- static GPIO_ID SSP1_gpio_ssel = { RTE_SSP1_SSEL_GPIO_PORT, RTE_SSP1_SSEL_GPIO_BIT};
- #endif
- static SSP_RESOURCES SSP1_Resources = {
- LPC_SSP1,
- { &SSP1_pin_sck,
- &SSP1_pin_miso,
- &SSP1_pin_mosi,
- #if (RTE_SSP1_SSEL_PIN_EN == 1U)
- &SSP1_pin_ssel,
- &SSP1_gpio_ssel,
- RTE_SSP1_SSEL_GPIO_FUNC,
- #else
- NULL,
- NULL,
- 0,
- #endif
- },
- { CGU_BASE_SSPx_CLK_AUTOBLOCK | ((CLK_SRC_PLL1 << 24) & CGU_BASE_SSPx_CLK_CLK_SEL),
- &(LPC_CGU->BASE_SSP1_CLK),
- CCU1_CLK_M3_SSPx_CFG_AUTO | CCU1_CLK_M3_SSPx_CFG_RUN,
- &(LPC_CCU1->CLK_M3_SSP1_CFG),
- CCU1_CLK_M3_SSPx_STAT_RUN,
- &(LPC_CCU1->CLK_M3_SSP1_STAT) },
- { RGU_RESET_CTRL1_SSP1_RST,
- &(LPC_RGU->RESET_CTRL1),
- RGU_RESET_ACTIVE_STATUS1_SSP1_RST,
- &(LPC_RGU->RESET_ACTIVE_STATUS1) },
- { RTE_SSP1_DMA_TX_EN,
- RTE_SSP1_DMA_TX_CH,
- RTE_SSP1_DMA_TX_PERI,
- RTE_SSP1_DMA_TX_PERI_SEL,
- SSP1_GPDMA_Tx_SignalEvent,
- RTE_SSP1_DMA_RX_EN,
- RTE_SSP1_DMA_RX_CH,
- RTE_SSP1_DMA_RX_PERI,
- RTE_SSP1_DMA_RX_PERI_SEL,
- SSP1_GPDMA_Rx_SignalEvent },
- SSP1_IRQn,
- &SSP1_Info,
- &SSP1_Xfer
- };
- #endif
- /**
- \fn ARM_DRIVER_VERSION SSP_GetVersion (void)
- \brief Get SSP driver version.
- \return \ref ARM_DRV_VERSION
- */
- static ARM_DRIVER_VERSION SSP_GetVersion (void) {
- return DriverVersion;
- }
- /**
- \fn ARM_SPI_CAPABILITIES SSP_GetCapabilities (void)
- \brief Get driver capabilities.
- \return \ref ARM_SPI_CAPABILITIES
- */
- static ARM_SPI_CAPABILITIES SSP_GetCapabilities (void) {
- return DriverCapabilities;
- }
- /**
- \fn int32_t SSPx_Initialize (ARM_SPI_SignalEvent_t cb_event, SSP_RESOURCES *ssp)
- \brief Initialize SSP Interface.
- \param[in] cb_event Pointer to \ref ARM_SPI_SignalEvent
- \param[in] ssp Pointer to SSP resources
- \return \ref execution_status
- */
- static int32_t SSPx_Initialize (ARM_SPI_SignalEvent_t cb_event, SSP_RESOURCES *ssp) {
- uint32_t val;
- if (ssp->info->state & SSP_INITIALIZED) { return ARM_DRIVER_OK; }
- // Initialize SSP Run-Time Resources
- ssp->info->cb_event = cb_event;
- ssp->info->status.busy = 0U;
- ssp->info->status.data_lost = 0U;
- ssp->info->status.mode_fault = 0U;
- // Clear transfer information
- memset(ssp->xfer, 0, sizeof(SSP_TRANSFER_INFO));
- // Configure pins
- val = SCU_PIN_CFG_PULLUP_DIS | SCU_PIN_CFG_HIGH_SPEED_SLEW_RATE_EN | SCU_PIN_CFG_INPUT_BUFFER_EN | SCU_PIN_CFG_INPUT_FILTER_DIS;
- SCU_PinConfigure (ssp->pin.sck->port, ssp->pin.sck->num, ssp->pin.sck->config_val | val);
- if (ssp->pin.sck->port == 16U) { SCU_CLK_PinConfigure (ssp->pin.sck->num, ssp->pin.sck->config_val | val); }
- else { SCU_PinConfigure (ssp->pin.sck->port, ssp->pin.sck->num, ssp->pin.sck->config_val | val); }
- SCU_PinConfigure (ssp->pin.miso->port, ssp->pin.miso->num, ssp->pin.miso->config_val | val);
- SCU_PinConfigure (ssp->pin.mosi->port, ssp->pin.mosi->num, ssp->pin.mosi->config_val | val);
- // Configure DMA if it will be used
- if (ssp->dma.tx_en || ssp->dma.rx_en) { GPDMA_Initialize (); }
- if (ssp->dma.tx_en) { GPDMA_PeripheralSelect (ssp->dma.tx_peri, ssp->dma.tx_peri_sel); }
- if (ssp->dma.rx_en) { GPDMA_PeripheralSelect (ssp->dma.rx_peri, ssp->dma.rx_peri_sel); }
- ssp->info->state = SSP_INITIALIZED; // SSP is initialized
- return ARM_DRIVER_OK;
- }
- /**
- \fn int32_t SSPx_Uninitialize (SSP_RESOURCES *ssp)
- \brief De-initialize SSP Interface.
- \param[in] ssp Pointer to SSP resources
- \return \ref execution_status
- */
- static int32_t SSPx_Uninitialize (SSP_RESOURCES *ssp) {
- // Unconfigure pins
- if (ssp->pin.ssel != NULL) { SCU_PinConfigure (ssp->pin.ssel->port, ssp->pin.ssel->num, 0U); }
- if (ssp->pin.sck->port == 16U) { SCU_CLK_PinConfigure (ssp->pin.sck->num, 0U); }
- else { SCU_PinConfigure (ssp->pin.sck->port, ssp->pin.sck->num, 0U); }
- SCU_PinConfigure (ssp->pin.miso->port, ssp->pin.miso->num, 0U);
- SCU_PinConfigure (ssp->pin.mosi->port, ssp->pin.mosi->num, 0U);
- // Uninitialize DMA
- if (ssp->dma.tx_en || ssp->dma.rx_en) { GPDMA_Uninitialize (); }
- ssp->info->state = 0U; // SSP is uninitialized
- return ARM_DRIVER_OK;
- }
- /**
- \fn int32_t SSPx_PowerControl (ARM_POWER_STATE state, SSP_RESOURCES *ssp)
- \brief Control SSP Interface Power.
- \param[in] state Power state
- \param[in] ssp Pointer to SSP resources
- \return \ref execution_status
- */
- static int32_t SSPx_PowerControl (ARM_POWER_STATE state, SSP_RESOURCES *ssp) {
- switch (state) {
- case ARM_POWER_OFF:
- NVIC_DisableIRQ (ssp->irq_num); // Disable SSP IRQ in NVIC
- if (ssp->info->status.busy) {
- // If DMA mode - disable DMA channel
- if (ssp->dma.tx_en) { GPDMA_ChannelDisable (ssp->dma.tx_ch); }
- // If DMA mode - disable DMA channel
- if (ssp->dma.rx_en) { GPDMA_ChannelDisable (ssp->dma.rx_ch); }
- }
- // Reset SSP peripheral
- *(ssp->rst.reg_cfg) = ssp->rst.reg_cfg_val;
- while (!(*(ssp->rst.reg_stat) & ssp->rst.reg_stat_val));
- if (*(ssp->clk.reg_cfg) == 0U) {
- *(ssp->clk.peri_cfg) = ~1U;
- while ( *(ssp->clk.peri_cfg) & 1U);
- // Power down, clock source set to IRC
- *(ssp->clk.reg_cfg) = 1U | (1U << 24) | (1U << 11);
- }
- // Reset SSP Run-Time Resources
- ssp->info->status.busy = 0U;
- ssp->info->status.data_lost = 0U;
- ssp->info->status.mode_fault = 0U;
- // Clear transfer information
- memset(ssp->xfer, 0, sizeof(SSP_TRANSFER_INFO));
- ssp->info->state &= ~SSP_POWERED; // SSP is not powered
- break;
- case ARM_POWER_FULL:
- if ((ssp->info->state & SSP_INITIALIZED) == 0U) { return ARM_DRIVER_ERROR; }
- if ((ssp->info->state & SSP_POWERED) != 0U) { return ARM_DRIVER_OK; }
- // Initialize SSP register clock
- *(ssp->clk.reg_cfg) = ssp->clk.reg_cfg_val;
- // Activate SSP peripheral clock
- *(ssp->clk.peri_cfg) = ssp->clk.peri_cfg_val;
- while (!(*(ssp->clk.peri_stat) & ssp->clk.peri_stat_val));
- // Reset SSP peripheral
- *(ssp->rst.reg_cfg) = ssp->rst.reg_cfg_val;
- while (!(*(ssp->rst.reg_stat) & ssp->rst.reg_stat_val));
- ssp->reg->IMSC = 0U; // Disable SSP interrupts
- ssp->reg->ICR = 3U; // Clear SSP interrupts
- // Reset SSP Run-Time Resources
- ssp->info->status.busy = 0U;
- ssp->info->status.data_lost = 0U;
- ssp->info->status.mode_fault = 0U;
- ssp->info->state |= SSP_POWERED; // SSP is powered
- // Enable DMA
- if (ssp->dma.tx_en) { ssp->reg->DMACR |= SSPx_DMACR_TXDMAE; }
- if (ssp->dma.rx_en) { ssp->reg->DMACR |= SSPx_DMACR_RXDMAE; }
- NVIC_ClearPendingIRQ (ssp->irq_num);
- NVIC_EnableIRQ (ssp->irq_num); // Enable SSP IRQ in NVIC
- break;
- default:
- return ARM_DRIVER_ERROR_UNSUPPORTED;
- }
- return ARM_DRIVER_OK;
- }
- /**
- \fn int32_t SSPx_Send (const void *data, uint32_t num, SSP_RESOURCES *ssp)
- \brief Start sending data to SSP transmitter.
- \param[in] data Pointer to buffer with data to send to SSP transmitter
- \param[in] num Number of data items to send
- \param[in] ssp Pointer to SSP resources
- \return \ref execution_status
- */
- static int32_t SSPx_Send (const void *data, uint32_t num, SSP_RESOURCES *ssp) {
- static uint32_t dummy_data;
- if ((data == NULL) || (num == 0U)) { return ARM_DRIVER_ERROR_PARAMETER; }
- if (!(ssp->info->state & SSP_CONFIGURED)) { return ARM_DRIVER_ERROR; }
- if ( ssp->info->status.busy) { return ARM_DRIVER_ERROR_BUSY; }
- ssp->info->status.busy = 1U;
- ssp->info->status.data_lost = 0U;
- ssp->info->status.mode_fault = 0U;
- ssp->xfer->rx_buf = NULL;
- ssp->xfer->tx_buf = (uint8_t *)data;
- ssp->xfer->num = num;
- ssp->xfer->rx_cnt = 0U;
- ssp->xfer->tx_cnt = 0U;
- if (ssp->dma.tx_en && ssp->dma.rx_en) {
- if (GPDMA_ChannelConfigure (ssp->dma.rx_ch,
- (uint32_t)&ssp->reg->DR,
- (uint32_t)&dummy_data,
- num,
- GPDMA_CH_CONTROL_SBSIZE(GPDMA_BSIZE_1) |
- GPDMA_CH_CONTROL_DBSIZE(GPDMA_BSIZE_1) |
- GPDMA_CH_CONTROL_SWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
- GPDMA_CH_CONTROL_DWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
- GPDMA_CH_CONTROL_S |
- GPDMA_CH_CONTROL_D |
- GPDMA_CH_CONTROL_I,
- GPDMA_CH_CONFIG_SRC_PERI(ssp->dma.rx_peri) |
- GPDMA_CH_CONFIG_FLOWCNTRL(GPDMA_TRANSFER_P2M_CTRL_DMA) |
- GPDMA_CH_CONFIG_IE |
- GPDMA_CH_CONFIG_ITC |
- GPDMA_CH_CONFIG_E,
- ssp->dma.rx_callback) == -1) {
- return ARM_DRIVER_ERROR;
- }
- if (GPDMA_ChannelConfigure (ssp->dma.tx_ch,
- (uint32_t)data,
- (uint32_t)&ssp->reg->DR,
- num,
- GPDMA_CH_CONTROL_SBSIZE(GPDMA_BSIZE_1) |
- GPDMA_CH_CONTROL_DBSIZE(GPDMA_BSIZE_1) |
- GPDMA_CH_CONTROL_SWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
- GPDMA_CH_CONTROL_DWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
- GPDMA_CH_CONTROL_S |
- GPDMA_CH_CONTROL_D |
- GPDMA_CH_CONTROL_SI |
- GPDMA_CH_CONTROL_I,
- GPDMA_CH_CONFIG_DEST_PERI(ssp->dma.tx_peri) |
- GPDMA_CH_CONFIG_FLOWCNTRL(GPDMA_TRANSFER_M2P_CTRL_DMA) |
- GPDMA_CH_CONFIG_IE |
- GPDMA_CH_CONFIG_ITC |
- GPDMA_CH_CONFIG_E,
- ssp->dma.tx_callback) == -1) {
- return ARM_DRIVER_ERROR;
- }
- } else {
- ssp->reg->IMSC = SSPx_IMSC_TXIM | SSPx_IMSC_RXIM | SSPx_IMSC_RTIM | SSPx_IMSC_RORIM;
- }
- return ARM_DRIVER_OK;
- }
- /**
- \fn int32_t SSPx_Receive (void *data, uint32_t num, SSP_RESOURCES *ssp)
- \brief Start receiving data from SSP receiver.
- \param[out] data Pointer to buffer for data to receive from SSP receiver
- \param[in] num Number of data items to receive
- \param[in] ssp Pointer to SSP resources
- \return \ref execution_status
- */
- static int32_t SSPx_Receive (void *data, uint32_t num, SSP_RESOURCES *ssp) {
- static uint32_t dummy_data;
- if ((data == NULL) || (num == 0U)) { return ARM_DRIVER_ERROR_PARAMETER; }
- if (!(ssp->info->state & SSP_CONFIGURED)) { return ARM_DRIVER_ERROR; }
- if ( ssp->info->status.busy) { return ARM_DRIVER_ERROR_BUSY; }
- ssp->info->status.busy = 1U;
- ssp->info->status.data_lost = 0U;
- ssp->info->status.mode_fault = 0U;
- dummy_data = ssp->xfer->def_val;
- ssp->xfer->rx_buf = (uint8_t *)data;
- ssp->xfer->tx_buf = NULL;
- ssp->xfer->num = num;
- ssp->xfer->rx_cnt = 0U;
- ssp->xfer->tx_cnt = 0U;
- if (ssp->dma.tx_en && ssp->dma.rx_en) {
- if (GPDMA_ChannelConfigure (ssp->dma.rx_ch,
- (uint32_t)&ssp->reg->DR,
- (uint32_t)data,
- num,
- GPDMA_CH_CONTROL_SBSIZE(GPDMA_BSIZE_1) |
- GPDMA_CH_CONTROL_DBSIZE(GPDMA_BSIZE_1) |
- GPDMA_CH_CONTROL_SWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
- GPDMA_CH_CONTROL_DWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
- GPDMA_CH_CONTROL_S |
- GPDMA_CH_CONTROL_D |
- GPDMA_CH_CONTROL_DI |
- GPDMA_CH_CONTROL_I,
- GPDMA_CH_CONFIG_SRC_PERI(ssp->dma.rx_peri) |
- GPDMA_CH_CONFIG_FLOWCNTRL(GPDMA_TRANSFER_P2M_CTRL_DMA) |
- GPDMA_CH_CONFIG_IE |
- GPDMA_CH_CONFIG_ITC |
- GPDMA_CH_CONFIG_E,
- ssp->dma.rx_callback) == -1) {
- return ARM_DRIVER_ERROR;
- }
- if (GPDMA_ChannelConfigure (ssp->dma.tx_ch,
- (uint32_t)&dummy_data,
- (uint32_t)&ssp->reg->DR,
- num,
- GPDMA_CH_CONTROL_SBSIZE(GPDMA_BSIZE_1) |
- GPDMA_CH_CONTROL_DBSIZE(GPDMA_BSIZE_1) |
- GPDMA_CH_CONTROL_SWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
- GPDMA_CH_CONTROL_DWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
- GPDMA_CH_CONTROL_S |
- GPDMA_CH_CONTROL_D |
- GPDMA_CH_CONTROL_I,
- GPDMA_CH_CONFIG_DEST_PERI(ssp->dma.tx_peri) |
- GPDMA_CH_CONFIG_FLOWCNTRL(GPDMA_TRANSFER_M2P_CTRL_DMA) |
- GPDMA_CH_CONFIG_IE |
- GPDMA_CH_CONFIG_ITC |
- GPDMA_CH_CONFIG_E,
- ssp->dma.tx_callback) == -1) {
- return ARM_DRIVER_ERROR;
- }
- } else {
- ssp->reg->IMSC = SSPx_IMSC_TXIM | SSPx_IMSC_RXIM | SSPx_IMSC_RTIM | SSPx_IMSC_RORIM;
- }
- return ARM_DRIVER_OK;
- }
- /**
- \fn int32_t SSPx_Transfer (const void *data_out,
- void *data_in,
- uint32_t num,
- SSP_RESOURCES *ssp)
- \brief Start sending/receiving data to/from SSP transmitter/receiver.
- \param[in] data_out Pointer to buffer with data to send to SSP transmitter
- \param[out] data_in Pointer to buffer for data to receive from SSP receiver
- \param[in] num Number of data items to transfer
- \param[in] ssp Pointer to SSP resources
- \return \ref execution_status
- */
- static int32_t SSPx_Transfer (const void *data_out, void *data_in, uint32_t num, SSP_RESOURCES *ssp) {
- if ((data_out == NULL) || (data_in == NULL) || (num == 0U)) { return ARM_DRIVER_ERROR_PARAMETER; }
- if (!(ssp->info->state & SSP_CONFIGURED)) { return ARM_DRIVER_ERROR; }
- if ( ssp->info->status.busy) { return ARM_DRIVER_ERROR_BUSY; }
- ssp->info->status.busy = 1U;
- ssp->info->status.data_lost = 0U;
- ssp->info->status.mode_fault = 0U;
- ssp->xfer->rx_buf = (uint8_t *)data_in;
- ssp->xfer->tx_buf = (uint8_t *)data_out;
- ssp->xfer->num = num;
- ssp->xfer->rx_cnt = 0U;
- ssp->xfer->tx_cnt = 0U;
- if (ssp->dma.tx_en && ssp->dma.rx_en) {
- if (GPDMA_ChannelConfigure (ssp->dma.rx_ch,
- (uint32_t)&ssp->reg->DR,
- (uint32_t)data_in,
- num,
- GPDMA_CH_CONTROL_SBSIZE(GPDMA_BSIZE_1) |
- GPDMA_CH_CONTROL_DBSIZE(GPDMA_BSIZE_1) |
- GPDMA_CH_CONTROL_SWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
- GPDMA_CH_CONTROL_DWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
- GPDMA_CH_CONTROL_S |
- GPDMA_CH_CONTROL_D |
- GPDMA_CH_CONTROL_DI |
- GPDMA_CH_CONTROL_I,
- GPDMA_CH_CONFIG_SRC_PERI(ssp->dma.rx_peri) |
- GPDMA_CH_CONFIG_FLOWCNTRL(GPDMA_TRANSFER_P2M_CTRL_DMA) |
- GPDMA_CH_CONFIG_IE |
- GPDMA_CH_CONFIG_ITC |
- GPDMA_CH_CONFIG_E,
- ssp->dma.rx_callback) == -1) {
- return ARM_DRIVER_ERROR;
- }
- if (GPDMA_ChannelConfigure (ssp->dma.tx_ch,
- (uint32_t)data_out,
- (uint32_t)&ssp->reg->DR,
- num,
- GPDMA_CH_CONTROL_SBSIZE(GPDMA_BSIZE_1) |
- GPDMA_CH_CONTROL_DBSIZE(GPDMA_BSIZE_1) |
- GPDMA_CH_CONTROL_SWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
- GPDMA_CH_CONTROL_DWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
- GPDMA_CH_CONTROL_S |
- GPDMA_CH_CONTROL_D |
- GPDMA_CH_CONTROL_SI |
- GPDMA_CH_CONTROL_I,
- GPDMA_CH_CONFIG_DEST_PERI(ssp->dma.tx_peri) |
- GPDMA_CH_CONFIG_FLOWCNTRL(GPDMA_TRANSFER_M2P_CTRL_DMA) |
- GPDMA_CH_CONFIG_IE |
- GPDMA_CH_CONFIG_ITC |
- GPDMA_CH_CONFIG_E,
- ssp->dma.tx_callback) == -1) {
- return ARM_DRIVER_ERROR;
- }
- } else {
- ssp->reg->IMSC = SSPx_IMSC_TXIM | SSPx_IMSC_RXIM | SSPx_IMSC_RTIM | SSPx_IMSC_RORIM;
- }
- return ARM_DRIVER_OK;
- }
- /**
- \fn uint32_t SSPx_GetDataCount (SSP_RESOURCES *ssp)
- \brief Get transferred data count.
- \param[in] ssp Pointer to SSP resources
- \return number of data items transferred
- */
- static uint32_t SSPx_GetDataCount (SSP_RESOURCES *ssp) {
- uint32_t cnt;
- if (!(ssp->info->state & SSP_CONFIGURED)) { return 0U; }
- if (ssp->dma.rx_en) {
- cnt = GPDMA_ChannelGetCount (ssp->dma.rx_ch);
- } else {
- cnt = ssp->xfer->rx_cnt;
- }
- return cnt;
- }
- /**
- \fn int32_t SSPx_Control (uint32_t control, uint32_t arg, SSP_RESOURCES *ssp)
- \brief Control SSP Interface.
- \param[in] control Operation
- \param[in] arg Argument of operation (optional)
- \param[in] ssp Pointer to SSP resources
- \return common \ref execution_status and driver specific \ref spi_execution_status
- */
- static int32_t SSPx_Control (uint32_t control, uint32_t arg, SSP_RESOURCES *ssp) {
- uint32_t cpsr, scr, bps = 0U, clk, data_bits;
- uint32_t best_cpsr = 2U, best_scr = 0U, best_bps = 0U;
- if (!(ssp->info->state & SSP_POWERED)) { return ARM_DRIVER_ERROR; }
- if ((control & ARM_SPI_CONTROL_Msk) == ARM_SPI_ABORT_TRANSFER) {
- ssp->reg->CR1 &= ~SSPx_CR1_SSE; // Disable SSP
- ssp->reg->IMSC = 0U; // Disable interrupts
- if (ssp->info->status.busy) {
- // If DMA mode - disable DMA channel
- if (ssp->dma.tx_en) { GPDMA_ChannelDisable (ssp->dma.tx_ch); }
- // If DMA mode - disable DMA channel
- if (ssp->dma.rx_en) { GPDMA_ChannelDisable (ssp->dma.rx_ch); }
- }
- memset(ssp->xfer, 0, sizeof(SSP_TRANSFER_INFO));
- ssp->info->status.busy = 0U;
- ssp->reg->CR1 |= SSPx_CR1_SSE; // Enable SSP
- return ARM_DRIVER_OK;
- }
- if (ssp->info->status.busy) { return ARM_DRIVER_ERROR_BUSY; }
- switch (control & ARM_SPI_CONTROL_Msk) {
- default:
- return ARM_DRIVER_ERROR_UNSUPPORTED;
- case ARM_SPI_MODE_INACTIVE: // SPI Inactive
- ssp->reg->CR1 &= ~SSPx_CR1_SSE; // Disable SSP
- ssp->reg->IMSC = 0U; // Disable interrupts
- ssp->info->mode &= ~ARM_SPI_CONTROL_Msk;
- ssp->info->mode |= ARM_SPI_MODE_INACTIVE;
- ssp->info->state &= ~SSP_CONFIGURED;
- return ARM_DRIVER_OK;
- case ARM_SPI_MODE_MASTER: // SPI Master (Output on MOSI, Input on MISO); arg = Bus Speed in bps
- ssp->reg->CR1 &= ~SSPx_CR1_SSE; // Disable SSP
- ssp->reg->IMSC = 0U; // Disable interrupts
- ssp->reg->CR1 &= ~SSPx_CR1_MS; // Set master mode
- ssp->info->mode &= ~ARM_SPI_CONTROL_Msk;
- ssp->info->mode |= ARM_SPI_MODE_MASTER;
- ssp->info->state |= SSP_CONFIGURED;
- ssp->reg->CR1 |= SSPx_CR1_SSE; // Enable SSP
- goto set_speed;
- case ARM_SPI_MODE_SLAVE: // SPI Slave (Output on MISO, Input on MOSI)
- ssp->reg->CR1 &= ~SSPx_CR1_SSE; // Disable SSP
- ssp->reg->CR1 |= SSPx_CR1_MS; // Set slave mode
- ssp->reg->IMSC = SSPx_IMSC_RORIM; // Enable receive overrun interrupt
- ssp->info->mode &= ~ARM_SPI_CONTROL_Msk;
- ssp->info->mode |= ARM_SPI_MODE_SLAVE;
- ssp->info->state |= SSP_CONFIGURED;
- ssp->reg->CR1 |= SSPx_CR1_SSE; // Enable SSP
- break;
- case ARM_SPI_MODE_MASTER_SIMPLEX: // SPI Master (Output/Input on MOSI); arg = Bus Speed in bps
- case ARM_SPI_MODE_SLAVE_SIMPLEX: // SPI Slave (Output/Input on MISO)
- return ARM_SPI_ERROR_MODE;
- case ARM_SPI_SET_BUS_SPEED: // Set Bus Speed in bps; arg = value
- set_speed:
- if (arg == 0U) {
- return ARM_DRIVER_ERROR;
- }
- clk = GetClockFreq(CLK_SRC_PLL1) << 4;
- arg = (arg << 4);
- for (cpsr = 2U; cpsr < 255U; cpsr+= 2U) {// Loop through clock prescaler
- for (scr = 0U; scr < 256U; scr++) { // Loop through bit prescaler
- bps = clk / (cpsr * (scr + 1U));
- if (arg == bps) {
- best_bps = bps;
- best_cpsr = cpsr;
- best_scr = scr;
- goto found_best;
- } else {
- if (arg > bps) {
- if ((arg - best_bps) > (arg - bps)) {
- best_bps = bps;
- best_cpsr = cpsr;
- best_scr = scr;
- }
- }
- }
- }
- }
- if (best_bps == 0U) {
- return ARM_DRIVER_ERROR;
- }
- found_best:
- ssp->reg->CPSR = best_cpsr & SSPx_CPSR_CPSDVSR;
- ssp->reg->CR0 &= ~SSPx_CR0_SCR;
- ssp->reg->CR0 |= ((best_scr << 8) & SSPx_CR0_SCR);
- if ((control & ARM_SPI_CONTROL_Msk) == ARM_SPI_SET_BUS_SPEED) {
- return ARM_DRIVER_OK;
- }
- break;
- case ARM_SPI_GET_BUS_SPEED: // Get Bus Speed in bps
- return (GetClockFreq(CLK_SRC_PLL1) / ((ssp->reg->CPSR & SSPx_CPSR_CPSDVSR) * (((ssp->reg->CR0 & SSPx_CR0_SCR) >> 8) + 1U)));
- case ARM_SPI_SET_DEFAULT_TX_VALUE: // Set default Transmit value; arg = value
- ssp->xfer->def_val = (uint16_t)(arg & 0xFFFF);
- return ARM_DRIVER_OK;
- case ARM_SPI_CONTROL_SS: // Control Slave Select; arg = 0:inactive, 1:active
- if (((ssp->info->mode & ARM_SPI_CONTROL_Msk) != ARM_SPI_MODE_MASTER) ||
- ((ssp->info->mode & ARM_SPI_SS_MASTER_MODE_Msk) != ARM_SPI_SS_MASTER_SW)) {
- return ARM_DRIVER_ERROR;
- }
- if (ssp->pin.ssel == NULL) {
- return ARM_DRIVER_ERROR;
- }
- if (arg == ARM_SPI_SS_INACTIVE) {
- GPIO_PinWrite (ssp->pin.gpio_ssel->port, ssp->pin.gpio_ssel->num, 1U);
- } else {
- GPIO_PinWrite (ssp->pin.gpio_ssel->port, ssp->pin.gpio_ssel->num, 0U);
- }
- return ARM_DRIVER_OK;
- }
- if ((ssp->info->mode & ARM_SPI_CONTROL_Msk) == ARM_SPI_MODE_MASTER) {
- switch (control & ARM_SPI_SS_MASTER_MODE_Msk) {
- case ARM_SPI_SS_MASTER_UNUSED: // SPI Slave Select when Master: Not used (default)
- if (ssp->pin.ssel != NULL) { SCU_PinConfigure (ssp->pin.ssel->port, ssp->pin.ssel->num, 0U); }
- ssp->info->mode &= ~ARM_SPI_SS_MASTER_MODE_Msk;
- ssp->info->mode |= ARM_SPI_SS_MASTER_UNUSED;
- break;
- case ARM_SPI_SS_MASTER_HW_INPUT: // SPI Slave Select when Master: Hardware monitored Input
- ssp->info->mode &= ~ARM_SPI_SS_MASTER_MODE_Msk;
- return ARM_SPI_ERROR_SS_MODE;
- case ARM_SPI_SS_MASTER_SW: // SPI Slave Select when Master: Software controlled
- ssp->info->mode &= ~ARM_SPI_SS_MASTER_MODE_Msk;
- if (ssp->pin.ssel != NULL) {
- SCU_PinConfigure (ssp->pin.ssel->port, ssp->pin.ssel->num, ssp->pin.gpio_ssel_af |
- SCU_PIN_CFG_PULLUP_DIS |
- SCU_PIN_CFG_HIGH_SPEED_SLEW_RATE_EN );
- GPIO_SetDir (ssp->pin.gpio_ssel->port, ssp->pin.gpio_ssel->num, GPIO_DIR_OUTPUT);
- GPIO_PinWrite (ssp->pin.gpio_ssel->port, ssp->pin.gpio_ssel->num, 1);
- ssp->info->mode |= ARM_SPI_SS_MASTER_SW;
- } else {
- return ARM_SPI_ERROR_SS_MODE;
- }
- break;
- case ARM_SPI_SS_MASTER_HW_OUTPUT: // SPI Slave Select when Master: Hardware controlled Output
- ssp->info->mode &= ~ARM_SPI_SS_MASTER_MODE_Msk;
- if (ssp->pin.ssel != NULL) {
- SCU_PinConfigure (ssp->pin.ssel->port, ssp->pin.ssel->num, ssp->pin.ssel->config_val |
- SCU_PIN_CFG_PULLUP_DIS |
- SCU_PIN_CFG_HIGH_SPEED_SLEW_RATE_EN );
- ssp->info->mode |= ARM_SPI_SS_MASTER_HW_OUTPUT;
- } else {
- return ARM_SPI_ERROR_SS_MODE;
- }
- default:
- break;
- }
- }
- if ((ssp->info->mode & ARM_SPI_CONTROL_Msk) == ARM_SPI_MODE_SLAVE) {
- switch (control & ARM_SPI_SS_SLAVE_MODE_Msk) {
- case ARM_SPI_SS_SLAVE_HW: // SPI Slave Select when Slave: Hardware monitored (default)
- ssp->info->mode &= ~ARM_SPI_SS_SLAVE_MODE_Msk;
- if (ssp->pin.ssel != NULL) {
- SCU_PinConfigure (ssp->pin.ssel->port, ssp->pin.ssel->num, ssp->pin.ssel->config_val |
- SCU_PIN_CFG_PULLUP_DIS |
- SCU_PIN_CFG_HIGH_SPEED_SLEW_RATE_EN |
- SCU_PIN_CFG_INPUT_BUFFER_EN |
- SCU_PIN_CFG_INPUT_FILTER_DIS );
- ssp->info->mode |= ARM_SPI_SS_SLAVE_HW;
- } else {
- return ARM_SPI_ERROR_SS_MODE;
- }
- break;
- case ARM_SPI_SS_SLAVE_SW: // SPI Slave Select when Slave: Software controlled
- ssp->info->mode &= ~ARM_SPI_SS_SLAVE_MODE_Msk;
- return ARM_SPI_ERROR_SS_MODE;
- default: return ARM_SPI_ERROR_SS_MODE;
- }
- }
- // Configure Frame Format
- switch (control & ARM_SPI_FRAME_FORMAT_Msk) {
- case ARM_SPI_CPOL0_CPHA0:
- ssp->reg->CR0 &= ~SSPx_CR0_FRF;
- ssp->reg->CR0 &= ~(SSPx_CR0_CPOL | SSPx_CR0_CPHA);
- break;
- case ARM_SPI_CPOL0_CPHA1:
- ssp->reg->CR0 &= ~SSPx_CR0_FRF;
- ssp->reg->CR0 &= ~SSPx_CR0_CPOL;
- ssp->reg->CR0 |= SSPx_CR0_CPHA;
- break;
- case ARM_SPI_CPOL1_CPHA0:
- ssp->reg->CR0 &= ~SSPx_CR0_FRF;
- ssp->reg->CR0 |= SSPx_CR0_CPOL;
- ssp->reg->CR0 &= ~SSPx_CR0_CPHA;
- break;
- case ARM_SPI_CPOL1_CPHA1:
- ssp->reg->CR0 &= ~SSPx_CR0_FRF;
- ssp->reg->CR0 |= (SSPx_CR0_CPOL | SSPx_CR0_CPHA);
- break;
- case ARM_SPI_TI_SSI:
- ssp->reg->CR0 = (ssp->reg->CR0 & (~SSPx_CR0_FRF)) | (1U << 4);
- break;
- case ARM_SPI_MICROWIRE:
- ssp->reg->CR0 = (ssp->reg->CR0 & (~SSPx_CR0_FRF)) | (2U << 4);
- break;
- default:
- return ARM_SPI_ERROR_FRAME_FORMAT;
- }
- // Configure Number of Data Bits
- data_bits = ((control & ARM_SPI_DATA_BITS_Msk) >> ARM_SPI_DATA_BITS_Pos);
- if ((data_bits >= 4U) && (data_bits <= 16U)) {
- ssp->reg->CR0 = (ssp->reg->CR0 & (~SSPx_CR0_DSS)) | ((data_bits - 1U) << 0);
- } else {
- return ARM_SPI_ERROR_DATA_BITS;
- }
- // Configure Bit Order
- if ((control & ARM_SPI_BIT_ORDER_Msk) == ARM_SPI_LSB_MSB) {
- return ARM_SPI_ERROR_BIT_ORDER;
- }
- return ARM_DRIVER_OK;
- }
- /**
- \fn ARM_SPI_STATUS SSPx_GetStatus (SSP_RESOURCES *ssp)
- \brief Get SSP status.
- \param[in] ssp Pointer to SSP resources
- \return SPI status \ref ARM_SPI_STATUS
- */
- static ARM_SPI_STATUS SSPx_GetStatus (SSP_RESOURCES *ssp) {
- ARM_SPI_STATUS status;
- status.busy = ssp->info->status.busy;
- status.data_lost = ssp->info->status.data_lost;
- status.mode_fault = ssp->info->status.mode_fault;
- return (status);
- }
- /**
- \fn void SSPx_GPDMA_Tx_SignalEvent (uint32_t event, SSP_RESOURCES *ssp)
- \brief SSP GPDMA Tx Event handler.
- \param[in] event GPDMA Tx Event
- \param[in] ssp Pointer to SSP resources
- */
- void SSPx_GPDMA_Tx_SignalEvent (uint32_t event, SSP_RESOURCES *ssp) {
- switch (event) {
- case GPDMA_EVENT_TERMINAL_COUNT_REQUEST:
- ssp->xfer->tx_cnt = ssp->xfer->num;
- break;
- case GPDMA_EVENT_ERROR:
- default:
- break;
- }
- }
- /**
- \fn void SSPx_GPDMA_Rx_SignalEvent (uint32_t event, SSP_RESOURCES *ssp)
- \brief SSP GPDMA Rx Event handler.
- \param[in] event GPDMA Rx Event
- \param[in] ssp Pointer to SSP resources
- */
- void SSPx_GPDMA_Rx_SignalEvent (uint32_t event, SSP_RESOURCES *ssp) {
- switch (event) {
- case GPDMA_EVENT_TERMINAL_COUNT_REQUEST:
- ssp->xfer->rx_cnt = ssp->xfer->num;
- ssp->info->status.busy = 0U;
- if (ssp->info->cb_event) {
- ssp->info->cb_event(ARM_SPI_EVENT_TRANSFER_COMPLETE);
- }
- break;
- case GPDMA_EVENT_ERROR:
- default:
- break;
- }
- }
- /**
- \fn void SSPx_IRQHandler (SSP_RESOURCES *ssp)
- \brief SSP Interrupt handler.
- \param[in] ssp Pointer to SSP resources
- */
- static void SSPx_IRQHandler (SSP_RESOURCES *ssp) {
- uint16_t data;
- uint32_t mis;
- mis = ssp->reg->MIS;
- ssp->reg->ICR = mis & 3U;
- // Handle transfer
- if ((ssp->reg->SR & SSPx_SR_TNF) && (ssp->xfer->num > ssp->xfer->tx_cnt)) {
- if (ssp->xfer->tx_buf) { // If data available
- data = *(ssp->xfer->tx_buf++);
- if ((ssp->reg->CR0 & SSPx_CR0_DSS) > 7U) { // If 9..16-bit data frame format
- data |= *(ssp->xfer->tx_buf++) << 8;
- }
- } else { // If default data send
- data = ssp->xfer->def_val;
- }
- ssp->reg->DR = data; // Activate send
- ssp->xfer->tx_cnt++;
- }
- if (ssp->reg->SR & SSPx_SR_RNE) {
- data = ssp->reg->DR; // Read data
- if (ssp->xfer->num > ssp->xfer->rx_cnt) {
- if (ssp->xfer->rx_buf) {
- *(ssp->xfer->rx_buf++) = (uint8_t)data; // Put data into buffer
- if ((ssp->reg->CR0 & SSPx_CR0_DSS) > 7U) { // If 9..16-bit data frame format
- *(ssp->xfer->rx_buf++) = (uint8_t)(data >> 8);
- }
- }
- ssp->xfer->rx_cnt++;
- if (ssp->xfer->rx_cnt == ssp->xfer->num) { // If all data received
- ssp->reg->IMSC &= ~(SSPx_IMSC_TXIM | SSPx_IMSC_RXIM | SSPx_IMSC_RTIM | SSPx_IMSC_RORIM);
- ssp->info->status.busy = 0U;
- if (ssp->info->cb_event) { ssp->info->cb_event(ARM_SPI_EVENT_TRANSFER_COMPLETE); }
- }
- }
- }
- if (mis & SSPx_MIS_RORMIS) { // Handle errors
- // Overrun flag is set
- ssp->info->status.data_lost = 1U;
- if (ssp->info->cb_event) { ssp->info->cb_event(ARM_SPI_EVENT_DATA_LOST); }
- }
- }
- #if (RTE_SSP0)
- static int32_t SSP0_Initialize (ARM_SPI_SignalEvent_t pSignalEvent) { return SSPx_Initialize (pSignalEvent, &SSP0_Resources); }
- static int32_t SSP0_Uninitialize (void) { return SSPx_Uninitialize (&SSP0_Resources); }
- static int32_t SSP0_PowerControl (ARM_POWER_STATE state) { return SSPx_PowerControl (state, &SSP0_Resources); }
- static int32_t SSP0_Send (const void *data, uint32_t num) { return SSPx_Send (data, num, &SSP0_Resources); }
- static int32_t SSP0_Receive (void *data, uint32_t num) { return SSPx_Receive (data, num, &SSP0_Resources); }
- static int32_t SSP0_Transfer (const void *data_out, void *data_in, uint32_t num) { return SSPx_Transfer (data_out, data_in, num, &SSP0_Resources); }
- static uint32_t SSP0_GetDataCount (void) { return SSPx_GetDataCount (&SSP0_Resources); }
- static int32_t SSP0_Control (uint32_t control, uint32_t arg) { return SSPx_Control (control, arg, &SSP0_Resources); }
- static ARM_SPI_STATUS SSP0_GetStatus (void) { return SSPx_GetStatus (&SSP0_Resources); }
- void SSP0_GPDMA_Tx_SignalEvent(uint32_t event) { SSPx_GPDMA_Tx_SignalEvent(event, &SSP0_Resources); }
- void SSP0_GPDMA_Rx_SignalEvent(uint32_t event) { SSPx_GPDMA_Rx_SignalEvent(event, &SSP0_Resources); }
- void SSP0_IRQHandler (void) { SSPx_IRQHandler (&SSP0_Resources); }
- // SPI0 Driver Control Block
- ARM_DRIVER_SPI Driver_SPI0 = {
- SSP_GetVersion,
- SSP_GetCapabilities,
- SSP0_Initialize,
- SSP0_Uninitialize,
- SSP0_PowerControl,
- SSP0_Send,
- SSP0_Receive,
- SSP0_Transfer,
- SSP0_GetDataCount,
- SSP0_Control,
- SSP0_GetStatus
- };
- #endif
- #if (RTE_SSP1)
- static int32_t SSP1_Initialize (ARM_SPI_SignalEvent_t pSignalEvent) { return SSPx_Initialize (pSignalEvent, &SSP1_Resources); }
- static int32_t SSP1_Uninitialize (void) { return SSPx_Uninitialize (&SSP1_Resources); }
- static int32_t SSP1_PowerControl (ARM_POWER_STATE state) { return SSPx_PowerControl (state, &SSP1_Resources); }
- static int32_t SSP1_Send (const void *data, uint32_t num) { return SSPx_Send (data, num, &SSP1_Resources); }
- static int32_t SSP1_Receive (void *data, uint32_t num) { return SSPx_Receive (data, num, &SSP1_Resources); }
- static int32_t SSP1_Transfer (const void *data_out, void *data_in, uint32_t num) { return SSPx_Transfer (data_out, data_in, num, &SSP1_Resources); }
- static uint32_t SSP1_GetDataCount (void) { return SSPx_GetDataCount (&SSP1_Resources); }
- static int32_t SSP1_Control (uint32_t control, uint32_t arg) { return SSPx_Control (control, arg, &SSP1_Resources); }
- static ARM_SPI_STATUS SSP1_GetStatus (void) { return SSPx_GetStatus (&SSP1_Resources); }
- void SSP1_GPDMA_Tx_SignalEvent(uint32_t event) { SSPx_GPDMA_Tx_SignalEvent(event, &SSP1_Resources); }
- void SSP1_GPDMA_Rx_SignalEvent(uint32_t event) { SSPx_GPDMA_Rx_SignalEvent(event, &SSP1_Resources); }
- void SSP1_IRQHandler (void) { SSPx_IRQHandler (&SSP1_Resources); }
- // SPI1 Driver Control Block
- ARM_DRIVER_SPI Driver_SPI1 = {
- SSP_GetVersion,
- SSP_GetCapabilities,
- SSP1_Initialize,
- SSP1_Uninitialize,
- SSP1_PowerControl,
- SSP1_Send,
- SSP1_Receive,
- SSP1_Transfer,
- SSP1_GetDataCount,
- SSP1_Control,
- SSP1_GetStatus
- };
- #endif
|