]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M7_SAMV71_Xplained_IAR_Keil/libchip_samv7/source/twid.c
Final V8.2.1 release ready for tagging:
[freertos] / FreeRTOS / Demo / CORTEX_M7_SAMV71_Xplained_IAR_Keil / libchip_samv7 / source / twid.c
1 /* ----------------------------------------------------------------------------\r
2  *         SAM Software Package License\r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2011, Atmel Corporation\r
5  *\r
6  * All rights reserved.\r
7  *\r
8  * Redistribution and use in source and binary forms, with or without\r
9  * modification, are permitted provided that the following conditions are met:\r
10  *\r
11  * - Redistributions of source code must retain the above copyright notice,\r
12  * this list of conditions and the disclaimer below.\r
13  *\r
14  * Atmel's name may not be used to endorse or promote products derived from\r
15  * this software without specific prior written permission.\r
16  *\r
17  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR\r
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
20  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,\r
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
23  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
24  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  * ----------------------------------------------------------------------------\r
28  */\r
29 \r
30 \r
31 /*----------------------------------------------------------------------------\r
32  *        Headers\r
33  *----------------------------------------------------------------------------*/\r
34 #include "chip.h"\r
35 \r
36 #include <assert.h>\r
37 \r
38 /*----------------------------------------------------------------------------\r
39  *        Definition\r
40  *----------------------------------------------------------------------------*/\r
41 #define TWITIMEOUTMAX 50000\r
42 static sXdmad twi_dma;\r
43 static sXdmadCfg twi_dmaCfg;\r
44 static uint32_t dmaWriteChannel,dmaReadChannel;\r
45 static LinkedListDescriporView1 dmaWriteLinkList[1];\r
46 static LinkedListDescriporView1 dmaReadLinkList[1];\r
47 /*----------------------------------------------------------------------------\r
48  *        Types\r
49  *----------------------------------------------------------------------------*/\r
50 \r
51 /** TWI driver callback function.*/\r
52 typedef void (*TwiCallback)(Async *);\r
53 \r
54 /** \brief TWI asynchronous transfer descriptor.*/\r
55 typedef struct _AsyncTwi {\r
56 \r
57     /** Asynchronous transfer status. */\r
58     volatile uint8_t status;\r
59     // Callback function to invoke when transfer completes or fails.*/\r
60     TwiCallback callback;\r
61     /** Pointer to the data buffer.*/\r
62     uint8_t *pData;\r
63     /** Total number of bytes to transfer.*/\r
64     uint32_t num;\r
65     /** Number of already transferred bytes.*/\r
66     uint32_t transferred;\r
67 \r
68 } AsyncTwi;\r
69 \r
70 /**\r
71  * \brief Initializes a TWI DMA Read channel.\r
72  */\r
73 static void TWID_DmaInitializeRead(uint8_t TWI_ID)\r
74 {\r
75     \r
76     /* Allocate a XDMA channel, Read accesses into TWI_THR */\r
77     dmaReadChannel = XDMAD_AllocateChannel( &twi_dma, TWI_ID, XDMAD_TRANSFER_MEMORY);\r
78     if ( dmaReadChannel == XDMAD_ALLOC_FAILED )\r
79     {\r
80         printf("-E- Can't allocate XDMA channel\n\r");\r
81     }\r
82     XDMAD_PrepareChannel(&twi_dma, dmaReadChannel );\r
83 }\r
84 \r
85 /**\r
86  * \brief Initializes a TWI DMA write channel.\r
87  */\r
88 static void TWID_DmaInitializeWrite(uint8_t TWI_ID)\r
89 {\r
90     \r
91     /* Allocate a XDMA channel, Write accesses into TWI_THR */\r
92     dmaWriteChannel = XDMAD_AllocateChannel( &twi_dma, XDMAD_TRANSFER_MEMORY, TWI_ID);\r
93     if ( dmaWriteChannel == XDMAD_ALLOC_FAILED )\r
94     {\r
95         printf("-E- Can't allocate XDMA channel\n\r");\r
96     }\r
97     XDMAD_PrepareChannel(&twi_dma, dmaWriteChannel );\r
98 \r
99    \r
100 }\r
101 \r
102 /**\r
103  * \brief Configure xDMA write linker list for TWI transfer.\r
104  */\r
105 static void TWID_XdmaConfigureWrite(uint8_t *buf, uint32_t len, uint8_t TWI_ID)\r
106 {\r
107     uint32_t i;\r
108     uint32_t xdmaCndc, Thr;\r
109     \r
110     Thr = (uint32_t)&(TWI0->TWIHS_THR);\r
111     if(TWI_ID==ID_TWI1)\r
112     {\r
113       Thr = (uint32_t)&(TWI1->TWIHS_THR);\r
114     }\r
115     if(TWI_ID==ID_TWI2)\r
116     {\r
117       Thr = (uint32_t)&(TWI2->TWIHS_THR);\r
118     }\r
119     for ( i = 0; i < 1; i++){\r
120         dmaWriteLinkList[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1 \r
121                                     |(( i == len - 1) ? 0: XDMA_UBC_NDE_FETCH_EN)\r
122                                     | len ;\r
123         dmaWriteLinkList[i].mbr_sa = (uint32_t)&buf[i];\r
124         dmaWriteLinkList[i].mbr_da = Thr;\r
125         if ( i == len - 1) dmaWriteLinkList[i].mbr_nda = 0;\r
126             else dmaWriteLinkList[i].mbr_nda = (uint32_t)&dmaWriteLinkList[ i + 1 ];\r
127         }\r
128         twi_dmaCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN \r
129                          | XDMAC_CC_MBSIZE_SINGLE \r
130                          | XDMAC_CC_DSYNC_MEM2PER \r
131                          | XDMAC_CC_CSIZE_CHK_1 \r
132                          | XDMAC_CC_DWIDTH_BYTE\r
133                          | XDMAC_CC_SIF_AHB_IF0 \r
134                          | XDMAC_CC_DIF_AHB_IF1 \r
135                          | XDMAC_CC_SAM_INCREMENTED_AM \r
136                          | XDMAC_CC_DAM_FIXED_AM \r
137                          | XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(TWI_ID, XDMAD_TRANSFER_TX ));\r
138         xdmaCndc = XDMAC_CNDC_NDVIEW_NDV1 \r
139                  | XDMAC_CNDC_NDE_DSCR_FETCH_EN \r
140                  | XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED\r
141                  | XDMAC_CNDC_NDDUP_DST_PARAMS_UNCHANGED ;\r
142         memory_barrier();\r
143         XDMAD_ConfigureTransfer( &twi_dma, dmaWriteChannel, &twi_dmaCfg, xdmaCndc, (uint32_t)&dmaWriteLinkList[0]);\r
144         memory_barrier();\r
145 }\r
146 \r
147 \r
148 /**\r
149  * \brief Configure xDMA read linker list for TWI transfer.\r
150  */\r
151 static void TWID_XdmaConfigureRead(uint8_t *buf, uint32_t len, uint8_t TWI_ID)\r
152 {\r
153     uint32_t i;\r
154     uint32_t xdmaCndc, Rhr;\r
155     \r
156     Rhr = (uint32_t)&(TWI0->TWIHS_RHR);\r
157     if(TWI_ID==ID_TWI1)\r
158     {\r
159       Rhr = (uint32_t)&(TWI1->TWIHS_RHR);\r
160     }\r
161     if(TWI_ID==ID_TWI2)\r
162     {\r
163       Rhr = (uint32_t)&(TWI2->TWIHS_RHR);\r
164     }\r
165     for ( i = 0; i < 1; i++){\r
166         dmaReadLinkList[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1 \r
167                                | (( i == len - 1) ? 0: XDMA_UBC_NDE_FETCH_EN)\r
168                                | len ;\r
169         dmaReadLinkList[i].mbr_sa  = Rhr;\r
170         dmaReadLinkList[i].mbr_da = (uint32_t)&buf[i];\r
171         if ( i == len - 1)\r
172              dmaReadLinkList[i].mbr_nda = 0;\r
173         else\r
174              dmaReadLinkList[i].mbr_nda = (uint32_t)&dmaReadLinkList[ i + 1 ];\r
175         }\r
176         twi_dmaCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN \r
177                          | XDMAC_CC_MBSIZE_SINGLE \r
178                          | XDMAC_CC_DSYNC_PER2MEM \r
179                          | XDMAC_CC_CSIZE_CHK_1 \r
180                          | XDMAC_CC_DWIDTH_BYTE\r
181                          | XDMAC_CC_SIF_AHB_IF1 \r
182                          | XDMAC_CC_DIF_AHB_IF0 \r
183                          | XDMAC_CC_SAM_FIXED_AM \r
184                          | XDMAC_CC_DAM_INCREMENTED_AM \r
185                          | XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(TWI_ID, XDMAD_TRANSFER_RX ));\r
186         xdmaCndc = XDMAC_CNDC_NDVIEW_NDV1 \r
187                  | XDMAC_CNDC_NDE_DSCR_FETCH_EN \r
188                  | XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED\r
189                  | XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED ;\r
190         memory_barrier();\r
191         XDMAD_ConfigureTransfer( &twi_dma, dmaReadChannel, &twi_dmaCfg, xdmaCndc, (uint32_t)&dmaReadLinkList[0]);\r
192         memory_barrier();\r
193 }\r
194 \r
195 /*----------------------------------------------------------------------------\r
196  *        Global functions\r
197  *----------------------------------------------------------------------------*/\r
198 \r
199  /**\r
200  * \brief Returns 1 if the given transfer has ended; otherwise returns 0.\r
201  * \param pAsync  Pointer to an Async instance.\r
202  */\r
203 uint32_t ASYNC_IsFinished( Async* pAsync )\r
204 {\r
205     return (pAsync->status != ASYNC_STATUS_PENDING) ;\r
206 }\r
207 \r
208 \r
209 \r
210 /**\r
211  * \brief Initializes a TWI driver instance, using the given TWI peripheral.\r
212  * \note The peripheral must have been initialized properly before calling this function.\r
213  * \param pTwid  Pointer to the Twid instance to initialize.\r
214  * \param pTwi  Pointer to the TWI peripheral to use.\r
215  */\r
216 void TWID_Initialize(Twid *pTwid, Twihs *pTwi)\r
217 {\r
218     TRACE_DEBUG( "TWID_Initialize()\n\r" ) ;\r
219     assert( pTwid != NULL ) ;\r
220     assert( pTwi != NULL ) ;\r
221 \r
222     /* Initialize driver. */\r
223     pTwid->pTwi = pTwi;\r
224     pTwid->pTransfer = 0;\r
225 }\r
226 \r
227 \r
228 /**\r
229  * \brief Interrupt handler for a TWI peripheral. Manages asynchronous transfer\r
230  * occuring on the bus. This function MUST be called by the interrupt service\r
231  * routine of the TWI peripheral if asynchronous read/write are needed.\r
232   * \param pTwid  Pointer to a Twid instance.\r
233  */\r
234 void TWID_Handler( Twid *pTwid )\r
235 {\r
236     uint8_t status;\r
237     AsyncTwi *pTransfer ;\r
238     Twihs *pTwi ;\r
239 \r
240     assert( pTwid != NULL ) ;\r
241 \r
242     pTransfer = (AsyncTwi*)pTwid->pTransfer ;\r
243     assert( pTransfer != NULL ) ;\r
244     pTwi = pTwid->pTwi ;\r
245     assert( pTwi != NULL ) ;\r
246 \r
247     /* Retrieve interrupt status */\r
248     status = TWI_GetMaskedStatus(pTwi);\r
249 \r
250     /* Byte received */\r
251     if (TWI_STATUS_RXRDY(status)) {\r
252 \r
253         pTransfer->pData[pTransfer->transferred] = TWI_ReadByte(pTwi);\r
254         pTransfer->transferred++;\r
255 \r
256         /* check for transfer finish */\r
257         if (pTransfer->transferred == pTransfer->num) {\r
258 \r
259             TWI_DisableIt(pTwi, TWIHS_IDR_RXRDY);\r
260             TWI_EnableIt(pTwi, TWIHS_IER_TXCOMP);\r
261         }\r
262         /* Last byte? */\r
263         else if (pTransfer->transferred == (pTransfer->num - 1)) {\r
264 \r
265             TWI_Stop(pTwi);\r
266         }\r
267     }\r
268     /* Byte sent*/\r
269     else if (TWI_STATUS_TXRDY(status)) {\r
270 \r
271         /* Transfer finished ? */\r
272         if (pTransfer->transferred == pTransfer->num) {\r
273 \r
274             TWI_DisableIt(pTwi, TWIHS_IDR_TXRDY);\r
275             TWI_EnableIt(pTwi, TWIHS_IER_TXCOMP);\r
276             TWI_SendSTOPCondition(pTwi);\r
277         }\r
278         /* Bytes remaining */\r
279         else {\r
280 \r
281             TWI_WriteByte(pTwi, pTransfer->pData[pTransfer->transferred]);\r
282             pTransfer->transferred++;\r
283         }\r
284     }\r
285     /* Transfer complete*/\r
286     else if (TWI_STATUS_TXCOMP(status)) {\r
287 \r
288         TWI_DisableIt(pTwi, TWIHS_IDR_TXCOMP);\r
289         pTransfer->status = 0;\r
290         if (pTransfer->callback) {\r
291 \r
292             pTransfer->callback((Async *) pTransfer);\r
293         }\r
294         pTwid->pTransfer = 0;\r
295     }\r
296 }\r
297 \r
298 /**\r
299  * \brief Asynchronously reads data from a slave on the TWI bus. An optional\r
300  * callback function is triggered when the transfer is complete.\r
301  * \param pTwid  Pointer to a Twid instance.\r
302  * \param address  TWI slave address.\r
303  * \param iaddress  Optional slave internal address.\r
304  * \param isize  Internal address size in bytes.\r
305  * \param pData  Data buffer for storing received bytes.\r
306  * \param num  Number of bytes to read.\r
307  * \param pAsync  Asynchronous transfer descriptor.\r
308  * \return 0 if the transfer has been started; otherwise returns a TWI error code.\r
309  */\r
310 uint8_t TWID_Read(\r
311     Twid *pTwid,\r
312     uint8_t address,\r
313     uint32_t iaddress,\r
314     uint8_t isize,\r
315     uint8_t *pData,\r
316     uint32_t num,\r
317     Async *pAsync)\r
318 {\r
319     Twihs *pTwi;\r
320     AsyncTwi *pTransfer;\r
321     uint32_t timeout;\r
322 \r
323     assert( pTwid != NULL ) ;\r
324     pTwi = pTwid->pTwi;\r
325     pTransfer = (AsyncTwi *) pTwid->pTransfer;\r
326 \r
327     assert( (address & 0x80) == 0 ) ;\r
328     assert( (iaddress & 0xFF000000) == 0 ) ;\r
329     assert( isize < 4 ) ;\r
330 \r
331     /* Check that no transfer is already pending*/\r
332     if (pTransfer) {\r
333 \r
334         TRACE_ERROR("TWID_Read: A transfer is already pending\n\r");\r
335         return TWID_ERROR_BUSY;\r
336     }\r
337 \r
338     /* Set STOP signal if only one byte is sent*/\r
339     if (num == 1) {\r
340 \r
341         TWI_Stop(pTwi);\r
342     }\r
343 \r
344     /* Asynchronous transfer*/\r
345     if (pAsync) {\r
346 \r
347         /* Update the transfer descriptor */\r
348         pTwid->pTransfer = pAsync;\r
349         pTransfer = (AsyncTwi *) pAsync;\r
350         pTransfer->status = ASYNC_STATUS_PENDING;\r
351         pTransfer->pData = pData;\r
352         pTransfer->num = num;\r
353         pTransfer->transferred = 0;\r
354 \r
355         /* Enable read interrupt and start the transfer */\r
356         TWI_EnableIt(pTwi, TWIHS_IER_RXRDY);\r
357         TWI_StartRead(pTwi, address, iaddress, isize);\r
358     }\r
359     /* Synchronous transfer*/\r
360     else {\r
361 \r
362         /* Start read*/\r
363         TWI_StartRead(pTwi, address, iaddress, isize);\r
364 \r
365         /* Read all bytes, setting STOP before the last byte*/\r
366         while (num > 0) {\r
367 \r
368             /* Last byte ?*/\r
369             if (num == 1) {\r
370 \r
371                 TWI_Stop(pTwi);\r
372             }\r
373 \r
374             /* Wait for byte then read and store it*/\r
375             timeout = 0;\r
376             while( !TWI_ByteReceived(pTwi) && (++timeout<TWITIMEOUTMAX) );\r
377             if (timeout == TWITIMEOUTMAX) {\r
378                 TRACE_ERROR("TWID Timeout BR\n\r");\r
379             }\r
380             *pData++ = TWI_ReadByte(pTwi);\r
381             num--;\r
382         }\r
383 \r
384         /* Wait for transfer to be complete */\r
385         timeout = 0;\r
386         while( !TWI_TransferComplete(pTwi) && (++timeout<TWITIMEOUTMAX) );\r
387         if (timeout == TWITIMEOUTMAX) {\r
388             TRACE_ERROR("TWID Timeout TC\n\r");\r
389         }\r
390     }\r
391 \r
392     return 0;\r
393 }\r
394 \r
395 /**\r
396  * \brief Asynchronously sends data to a slave on the TWI bus. An optional callback\r
397  * function is invoked whenever the transfer is complete.\r
398  * \param pTwid  Pointer to a Twid instance.\r
399  * \param address  TWI slave address.\r
400  * \param iaddress  Optional slave internal address.\r
401  * \param isize  Number of internal address bytes.\r
402  * \param pData  Data buffer for storing received bytes.\r
403  * \param num  Data buffer to send.\r
404  * \param pAsync  Asynchronous transfer descriptor.\r
405  * \return 0 if the transfer has been started; otherwise returns a TWI error code.\r
406  */\r
407 uint8_t TWID_Write(\r
408     Twid *pTwid,\r
409     uint8_t address,\r
410     uint32_t iaddress,\r
411     uint8_t isize,\r
412     uint8_t *pData,\r
413     uint32_t num,\r
414     Async *pAsync)\r
415 {\r
416     Twihs *pTwi = pTwid->pTwi;\r
417     AsyncTwi *pTransfer = (AsyncTwi *) pTwid->pTransfer;\r
418     uint32_t timeout;\r
419 \r
420     assert( pTwi != NULL ) ;\r
421     assert( (address & 0x80) == 0 ) ;\r
422     assert( (iaddress & 0xFF000000) == 0 ) ;\r
423     assert( isize < 4 ) ;\r
424 \r
425     /* Check that no transfer is already pending */\r
426     if (pTransfer) {\r
427 \r
428         TRACE_ERROR("TWI_Write: A transfer is already pending\n\r");\r
429         return TWID_ERROR_BUSY;\r
430     }\r
431 \r
432     /* Asynchronous transfer */\r
433     if (pAsync) {\r
434 \r
435         /* Update the transfer descriptor */\r
436         pTwid->pTransfer = pAsync;\r
437         pTransfer = (AsyncTwi *) pAsync;\r
438         pTransfer->status = ASYNC_STATUS_PENDING;\r
439         pTransfer->pData = pData;\r
440         pTransfer->num = num;\r
441         pTransfer->transferred = 1;\r
442 \r
443         /* Enable write interrupt and start the transfer */\r
444         TWI_StartWrite(pTwi, address, iaddress, isize, *pData);\r
445         TWI_EnableIt(pTwi, TWIHS_IER_TXRDY);\r
446     }\r
447     /* Synchronous transfer*/\r
448     else {\r
449 \r
450         // Start write\r
451         TWI_StartWrite(pTwi, address, iaddress, isize, *pData++);\r
452         num--;\r
453 \r
454         /* Send all bytes */\r
455         while (num > 0) {\r
456 \r
457             /* Wait before sending the next byte */\r
458             timeout = 0;\r
459             while( !TWI_ByteSent(pTwi) && (++timeout<TWITIMEOUTMAX) );\r
460             if (timeout == TWITIMEOUTMAX) {\r
461                 TRACE_ERROR("TWID Timeout BS\n\r");\r
462             }\r
463 \r
464             TWI_WriteByte(pTwi, *pData++);\r
465             num--;\r
466         }\r
467 \r
468         /* Wait for actual end of transfer */\r
469         timeout = 0;\r
470 \r
471         /* Send a STOP condition */\r
472         TWI_SendSTOPCondition(pTwi);\r
473 \r
474         while( !TWI_TransferComplete(pTwi) && (++timeout<TWITIMEOUTMAX) );\r
475         if (timeout == TWITIMEOUTMAX) {\r
476             TRACE_ERROR("TWID Timeout TC2\n\r");\r
477         }\r
478 \r
479     }\r
480 \r
481     return 0;\r
482 }\r
483 \r
484 /**\r
485  * \brief Initializes a TWI driver instance, using the given TWI peripheral.\r
486  * \note The peripheral must have been initialized properly before calling this function.\r
487  * \param pTwid  Pointer to the Twid instance to initialize.\r
488  * \param pTwi  Pointer to the TWI peripheral to use.\r
489  */\r
490 void TWID_DmaInitialize(Twid *pTwid, Twihs *pTwi)\r
491 {\r
492     TRACE_DEBUG( "TWID_Initialize()\n\r" ) ;\r
493     assert( pTwid != NULL ) ;\r
494     assert( pTwi != NULL ) ;\r
495 \r
496     /* Initialize driver. */\r
497     pTwid->pTwi = pTwi;\r
498     pTwid->pTransfer = 0;\r
499     \r
500     /* Initialize XDMA driver instance with polling mode */\r
501     XDMAD_Initialize( &twi_dma, 1 );\r
502 }\r
503 \r
504 /**\r
505  * \brief Asynchronously reads data from a slave on the TWI bus. An optional\r
506  * callback function is triggered when the transfer is complete.\r
507  * \param pTwid  Pointer to a Twid instance.\r
508  * \param address  TWI slave address.\r
509  * \param iaddress  Optional slave internal address.\r
510  * \param isize  Internal address size in bytes.\r
511  * \param pData  Data buffer for storing received bytes.\r
512  * \param num  Number of bytes to read.\r
513  * \param pAsync  Asynchronous transfer descriptor.\r
514  * \param TWI_ID  TWI ID for TWI0, TWI1, TWI2.\r
515  * \return 0 if the transfer has been started; otherwise returns a TWI error code.\r
516  */\r
517 uint8_t TWID_DmaRead(\r
518     Twid *pTwid,\r
519     uint8_t address,\r
520     uint32_t iaddress,\r
521     uint8_t isize,\r
522     uint8_t *pData,\r
523     uint32_t num,\r
524     Async *pAsync,\r
525     uint8_t TWI_ID)\r
526 {\r
527     Twihs *pTwi;\r
528     AsyncTwi *pTransfer;\r
529     uint32_t timeout = 0;\r
530     uint32_t status;\r
531 \r
532     assert( pTwid != NULL ) ;\r
533     pTwi = pTwid->pTwi;\r
534     pTransfer = (AsyncTwi *) pTwid->pTransfer;\r
535 \r
536     assert( (address & 0x80) == 0 ) ;\r
537     assert( (iaddress & 0xFF000000) == 0 ) ;\r
538     assert( isize < 4 ) ;\r
539 \r
540     /* Check that no transfer is already pending*/\r
541     if (pTransfer) {\r
542 \r
543         TRACE_ERROR("TWID_Read: A transfer is already pending\n\r");\r
544         return TWID_ERROR_BUSY;\r
545     }\r
546 \r
547     /* Asynchronous transfer*/\r
548     if (pAsync) {\r
549 \r
550         /* Update the transfer descriptor */\r
551         pTwid->pTransfer = pAsync;\r
552         pTransfer = (AsyncTwi *) pAsync;\r
553         pTransfer->status = ASYNC_STATUS_PENDING;\r
554         pTransfer->pData = pData;\r
555         pTransfer->num = num;\r
556         pTransfer->transferred = 0;\r
557 \r
558         /* Enable read interrupt and start the transfer */\r
559         TWI_EnableIt(pTwi, TWI_IER_RXRDY);\r
560         TWI_StartRead(pTwi, address, iaddress, isize);\r
561     }\r
562     /* Synchronous transfer*/\r
563     else {\r
564 \r
565         TWID_DmaInitializeRead(TWI_ID);\r
566         TWID_XdmaConfigureRead(pData, num, TWI_ID);\r
567         /* Start read*/\r
568         XDMAD_StartTransfer( &twi_dma, dmaReadChannel );\r
569         \r
570         TWI_StartRead(pTwi, address, iaddress, isize);   \r
571         \r
572         while((XDMAD_IsTransferDone(&twi_dma, dmaReadChannel)) && (++timeout<TWITIMEOUTMAX));\r
573         \r
574         XDMAD_StopTransfer( &twi_dma, dmaReadChannel );\r
575         \r
576         status = TWI_GetStatus(pTwi);\r
577         timeout=0;\r
578         while( !(status & TWI_SR_RXRDY) && (++timeout<TWITIMEOUTMAX));\r
579         \r
580         TWI_Stop(pTwi);\r
581         \r
582         TWI_ReadByte(pTwi);\r
583         \r
584         status = TWI_GetStatus(pTwi);\r
585         timeout=0;\r
586         while( !(status & TWI_SR_RXRDY) && (++timeout<TWITIMEOUTMAX));\r
587         \r
588         TWI_ReadByte(pTwi);\r
589         \r
590         status = TWI_GetStatus(pTwi);\r
591         timeout=0;\r
592         while( !(status & TWI_SR_TXCOMP) && (++timeout<TWITIMEOUTMAX));\r
593         if (timeout == TWITIMEOUTMAX) {\r
594             TRACE_ERROR("TWID Timeout Read\n\r");\r
595         }\r
596         XDMAD_FreeChannel(&twi_dma, dmaReadChannel);\r
597 \r
598     }\r
599 \r
600     return 0;\r
601 }\r
602 \r
603 \r
604 /**\r
605  * \brief Asynchronously sends data to a slave on the TWI bus. An optional callback\r
606  * function is invoked whenever the transfer is complete.\r
607  * \param pTwid  Pointer to a Twid instance.\r
608  * \param address  TWI slave address.\r
609  * \param iaddress  Optional slave internal address.\r
610  * \param isize  Number of internal address bytes.\r
611  * \param pData  Data buffer for storing received bytes.\r
612  * \param num  Data buffer to send.\r
613  * \param pAsync  Asynchronous transfer descriptor.\r
614  * \param TWI_ID  TWI ID for TWI0, TWI1, TWI2.\r
615  * \return 0 if the transfer has been started; otherwise returns a TWI error code.\r
616  */\r
617 uint8_t TWID_DmaWrite(\r
618     Twid *pTwid,\r
619     uint8_t address,\r
620     uint32_t iaddress,\r
621     uint8_t isize,\r
622     uint8_t *pData,\r
623     uint32_t num,\r
624     Async *pAsync,\r
625     uint8_t TWI_ID)\r
626 {\r
627     Twihs *pTwi = pTwid->pTwi;\r
628     AsyncTwi *pTransfer = (AsyncTwi *) pTwid->pTransfer;\r
629     uint32_t timeout = 0;\r
630     uint32_t status;\r
631     //uint8_t singleTransfer = 0;\r
632     assert( pTwi != NULL ) ;\r
633     assert( (address & 0x80) == 0 ) ;\r
634     assert( (iaddress & 0xFF000000) == 0 ) ;\r
635     assert( isize < 4 ) ;\r
636 \r
637 //    if(num == 1) singleTransfer = 1;\r
638     /* Check that no transfer is already pending */\r
639     if (pTransfer) {\r
640 \r
641         TRACE_ERROR("TWI_Write: A transfer is already pending\n\r");\r
642         return TWID_ERROR_BUSY;\r
643     }\r
644 \r
645     /* Asynchronous transfer */\r
646     if (pAsync) {\r
647 \r
648         /* Update the transfer descriptor */\r
649         pTwid->pTransfer = pAsync;\r
650         pTransfer = (AsyncTwi *) pAsync;\r
651         pTransfer->status = ASYNC_STATUS_PENDING;\r
652         pTransfer->pData = pData;\r
653         pTransfer->num = num;\r
654         pTransfer->transferred = 1;\r
655 \r
656         /* Enable write interrupt and start the transfer */\r
657         TWI_StartWrite(pTwi, address, iaddress, isize, *pData);\r
658         TWI_EnableIt(pTwi, TWI_IER_TXRDY);\r
659     }\r
660     /* Synchronous transfer*/\r
661     else {\r
662 \r
663         TWID_DmaInitializeWrite(TWI_ID);\r
664         TWID_XdmaConfigureWrite(pData, num, TWI_ID);\r
665         /* Set slave address and number of internal address bytes. */\r
666         pTwi->TWIHS_MMR = 0;\r
667         pTwi->TWIHS_MMR = (isize << 8) | (address << 16);\r
668 \r
669         /* Set internal address bytes. */\r
670         pTwi->TWIHS_IADR = 0;\r
671         pTwi->TWIHS_IADR = iaddress;\r
672         XDMAD_StartTransfer( &twi_dma, dmaWriteChannel );\r
673            \r
674         while(XDMAD_IsTransferDone(&twi_dma, dmaWriteChannel));\r
675         \r
676         XDMAD_StopTransfer( &twi_dma, dmaWriteChannel );\r
677         \r
678         status = TWI_GetStatus(pTwi);\r
679         timeout = 0;\r
680         while( !(status & TWI_SR_TXRDY) && (timeout++ < TWITIMEOUTMAX) )\r
681         {\r
682             status = TWI_GetStatus(pTwi);\r
683         }\r
684         if (timeout == TWITIMEOUTMAX) {\r
685             TRACE_ERROR("TWID Timeout TXRDY\n\r");\r
686         }\r
687         \r
688         /* Send a STOP condition */\r
689         TWI_Stop(pTwi);\r
690         \r
691         status = TWI_GetStatus(pTwi);\r
692         timeout = 0;\r
693         while( !(status & TWI_SR_TXCOMP) && (++timeout<TWITIMEOUTMAX))\r
694         {\r
695             status = TWI_GetStatus(pTwi);\r
696         }\r
697         if (timeout == TWITIMEOUTMAX) {\r
698             TRACE_ERROR("TWID Timeout Write\n\r");\r
699         }\r
700        \r
701         XDMAD_FreeChannel(&twi_dma, dmaWriteChannel);\r
702         \r
703     }\r
704 \r
705     return 0;\r
706 }\r