]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A2F200_IAR_and_Keil/MicroSemi_Code/drivers/mss_spi/mss_spi.c
Add FreeRTOS-Plus directory.
[freertos] / FreeRTOS / Demo / CORTEX_A2F200_IAR_and_Keil / MicroSemi_Code / drivers / mss_spi / mss_spi.c
1 /*******************************************************************************\r
2  * (c) Copyright 2008 Actel Corporation.  All rights reserved.\r
3  * \r
4  * SmartFusion microcontroller subsystem SPI bare metal software driver\r
5  * implementation.\r
6  *\r
7  * SVN $Revision: 2176 $\r
8  * SVN $Date: 2010-02-15 21:04:22 +0000 (Mon, 15 Feb 2010) $\r
9  */\r
10 #include "mss_spi.h"\r
11 #include "../../CMSIS/mss_assert.h"\r
12 \r
13 #ifdef __cplusplus\r
14 extern "C" {\r
15 #endif \r
16 \r
17 /***************************************************************************//**\r
18   MSS SPI can operate as master or slave.\r
19  */\r
20 #define MSS_SPI_MODE_SLAVE      (uint32_t)0\r
21 #define MSS_SPI_MODE_MASTER     (uint32_t)1\r
22 \r
23 /***************************************************************************//**\r
24  * Mask of transfer protocol and SPO, SPH bits within control register.\r
25  */\r
26 #define PROTOCOL_MODE_MASK  (uint32_t)0x030000C0\r
27 \r
28 /***************************************************************************//**\r
29  * Mask of theframe count bits within the SPI control register.\r
30  */\r
31 #define TXRXDFCOUNT_MASK    (uint32_t)0x00FFFF00\r
32 #define TXRXDFCOUNT_SHIFT   (uint32_t)8\r
33 \r
34 /***************************************************************************//**\r
35  * SPI hardware FIFO depth.\r
36  */\r
37 #define RX_FIFO_SIZE    4u\r
38 \r
39 /***************************************************************************//**\r
40   Marker used to detect that the configuration has not been selected for a\r
41   specific slave when operating as a master.\r
42  */\r
43 #define NOT_CONFIGURED  0xFFFFFFFF\r
44 \r
45 /***************************************************************************//**\r
46  * SPI instance data structures for SPI0 and SPI1. A pointer to these data\r
47  * structures must be used as first parameter to any of the SPI driver functions\r
48  * to identify the SPI hardware block that will perform the requested operation.\r
49  */\r
50 mss_spi_instance_t g_mss_spi0;\r
51 mss_spi_instance_t g_mss_spi1;\r
52 \r
53 /***************************************************************************//**\r
54   SPI0 interrupt service routine\r
55  */\r
56 #if defined(__GNUC__)\r
57 __attribute__((__interrupt__)) void SPI0_IRQHandler( void );\r
58 #else\r
59 void SPI0_IRQHandler( void );\r
60 #endif\r
61 \r
62 /***************************************************************************//**\r
63   SPI1 interrupt service routine\r
64  */\r
65 #if defined(__GNUC__)\r
66 __attribute__((__interrupt__)) void SPI1_IRQHandler( void );\r
67 #else\r
68 void SPI1_IRQHandler( void );\r
69 #endif\r
70 \r
71 /***************************************************************************//**\r
72  * MSS_SPI_init()\r
73  * See "mss_spi.h" for details of how to use this function.\r
74  */\r
75 void MSS_SPI_init\r
76 (\r
77         mss_spi_instance_t * this_spi\r
78 )\r
79 {\r
80     uint16_t i;\r
81     \r
82     ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );\r
83     \r
84     if (this_spi == &g_mss_spi0)\r
85     {\r
86         this_spi->hw_reg = SPI0;\r
87         this_spi->hw_reg_bit = SPI0_BITBAND;\r
88         this_spi->irqn = SPI0_IRQn;\r
89 \r
90         /* reset SPI0 */\r
91         SYSREG->SOFT_RST_CR |= SYSREG_SPI0_SOFTRESET_MASK;\r
92         /* Clear any previously pended SPI0 interrupt */\r
93         NVIC_ClearPendingIRQ( SPI0_IRQn );\r
94         /* Take SPI0 out of reset. */\r
95         SYSREG->SOFT_RST_CR &= ~SYSREG_SPI0_SOFTRESET_MASK;\r
96     }\r
97     else\r
98     {\r
99         this_spi->hw_reg = SPI1;\r
100         this_spi->hw_reg_bit = SPI1_BITBAND;\r
101         this_spi->irqn = SPI1_IRQn;\r
102         \r
103         /* reset SPI1 */\r
104         SYSREG->SOFT_RST_CR |= SYSREG_SPI1_SOFTRESET_MASK;\r
105         /* Clear any previously pended SPI1 interrupt */\r
106         NVIC_ClearPendingIRQ( SPI1_IRQn );\r
107         /* Take SPI1 out of reset. */\r
108         SYSREG->SOFT_RST_CR &= ~SYSREG_SPI1_SOFTRESET_MASK;\r
109     }\r
110     \r
111     this_spi->frame_rx_handler = 0U;\r
112     this_spi->slave_tx_frame = 0U;\r
113     \r
114     this_spi->block_rx_handler = 0U;\r
115     \r
116     this_spi->slave_tx_buffer = 0U;\r
117     this_spi->slave_tx_size = 0U;\r
118     this_spi->slave_tx_idx = 0U;\r
119     \r
120     for ( i = 0u; i < (uint16_t)MSS_SPI_MAX_NB_OF_SLAVES; ++i )\r
121     {\r
122         this_spi->slaves_cfg[i].ctrl_reg = NOT_CONFIGURED;\r
123     }\r
124 }\r
125 \r
126 /***************************************************************************//**\r
127  * MSS_SPI_configure_slave_mode()\r
128  * See "mss_spi.h" for details of how to use this function.\r
129  */\r
130 void MSS_SPI_configure_slave_mode\r
131 (\r
132         mss_spi_instance_t * this_spi,\r
133     mss_spi_protocol_mode_t protocol_mode,\r
134     mss_spi_pclk_div_t clk_rate,\r
135     uint8_t frame_bit_length\r
136 )\r
137 {\r
138     ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );\r
139     ASSERT( frame_bit_length <= 32 );\r
140     \r
141         /* Set the mode. */\r
142     this_spi->hw_reg_bit->CTRL_MASTER = MSS_SPI_MODE_SLAVE;\r
143 \r
144     /* Set the clock rate. */\r
145     this_spi->hw_reg_bit->CTRL_ENABLE = 0U;\r
146     this_spi->hw_reg->CONTROL = (this_spi->hw_reg->CONTROL & ~PROTOCOL_MODE_MASK) | (uint32_t)protocol_mode;\r
147     this_spi->hw_reg->CLK_GEN = (uint32_t)clk_rate;\r
148     \r
149     /* Set default frame size to byte size and number of data frames to 1. */\r
150     this_spi->hw_reg->CONTROL = (this_spi->hw_reg->CONTROL & ~TXRXDFCOUNT_MASK) | ((uint32_t)1 << TXRXDFCOUNT_SHIFT);\r
151     this_spi->hw_reg->TXRXDF_SIZE = frame_bit_length;\r
152     this_spi->hw_reg_bit->CTRL_ENABLE = 1U;\r
153 }\r
154 \r
155 /***************************************************************************//**\r
156  * MSS_SPI_configure_master_mode()\r
157  * See "mss_spi.h" for details of how to use this function.\r
158  */\r
159 void MSS_SPI_configure_master_mode\r
160 (\r
161         mss_spi_instance_t *    this_spi,\r
162         mss_spi_slave_t         slave,\r
163     mss_spi_protocol_mode_t protocol_mode,\r
164     mss_spi_pclk_div_t      clk_rate,\r
165     uint8_t                 frame_bit_length\r
166 )\r
167 {\r
168     ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );\r
169     ASSERT( slave < MSS_SPI_MAX_NB_OF_SLAVES );\r
170     ASSERT( frame_bit_length <= 32 );\r
171     \r
172         /* Set the mode. */\r
173     this_spi->hw_reg_bit->CTRL_ENABLE = 0U;\r
174     this_spi->hw_reg_bit->CTRL_MASTER = MSS_SPI_MODE_MASTER;\r
175     this_spi->hw_reg_bit->CTRL_ENABLE = 1U;\r
176 \r
177     /*\r
178      * Keep track of the required register configuration for this slave. These\r
179      * values will be used by the MSS_SPI_set_slave_select() function to configure\r
180      * the master to match the slave being selected.\r
181      */\r
182     if ( slave < MSS_SPI_MAX_NB_OF_SLAVES )     \r
183     {\r
184         this_spi->slaves_cfg[slave].ctrl_reg = 0x00000002uL | (uint32_t)protocol_mode | ((uint32_t)1 << TXRXDFCOUNT_SHIFT);\r
185         this_spi->slaves_cfg[slave].txrxdf_size_reg = frame_bit_length;\r
186         this_spi->slaves_cfg[slave].clk_gen = (uint8_t)clk_rate;\r
187     }\r
188 }\r
189 \r
190 /***************************************************************************//**\r
191  * MSS_SPI_set_slave_select()\r
192  * See "mss_spi.h" for details of how to use this function.\r
193  */\r
194 void MSS_SPI_set_slave_select\r
195 (\r
196         mss_spi_instance_t * this_spi,\r
197         mss_spi_slave_t slave\r
198 )\r
199 {\r
200     ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );\r
201     \r
202     /* This function is only intended to be used with an SPI master. */\r
203     ASSERT( this_spi->hw_reg_bit->CTRL_MASTER == MSS_SPI_MODE_MASTER );\r
204     ASSERT( this_spi->slaves_cfg[slave].ctrl_reg != NOT_CONFIGURED );\r
205 \r
206     /* Set the clock rate. */\r
207     this_spi->hw_reg_bit->CTRL_ENABLE = 0U;\r
208     this_spi->hw_reg->CONTROL = this_spi->slaves_cfg[slave].ctrl_reg;\r
209     this_spi->hw_reg->CLK_GEN = this_spi->slaves_cfg[slave].clk_gen;\r
210     this_spi->hw_reg->TXRXDF_SIZE = this_spi->slaves_cfg[slave].txrxdf_size_reg;\r
211     this_spi->hw_reg_bit->CTRL_ENABLE = 1U;\r
212     \r
213     /* Set slave select */\r
214     this_spi->hw_reg->SLAVE_SELECT |= ((uint32_t)1 << (uint32_t)slave);\r
215 }\r
216 \r
217 /***************************************************************************//**\r
218  * MSS_SPI_clear_slave_select()\r
219  * See "mss_spi.h" for details of how to use this function.\r
220  */\r
221 void MSS_SPI_clear_slave_select\r
222 (\r
223         mss_spi_instance_t * this_spi,\r
224         mss_spi_slave_t slave\r
225 )\r
226 {\r
227     ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );\r
228     \r
229     /* This function is only intended to be used with an SPI master. */\r
230     ASSERT( this_spi->hw_reg_bit->CTRL_MASTER == MSS_SPI_MODE_MASTER );\r
231 \r
232     this_spi->hw_reg->SLAVE_SELECT &= ~((uint32_t)1 << (uint32_t)slave);\r
233 }\r
234 \r
235 /***************************************************************************//**\r
236  * MSS_SPI_transfer_frame()\r
237  * See "mss_spi.h" for details of how to use this function.\r
238  */\r
239 uint32_t MSS_SPI_transfer_frame\r
240 (\r
241     mss_spi_instance_t * this_spi,\r
242     uint32_t tx_bits\r
243 )\r
244 {\r
245     volatile uint32_t dummy;\r
246     \r
247     ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );\r
248     \r
249     /* This function is only intended to be used with an SPI master. */\r
250     ASSERT( this_spi->hw_reg_bit->CTRL_MASTER == MSS_SPI_MODE_MASTER );\r
251     \r
252     /* Flush Rx FIFO. */\r
253     while ( this_spi->hw_reg_bit->STATUS_RX_RDY == 1U )\r
254     {\r
255         dummy = this_spi->hw_reg->RX_DATA;\r
256         dummy = dummy;  /* Prevent Lint warning. */\r
257     }\r
258     \r
259     /* Send frame. */\r
260     this_spi->hw_reg->TX_DATA = tx_bits;\r
261     \r
262     /* Wait for frame Tx to complete. */\r
263     while ( this_spi->hw_reg_bit->STATUS_TX_DONE == 0U )\r
264     {\r
265         ;\r
266     }\r
267     \r
268     /* Read received frame. */\r
269     /* Wait for Rx complete. */\r
270     while ( this_spi->hw_reg_bit->STATUS_RX_RDY == 0U )\r
271     {\r
272         ;\r
273     }\r
274     /* Return Rx data. */\r
275     return( this_spi->hw_reg->RX_DATA );\r
276 }\r
277 \r
278 \r
279 /***************************************************************************//**\r
280  * MSS_SPI_transfer_block()\r
281  * See "mss_spi.h" for details of how to use this function.\r
282  */\r
283 void MSS_SPI_transfer_block\r
284 (\r
285     mss_spi_instance_t * this_spi,\r
286     const uint8_t * cmd_buffer,\r
287     uint16_t cmd_byte_size,\r
288     uint8_t * rd_buffer,\r
289     uint16_t rd_byte_size\r
290 )\r
291 {\r
292     uint16_t transfer_idx = 0U;\r
293     uint16_t tx_idx;\r
294     uint16_t rx_idx;\r
295     uint32_t frame_count;\r
296     volatile uint32_t rx_raw;\r
297     uint16_t transit = 0U;\r
298     \r
299     uint16_t transfer_size;     /* Total number of bytes transfered. */\r
300     \r
301     ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );\r
302     \r
303     /* This function is only intended to be used with an SPI master. */\r
304     ASSERT( this_spi->hw_reg_bit->CTRL_MASTER == MSS_SPI_MODE_MASTER );\r
305     \r
306     /* Compute number of bytes to transfer. */\r
307     transfer_size = cmd_byte_size + rd_byte_size;\r
308     \r
309     /* Adjust to 1 byte transfer to cater for DMA transfers. */\r
310     if ( transfer_size == 0U )\r
311     {\r
312         frame_count = 1U;\r
313     }\r
314     else\r
315     {\r
316         frame_count = transfer_size;\r
317     }\r
318     \r
319     /* Set frame size to 8 bits and the frame count to the tansfer size. */\r
320     this_spi->hw_reg_bit->CTRL_ENABLE = 0U;\r
321     this_spi->hw_reg->CONTROL = (this_spi->hw_reg->CONTROL & ~TXRXDFCOUNT_MASK) | ( (frame_count << TXRXDFCOUNT_SHIFT) & TXRXDFCOUNT_MASK);\r
322     this_spi->hw_reg->TXRXDF_SIZE = 8U;\r
323     this_spi->hw_reg_bit->CTRL_ENABLE = 1U;\r
324 \r
325     /* Flush the receive FIFO. */\r
326     while ( !this_spi->hw_reg_bit->STATUS_RX_FIFO_EMPTY )\r
327     {\r
328         rx_raw = this_spi->hw_reg->RX_DATA;\r
329     }\r
330     \r
331     tx_idx = 0u;\r
332     rx_idx = 0u;\r
333     if ( tx_idx < cmd_byte_size )\r
334     {\r
335         this_spi->hw_reg->TX_DATA = cmd_buffer[tx_idx];\r
336         ++tx_idx;\r
337         ++transit;\r
338     }\r
339     else\r
340     {\r
341         if ( tx_idx < transfer_size )\r
342         {\r
343             this_spi->hw_reg->TX_DATA = 0x00U;\r
344             ++tx_idx;\r
345             ++transit;\r
346         }\r
347     }\r
348     /* Perform the remainder of the transfer by sending a byte every time a byte\r
349      * has been received. This should ensure that no Rx overflow can happen in\r
350      * case of an interrupt occurs during this function. */\r
351     while ( transfer_idx < transfer_size )\r
352     {\r
353         if ( !this_spi->hw_reg_bit->STATUS_RX_FIFO_EMPTY )\r
354         {\r
355             /* Process received byte. */\r
356             rx_raw = this_spi->hw_reg->RX_DATA;\r
357             if ( transfer_idx >= cmd_byte_size )\r
358             {\r
359                 if ( rx_idx < rd_byte_size )\r
360                 {\r
361                     rd_buffer[rx_idx] = (uint8_t)rx_raw;   \r
362                 }\r
363                 ++rx_idx;\r
364             }\r
365             ++transfer_idx;\r
366             --transit;\r
367         }\r
368 \r
369         if ( !this_spi->hw_reg_bit->STATUS_TX_FIFO_FULL )\r
370         {\r
371             if (transit < RX_FIFO_SIZE)\r
372             {\r
373                 /* Send another byte. */\r
374                 if ( tx_idx < cmd_byte_size )\r
375                 {\r
376                     this_spi->hw_reg->TX_DATA = cmd_buffer[tx_idx];\r
377                     ++tx_idx;\r
378                     ++transit;\r
379                 }\r
380                 else\r
381                 {\r
382                     if ( tx_idx < transfer_size )\r
383                     {\r
384                         this_spi->hw_reg->TX_DATA = 0x00U;\r
385                         ++tx_idx;\r
386                         ++transit;\r
387                     }\r
388                 }\r
389             }\r
390         }\r
391     }\r
392 }\r
393 \r
394 /***************************************************************************//**\r
395  * MSS_SPI_set_frame_rx_handler()\r
396  * See "mss_spi.h" for details of how to use this function.\r
397  */\r
398 void MSS_SPI_set_frame_rx_handler\r
399 (\r
400     mss_spi_instance_t * this_spi,\r
401     mss_spi_frame_rx_handler_t rx_handler\r
402 )\r
403 {\r
404     ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );\r
405     \r
406     /* This function is only intended to be used with an SPI slave. */\r
407     ASSERT( this_spi->hw_reg_bit->CTRL_MASTER == MSS_SPI_MODE_SLAVE );\r
408     \r
409     /* Disable block Rx handler as they are mutually exclusive. */\r
410     this_spi->block_rx_handler = 0U;\r
411     \r
412     /* Keep a copy of the pointer to the rx hnadler function. */\r
413     this_spi->frame_rx_handler = rx_handler;\r
414     \r
415     /* Enable Rx interrupt. */\r
416     this_spi->hw_reg_bit->CTRL_RX_INT_EN = 1U;\r
417     NVIC_EnableIRQ( this_spi->irqn );\r
418 }\r
419 \r
420 /***************************************************************************//**\r
421  * MSS_SPI_set_slave_tx_frame()\r
422  * See "mss_spi.h" for details of how to use this function.\r
423  */\r
424 void MSS_SPI_set_slave_tx_frame\r
425 (\r
426     mss_spi_instance_t * this_spi,\r
427     uint32_t frame_value\r
428 )\r
429 {\r
430     ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );\r
431 \r
432     /* This function is only intended to be used with an SPI slave. */\r
433     ASSERT( this_spi->hw_reg_bit->CTRL_MASTER == MSS_SPI_MODE_SLAVE );\r
434     \r
435     /* Disable slave block tx buffer as it is mutually exclusive with frame\r
436      * level handling. */    \r
437     this_spi->slave_tx_buffer = 0U;\r
438     this_spi->slave_tx_size = 0U;\r
439     this_spi->slave_tx_idx = 0U;\r
440     \r
441     /* Keep a copy of the slave tx frame value. */\r
442     this_spi->slave_tx_frame = frame_value;\r
443     \r
444     /* Load frame into Tx data register. */\r
445     this_spi->hw_reg->TX_DATA = this_spi->slave_tx_frame;\r
446     \r
447     /* Enable Tx Done interrupt in order to reload the slave Tx frame after each\r
448      * time it has been sent. */\r
449     this_spi->hw_reg_bit->CTRL_TX_INT_EN = 1U;\r
450     NVIC_EnableIRQ( this_spi->irqn );\r
451 }\r
452 \r
453 /***************************************************************************//**\r
454  * MSS_SPI_set_slave_block_buffers()\r
455  * See "mss_spi.h" for details of how to use this function.\r
456  */\r
457 void MSS_SPI_set_slave_block_buffers\r
458 (\r
459     mss_spi_instance_t * this_spi,\r
460     const uint8_t * tx_buffer,\r
461     uint32_t tx_buff_size,\r
462     uint8_t * rx_buffer,\r
463     uint32_t rx_buff_size,\r
464     mss_spi_block_rx_handler_t block_rx_handler\r
465 )\r
466 {\r
467     uint32_t frame_count;\r
468     \r
469     ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );\r
470     \r
471     /* This function is only intended to be used with an SPI slave. */\r
472     ASSERT( this_spi->hw_reg_bit->CTRL_MASTER == MSS_SPI_MODE_SLAVE );\r
473     \r
474     /* Disable Rx frame handler as it is mutually exclusive with block rx handler. */\r
475     this_spi->frame_rx_handler = 0U;\r
476     \r
477     /* Keep a copy of the pointer to the block rx handler function. */\r
478     this_spi->block_rx_handler = block_rx_handler;\r
479     \r
480     this_spi->slave_rx_buffer = rx_buffer;\r
481     this_spi->slave_rx_size = rx_buff_size;\r
482     this_spi->slave_rx_idx = 0U;\r
483     \r
484     /**/\r
485     this_spi->slave_tx_buffer = tx_buffer;\r
486     this_spi->slave_tx_size = tx_buff_size;\r
487     this_spi->slave_tx_idx = 0U;\r
488 \r
489     frame_count = rx_buff_size;\r
490     \r
491     /**/\r
492     this_spi->hw_reg_bit->CTRL_ENABLE = 0U;\r
493     this_spi->hw_reg->CONTROL = (this_spi->hw_reg->CONTROL & ~TXRXDFCOUNT_MASK) | (frame_count << TXRXDFCOUNT_SHIFT);\r
494     this_spi->hw_reg->TXRXDF_SIZE = 8U;\r
495     this_spi->hw_reg_bit->CTRL_ENABLE = 1U;\r
496     \r
497     /* Load the transmit FIFO. */\r
498     while ( !(this_spi->hw_reg_bit->STATUS_TX_FIFO_FULL) && ( this_spi->slave_tx_idx < this_spi->slave_tx_size ) )\r
499     {\r
500         this_spi->hw_reg->TX_DATA = this_spi->slave_tx_buffer[this_spi->slave_tx_idx];\r
501         ++this_spi->slave_tx_idx;\r
502     }\r
503     \r
504     /* Enable Rx interrupt. */\r
505     this_spi->hw_reg_bit->CTRL_RX_INT_EN = 1U;\r
506     NVIC_EnableIRQ( this_spi->irqn );\r
507 }\r
508 \r
509 /***************************************************************************//**\r
510  * SPI interrupt service routine.\r
511  */\r
512 static void mss_spi_isr\r
513 (\r
514     mss_spi_instance_t * this_spi\r
515 )\r
516 {\r
517     uint32_t rx_frame;\r
518     \r
519     ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );\r
520     \r
521     if ( this_spi->hw_reg_bit->MIS_RX_RDY )\r
522     {\r
523         while( !this_spi->hw_reg_bit->STATUS_RX_FIFO_EMPTY )\r
524         {\r
525             rx_frame = this_spi->hw_reg->RX_DATA;\r
526             if ( this_spi->frame_rx_handler != 0U )\r
527             {\r
528                 /* Single frame handling mode. */\r
529                 this_spi->frame_rx_handler( rx_frame );\r
530             }\r
531             else \r
532             {\r
533                 if ( this_spi->block_rx_handler != 0U )\r
534                 {\r
535                     /* Block handling mode. */\r
536                     if ( this_spi->slave_rx_idx < this_spi->slave_rx_size )\r
537                     {\r
538                         this_spi->slave_rx_buffer[this_spi->slave_rx_idx] = (uint8_t)rx_frame;\r
539                         ++this_spi->slave_rx_idx;\r
540                         if ( this_spi->slave_rx_idx == this_spi->slave_rx_size )\r
541                         {\r
542                             (*this_spi->block_rx_handler)( this_spi->slave_rx_buffer, this_spi->slave_rx_size );\r
543                         }\r
544                     }\r
545                 }\r
546             }\r
547             \r
548             /* Feed transmit FIFO. */\r
549             if ( !(this_spi->hw_reg_bit->STATUS_TX_FIFO_FULL) && ( this_spi->slave_tx_idx < this_spi->slave_tx_size ) )\r
550             {\r
551                 this_spi->hw_reg->TX_DATA = this_spi->slave_tx_buffer[this_spi->slave_tx_idx];\r
552                 ++this_spi->slave_tx_idx;\r
553             }\r
554         }\r
555         this_spi->hw_reg_bit->INT_CLEAR_RX_RDY = 1U;\r
556     }\r
557     \r
558     if ( this_spi->hw_reg_bit->MIS_TX_DONE )\r
559     {\r
560         if ( this_spi->slave_tx_buffer != 0U )\r
561         {\r
562             this_spi->hw_reg->TX_DATA = this_spi->slave_tx_buffer[this_spi->slave_tx_idx];\r
563             ++this_spi->slave_tx_idx;\r
564             if ( this_spi->slave_tx_idx >= this_spi->slave_tx_size )\r
565             {\r
566                 this_spi->slave_tx_idx = 0U;\r
567             }\r
568         }\r
569         else\r
570         {\r
571             /* Reload slave tx frame into Tx data register. */\r
572             this_spi->hw_reg->TX_DATA = this_spi->slave_tx_frame;\r
573         }\r
574     }\r
575 }\r
576 \r
577 /***************************************************************************//**\r
578  * SPIO interrupt service routine.\r
579  * Please note that the name of this ISR is defined as part of the SmartFusion\r
580  * CMSIS startup code.\r
581  */\r
582 #if defined(__GNUC__)\r
583 __attribute__((__interrupt__)) void SPI0_IRQHandler( void )\r
584 #else\r
585 void SPI0_IRQHandler( void )\r
586 #endif\r
587 {\r
588     mss_spi_isr( &g_mss_spi0 );\r
589     NVIC_ClearPendingIRQ( SPI0_IRQn );\r
590 }\r
591 \r
592 /***************************************************************************//**\r
593  * SPI1 interrupt service routine.\r
594  * Please note that the name of this ISR is defined as part of the SmartFusion\r
595  * CMSIS startup code.\r
596  */\r
597 #if defined(__GNUC__)\r
598 __attribute__((__interrupt__)) void SPI1_IRQHandler( void )\r
599 #else\r
600 void SPI1_IRQHandler( void )\r
601 #endif\r
602 {\r
603     mss_spi_isr( &g_mss_spi1 );\r
604     NVIC_ClearPendingIRQ( SPI1_IRQn );\r
605 }\r
606 \r
607 #ifdef __cplusplus\r
608 }\r
609 #endif\r
610 \r