Peripheral feature
The serial peripheral interface (SPI) module enables full-duplex, synchronous, serial communication between the chip and peripheral devices, including other chips. Software can poll the SPI status flags or SPI operation can be interrupt driven. The block contains six 16-bit memory mapped registers for control parameters, status, and data transfer.
Features of the SPI module include the following:
- Full-duplex operation
- Master and slave modes
- Double-buffered operation with separate transmit and receive registers
- Programmable Length Transactions (2 to 16 bits)
- Programmable transmit and receive shift order (MSB or LSB first)
- Fourteen master mode frequencies (maximum = bus frequency / 2)
- Maximum slave mode frequency = bus frequency / 4
- Serial clock with programmable polarity and phase
- Two separately enabled interrupts:
- SPRF (SPI receiver full)
- SPTE (SPI transmitter empty)
- Mode fault error flag with interrupt capability
- Overflow error flag with interrupt capability
- Wired OR mode functionality enabling connection to multiple SPIs
- Stop mode holdoff
- Separate RX and TX FIFO capable of handling 4 transactions
Signals
- MOSI : Master-Output Slave-Input Pad Pin
- MISO : Master-Input Slave-Output Pad Pin
- SCLK : Slave clock pad pin
- SS : Slave select pad pin (Active Low)
How this driver is designed to make this peripheral works
The Queued SPI driver is provided with 2 parallel layers for different users with different requirements on flexibility, abstraction level: Functional layer and Transactional layer. Do not mix the usage of these layers with one exception that transactional layer need the QSPI_MasterInit and QSPI_SlaveInit. See detail in section transactional- layer-usage-model.
- Functional Layer is provided with highly optimized implementation and highly flexible usage of the peripheral features. All hardware features are supported while requiring user get a decent understanding of the hardware detail so that user know how to organize these functional API together to meet the requirement of application.
- Transactional layer is provided with high abstraction level, limited flexibility / optimization and not all features are covered. It aims at getting user implement Queued SPI transaction with least knowledge requirement of this specific Queued SPI peripheral and least coding effort. It achieves this goal by hiddening the interrupt processing setup inside driver and providing functionaly from transaction level. To distinguish transactional layer for functional layer easily, all transactional API get 'Transfer' in API name.
SPI peripheral is working either as the role of Master or Slave. Functions in both layers get the Master/Slave inside meaning they are prepared for Master or Slave, other wise it apply for both Master/Slave mode.
Functional Layer
This layer provider multiple function API sorted in groups
- Module Init/Deinit
- Module Initialization function for Master or Slave with their help function QSPI_MasterGetDefault and QSPI_SlaveGetDefault.
- Deinitialization is for both Master or Salve.
- FIFO Configuration
- APIs for FIFO relevant features.
- DMA Configuration
- APIs for DMA relevant features.
- Slave Select(SS) Configuration
- APIs for Slave Select (SS) related features.
- Status Flags Get/Clear
- APIs to Get/Clear all supported status flags.
- Interrupt Configuration
- APIs to Enable/Disable interrupts.
- Bus Operation
- APIs for SPI data transfer.
- General Configuration
- APIs for features not covered in above groups.
Transactional Layer
Transactional layer is state retained thus it use the _qspi_master_handle or _qspi_slave_handle to specify the peripheral. User need to initialize the handle by calling QSPI_MasterTransferCreateHandle or QSPI_SlaveTransferCreateHandle.
Transactional layer abstract the provided functionality in transaction level rather than peripheral register level. The background knowledgement requested from user is the common SPI transaction model with optional peripheral specific transfer configuration for transaction. This layer use the data structure _qspi_transfer to describe a transfer
- Tranmit data buffer if applicable
- Receive data buffer if applicable
- Size of Transmit/Receive buffer
- Peripheral specific configuration from _qspi_master_transfer_flag
Transaction get 2 modes: Blocking and NonBlocking. Blocking is using the polling mode while NonBlocking using the interrupt or DMA. In Blocking mode, not context need to be kept on return of the function calling thus handle parameter is not needed.
Transactional layer greatly simplify the interrupt handling coding efforts
- Interrupt handling codes are automatically active when user get this driver files into application project. This is provided by the 'double weak' mechanism. You can find the detail in the general section of API Reference Manual. In breif, SDK place a weak function A in the vector entry for this periperhal. The default implementation of this function call another weak function B. By default, when a interrupt happen, the code will be executed as A (Weak) -> B (Weak). This driver provide the function B thus once user get the driver file into the application project, when interrupt happend, code will be executed as A (Weak) -> B (Non-Weak, in this driver) thus user is no longer need to do with the interrupt handling himself. If user get his/her own requirement of interrupt handling, define the A in the application and interrupt will be routed to his/her own interrupt function.
- Hidden interrupt handling doesn't mean user get no chance to insert his/her processing logic in the interrupt handling. User is requested to provide the callback function on QSPI_MasterCreateHandle or QSPI_SlaveTransferCreateHandle and when interrupt happens, callback will be invoked immediately that user codes can be executed when interrupt happens. In the callback, user code will be notified about status code from _qspi_status or _common_status of the transaction requested.
This layer provider multiple function API sorted in groups
- Master Transaction
- APIs for transaction as Master
- Slave Transaction
- APIs for transaction as Slave
How to use this driver
General Preprocessor Configuraiton Macros
- FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL SDK genneral Macro, controls whether to ungate/gate peripheral's clock source inside driver. Set it to none-zero value then driver will not ungate/gate clock source during initialization/de-initialization.
- QSPI_DUMMY_DATA For transaction receiving with no Transmit data needed, DUMMY data specify the data to be put in the MOSI as master or MISO as slave. By default, it is all 0 bit.
Configuration Items Before Calling Driver APIs
- Mux the QUEUESPI MISO/MOSI/SCLK/SS signals to on-board pins, and configure them with expected port pin feature.
- Select and attach proper clock source to this module.
- Ungate the QUEUESPI clock if user wish to do it outside driver by setting FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL to non-zero value.
- Set the priority base for the IRQ needed by the SPI module.
Functional layer usage model
- Configuration Items Before Calling Driver APIs
- Except the items described in the general part, define the QUEUEDSPI interrupt entry in the application code if interrupt is needed for this peripheral usage.
- Call flow
- Init the module with QSPI_MasterInit or QSPI_SlaveInit. Note QSPI_MasterGetDefaultConfig or QSPI_SlaveGetDefaultConfig can help user to get a ready-to-use init data structure.
- Do the QUEUEDSPI transaction with other functional layer APIs
Transactional layer usage model
- Call flow for Polling-Based Master Transaction
- Init the module with QSPI_MasterInit or QSPI_SlaveInit. Note QSPI_MasterGetDefaultConfig or QSPI_SlaveGetDefaultConfig can help user to get a ready-to-use init data structure.
- Do the transfer with QSPI_MasterTransferBlocking
- Call flow for Polling-Based transaction
- Init the module with QSPI_MasterInit or QSPI_SlaveInit. Note QSPI_MasterGetDefaultConfig or QSPI_SlaveGetDefaultConfig can help user to get a ready-to-use init data structure.
- Init the handle with QSPI_MasterCreateHandle or QSPI_SlaveTransferCreateHandle with callback function registered if applicable
- Do transaction with QSPI_MasterTransferNonBlocking or QSPI_SlaveTransferNonBlocking if applicable
- User can query how many data are transferred by QSPI_MasterGetTranferGetCount or QSPI_SlaveTransferGetCount
- User can abort transaction by QSPI_MasterGetTranferAbort or QSPI_SlaveTransferAbort
Typical Use Cases
NA