twid.c
上传用户:jnhtjd
上传日期:2022-07-16
资源大小:403k
文件大小:11k
源码类别:

微处理器开发

开发平台:

C/C++

  1. /* ----------------------------------------------------------------------------
  2.  *         ATMEL Microcontroller Software Support 
  3.  * ----------------------------------------------------------------------------
  4.  * Copyright (c) 2008, Atmel Corporation
  5.  *
  6.  * All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions are met:
  10.  *
  11.  * - Redistributions of source code must retain the above copyright notice,
  12.  * this list of conditions and the disclaimer below.
  13.  *
  14.  * Atmel's name may not be used to endorse or promote products derived from
  15.  * this software without specific prior written permission.
  16.  *
  17.  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
  20.  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  22.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  23.  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  24.  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  25.  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  26.  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  * ----------------------------------------------------------------------------
  28.  */
  29. #define TWITIMEOUTMAX 50000
  30. //------------------------------------------------------------------------------
  31. //         Headers
  32. //------------------------------------------------------------------------------
  33. #include "twid.h"
  34. #include <twi/twi.h>
  35. #include <utility/assert.h>
  36. #include <utility/trace.h>
  37. //------------------------------------------------------------------------------
  38. //         Local types
  39. //------------------------------------------------------------------------------
  40. /// TWI driver callback function.
  41. typedef void (*TwiCallback)(Async *);
  42. //------------------------------------------------------------------------------
  43. /// TWI asynchronous transfer descriptor.
  44. //------------------------------------------------------------------------------
  45. typedef struct _AsyncTwi {
  46.     /// Asynchronous transfer status.
  47.     volatile unsigned char status;
  48.     // Callback function to invoke when transfer completes or fails.
  49.     TwiCallback callback;
  50.     /// Pointer to the data buffer.
  51.     unsigned char *pData;
  52.     /// Total number of bytes to transfer.
  53.     unsigned int num;
  54.     /// Number of already transferred bytes.
  55.     unsigned int transferred;
  56. } AsyncTwi;
  57. //------------------------------------------------------------------------------
  58. //         Global functions
  59. //------------------------------------------------------------------------------
  60. //------------------------------------------------------------------------------
  61. /// Initializes a TWI driver instance, using the given TWI peripheral. The
  62. /// peripheral must have been initialized properly before calling this function.
  63. /// param pTwid  Pointer to the Twid instance to initialize.
  64. /// param pTwi  Pointer to the TWI peripheral to use.
  65. //------------------------------------------------------------------------------
  66. void TWID_Initialize(Twid *pTwid, AT91S_TWI *pTwi)
  67. {
  68.     TRACE_DEBUG("TWID_Initialize()nr");
  69.     SANITY_CHECK(pTwid);
  70.     SANITY_CHECK(pTwi);
  71.     // Initialize driver
  72.     pTwid->pTwi = pTwi;
  73.     pTwid->pTransfer = 0;
  74. }
  75. //------------------------------------------------------------------------------
  76. /// Interrupt handler for a TWI peripheral. Manages asynchronous transfer
  77. /// occuring on the bus. This function MUST be called by the interrupt service
  78. /// routine of the TWI peripheral if asynchronous read/write are needed.
  79. /// param pTwid  Pointer to a Twid instance.
  80. //------------------------------------------------------------------------------
  81. void TWID_Handler(Twid *pTwid)
  82. {
  83.     unsigned char status;
  84.     AsyncTwi *pTransfer = (AsyncTwi *) pTwid->pTransfer;
  85.     AT91S_TWI *pTwi = pTwid->pTwi;
  86.     SANITY_CHECK(pTwid);
  87.     // Retrieve interrupt status
  88.     status = TWI_GetMaskedStatus(pTwi);
  89.     // Byte received
  90.     if (TWI_STATUS_RXRDY(status)) {
  91.         pTransfer->pData[pTransfer->transferred] = TWI_ReadByte(pTwi);
  92.         pTransfer->transferred++;
  93.         // Transfer finished ?
  94.         if (pTransfer->transferred == pTransfer->num) {
  95.             TWI_DisableIt(pTwi, AT91C_TWI_RXRDY);
  96.             TWI_EnableIt(pTwi, AT91C_TWI_TXCOMP);
  97.         }
  98.         // Last byte ?
  99.         else if (pTransfer->transferred == (pTransfer->num - 1)) {
  100.             TWI_Stop(pTwi);
  101.         }
  102.     }
  103.     // Byte sent
  104.     else if (TWI_STATUS_TXRDY(status)) {
  105.         // Transfer finished ?
  106.         if (pTransfer->transferred == pTransfer->num) {
  107.             TWI_DisableIt(pTwi, AT91C_TWI_TXRDY);
  108.             TWI_EnableIt(pTwi, AT91C_TWI_TXCOMP);
  109.         }
  110.         // Bytes remaining
  111.         else {
  112.             TWI_WriteByte(pTwi, pTransfer->pData[pTransfer->transferred]);
  113.             pTransfer->transferred++;
  114.         }
  115.     }
  116.     // Transfer complete
  117.     else if (TWI_STATUS_TXCOMP(status)) {
  118.         TWI_DisableIt(pTwi, AT91C_TWI_TXCOMP);
  119.         pTransfer->status = 0;
  120.         if (pTransfer->callback) {
  121.             
  122.             pTransfer->callback((Async *) pTransfer);
  123.         }
  124.         pTwid->pTransfer = 0;
  125.     }
  126. }
  127. //-----------------------------------------------------------------------------
  128. /// Asynchronously reads data from a slave on the TWI bus. An optional
  129. /// callback function is triggered when the transfer is complete.
  130. /// Returns 0 if the transfer has been started; otherwise returns a TWI error
  131. /// code.
  132. /// param pTwid  Pointer to a Twid instance.
  133. /// param address  TWI slave address.
  134. /// param iaddress  Optional slave internal address.
  135. /// param isize  Internal address size in bytes.
  136. /// param pData  Data buffer for storing received bytes.
  137. /// param num  Number of bytes to read.
  138. /// param pAsync  Asynchronous transfer descriptor.
  139. //-----------------------------------------------------------------------------
  140. unsigned char TWID_Read(
  141.     Twid *pTwid,
  142.     unsigned char address,
  143.     unsigned int iaddress,
  144.     unsigned char isize,
  145.     unsigned char *pData,
  146.     unsigned int num,
  147.     Async *pAsync)
  148. {
  149.     AT91S_TWI *pTwi = pTwid->pTwi;
  150.     AsyncTwi *pTransfer = (AsyncTwi *) pTwid->pTransfer;
  151.     unsigned int timeout;
  152.     //TRACE_DEBUG("TWID_Read()nr");
  153.     SANITY_CHECK(pTwid);
  154.     SANITY_CHECK((address & 0x80) == 0);
  155.     SANITY_CHECK((iaddress & 0xFF000000) == 0);
  156.     SANITY_CHECK(isize < 4);
  157.     // Check that no transfer is already pending
  158.     if (pTransfer) {
  159.         TRACE_ERROR("TWID_Read: A transfer is already pendingnr");
  160.         return TWID_ERROR_BUSY;
  161.     }
  162.     // Set STOP signal if only one byte is sent
  163.     if (num == 1) {
  164.         TWI_Stop(pTwi);
  165.     }
  166.     // Asynchronous transfer
  167.     if (pAsync) {
  168.     
  169.         // Update the transfer descriptor
  170.         pTwid->pTransfer = pAsync;
  171.         pTransfer = (AsyncTwi *) pAsync;
  172.         pTransfer->status = ASYNC_STATUS_PENDING;
  173.         pTransfer->pData = pData;
  174.         pTransfer->num = num;
  175.         pTransfer->transferred = 0;
  176.         
  177.         // Enable read interrupt and start the transfer
  178.         TWI_EnableIt(pTwi, AT91C_TWI_RXRDY);
  179.         TWI_StartRead(pTwi, address, iaddress, isize);
  180.     }
  181.     // Synchronous transfer
  182.     else {
  183.         // Start read
  184.         TWI_StartRead(pTwi, address, iaddress, isize);
  185.         // Read all bytes, setting STOP before the last byte
  186.         while (num > 0) {
  187.             // Last byte
  188.             if (num == 1) {
  189.                 TWI_Stop(pTwi);
  190.             }
  191.             // Wait for byte then read and store it
  192.             timeout = 0;
  193.             while( !TWI_ByteReceived(pTwi) && (++timeout<TWITIMEOUTMAX) );
  194.             if (timeout == TWITIMEOUTMAX) {
  195.                 TRACE_ERROR("TWID Timeout BRnr");
  196.             }
  197.             *pData++ = TWI_ReadByte(pTwi);
  198.             num--;
  199.         }
  200.         // Wait for transfer to be complete
  201.         timeout = 0;
  202.         while( !TWI_TransferComplete(pTwi) && (++timeout<TWITIMEOUTMAX) );
  203.         if (timeout == TWITIMEOUTMAX) {
  204.             TRACE_ERROR("TWID Timeout TCnr");
  205.         }
  206.     }
  207.     return 0;
  208. }
  209. //------------------------------------------------------------------------------
  210. /// Asynchronously sends data to a slave on the TWI bus. An optional callback
  211. /// function is invoked whenever the transfer is complete.
  212. /// param pTwid  Pointer to a Twid instance.
  213. /// param address  Slave address.
  214. /// param iaddress  Optional slave internal address.
  215. /// param isize  Number of internal address bytes.
  216. /// param pData  Data buffer to send.
  217. /// param num  Number of bytes to send.
  218. /// param pAsync  Pointer to an Asynchronous transfer descriptor.
  219. //------------------------------------------------------------------------------
  220. unsigned char TWID_Write(
  221.     Twid *pTwid,
  222.     unsigned char address,
  223.     unsigned int iaddress,
  224.     unsigned char isize,
  225.     unsigned char *pData,
  226.     unsigned int num,
  227.     Async *pAsync)
  228. {
  229.     AT91S_TWI *pTwi = pTwid->pTwi;
  230.     AsyncTwi *pTransfer = (AsyncTwi *) pTwid->pTransfer;
  231.     unsigned int timeout;
  232.     //TRACE_DEBUG("TWID_Write()nr");
  233.     //TRACE_DEBUG("0x%Xnr", pData[0]);
  234.     SANITY_CHECK(pTwi);
  235.     SANITY_CHECK((address & 0x80) == 0);
  236.     SANITY_CHECK((iaddress & 0xFF000000) == 0);
  237.     SANITY_CHECK(isize < 4);
  238.     // Check that no transfer is already pending
  239.     if (pTransfer) {
  240.         TRACE_ERROR("TWI_Write: A transfer is already pendingnr");
  241.         return TWID_ERROR_BUSY;
  242.     }
  243.     // Asynchronous transfer
  244.     if (pAsync) {
  245.     
  246.         // Update the transfer descriptor
  247.         pTwid->pTransfer = pAsync;
  248.         pTransfer = (AsyncTwi *) pAsync;
  249.         pTransfer->status = ASYNC_STATUS_PENDING;
  250.         pTransfer->pData = pData;
  251.         pTransfer->num = num;
  252.         pTransfer->transferred = 1;
  253.     
  254.         // Enable write interrupt and start the transfer
  255.         TWI_StartWrite(pTwi, address, iaddress, isize, *pData);
  256.         TWI_EnableIt(pTwi, AT91C_TWI_TXRDY);
  257.     }
  258.     // Synchronous transfer
  259.     else {
  260.         // Start write
  261.         TWI_StartWrite(pTwi, address, iaddress, isize, *pData++);
  262.         num--;
  263.         // Send all bytes
  264.         while (num > 0) {
  265.         
  266.             // Wait before sending the next byte
  267.             timeout = 0;
  268.             while( !TWI_ByteSent(pTwi) && (++timeout<TWITIMEOUTMAX) );
  269.             if (timeout == TWITIMEOUTMAX) {
  270.                 TRACE_ERROR("TWID Timeout BSnr");
  271.             }
  272.             TWI_WriteByte(pTwi, *pData++);
  273.             num--;
  274.         }
  275.         // Wait for actual end of transfer
  276.         timeout = 0;
  277. #ifdef TWI_V3XX
  278.         // Send a STOP condition
  279.         TWI_SendSTOPCondition(pTwi);
  280. #endif
  281.         while( !TWI_TransferComplete(pTwi) && (++timeout<TWITIMEOUTMAX) );
  282.         if (timeout == TWITIMEOUTMAX) {
  283.             TRACE_ERROR("TWID Timeout TC2nr");
  284.         }
  285.     }
  286.     
  287.     return 0;
  288. }