Ejemplo n.º 1
0
/**
 * @brief   Transmits data via the I2C bus as master.
 * @details Number of receiving bytes must be 0 or more than 1 on STM32F1x.
 *          This is hardware restriction.
 *
 * @param[in] i2cp      pointer to the @p I2CDriver object
 * @param[in] addr      slave device address
 * @param[in] txbuf     pointer to the transmit buffer
 * @param[in] txbytes   number of bytes to be transmitted
 * @param[out] rxbuf    pointer to the receive buffer
 * @param[in] rxbytes   number of bytes to be received
 * @param[in] timeout   the number of ticks before the operation timeouts,
 *                      the following special values are allowed:
 *                      - @a TIME_INFINITE no timeout.
 *                      .
 * @return              The operation status.
 * @retval RDY_OK       if the function succeeded.
 * @retval RDY_RESET    if one or more I2C errors occurred, the errors can
 *                      be retrieved using @p i2cGetErrors().
 * @retval RDY_TIMEOUT  if a timeout occurred before operation end. <b>After a
 *                      timeout the driver must be stopped and restarted
 *                      because the bus is in an uncertain state</b>.
 *
 * @notapi
 */
msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
                                      const uint8_t *txbuf, size_t txbytes,
                                      uint8_t *rxbuf, size_t rxbytes,
                                      systime_t timeout) {

    (void)i2cp;
    (void)addr;
    (void)txbuf;
    (void)txbytes;
    (void)rxbuf;
    (void)rxbytes;
    (void)timeout;

    i2cdef_t i2c = i2cp->i2c;
    uint32_t status;

    /* Set write mode, slave address and 3 internal address byte lengths */
    i2c->TWI_MMR = 0;
    i2c->TWI_MMR = TWI_MMR_DADR(addr->chip) |
                   ((addr->len << TWI_MMR_IADRSZ_Pos) &
                    TWI_MMR_IADRSZ_Msk);

    /* Set internal address for remote chip */
    i2c->TWI_IADR = 0;
    i2c->TWI_IADR = twi_mk_addr(addr->addr, addr->len);

    /* Send all bytes */
    while (txbytes > 0) {
        status = i2c->TWI_SR;
        if (status & TWI_SR_NACK) {
            return RDY_RESET;
        }

        if (!(status & TWI_SR_TXRDY)) {
            continue;
        }
        i2c->TWI_THR = *txbuf++;

        txbytes--;
    }

    while (1) {
        status = i2c->TWI_SR;
        if (status & TWI_SR_NACK) {
            return RDY_RESET;
        }

        if (status & TWI_SR_TXRDY) {
            break;
        }
    }

    i2c->TWI_CR = TWI_CR_STOP;

    while (!(i2c->TWI_SR & TWI_SR_TXCOMP)) {
    }


    return RDY_OK;
}
Ejemplo n.º 2
0
Archivo: twi.c Proyecto: roby85/Viper
/**
 * \brief Read multiple bytes from a TWI compatible slave device.
 *
 * \note This function will NOT return until all data has been read or error occurs.
 *
 * \param p_twi Pointer to a TWI instance.
 * \param p_packet Packet information and data (see \ref twi_packet_t).
 *
 * \return TWI_SUCCESS if all bytes were read, error code otherwise.
 */
uint32_t twi_master_read(Twi *p_twi, twi_packet_t *p_packet)
{
	uint32_t status;
	uint32_t cnt = p_packet->length;
	uint8_t *buffer = p_packet->buffer;
	uint8_t stop_sent = 0;
	
	/* Check argument */
	if (cnt == 0) {
		return TWI_INVALID_ARGUMENT;
	}

	/* Set read mode, slave address and 3 internal address byte lengths */
	p_twi->TWI_MMR = 0;
	p_twi->TWI_MMR = TWI_MMR_MREAD | TWI_MMR_DADR(p_packet->chip) |
			((p_packet->addr_length << TWI_MMR_IADRSZ_Pos) &
			TWI_MMR_IADRSZ_Msk);

	/* Set internal address for remote chip */
	p_twi->TWI_IADR = 0;
	p_twi->TWI_IADR = twi_mk_addr(p_packet->addr, p_packet->addr_length);

	/* Send a START condition */
	if (cnt == 1) {
		p_twi->TWI_CR = TWI_CR_START | TWI_CR_STOP;
		stop_sent = 1;
	} else {
		p_twi->TWI_CR = TWI_CR_START;
		stop_sent = 0;
	}

	while (cnt > 0) {
		status = p_twi->TWI_SR;
		if (status & TWI_SR_NACK) {
			return TWI_RECEIVE_NACK;
		}

		/* Last byte ? */
		if (cnt == 1  && !stop_sent) {
			p_twi->TWI_CR = TWI_CR_STOP;
			stop_sent = 1;
		}

		if (!(status & TWI_SR_RXRDY)) {
			continue;
		}
		*buffer++ = p_twi->TWI_RHR;

		cnt--;
	}

	while (!(p_twi->TWI_SR & TWI_SR_TXCOMP)) {
	}

	p_twi->TWI_SR;

	return TWI_SUCCESS;
}
Ejemplo n.º 3
0
/**
 * \brief Write multiple bytes to a TWI compatible slave device.
 *
 * \note This function will NOT return until all data has been written or error occurred.
 *
 * \param p_twi Pointer to a TWI instance.
 * \param p_packet Packet information and data (see \ref twi_packet_t).
 *
 * \return TWI_SUCCESS if all bytes were written, error code otherwise.
 */
uint32_t twi_master_write(Twi *p_twi, twi_packet_t *p_packet)
{
	uint32_t status;
	uint32_t cnt = p_packet->length;
	uint8_t *buffer = p_packet->buffer;

	/* Check argument */
	if (cnt == 0) {
		return TWI_INVALID_ARGUMENT;
	}

	/* Set write mode, slave address and 3 internal address byte lengths */
	p_twi->TWI_MMR = 0;
	p_twi->TWI_MMR = TWI_MMR_DADR(p_packet->chip) |
			((p_packet->addr_length << TWI_MMR_IADRSZ_Pos) &
			TWI_MMR_IADRSZ_Msk);

	/* Set internal address for remote chip */
	p_twi->TWI_IADR = 0;
	p_twi->TWI_IADR = twi_mk_addr(p_packet->addr, p_packet->addr_length);

	/* Send all bytes */
	while (cnt > 0) {
		status = p_twi->TWI_SR;
		if (status & TWI_SR_NACK) {
			return TWI_RECEIVE_NACK;
		}

		if (!(status & TWI_SR_TXRDY)) {
			continue;
		}
		p_twi->TWI_THR = *buffer++;

		cnt--;
	}

	while (1) {
		status = p_twi->TWI_SR;
		if (status & TWI_SR_NACK) {
			return TWI_RECEIVE_NACK;
		}

		if (status & TWI_SR_TXRDY) {
			break;
		}
	}

	p_twi->TWI_CR = TWI_CR_STOP;

	while (!(p_twi->TWI_SR & TWI_SR_TXCOMP)) {
	}

	return TWI_SUCCESS;
}
Ejemplo n.º 4
0
/**
 * @brief   Receives data via the I2C bus as master.
 * @details Number of receiving bytes must be more than 1 on STM32F1x. This is
 *          hardware restriction.
 *
 * @param[in] i2cp      pointer to the @p I2CDriver object
 * @param[in] addr      slave device address
 * @param[out] rxbuf    pointer to the receive buffer
 * @param[in] rxbytes   number of bytes to be received
 * @param[in] timeout   the number of ticks before the operation timeouts,
 *                      the following special values are allowed:
 *                      - @a TIME_INFINITE no timeout.
 *                      .
 * @return              The operation status.
 * @retval RDY_OK       if the function succeeded.
 * @retval RDY_RESET    if one or more I2C errors occurred, the errors can
 *                      be retrieved using @p i2cGetErrors().
 * @retval RDY_TIMEOUT  if a timeout occurred before operation end. <b>After a
 *                      timeout the driver must be stopped and restarted
 *                      because the bus is in an uncertain state</b>.
 *
 * @notapi
 */
msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
                                     uint8_t *rxbuf, size_t rxbytes,
                                     systime_t timeout) {

    (void)i2cp;
    (void)addr;
    (void)rxbuf;
    (void)rxbytes;
    (void)timeout;
    uint32_t status;
    uint32_t stop_sent;
    i2cdef_t i2c = i2cp->i2c;

    /* Set read mode, slave address and 3 internal address byte lengths */
    i2c->TWI_MMR = 0;
    i2c->TWI_MMR = TWI_MMR_MREAD | TWI_MMR_DADR(addr->chip) | ((addr->len << TWI_MMR_IADRSZ_Pos) & TWI_MMR_IADRSZ_Msk);

    /* Set internal address for remote chip */
    i2c->TWI_IADR = 0;
    i2c->TWI_IADR = twi_mk_addr(addr->addr, addr->len);




    /* Send a START condition */
    if (rxbytes = 1) {
        i2c->TWI_CR = TWI_CR_START | TWI_CR_STOP;
        while (!(i2c->TWI_SR & TWI_SR_RXRDY));
        *rxbuf = i2c->TWI_RHR;

    } else {
        i2c->TWI_PTCR = TWI_PTCR_RXTDIS | TWI_PTCR_TXTDIS;


        i2c->TWI_IER = TWI_IER_ENDRX | TWI_IER_NACK | TWI_IER_OVRE;

        chSysLock();
        i2cp->thread = chThdSelf();
        i2c->TWI_RNPR = 0;
        i2c->TWI_RNCR = 0;
        i2c->TWI_RPR = (uint32_t) rxbuf;
        i2c->TWI_RCR = rxbytes - 2;
        i2c->TWI_PTCR = TWI_PTCR_RXTEN;
        i2cp->curbuf = rxbuf + (rxbytes - 2);

        i2c->TWI_CR = TWI_CR_START;
        chSchGoSleepS(THD_STATE_SUSPENDED);

        return chThdSelf()->p_u.rdymsg;
    }

    return RDY_OK;
}
Ejemplo n.º 5
0
//! This function is not blocking.
int twi_master_write_ex(volatile avr32_twi_t *twi, const twi_package_t *package)
{
  int status = TWI_SUCCESS;

  if( twi_nack )
    status = TWI_RECEIVE_NACK;  // Previous transaction returns a NACK

  else if( twi_tx_nb_bytes )
    return TWI_BUSY;          // Still transmitting...

  // No data to send
  if (package->length == 0)
  {
    return TWI_INVALID_ARGUMENT;
  }

  twi_nack = false;

  // Enable master transfer, disable slave
  twi->cr =   AVR32_TWI_CR_MSEN_MASK
#ifndef AVR32_TWI_180_H_INCLUDED
            | AVR32_TWI_CR_SVDIS_MASK
#endif
            ;

  // set write mode, slave address and 3 internal address byte length
  twi->mmr = (0 << AVR32_TWI_MMR_MREAD_OFFSET) |
             (package->chip << AVR32_TWI_MMR_DADR_OFFSET) |
             ((package->addr_length << AVR32_TWI_MMR_IADRSZ_OFFSET) & AVR32_TWI_MMR_IADRSZ_MASK);

  // Set pointer to TWIM instance for IT
  twi_inst = twi;

  // set internal address for remote chip
  twi->iadr = twi_mk_addr(package->addr, package->addr_length);

  // get a pointer to applicative data
  twi_tx_data = package->buffer;

  // get a copy of nb bytes to write
  twi_tx_nb_bytes = package->length;

  // put the first byte in the Transmit Holding Register
  twi->thr = *twi_tx_data++;

  // mask NACK and TXRDY interrupts
  twi_it_mask = AVR32_TWI_IER_NACK_MASK | AVR32_TWI_IER_TXRDY_MASK;

  // update IMR through IER
  twi->ier = twi_it_mask;

  return status;
}
Ejemplo n.º 6
0
int twi_master_read(volatile avr32_twi_t *twi, const twi_package_t *package)
{
  // check argument
  if (package->length == 0)
  {
    return TWI_INVALID_ARGUMENT;
  }

  while( twi_is_busy() ) {
    cpu_relax();
  };

  twi_nack = false;
  twi_busy = true;

  // set read mode, slave address and 3 internal address byte length
  twi->mmr = (package->chip << AVR32_TWI_MMR_DADR_OFFSET) |
             ((package->addr_length << AVR32_TWI_MMR_IADRSZ_OFFSET) & AVR32_TWI_MMR_IADRSZ_MASK) |
             (1 << AVR32_TWI_MMR_MREAD_OFFSET);

  // Set pointer to TWIM instance for IT
  twi_inst = twi;

  // set internal address for remote chip
  twi->iadr = twi_mk_addr(package->addr, package->addr_length);

  // get a pointer to applicative data
  twi_rx_data = package->buffer;

  // get a copy of nb bytes to read
  twi_rx_nb_bytes = package->length;

  // Enable master transfer
  twi->cr =  AVR32_TWI_CR_MSEN_MASK;

  // Send start condition
  twi->cr = AVR32_TWI_START_MASK;

  // only one byte to receive
  if(twi_rx_nb_bytes == 1)
  {
    // set stop bit
    twi->cr = AVR32_TWI_STOP_MASK;
  }

  // mask NACK and RXRDY interrupts
  twi_it_mask = AVR32_TWI_IER_NACK_MASK | AVR32_TWI_IER_RXRDY_MASK;

  // update IMR through IER
  twi->ier = twi_it_mask;

  // get data
  while( twi_is_busy() ) {
    cpu_relax();
  }

  // Disable master transfer
  twi->cr =  AVR32_TWI_CR_MSDIS_MASK;

  if( twi_nack )
    return TWI_RECEIVE_NACK;

  return TWI_SUCCESS;
}
Ejemplo n.º 7
0
int twi_master_write(volatile avr32_twi_t *twi, const twi_package_t *package)
{
	// No data to send
	if (package->length == 0) {
		return TWI_INVALID_ARGUMENT;
	}

	while (twi_is_busy()) {
		cpu_relax();
	};

	twi_nack = false;
	twi_busy = true;
        SCOPE_0_ON;

	// Enable master transfer, disable slave
	twi->cr =   AVR32_TWI_CR_MSEN_MASK
#ifndef AVR32_TWI_180_H_INCLUDED
			| AVR32_TWI_CR_SVDIS_MASK
#endif
			;

	// set write mode, slave address and 3 internal address byte length
	twi->mmr = (0 << AVR32_TWI_MMR_MREAD_OFFSET) |
			(package->chip << AVR32_TWI_MMR_DADR_OFFSET) |
			((package->addr_length << AVR32_TWI_MMR_IADRSZ_OFFSET) & AVR32_TWI_MMR_IADRSZ_MASK);

	// Set pointer to TWI instance for IT
	twi_inst = twi;

	// set internal address for remote chip
	twi->iadr = twi_mk_addr(package->addr, package->addr_length);

	// get a pointer to applicative data
	twi_tx_data = package->buffer;

	// get a copy of nb bytes to write
	twi_tx_nb_bytes = package->length;

	// put the first byte in the Transmit Holding Register
	twi->thr = *twi_tx_data++;

	// mask NACK and TXRDY interrupts
	twi_it_mask = AVR32_TWI_IER_NACK_MASK | AVR32_TWI_IER_TXRDY_MASK;

	// update IMR through IER
	twi->ier = twi_it_mask;

	// send data
	while (twi_is_busy()) {
		cpu_relax();
	}

	// Disable master transfer
	twi->cr =  AVR32_TWI_CR_MSDIS_MASK;

	if (twi_nack) {
		return TWI_RECEIVE_NACK;
	}

	return TWI_SUCCESS;
}