/** * \brief Asynchronously reads data from a slave on the TWI bus. An optional * callback function is triggered when the transfer is complete. * \param pTwid Pointer to a Twid instance. * \param address TWI slave address. * \param iaddress Optional slave internal address. * \param isize Internal address size in bytes. * \param pData Data buffer for storing received bytes. * \param num Number of bytes to read. * \param pAsync Asynchronous transfer descriptor. * \return 0 if the transfer has been started; otherwise returns a TWI error code. */ uint8_t TWID_Read( Twi *pTwi, uint8_t address, uint32_t iaddress, uint8_t isize, uint8_t *pData, uint32_t num) { //Twi *pTwi; uint32_t timeout; assert( pTwi != NULL ) ; assert( (address & 0x80) == 0 ) ; assert( (iaddress & 0xFF000000) == 0 ) ; assert( isize < 4 ) ; /* Set STOP signal if only one byte is sent*/ if (num == 1) { TWI_Stop(pTwi); } /* Synchronous transfer*/ /* Start read*/ TWI_StartRead(pTwi, address, iaddress, isize); /* Read all bytes, setting STOP before the last byte*/ while (num > 0) { /* Last byte ?*/ if (num == 1) { TWI_Stop(pTwi); } /* Wait for byte then read and store it*/ timeout = 0; while( !TWI_ByteReceived(pTwi) && (++timeout<TWITIMEOUTMAX) ); if (timeout == TWITIMEOUTMAX) { TRACE_ERROR("TWID Timeout BR\n\r"); } *pData++ = TWI_ReadByte(pTwi); num--; } /* Wait for transfer to be complete */ timeout = 0; while( !TWI_TransferComplete(pTwi) && (++timeout<TWITIMEOUTMAX) ); if (timeout == TWITIMEOUTMAX) { TRACE_ERROR("TWID Timeout TC\n\r"); } return 0; }
static inline bool TWI_WaitByteReceived(Twi *_twi, uint32_t _timeout) { while (!TWI_ByteReceived(_twi)) { if (TWI_FailedAcknowledge(_twi)) return false; if (--_timeout == 0) return false; } return true; }
// i2c_eeprom_master_read/write are based on twid.c from atmels at91lib and // adapted for better handling when there is no eeprom present. // This handling is needed for the bricklet initialization bool i2c_eeprom_master_read(Twi *twi, const uint16_t internal_address, char *data, const uint16_t length) { uint32_t timeout; mutex_take(mutex_twi_bricklet, MUTEX_BLOCKING); // Start read TWI_StartRead(twi, bricklet_eeprom_address, internal_address, I2C_EEPROM_INTERNAL_ADDRESS_BYTES); for(uint16_t i = 0; i < length; i++) { // If last Byte -> send STOP if(i == length-1) { TWI_Stop(twi); } uint32_t timeout = 0; // Wait until byte is received, otherwise return false while(!TWI_ByteReceived(twi) && (++timeout < I2C_EEPROM_TIMEOUT)); if(timeout == I2C_EEPROM_TIMEOUT) { logieew("read timeout (nothing received)\n\r"); mutex_give(mutex_twi_bricklet); return false; } data[i] = TWI_ReadByte(twi); } timeout = 0; // Wait for transfer to be complete while(!TWI_TransferComplete(twi) && (++timeout < I2C_EEPROM_TIMEOUT)); if (timeout == I2C_EEPROM_TIMEOUT) { logieew("read timeout (transfer incomplete)\n\r"); mutex_give(mutex_twi_bricklet); return false; } mutex_give(mutex_twi_bricklet); return true; }
unsigned char ReadAccelData(unsigned int iaddress, char *bytes, unsigned int num) { unsigned int timeout; // wait for TWI bus to be ready while(!(TWI_TransferComplete(AT91C_BASE_TWI))) nop(); // Start Reading TWI_StartRead(AT91C_BASE_TWI, ACCELADDR,iaddress,1); while (num > 0) { // Last byte if(num == 1) TWI_Stop(AT91C_BASE_TWI); // wait for byte then read and store it timeout = 0; while(!TWI_ByteReceived(AT91C_BASE_TWI) && (++timeout<TWITIMEOUTMAX)) nop(); if(timeout == TWITIMEOUTMAX) return 2; *bytes++ = TWI_ReadByte(AT91C_BASE_TWI); num--; } return 0; }
/** * \brief Asynchronously reads data from a slave on the TWI bus. An optional * callback function is triggered when the transfer is complete. * \param pTwid Pointer to a Twid instance. * \param address TWI slave address. * \param iaddress Optional slave internal address. * \param isize Internal address size in bytes. * \param pData Data buffer for storing received bytes. * \param num Number of bytes to read. * \param pAsync Asynchronous transfer descriptor. * \return 0 if the transfer has been started; otherwise returns a TWI error code. */ uint8_t TWID_Read( Twid *pTwid, uint8_t address, uint32_t iaddress, uint8_t isize, uint8_t *pData, uint32_t num, Async *pAsync) { Twi *pTwi; AsyncTwi *pTransfer; uint32_t timeout; assert( pTwid != NULL ) ; pTwi = pTwid->pTwi; pTransfer = (AsyncTwi *) pTwid->pTransfer; assert( (address & 0x80) == 0 ) ; assert( (iaddress & 0xFF000000) == 0 ) ; assert( isize < 4 ) ; /* Check that no transfer is already pending*/ if (pTransfer) { TRACE_ERROR("TWID_Read: A transfer is already pending\n\r"); return TWID_ERROR_BUSY; } /* Set STOP signal if only one byte is sent*/ if (num == 1) { TWI_Stop(pTwi); } /* Asynchronous transfer*/ if (pAsync) { /* Update the transfer descriptor */ pTwid->pTransfer = pAsync; pTransfer = (AsyncTwi *) pAsync; pTransfer->status = ASYNC_STATUS_PENDING; pTransfer->pData = pData; pTransfer->num = num; pTransfer->transferred = 0; /* Enable read interrupt and start the transfer */ TWI_EnableIt(pTwi, TWI_IER_RXRDY); TWI_StartRead(pTwi, address, iaddress, isize); } /* Synchronous transfer*/ else { /* Start read*/ TWI_StartRead(pTwi, address, iaddress, isize); /* Read all bytes, setting STOP before the last byte*/ while (num > 0) { /* Last byte ?*/ if (num == 1) { TWI_Stop(pTwi); } /* Wait for byte then read and store it*/ timeout = 0; while( !TWI_ByteReceived(pTwi) && (++timeout<TWITIMEOUTMAX) ) { if(pTwi->TWI_SR & TWI_SR_NACK) { return 0; } } if (timeout == TWITIMEOUTMAX) { TRACE_ERROR("TWID Timeout BR\n\r"); *pData++ = 0; } else { *pData++ = TWI_ReadByte(pTwi); } num--; } /* Wait for transfer to be complete */ timeout = 0; while( !TWI_TransferComplete(pTwi) && (++timeout<TWITIMEOUTMAX) ); if (timeout == TWITIMEOUTMAX) { TRACE_ERROR("TWID Timeout TC\n\r"); } } pTwi->TWI_SR; pTwi->TWI_RHR; return 0; }
/** * \brief Asynchronously reads data from a slave on the TWI bus. An optional * callback function is triggered when the transfer is complete. * \param pTwid Pointer to a Twid instance. * \param address TWI slave address. * \param iaddress Optional slave internal address. * \param isize Internal address size in bytes. * \param pData Data buffer for storing received bytes. * \param num Number of bytes to read. * \param pAsync Asynchronous transfer descriptor. * \return 0 if the transfer has been started; otherwise returns a TWI error code. */ uint8_t TWID_Read( Twid *pTwid, uint8_t address, uint32_t iaddress, uint8_t isize, uint8_t *pData, uint32_t num, Async *pAsync) { Twi *pTwi; AsyncTwi *pTransfer; uint32_t timeout = 0; uint32_t i = 0; uint32_t status; assert( pTwid != NULL ) ; pTwi = pTwid->pTwi; pTransfer = (AsyncTwi *) pTwid->pTransfer; assert( (address & 0x80) == 0 ) ; assert( (iaddress & 0xFF000000) == 0 ) ; assert( isize < 4 ) ; /* Check that no transfer is already pending*/ if (pTransfer) { TRACE_ERROR("TWID_Read: A transfer is already pending\n\r"); return TWID_ERROR_BUSY; } /* Asynchronous transfer*/ if (pAsync) { /* Update the transfer descriptor */ pTwid->pTransfer = pAsync; pTransfer = (AsyncTwi *) pAsync; pTransfer->status = ASYNC_STATUS_PENDING; pTransfer->pData = pData; pTransfer->num = num; pTransfer->transferred = 0; /* Enable read interrupt and start the transfer */ TWI_EnableIt(pTwi, TWI_IER_RXRDY); TWI_StartRead(pTwi, address, iaddress, isize); } /* Synchronous transfer*/ else { /* Start read*/ TWI_StartRead(pTwi, address, iaddress, isize); if (num != 1) { status = TWI_GetStatus(pTwi); if(status & TWI_SR_NACK) TRACE_ERROR("TWID NACK error\n\r"); timeout = 0; while( ! (status & TWI_SR_RXRDY) && (++timeout<TWITIMEOUTMAX)) { status = TWI_GetStatus(pTwi); //TRACE_ERROR("TWID status %x\n\r",TWI_GetStatus(pTwi)); } pData[0] = TWI_ReadByte(pTwi); for( i = 1; i < num - 1; i++) { status = TWI_GetStatus(pTwi); if(status & TWI_SR_NACK) TRACE_ERROR("TWID NACK error\n\r"); timeout = 0; while( ! (status & TWI_SR_RXRDY) && (++timeout<TWITIMEOUTMAX)) { status = TWI_GetStatus(pTwi); //TRACE_ERROR("TWID status %x\n\r",TWI_GetStatus(pTwi)); } pData[i] = TWI_ReadByte(pTwi); } } TWI_Stop(pTwi); status = TWI_GetStatus(pTwi); if(status & TWI_SR_NACK) TRACE_ERROR("TWID NACK error\n\r"); timeout = 0; while( ! (status & TWI_SR_RXRDY) && (++timeout<TWITIMEOUTMAX)) { status = TWI_GetStatus(pTwi); //TRACE_ERROR("TWID status %x\n\r",TWI_GetStatus(pTwi)); } pData[i] = TWI_ReadByte(pTwi); timeout = 0; status = TWI_GetStatus(pTwi); while( !(status & TWI_SR_TXCOMP) && (++timeout<TWITIMEOUTMAX)) { status = TWI_GetStatus(pTwi); //TRACE_ERROR("TWID status %x\n\r",TWI_GetStatus(pTwi)); } #if 0 /* Read all bytes, setting STOP before the last byte*/ while (num > 0) { /* Last byte ?*/ if (num == 1) { TWI_Stop(pTwi); } /* Wait for byte then read and store it*/ timeout = 0; while( !TWI_ByteReceived(pTwi) && (++timeout<TWITIMEOUTMAX) ); if (timeout == TWITIMEOUTMAX) { TRACE_ERROR("TWID Timeout BR\n\r"); } *pData++ = TWI_ReadByte(pTwi); num--; } /* Wait for transfer to be complete */ timeout = 0; while( !TWI_TransferComplete(pTwi) && (++timeout<TWITIMEOUTMAX) ); if (timeout == TWITIMEOUTMAX) { TRACE_ERROR("TWID Timeout TC\n\r"); } #endif } return 0; }
//----------------------------------------------------------------------------- /// Asynchronously reads data from a slave on the TWI bus. An optional /// callback function is triggered when the transfer is complete. /// Returns 0 if the transfer has been started; otherwise returns a TWI error /// code. /// \param pTwid Pointer to a Twid instance. /// \param address TWI slave address. /// \param iaddress Optional slave internal address. /// \param isize Internal address size in bytes. /// \param pData Data buffer for storing received bytes. /// \param num Number of bytes to read. /// \param pAsync Asynchronous transfer descriptor. //----------------------------------------------------------------------------- unsigned char TWID_Read( Twid *pTwid, unsigned char address, unsigned int iaddress, unsigned char isize, unsigned char *pData, unsigned int num, Async *pAsync) { AT91S_TWI *pTwi = pTwid->pTwi; AsyncTwi *pTransfer = (AsyncTwi *) pTwid->pTransfer; unsigned int timeout; //TRACE_DEBUG("TWID_Read()\n\r"); SANITY_CHECK(pTwid); SANITY_CHECK((address & 0x80) == 0); SANITY_CHECK((iaddress & 0xFF000000) == 0); SANITY_CHECK(isize < 4); // Check that no transfer is already pending if (pTransfer) { TRACE_ERROR("TWID_Read: A transfer is already pending\n\r"); return TWID_ERROR_BUSY; } // Set STOP signal if only one byte is sent if (num == 1) { TWI_Stop(pTwi); } // Asynchronous transfer if (pAsync) { // Update the transfer descriptor pTwid->pTransfer = pAsync; pTransfer = (AsyncTwi *) pAsync; pTransfer->status = ASYNC_STATUS_PENDING; pTransfer->pData = pData; pTransfer->num = num; pTransfer->transferred = 0; // Enable read interrupt and start the transfer TWI_EnableIt(pTwi, AT91C_TWI_RXRDY); TWI_StartRead(pTwi, address, iaddress, isize); } // Synchronous transfer else { // Start read TWI_StartRead(pTwi, address, iaddress, isize); // Read all bytes, setting STOP before the last byte while (num > 0) { // Last byte if (num == 1) { TWI_Stop(pTwi); } // Wait for byte then read and store it timeout = 0; while( !TWI_ByteReceived(pTwi) && (++timeout<TWITIMEOUTMAX) ); if (timeout == TWITIMEOUTMAX) { TRACE_ERROR("TWID Timeout BR\n\r"); return TWID_ERROR_TIMEOUT; } *pData++ = TWI_ReadByte(pTwi); num--; } // Wait for transfer to be complete timeout = 0; while( !TWI_TransferComplete(pTwi) && (++timeout<TWITIMEOUTMAX) ); if (timeout == TWITIMEOUTMAX) { TRACE_ERROR("TWID Timeout TC\n\r"); return TWID_ERROR_TIMEOUT; } } return 0; }