1 /*******************************************************************************
2  * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  *
24  * PolarFire SoC Microprocessor Subsystem SPI bare metal software
25  * driver public API.
26  */
27 /*=========================================================================*//**
28   @mainpage PolarFire SoC MSS SPI Bare Metal Driver.
29 
30   @section intro_sec Introduction
31   The PolarFire SoC Microprocessor Subsystem (MSS) includes two serial
32   peripheral interface (SPI) peripherals for serial communication. This driver
33   provides a set of functions for controlling the MSS SPIs as part of a bare
34   metal system where no operating system is available. These drivers can be
35   adapted for use as part of an operating system, but the implementation of the
36   adaptation layer between this driver and the operating system's driver model
37   is outside the scope of this driver.
38 
39   @section hw_dependencies Hardware Flow Dependencies
40   The configuration of all features of the MSS SPI peripherals is covered by
41   this driver with the exception of the PolarFire SoC IOMUX configuration.
42   PolarFire SoC allows multiple non-concurrent uses of some external pins through
43   IOMUX configuration. This feature allows optimization of external pin usage by
44   assigning external pins for use by either the microprocessor subsystem or the
45   FPGA fabric. The MSS SPI serial signals are routed through IOMUXs to the
46   PolarFire SoC device external pins. The MSS SPI serial signals may also be
47   routed through IOMUXs to the PolarFire SoC FPGA fabric.
48   The IOMUXs are configured using the PolarFire SoC MSS configurator tool. You
49   must ensure that the MSS SPI peripherals are enabled and configured in the
50   PolarFire SoC MSS configurator if you wish to use them. For more information
51   on IOMUX, refer to the I/O Configuration section of the PolarFire SoC
52   Microprocessor Subsystem (MSS) User's Guide.
53   The base address, register addresses and interrupt number assignment for the
54   MSS SPI peripherals are defined as constants in the PolarFire SoC HAL.
55   You must ensure that the latest PolarFire SoC HAL is included in the
56   project settings of the software tool chain used to build your project and
57   that it is generated into your project.
58 
59   @section theory_op Theory of Operation
60 The MSS SPI driver functions are grouped in following categories:
61     •   Initialization
62     •   Configure either master or slave mode
63     •   SPI Master frame transfer control
64     •   SPI Master block transfer control
65     •   SPI Slave frame transfer control
66     •   SPI Slave block transfer control
67   Frame transfer allows the MSS SPI to write or read up to 32 bits of data in a
68   SPI transaction. For example, a frame transfer of 12 bits might be used to
69   read the result of ADC conversion from SPI analog to digital converter.
70   Block transfer allows the MSS SPI to write and read several bytes in a SPI
71   transaction. Block transfer transaction allow the data transfer in multiple of
72   8 bits (8, 16, 24, 32 ….). Block transfers are typically used with the
73   byte-oriented devices such as SPI FLASH device.
74 
75 
76   Initialization
77   The MSS SPI driver is initialized through a call to the MSS_SPI_init()
78   function. The MSS_SPI_init() function takes only one parameter, a pointer to
79   one of two global data structures used by the driver to store state
80   information for each MSS SPI. A pointer to these data structures is also used
81   as first parameter to any of the driver functions to identify which MSS SPI
82   will be used by the called function. The names of these two data structures
83   are g_mss_spi0 and g_mss_spi1. Therefore any call to an MSS SPI driver
84   function should be of the form MSS_SPI_function_name(&g_mss_spi0, ... ) or
85   MSS_SPI_function_name( &g_mss_spi1, ... ).
86   The user must reset the MSS SPI core before calling MSS_SPI_init() function.
87   The MSS_SPI_init() function resets the specified MSS SPI hardware block and
88   clears any pending interrupts from local interrupt controller or PLIC.
89   The MSS_SPI_init() function must be called before any other MSS SPI driver
90   functions can be called.
91 
92   Configuration
93   An MSS SPI block can operate either as a master or slave SPI device. There are
94   two distinct functions for configuring a MSS SPI block for master or slave
95   operations.
96 
97   Master configuration
98   The MSS_SPI_configure_master_mode() function configures the specified MSS SPI
99   block for operations as a SPI master. It must be called once for each remote
100   SPI slave device which the MSS SPI block will communicate with. It is used to
101   provide the following information about each SPI slave’s communication
102   characteristics:
103     •   The SPI protocol mode
104     •   The SPI clock speed
105     •   The frame bit length
106     •   The SPI overflow handler
107   This information is held by the driver and will be used to alter the
108   configuration of the MSS SPI block each time a slave is selected through a
109   call to MSS_SPI_set_slave_select(). The SPI protocol mode defines the initial
110   state of the clock signal at the start of a transaction and which clock edge
111   will be used to sample the data signal (Motorola SPI modes), or it defines
112   whether the SPI block will operate in Texas Instruments (TI) synchronous
113   serial mode or in National Semiconductor (NSC) MICROWIRE mode.
114   The MSS_SPI_configure_master_mode() function will register the
115   MSS_SPI_overflow_handler() function to the SPI instance,
116   MSS_SPI_overflow_handler() function is used by driver in case of buffer
117   overflow.
118 
119   Slave configuration
120   The MSS_SPI_configure_slave_mode() function configures the specified MSS SPI
121   block for operations  as a SPI slave. It configures the following SPI
122   communication characteristics:
123     •   The SPI protocol mode
124     •   The frame bit length
125     •   The SPI overflow handler
126   The SPI protocol mode defines the initial state of the clock signal at the
127   start of a transaction and which clock edge will be used to sample the data
128   signal (Motorola SPI modes), or it defines whether the SPI block will operate
129   in TI synchronous serial mode or in NSC MICROWIRE mode.
130   The MSS_SPI_configure_slave_mode() function will register the
131   MSS_SPI_overflow_handler() function to the SPI instance,
132   MSS_SPI_overflow_handler() function is used by driver in case of buffer
133   overflow.
134 
135   SPI master frame transfer control
136   The following functions are used as part of SPI master frame transfers:
137     - MSS_SPI_set_slave_select()
138     - MSS_SPI_transfer_frame()
139     - MSS_SPI_clear_slave_select()
140   The master must first select the target slave through a call to
141   MSS_SPI_set_slave_select(). This causes the relevant slave select line to
142   become asserted while data is clocked out onto the SPI data line.
143   A call is then made to MSS_SPI_transfer_frame() specifying the value of the
144   data frame to be sent.
145   The function MSS_SPI_clear_slave_select() can be used after the transfer is
146   complete to prevent this slave select line from being asserted during
147   subsequent SPI transactions. A call to this function is only required if the
148   master is communicating with multiple slave devices.
149 
150   SPI master block transfer control
151   The following functions are used as part of SPI master block transfers:
152     - MSS_SPI_set_slave_select()
153     - MSS_SPI_clear_slave_select()
154     - MSS_SPI_transfer_block()
155   The master must first select the target slave through a call to
156   MSS_SPI_set_slave_select(). This causes the relevant slave select line to
157   become asserted while data is clocked out onto the SPI data line.
158   A call is then made to MSS_SPI_transfer_block (). The parameters of
159   this function specify:
160     - the number of bytes to be transmitted
161     - a pointer to the buffer containing the data to be transmitted
162     - the number of bytes to be received
163     - a pointer to the buffer where received data will be stored
164   The number of bytes to be transmitted can be set to zero to indicate that the
165   transfer is purely a block read transfer. Alternatively, the number of bytes
166   to be received can be set to zero to specify that the transfer is purely a
167   block write transfer.
168   The function MSS_SPI_clear_slave_select() can be used after the transfer is
169   complete to prevent this slave select line from being asserted during
170   subsequent SPI transactions. A call to this function is only required if the
171   master is communicating with multiple slave devices.
172   Note: Unlike in previous versions of this driver, the SPS bit is set in the
173         CONTROL register in Motorola modes so that the Slave Select line remains
174         asserted throughout block transfers.
175 
176   SPI slave frame transfer control
177   The following functions are used as part of SPI slave frame transfers:
178     - MSS_SPI_set_slave_tx_frame()
179     - MSS_SPI_set_frame_rx_handler()
180   The MSS_SPI_set_slave_tx_frame() function specifies the frame data that will
181   be returned to the SPI master. The frame data specified through this function
182   is the value that will be read over the SPI bus by the remote SPI master when
183   it initiates a transaction. A call to MSS_SPI_set_slave_tx_frame() is only
184   required if the MSS SPI slave is the target of SPI  read transactions, i.e. if
185   data is meant to be read from the PolarFire SoC device over SPI.
186   The MSS_SPI_set_frame_rx_handler() function specifies the receive handler
187   function that will called when a frame of data has been received by the MSS
188   SPI when it is configured as a slave. The receive handler function specified
189   through this call will process the frame data written, over the SPI bus, to
190   the MSS SPI slave by the remote SPI master. The receive handler function must
191   be implemented as part of the application. It is only required if the MSS SPI
192   slave is the target of SPI frame write transactions.
193   Successive master writes need to take into account the time taken to execute
194   the receive handler if the interface is to work reliably.
195   SPI slave block transfer control
196   The following functions are used as part of SPI slave block transfers:
197     - MSS_SPI_set_slave_block_buffers()
198     - MSS_SPI_set_cmd_handler()
199     - MSS_SPI_set_cmd_response()
200   The MSS_SPI_set_slave_block_buffers() function is used to configure a MSS SPI
201   slave for block transfer operations. It specifies:
202     - The buffer containing the data that will be returned to the remote SPI
203       master
204     - The buffer where data received from the remote SPI master will be stored
205     - The handler function that will be called after the receive buffer has been
206       filled
207   The MSS_SPI_set_cmd_handler() function specifies a command handler function
208   that will be called by the driver once a specific number of bytes has been
209   received after the SPI chip select signal becoming active. The number of bytes
210   making up the command part of the transaction is specified as part of the
211   parameters to MSS_SPI_set_cmd_handler(). The command handler function
212   is implemented as part of the application making use of the SPI driver and
213   would typically call the MSS_SPI_set_cmd_response() function.
214   The MSS_SPI_set_cmd_response() function specifies the data that will be
215   returned to the master. Typically the MSS_SPI_set_slave_block_buffers() will
216   have been called as part of the system initialization to specify the data sent
217   to the master while the command bytes are being received. The transmit buffer
218   specified through the call to MSS_SPI_set_slave_block_buffers() would also
219   typically include one or more bytes allowing for the turn around time required
220   for the command handler function to execute and call
221   MSS_SPI_set_cmd_response().
222 
223  *//*=========================================================================*/
224 #ifndef MSS_SPI_H_
225 #define MSS_SPI_H_
226 
227 #include <stddef.h>
228 #include <stdint.h>
229 
230 /*Register map of the MPFS MSS SPI*/
231 typedef struct
232 {
233     volatile uint32_t CONTROL;
234     volatile uint32_t FRAMESIZE;/* SPEC 2.13 , removed TXRXDF_SIZE;*/
235     volatile uint32_t STATUS;
236     volatile uint32_t INT_CLEAR;
237     volatile uint32_t RX_DATA;
238     volatile uint32_t TX_DATA;
239     volatile uint32_t CLK_GEN;
240     volatile uint32_t SLAVE_SELECT;
241     volatile uint32_t MIS;
242     volatile uint32_t RIS;
243     volatile uint32_t CONTROL2;
244     volatile uint32_t COMMAND;
245     volatile uint32_t PKTSIZE;
246     volatile uint32_t CMDSIZE;
247     volatile uint32_t HWSTATUS;
248     volatile uint32_t STAT8;
249     volatile uint32_t CTRL0;
250     volatile uint32_t CTRL1;
251     volatile uint32_t CTRL2;
252     volatile uint32_t CTRL3;
253     volatile uint32_t FRAMESUP; /* SPEC 2.13 */
254 } SPI_TypeDef;
255 
256 #define SPI0_LO_BASE               0x20108000u
257 #define SPI1_LO_BASE               0x20109000u
258 #define SPI0_HI_BASE               0x28108000u
259 #define SPI1_HI_BASE               0x28109000u
260 
261 #define MSS_SPI0_LO_BASE                    ((SPI_TypeDef *) SPI0_LO_BASE)
262 #define MSS_SPI1_LO_BASE                    ((SPI_TypeDef *) SPI1_LO_BASE)
263 #define MSS_SPI0_HI_BASE                    ((SPI_TypeDef *) SPI0_HI_BASE)
264 #define MSS_SPI1_HI_BASE                    ((SPI_TypeDef *) SPI1_HI_BASE)
265 
266 #ifdef __cplusplus
267 extern "C" {
268 #endif
269 
270 /***************************************************************************//**
271   This defines the function prototype that must be followed by MSS SPI slave
272   frame receive handler functions. These functions are registered with the MSS
273   SPI driver through the MSS_SPI_set_frame_rx_handler () function.
274 
275   Declaring and Implementing Slave Frame Receive Handler Functions:
276     Slave frame receive handler functions should follow the following prototype:
277         void slave_frame_receive_handler ( uint32_t rx_frame );
278     The actual name of the receive handler is unimportant. You can use any name
279     of your choice for the receive frame handler. The rx_frame parameter will
280     contain the value of the received frame.
281  */
282 typedef void (*mss_spi_frame_rx_handler_t)( uint32_t rx_frame );
283 
284 /***************************************************************************//**
285   This defines the function prototype that must be followed by MSS SPI slave
286   block receive handler functions. These functions are registered with the MSS
287   SPI driver through the MSS_SPI_set_slave_block_buffers() function.
288 
289   Declaring and Implementing Slave Block Receive Handler Functions
290     Slave block receive handler functions should follow the following prototype:
291         void mss_spi_block_rx_handler ( uint8_t * rx_buff, uint16_t rx_size );
292     The actual name of the receive handler is unimportant. You can use any name
293     of your choice for the receive frame handler. The rx_buff parameter will
294     contain a pointer to the start of the received block. The rx_size parameter
295     indicates the number of bytes in the received block.
296 
297  */
298 typedef void (*mss_spi_block_rx_handler_t)(uint8_t * rx_buff, uint32_t rx_size);
299 
300 /**************************************************************************//**
301   This defines the function prototype that must be used by the MSS SPI init
302   functions. This handler functions is registered with the MSS SPI driver
303   through the MSS_SPI_init() function.
304   Declaring and Implementing Overflow handler functions
305      The buffer overflow handler functions must use the following prototype
306           void mss_spi0_overflow_handler(uint8_t mss_spi_core);
307      The actual name of the overflow handler is not important. User can use any
308      name of choice. This function is passed as a argument to the MSS_SPI_init(),
309      which registers overflow handler to the MSS SPI instance.The parameter
310      passed with the function informs the handler function about which SPI core
311      to reset.This variable can later be used by the driver to recover from
312      buffer overflow situations.
313  */
314 typedef void (*mss_spi_oveflow_handler_t)(uint8_t mss_spi_core);
315 
316 /***************************************************************************//**
317   This enumeration is used to define the settings for the SPI protocol mode
318   bits which select the different modes of operation for the MSS SPI. It is used
319   as a parameter to the MSS_SPI_configure_master_mode() and
320   MSS_SPI_configure_slave_mode() functions.
321 
322   - MSS_SPI_MODE0:
323         Clock starts low, data read on clock's rising edge, data changes on
324         falling edge.
325 
326   - MSS_SPI_MODE1:
327         Clock starts low, data read on clock's falling edge, data changes on
328         rising edge.
329 
330   - MSS_SPI_MODE2:
331         Clock starts high, data read on clock's falling edge, data changes on
332         rising edge.
333 
334   - MSS_SPI_MODE3:
335         Clock starts high, data read on clock's rising edge, data changes on
336         falling edge.
337 
338   - MSS_TI_MODE:
339         TI synchronous serial mode. Slave select is pulsed at start of transfer.
340 
341   - MSS_NSC_MODE:
342         NSC Microwire mode.
343  */
344 typedef enum __mss_spi_protocol_mode_t
345 {
346     MSS_SPI_MODE0    = 0x00000000,
347     MSS_SPI_TI_MODE  = 0x01000004,
348     MSS_SPI_NSC_MODE = 0x00000008,
349     MSS_SPI_MODE2    = 0x01000000,
350     MSS_SPI_MODE1    = 0x02000000,
351     MSS_SPI_MODE3    = 0x03000000
352 } mss_spi_protocol_mode_t;
353 
354 /***************************************************************************//**
355  This enumeration is used to select a specific SPI slave device (0 to 7). It is
356  used as a parameter to the MSS_SPI_configure_master_mode(),
357  MSS_SPI_set_slave_select() and MSS_SPI_clear_slave_select () functions.
358  */
359  typedef enum __mss_spi_slave_t
360  {
361     MSS_SPI_SLAVE_0             = 0,
362     MSS_SPI_SLAVE_1             = 1,
363     MSS_SPI_SLAVE_2             = 2,
364     MSS_SPI_SLAVE_3             = 3,
365     MSS_SPI_SLAVE_4             = 4,
366     MSS_SPI_SLAVE_5             = 5,
367     MSS_SPI_SLAVE_6             = 6,
368     MSS_SPI_SLAVE_7             = 7,
369     MSS_SPI_MAX_NB_OF_SLAVES    = 8
370 } mss_spi_slave_t;
371 
372 /***************************************************************************//**
373   MSS_SPI_BLOCK_TRANSFER_FRAME_SIZE
374   =================================
375   This constant defines a frame size of 8 bits when configuring an MSS SPI to
376   perform block transfer data transactions.
377   It must be used as the value for the frame_bit_length parameter of function
378   MSS_SPI_configure_master_mode() when performing block transfers between the
379   MSS SPI master and the target SPI slave.
380   It must also be used as the value for the frame_bit_length parameter of
381   MSS_SPI_configure_slave_mode() when performing block transfers between the
382   MSS SPI slave and the remote SPI master.
383  */
384 #define MSS_SPI_BLOCK_TRANSFER_FRAME_SIZE   8u
385 
386 /***************************************************************************//**
387   The mss_spi_slave_cfg_t holds the MSS SPI configuration that must be used to
388   communicate with a specific SPI slave.
389  */
390 typedef struct __mss_spi_slave_cfg_t
391 {
392     uint32_t ctrl_reg;
393     uint8_t txrxdf_size_reg;
394     uint8_t clk_gen;
395 } mss_spi_slave_cfg_t;
396 
397 /***************************************************************************//**
398  This enumeration is used to indicate the current slave mode transfer type so
399  that we are not relying on buffer comparisons to dictate the logic of the driver.
400  */
401 typedef enum __mss_spi_sxfer_mode_t
402 {
403     MSS_SPI_SLAVE_XFER_NONE  = 0, /* Not configured yet */
404     MSS_SPI_SLAVE_XFER_BLOCK = 1, /* Block transfers, with SSEND delimiting end
405                                      of block */
406     MSS_SPI_SLAVE_XFER_FRAME = 2  /* Single frame transfers */
407 } mss_spi_sxfer_mode_t;
408 
409 /***************************************************************************//**
410   There is one instance of this structure for each of the microprocessor
411   subsystem's SPIs. Instances of this structure are used to identify a specific
412   SPI. A pointer to an instance of the mss_spi_instance_t structure is passed as
413   the first parameter to MSS SPI driver functions to identify which SPI should
414   perform the requested operation.
415  */
416 typedef struct __mss_spi_instance_t
417 {
418     /* SPI hardware identification definitions . */
419     SPI_TypeDef *           hw_reg;     /*!< Pointer to SPI registers. */
420     uint8_t          irqn;       /*!< SPI's PLIC interrupt number. */
421 
422     /* Internal transmit state: */
423     const uint8_t * slave_tx_buffer;    /*!< Pointer to slave transmit buffer. */
424     uint32_t slave_tx_size;             /*!< Size of slave transmit buffer. */
425     uint32_t slave_tx_idx;              /*!< Current index into slave transmit buffer. */
426 
427     /* Slave command response buffer: */
428     const uint8_t * resp_tx_buffer;
429     uint32_t resp_buff_size;
430     uint32_t resp_buff_tx_idx;
431     mss_spi_block_rx_handler_t cmd_handler;
432     uint32_t cmd_done;                  /*!< Flag which indicates response has been set up and
433                                              it is safe to pad with 0s once the response is sent. */
434 
435     /* Internal receive state: */
436     uint8_t * slave_rx_buffer;          /*!< Pointer to buffer where data received by a slave will be stored. */
437     uint32_t slave_rx_size;             /*!< Slave receive buffer siSze. */
438     uint32_t slave_rx_idx;              /*!< Current index into slave receive buffer. */
439 
440     /* Configuration for each target slave. */
441     mss_spi_slave_cfg_t slaves_cfg[MSS_SPI_MAX_NB_OF_SLAVES];
442 
443     /* Slave received frame handler: */
444     mss_spi_frame_rx_handler_t frame_rx_handler;    /*!< Pointer to function that will be called when a frame is received when the SPI block is configured as slave. */
445 
446     uint32_t slave_tx_frame;                        /*!< Value of the data frame that will be transmitted when the SPI block is configured as slave. */
447 
448     /* Slave block rx handler: */
449     mss_spi_block_rx_handler_t block_rx_handler;    /*!< Pointer to the function that will be called when a data block has been received. */
450 
451     /* How we are expecting to deal with slave transfers */
452     mss_spi_sxfer_mode_t slave_xfer_mode;               /*!< Current slave mode transfer configuration. */
453 
454     /* MSS SPI reset handler*/
455     mss_spi_oveflow_handler_t buffer_overflow_handler;
456 
457 } mss_spi_instance_t;
458 
459 
460 /***************************************************************************//**
461   This instance of mss_spi_instance_t holds all data related to the operations
462   performed by the MSS SPI. The function MSS_SPI_init() initializes this structure.
463   A pointer to g_mss_spi0_lo is passed as the first parameter to MSS SPI driver
464   functions to indicate that SPI0 should perform the requested operation.
465  */
466 
467 extern mss_spi_instance_t g_mss_spi0_lo;
468 extern mss_spi_instance_t g_mss_spi1_lo;
469 
470 extern mss_spi_instance_t g_mss_spi0_hi;
471 extern mss_spi_instance_t g_mss_spi1_hi;
472 /***************************************************************************//**
473   The MSS_SPI_init() function initializes and hardware and data structures of
474   one of the MSS SPIs. The MSS_SPI_init() function must be called before any
475   other MSS SPI driver functions can be called.
476 
477   @param this_spi
478     The this_spi parameter is a pointer to an mss_spi_instance_t structure
479     identifying the MSS SPI hardware block to be initialized. There are two such
480     data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
481     MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
482     or g_mss_spi1 global data structure defined within the SPI driver.
483 
484   Example:
485   @code
486   MSS_SPI_init(&g_mss_spi0);
487   @endcode
488  */
489 void MSS_SPI_init
490 (
491     mss_spi_instance_t * this_spi
492 );
493 
494 /***************************************************************************//**
495   The MSS_SPI_configure_slave_mode() function configure a MSS SPI block for
496   operations as a slave SPI device. It configures the SPI hardware with the
497   selected SPI protocol mode and frame size for communication with a specific
498   SPI master.
499 
500   @param this_spi
501     The this_spi parameter is a pointer to an mss_spi_instance_t structure
502     identifying the MSS SPI hardware block to be configured. There are two such
503     data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
504     MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
505     or g_mss_spi1 global data structure defined within the SPI driver.
506 
507   @param protocol_mode
508     This parameter is used to specify the SPI operating mode. Allowed values are:
509         - MSS_SPI_MODE0
510         - MSS_SPI_MODE1
511         - MSS_SPI_MODE2
512         - MSS_SPI_MODE3
513         - MSS_TI_MODE
514         - MSS_NSC_MODE
515 
516   @param frame_bit_length
517     Number of bits making up the frame. You must use the
518     MSS_SPI_BLOCK_TRANSFER_FRAME_SIZE constant as the value for frame_bit_length
519     when configuring the MSS SPI master for block transfer transactions with the
520     target SPI slave.
521 
522   @param recieve_buffer_overflow_handler
523   The recieve_buffer_overflow_handler parameter is a pointer to the callback
524   function which is called when rx overflow occurs. The
525   MSS_SPI_configure_master_mode() function registers user implemented receive
526   buffer overflow handler to the mss_spi_instance_t structure. This registered
527   handler is used by driver to recover from buffer overflow situation.
528       Note: There is no restriction in naming the buffer overflow handler,
529             User can name as per wish.
530 
531 
532   Example:
533   @code
534   MSS_SPI_init(&g_mss_spi0);
535   MSS_SPI_configure_slave_mode
536     (
537         &g_mss_spi0,
538         MSS_SPI_MODE2,
539         MSS_SPI_BLOCK_TRANSFER_FRAME_SIZE,
540         mss_spi_overflow_handler
541     );
542   @endcode
543 
544  */
545 void MSS_SPI_configure_slave_mode
546 (
547     mss_spi_instance_t * this_spi,
548     mss_spi_protocol_mode_t protocol_mode,
549     uint8_t frame_bit_length,
550     mss_spi_oveflow_handler_t recieve_buffer_overflow_handler
551 );
552 
553 /***************************************************************************//**
554   The MSS_SPI_configure_master_mode() function configures the protocol mode,
555   serial clock speed and frame size for a specific target SPI slave device. It
556   is used when the MSS SPI hardware block is used as a SPI master. This function
557   must be called once for each target SPI slave which the MSS SPI master is
558   wishes to communicate with. The SPI master hardware will be configured with
559   the configuration specified by this function during calls to
560   MSS_SPI_set_slave_select().
561 
562   @param this_spi
563     The this_spi parameter is a pointer to an mss_spi_instance_t structure
564     identifying the MSS SPI hardware block to be configured. There are two such
565     data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
566     MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
567     or g_mss_spi1 global data structure defined within the SPI driver.
568 
569   @param slave
570     The slave parameter is used to identify a target SPI slave. The driver will
571     hold the MSS SPI master configuration required to communicate with this
572     slave, as specified by the other function parameters. Allowed values are:
573        * MSS_SPI_SLAVE_0
574        * MSS_SPI_SLAVE_1
575        * MSS_SPI_SLAVE_2
576        * MSS_SPI_SLAVE_3
577        * MSS_SPI_SLAVE_4
578        * MSS_SPI_SLAVE_5
579        * MSS_SPI_SLAVE_6
580        * MSS_SPI_SLAVE_7
581 
582   @param protocol_mode
583     This parameter is used to specify the SPI operating mode. Allowed values are:
584        * MSS_SPI_MODE0
585        * MSS_SPI_MODE1
586        * MSS_SPI_MODE2
587        * MSS_SPI_MODE3
588        * MSS_SPI_TI_MODE
589        * MSS_SPI_NSC_MODE
590 
591   @param clk_div
592     SPI clock divider value used to generate serial interface clock signal from
593     PCLK. Allowed values are even numbers in the range from 2 to 512. The PCLK
594     frequency is divided by the specified value to give the serial interface
595     clock frequency.
596 
597   @param frame_bit_length
598     Number of bits making up the frame. The maximum frame length is 32 bits. You
599     must use the MSS_SPI_BLOCK_TRANSFER_FRAME_SIZE constant as the value for
600     frame_bit_length when configuring the MSS SPI master for block transfer
601     transactions with the target SPI slave.
602 
603   @param recieve_buffer_overflow_handler
604     The recieve_buffer_overflow_handler parameter is a pointer to the callback
605     function receive buffer overflow handler. User must implement a local
606     function to handle buffer overflow. The MSS_SPI_configure_master_mode()
607     function registers user implemented receive buffer overflow handler to
608     the mss_spi_instance_t structure. This registered handler is used by driver
609     to prevent in state of buffer overflow.
610 
611     Note: There is no limitation in naming the buffer overflow handler, User
612           can name as per wish  .
613 
614   Example:
615   @code
616   MSS_SPI_init(&g_mss_spi0);
617 
618   MSS_SPI_configure_master_mode
619     (
620         &g_mss_spi0,
621         MSS_SPI_SLAVE_0,
622         MSS_SPI_MODE2,
623         64u,
624         12,
625         mss_spi_overflow_handler
626      );
627 
628   MSS_SPI_configure_master_mode
629     (
630         &g_mss_spi0,
631         MSS_SPI_SLAVE_1,
632         MSS_SPI_TI_MODE,
633         128u,
634         MSS_SPI_BLOCK_TRANSFER_FRAME_SIZE,
635         mss_spi_overflow_handler
636      );
637 
638   MSS_SPI_set_slave_select(&g_mss_spi0, MSS_SPI_SLAVE_0);
639   MSS_SPI_transfer_frame(&g_mss_spi0, 0xaaa);
640   MSS_SPI_clear_slave_select(&g_mss_spi0, MSS_SPI_SLAVE_0);
641 
642   MSS_SPI_set_slave_select(&g_mss_spi0, MSS_SPI_SLAVE_1);
643   MSS_SPI_transfer_frame(&g_mss_spi0, 0x55);
644   MSS_SPI_clear_slave_select(&g_mss_spi0, MSS_SPI_SLAVE_1);
645   @endcode
646  */
647 void MSS_SPI_configure_master_mode
648 (
649     mss_spi_instance_t *    this_spi,
650     mss_spi_slave_t         slave,
651     mss_spi_protocol_mode_t protocol_mode,
652     uint32_t                clk_div,
653     uint8_t                 frame_bit_length,
654     mss_spi_oveflow_handler_t recieve_buffer_overflow_handler
655 );
656 /*==============================================================================
657  * Master functions
658  *============================================================================*/
659 
660 /***************************************************************************//**
661   The MSS_SPI_set_slave_select() function is used by a MSS SPI master to select
662   a specific slave. This function causes the relevant slave select signal to be
663   asserted while data is clocked out onto the SPI data line. This function also
664   configures the MSS SPI master with the configuration settings necessary for
665   communication with the specified slave. These configuration settings must be
666   specified in a previous call to the MSS_SPI_configure_master_mode() function.
667 
668   @param this_spi
669     The this_spi parameter is a pointer to an mss_spi_instance_t structure
670     identifying the MSS SPI hardware block to operate on. There are two such
671     data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
672     MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
673     or g_mss_spi1 global data structure defined within the SPI driver.
674 
675   @param slave
676     The slave parameter is one of the mss_spi_slave_t enumerated constants
677     identifying the slave.
678 
679   Example:
680   @code
681   const uint8_t frame_size = 25;
682   const uint32_t master_tx_frame = 0x0100A0E1;
683 
684   MSS_SPI_init(&g_mss_spi0);
685   MSS_SPI_configure_master_mode
686     (
687         &g_mss_spi0,
688         MSS_SPI_SLAVE_0,
689         MSS_SPI_MODE1,
690         256u,
691         frame_size,
692         mss_spi_overflow_handler
693      );
694 
695   MSS_SPI_set_slave_select(&g_mss_spi0, MSS_SPI_SLAVE_0);
696   MSS_SPI_transfer_frame(&g_mss_spi0, master_tx_frame);
697   MSS_SPI_clear_slave_select(&g_mss_spi0, MSS_SPI_SLAVE_0);
698   @endcode
699  */
700 void MSS_SPI_set_slave_select
701 (
702     mss_spi_instance_t * this_spi,
703     mss_spi_slave_t slave
704 );
705 
706 /***************************************************************************//**
707   The MSS_SPI_clear_slave_select() function is used by a MSS SPI Master to
708   deselect a specific slave. This function causes the relevant slave select
709   signal to be de-asserted.
710 
711   @param this_spi
712     The this_spi parameter is a pointer to an mss_spi_instance_t structure
713     identifying the MSS SPI hardware block to operate on. There are two such
714     data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
715     MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
716     or g_mss_spi1 global data structure defined within the SPI driver.
717 
718   @param slave
719     The slave parameter is one of mss_spi_slave_t enumerated constants
720     identifying a slave.
721 
722   Example:
723   @code
724   const uint8_t frame_size = 25;
725   const uint32_t master_tx_frame = 0x0100A0E1;
726 
727   MSS_SPI_init(&g_mss_spi0);
728   MSS_SPI_configure_master_mode
729     (
730         &g_mss_spi0,
731         MSS_SPI_SLAVE_0,
732         MSS_SPI_MODE1,
733         256u,
734         frame_size,
735         mss_spi_overflow_handler
736      );
737   MSS_SPI_set_slave_select(&g_mss_spi0, MSS_SPI_SLAVE_0);
738   MSS_SPI_transfer_frame(&g_mss_spi0, master_tx_frame);
739   MSS_SPI_clear_slave_select(&g_mss_spi0, MSS_SPI_SLAVE_0);
740   @endcode
741  */
742 void MSS_SPI_clear_slave_select
743 (
744     mss_spi_instance_t * this_spi,
745     mss_spi_slave_t slave
746 );
747 
748 /***************************************************************************//**
749   The MSS_SPI_disable() function is used to temporarily disable a MSS SPI
750   hardware block.
751 
752   @param this_spi
753     The this_spi parameter is a pointer to an mss_spi_instance_t structure
754     identifying the MSS SPI hardware block to operate on. There are two such
755     data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
756     MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
757     or g_mss_spi1 global data structure defined within the SPI driver.
758 
759   Example:
760   @code
761   uint32_t transfer_size;
762   uint8_t tx_buffer[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
763 
764   transfer_size = sizeof(tx_buffer);
765 
766   MSS_SPI_disable(&g_mss_spi0);
767   MSS_SPI_set_transfer_byte_count(&g_mss_spi0, transfer_size);
768 
769   @endcode
770  */
771 void MSS_SPI_disable
772 (
773     mss_spi_instance_t * this_spi
774 );
775 
776 /***************************************************************************//**
777   The MSS_SPI_enable() function is used to re-enable a MSS SPI hardware block
778   after it was disabled using the SPI_disable() function.
779 
780   @param this_spi
781     The this_spi parameter is a pointer to an mss_spi_instance_t structure
782     identifying the MSS SPI hardware block to operate on. There are two such
783     data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
784     MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
785     or g_mss_spi1 global data structure defined within the SPI driver.
786 
787   Example:
788   @code
789   uint32_t transfer_size;
790   uint8_t tx_buffer[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
791 
792   transfer_size = sizeof(tx_buffer);
793 
794   MSS_SPI_disable(&g_mss_spi0);
795   MSS_SPI_set_transfer_byte_count(&g_mss_spi0, transfer_size);
796 
797   MSS_SPI_enable(&g_mss_spi0);
798 
799   @endcode
800  */
801 void MSS_SPI_enable
802 (
803     mss_spi_instance_t * this_spi
804 );
805 
806 /***************************************************************************//**
807   The MSS_SPI_transfer_frame() function is used by a MSS SPI master to transmit
808   and receive a frame up to 32 bits long. This function is typically used for
809   transactions with a SPI slave where the number of transmit and receive bits is
810   not divisible by 8.
811 
812   Note: The maximum frame size in NSC Microwire mode is 24 bits organized as an
813         8 bit command followed by up to 16 bits of data .
814   @param this_spi
815     The this_spi parameter is a pointer to an mss_spi_instance_t structure
816     identifying the MSS SPI hardware block to operate on. There are two such
817     data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
818     MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
819     or g_mss_spi1 global data structure defined within the SPI driver.
820 
821 
822   @param tx_bits
823     The tx_bits parameter is a 32 bits word containing the data that will be
824     transmitted.
825     Note:   The bit length of the value to be transmitted to the slave must be
826             specified as the frame_bit_length parameter in a previous call to
827             the MSS_SPI_configure_master_mode() function.
828 
829   @return
830     This function returns a 32 bits word containing the value that is received
831     from the slave.
832 
833   Example:
834   @code
835       const uint8_t frame_size = 25;
836       const uint32_t master_tx_frame = 0x0100A0E1;
837       uint32_t master_rx;
838 
839       MSS_SPI_init(&g_mss_spi0);
840       MSS_SPI_configure_master_mode
841         (
842             &g_mss_spi0,
843             MSS_SPI_SLAVE_0,
844             MSS_SPI_MODE1,
845             256u,
846             frame_size,
847             mss_spi_overflow_handler
848          );
849 
850       MSS_SPI_set_slave_select(&g_mss_spi0, MSS_SPI_SLAVE_0);
851       master_rx = MSS_SPI_transfer_frame(&g_mss_spi0, master_tx_frame);
852       MSS_SPI_clear_slave_select(&g_mss_spi0, MSS_SPI_SLAVE_0);
853   @endcode
854  */
855 uint32_t MSS_SPI_transfer_frame
856 (
857     mss_spi_instance_t * this_spi,
858     uint32_t tx_bits
859 );
860 
861 /***************************************************************************//**
862   The MSS_SPI_transfer_block() function is used by MSS SPI masters to transmit
863   and receive blocks of data organized as a specified number of bytes. It can
864   be used for:
865     •   Writing a data block to a slave
866     •   Reading a data block from a slave
867     •   Sending a command to a slave followed by reading the response to the
868         command in a single SPI transaction.
869 
870   @param this_spi
871     The this_spi parameter is a pointer to an mss_spi_instance_t structure
872     identifying the MSS SPI hardware block to operate on. There are two such
873     data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
874     MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
875     or g_mss_spi1 global data structure defined within the SPI driver.
876 
877   @param cmd_buffer
878     The cmd_buffer parameter is a pointer to the buffer containing the data that
879     will be sent by the master from the beginning of the transfer.
880 
881   @param cmd_byte_size
882     The cmd_byte_size parameter specifies the number of bytes contained in
883     cmd_buffer that will be sent. A value of 0 indicates that no data needs to
884     be sent to the slave.
885 
886   @param rd_buffer
887     The rd_buffer parameter is a pointer to the buffer where the data received
888     from the slave after the command has been sent will be stored.
889 
890   @param rd_byte_size
891     The rd_byte_size parameter specifies the number of bytes to be received from
892     the slave and stored in the rd_buffer. A value of 0 indicates that no data
893     is to be read from the slave.
894 
895   Polled write transfer example:
896   @code
897       uint8_t master_tx_buffer[MASTER_TX_BUFFER] =
898       {
899           0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
900       };
901       MSS_SPI_init(&g_mss_spi0);
902       MSS_SPI_configure_master_mode
903         (
904             &g_mss_spi0,
905             MSS_SPI_SLAVE_0,
906             MSS_SPI_MODE1,
907             256u,
908             MSS_SPI_BLOCK_TRANSFER_FRAME_SIZE,
909             mss_spi_overflow_handler
910          );
911 
912       MSS_SPI_set_slave_select(&g_mss_spi0, MSS_SPI_SLAVE_0);
913       MSS_SPI_transfer_block
914         (
915             &g_mss_spi0,
916             master_tx_buffer,
917             sizeof(master_tx_buffer),
918             0,
919             0
920         );
921       MSS_SPI_clear_slave_select(&g_mss_spi0, MSS_SPI_SLAVE_0);
922   @endcode
923  */
924 void MSS_SPI_transfer_block
925 (
926     mss_spi_instance_t * this_spi,
927     const uint8_t cmd_buffer[],
928     uint32_t cmd_byte_size,
929     uint8_t rd_buffer[],
930     uint32_t rd_byte_size
931 );
932 
933 /*==============================================================================
934  * Slave functions
935  *============================================================================*/
936 
937 /***************************************************************************//**
938   The MSS_SPI_set_frame_rx_handler() function is used by MSS SPI slaves to
939   specify the receive handler function that will be called by the MSS SPI driver
940   interrupt handler when a a frame of data is received by the MSS SPI slave.
941 
942   @param this_spi
943     The this_spi parameter is a pointer to an mss_spi_instance_t structure
944     identifying the MSS SPI hardware block to operate on. There are two such
945     data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
946     MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
947     or g_mss_spi1 global data structure defined within the SPI driver.
948 
949   @param rx_handler
950     The rx_handler parameter is a pointer to the frame receive handler that must
951     be called when a frame is received by the MSS SPI slave.
952 
953   Example:
954   @code
955       uint32_t g_slave_rx_frame = 0;
956 
957       void slave_frame_handler(uint32_t rx_frame)
958       {
959           g_slave_rx_frame = rx_frame;
960       }
961 
962       int setup_slave(void)
963       {
964           const uint16_t frame_size = 25;
965           MSS_SPI_init(&g_mss_spi1);
966           MSS_SPI_configure_slave_mode
967             (
968                 &g_mss_spi0,
969                 MSS_SPI_MODE2,
970                 frame_size,
971                 mss_spi_overflow_handler
972             );
973           MSS_SPI_set_frame_rx_handler(&g_mss_spi1, slave_frame_handler);
974       }
975   @endcode
976  */
977 void MSS_SPI_set_frame_rx_handler
978 (
979     mss_spi_instance_t * this_spi,
980     mss_spi_frame_rx_handler_t rx_handler
981 );
982 
983 /***************************************************************************//**
984   The MSS_SPI_set_slave_tx_frame() function is used by MSS SPI slaves to specify
985   the frame that will be transmitted when a transaction is initiated by the SPI
986   master.
987 
988   @param this_spi
989     The this_spi parameter is a pointer to an mss_spi_instance_t structure
990     identifying the MSS SPI hardware block to operate on. There are two such
991     data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
992     MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
993     or g_mss_spi1 global data structure defined within the SPI driver.
994 
995 
996   @param frame_value
997     The frame_value parameter contains the value of the frame to be sent to the
998     master.
999     Note:   The bit length of the value to be transmitted to the master must be
1000             specified as the frame_bit_length parameter in a previous call to
1001             the MSS_SPI_configure_slave_mode() function.
1002 
1003   Example:
1004   @code
1005       const uint16_t frame_size = 25;
1006       const uint32_t slave_tx_frame = 0x0110F761;
1007       uint32_t master_rx;
1008 
1009       MSS_SPI_init(&g_mss_spi1);
1010       MSS_SPI_configure_slave_mode
1011         (
1012             &g_mss_spi0,
1013             MSS_SPI_MODE2,
1014             frame_size,
1015             mss_spi_overflow_handler
1016         );
1017       MSS_SPI_set_slave_tx_frame(&g_mss_spi1, slave_tx_frame);
1018   @endcode
1019  */
1020 void MSS_SPI_set_slave_tx_frame
1021 (
1022     mss_spi_instance_t * this_spi,
1023     uint32_t frame_value
1024 );
1025 
1026 /***************************************************************************//**
1027   The MSS_SPI_set_slave_block_buffers() function is used to configure an MSS
1028   SPI slave for block transfer operations. It specifies one or more of the
1029   following:
1030     - The data that will be transmitted when accessed by a master.
1031     - The buffer where data received from a master will be stored.
1032     - The handler function that must be called after the receive buffer has been
1033       filled.
1034     - The maximum number of bytes that the slave will accept from the master
1035       (excess bytes are discarded).
1036   These parameters allow the following use cases:
1037     - Slave performing an action after receiving a block of data from a master
1038       containing a command. The action will be performed by the receive handler
1039       based on the content of the receive data buffer.
1040     - Slave returning a block of data to the master. The type of information is
1041       always the same but the actual values change over time. For example,
1042       returning the voltage of a predefined set of analog inputs.
1043     - Slave returning data based on a command contained in the first part of the
1044       SPI transaction. For example, reading the voltage of the analog input
1045       specified by the first data byte by the master. This is achieved by using
1046       the MSS_SPI_set_slave_block_buffers() function in conjunction with
1047       functions MSS_SPI_set_cmd_handler() and MSS_SPI_set_cmd_response(). Please
1048       refer to the MSS_SPI_set_cmd_handler() function description for details of
1049       this use case.
1050 
1051   @param this_spi
1052     The this_spi parameter is a pointer to an mss_spi_instance_t structure
1053     identifying the MSS SPI hardware block to operate on. There are two such
1054     data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
1055     MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
1056     or g_mss_spi1 global data structure defined within the SPI driver.
1057 
1058   @param tx_buffer
1059     The tx_buffer parameter is a pointer to a buffer containing the data that
1060     will be sent to the master. This parameter can be set to 0 if the MSS SPI
1061     slave is not intended to be the target of SPI read.
1062 
1063   @param tx_buff_size
1064     The tx_buff_size parameter specifies the number of bytes that will be
1065     transmitted by the SPI slave. It is the number of bytes contained in the
1066     tx_buffer. This parameter can be set to 0 if the MSS SPI slave is not
1067     intended to be the target of SPI read transactions.
1068 
1069   @param rx_buffer
1070     The rx_buffer parameter is a pointer to the buffer where data received from
1071     the master will be stored. This parameter can be set to 0 if the MSS SPI
1072     slave is not intended to be the target of SPI write or write-read
1073     transactions.
1074 
1075   @param rx_buff_size
1076     The rx_buff_size parameter specifies the size of the receive buffer. It is
1077     also the number of bytes that must be received before the receive handler
1078     is called, if a receive handler is specified using the block_rx_handler
1079     parameter. This parameter can be set to 0 if the MSS SPI slave is not
1080     intended to be the target of SPI write or write-read transactions.
1081 
1082   @param block_rx_handler
1083     The block_rx_handler parameter is a pointer to a function that will be
1084     called when the receive buffer has been filled. This parameter can be set to
1085     0 if the MSS SPI slave is not intended to be the target of SPI write or
1086     write-read transactions.
1087 
1088   Slave performing operation based on master command:
1089   In this example the SPI slave is configured to receive 10 bytes of data or
1090   command from the SPI master and process the data received.
1091   @code
1092      uint32_t nb_of_rx_handler_calls = 0;
1093 
1094      void spi1_block_rx_handler_b
1095      (
1096          uint8_t * rx_buff,
1097          uint16_t rx_size
1098      )
1099      {
1100          ++nb_of_rx_handler_calls;
1101      }
1102 
1103      void setup_slave(void)
1104      {
1105          uint8_t slave_rx_buffer[10] =
1106          {
1107              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1108          };
1109 
1110          MSS_SPI_init(&g_mss_spi1);
1111          MSS_SPI_configure_slave_mode
1112             (
1113                 &g_mss_spi0,
1114                 MSS_SPI_MODE2,
1115                 MSS_SPI_BLOCK_TRANSFER_FRAME_SIZE,
1116                 mss_spi_overflow_handler
1117             );
1118 
1119          MSS_SPI_set_slave_block_buffers
1120              (
1121                  &g_mss_spi1,
1122                  0,
1123                  0,
1124                  slave_rx_buffer,
1125                  sizeof(slave_rx_buffer),
1126                  spi1_block_rx_handler_b
1127              );
1128      }
1129   @endcode
1130  */
1131 void MSS_SPI_set_slave_block_buffers
1132 (
1133     mss_spi_instance_t * this_spi,
1134     const uint8_t * tx_buffer,
1135     uint32_t tx_buff_size,
1136     uint8_t * rx_buffer,
1137     uint32_t rx_buff_size,
1138     mss_spi_block_rx_handler_t spi_block_rx_handler
1139 );
1140 
1141 /***************************************************************************//**
1142   The MSS_SPI_set_cmd_handler() function specifies a command handler function
1143   that will be called when the number of bytes received reaches the command size
1144   specified as parameter.
1145   This function is used by SPI slaves performing block transfers. Its purpose is
1146   to allow a SPI slave to decide the data that will be returned to the master
1147   while a SPI transaction is taking place. Typically, one of more command bytes
1148   are sent by the master to request some specific data. The slave interprets the
1149   command byte(s) while one or more turn-around bytes are transmitted. The
1150   slave adjusts its transmit data buffer based on the command during the
1151   turnaround time.
1152   The diagram below provides an example of the use of this function where the
1153   SPI slave returns data bytes D0 to D6 based on the value of a command. The
1154   3 bytes long command is made up of a command opcode byte followed by an address
1155   byte followed by a size byte. The cmd_handler() function specified through an
1156   earlier call to MSS_SPI_set_cmd_handler() is called by the SPI driver once the
1157   third byte is received. The cmd_handler() function interprets the command bytes
1158   and calls MSS_SPI_set_cmd_response() to set the SPI slave's response transmit
1159   buffer with the data to be transmitted after the turnaround bytes (T0 to T3).
1160   The number of turnaround bytes must be sufficient to give enough time for the
1161   cmd_handler() to execute. The number of turnaround bytes is specified by the
1162   protocol used on top of the SPI transport layer, so both the master and slave
1163   must adhere to this.
1164 
1165     t0          t1       t2         t3                                 t4
1166     |           |        |          |                                  |
1167     |------------------------------------------------------------------|
1168     |  COMMAND  |    TURN-AROUND    |               DATA               |
1169     |------------------------------------------------------------------|
1170     | C | A | S | T0 | T1 | T2 | T4 | D0 | D1 | D2 | D3 | D4 | D5 | D6 |
1171     |------------------------------------------------------------------|
1172                 |
1173                 |
1174                 --> cmd_handler() called here.
1175                          |
1176                          |
1177                          --> MSS_SPI_set_cmd_response() called here by
1178                              implementation of cmd_handler() to set the data
1179                              that will be transmitted by the SPI slave.
1180 
1181   @param this_spi
1182     The this_spi parameter is a pointer to an mss_spi_instance_t structure
1183     identifying the MSS SPI hardware block used. There are two such data
1184     structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and MSS SPI
1185     1 respectively. This parameter must point to either the g_mss_spi0 or
1186     g_mss_spi1 global data structure defined within the SPI driver.
1187 
1188   @param cmd_handler
1189     The cmd_handler parameter is a pointer to a function with prototype:
1190         void cmd_handler(uint8_t * rx_buff, uint32_t rx_size);
1191     It specifies the function that will be called when the number of bytes
1192     specified by parameter cmd_size has been received.
1193 
1194     Passing in a null pointer for this disables the command handler and the
1195     associated interrupt.
1196 
1197  @param cmd_size
1198     The cmd_size parameter specifies the number of bytes that must be received
1199     before the command handler function specified by cmd_handler is called.
1200 
1201   The example below demonstrates how to configure SPI1 to implement the protocol
1202   given as example in the diagram above.
1203   The configure_slave() function configures SPI1. It sets the receive and transmit
1204   buffers. The transmit buffer specified through the call to
1205   MSS_SPI_set_slave_block_buffers() specifies the data that will be returned to
1206   the master in bytes between t0 and t3. These are the bytes that will be sent
1207   to the master while the master transmits the command and dummy bytes.
1208   The spi1_slave_cmd_handler() function will be called by the driver at time t1
1209   after the 3 command bytes have been received.
1210   The spi1_block_rx_handler() function will be called by the driver at time t4
1211   when the transaction completes when the slave select signal becomes de-asserted.
1212 
1213   @code
1214     #define COMMAND_SIZE            3
1215     #define NB_OF_DUMMY_BYTES       4
1216     #define MAX_TRANSACTION_SIZE    16
1217 
1218     uint8_t slave_tx_buffer[COMMAND_SIZE + NB_OF_DUMMY_BYTES];
1219     uint8_t slave_rx_buffer[MAX_TRANSACTION_SIZE];
1220 
1221     void configure_slave(void)
1222     {
1223         MSS_SPI_init(&g_mss_spi1);
1224 
1225         MSS_SPI_configure_slave_mode
1226           (
1227             &g_mss_spi1,
1228             MSS_SPI_MODE1,
1229             MSS_SPI_BLOCK_TRANSFER_FRAME_SIZE,
1230             mss_spi_overflow_handler
1231           );
1232 
1233         MSS_SPI_set_slave_block_buffers
1234             (
1235                 &g_mss_spi1,
1236                 slave_tx_buffer,
1237                 COMMAND_SIZE + NB_OF_DUMMY_BYTES,
1238                 slave_rx_buffer,
1239                 sizeof(slave_rx_buffer),
1240                 spi1_block_rx_handler
1241             );
1242 
1243 
1244         MSS_SPI_set_cmd_handler
1245             (
1246                 &g_mss_spi1,
1247                 spi1_slave_cmd_handler,
1248                 COMMAND_SIZE
1249             );
1250     }
1251 
1252     void spi1_slave_cmd_handler
1253     (
1254         uint8_t * rx_buff,
1255         uint32_t rx_size
1256     )
1257     {
1258         uint8_t command;
1259         uint8_t address;
1260         uint8_t size;
1261 
1262         uint8_t * p_response;
1263         uint32_t response_size;
1264 
1265         command = rx_buff[0];
1266         address = rx_buff[1];
1267         size = rx_buff[2];
1268 
1269         p_response = get_response_data(command, address, size, &response_size);
1270 
1271         MSS_SPI_set_cmd_response(&g_mss_spi1, p_response, response_size);
1272     }
1273 
1274     void spi1_block_rx_handler
1275     (
1276         uint8_t * rx_buff,
1277         uint32_t rx_size
1278     )
1279     {
1280         process_rx_data(rx_buff, rx_size);
1281     }
1282   @endcode
1283  */
1284 void MSS_SPI_set_cmd_handler
1285 (
1286     mss_spi_instance_t * this_spi,
1287     mss_spi_block_rx_handler_t cmd_handler,
1288     uint32_t cmd_size
1289 );
1290 
1291 /***************************************************************************//**
1292  The MSS_SPI_set_cmd_response() function specifies the data that will be
1293  returned to the master, when a command has been received by the slave. This
1294  function is called as part of the MSS_SPI_set_cmd_handler().
1295  See the description of MSS_SPI_set_cmd_handler() for more details.
1296 
1297   @param this_spi
1298     The this_spi parameter is a pointer to an mss_spi_instance_t structure
1299     identifying the MSS SPI hardware block used. There are two such data
1300     structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and MSS SPI
1301     1 respectively. This parameter must point to either the g_mss_spi0 or
1302     g_mss_spi1 global data structure defined within the SPI driver.
1303 
1304   @param resp_tx_buffer
1305     The resp_tx_buffer parameter is a pointer to the buffer containing the data
1306     that must be returned to the host in the data phase of a SPI command oriented
1307     transaction.
1308 
1309   @param resp_buff_size
1310     The resp_buff_size parameter specifies the size of the buffer pointed to by
1311     the resp_tx_buffer parameter.
1312  */
1313 void MSS_SPI_set_cmd_response
1314 (
1315     mss_spi_instance_t * this_spi,
1316     const uint8_t * resp_tx_buffer,
1317     uint32_t resp_buff_size
1318 );
1319 
1320 #ifdef __cplusplus
1321 }
1322 #endif
1323 
1324 #endif /* MSS_SPI_H_*/
1325