/**
 * \brief Enable NACK transfer in Slave Receive Mode
 *
 * \param twis           Base address of the TWI (i.e. &AVR32_TWIS).
 * \param stop_callback  Set true to use Stop condition Callback function
 */
void twis_send_data_nack(volatile avr32_twis_t *twis, bool stop_callback) {
	// Send NACK
	twis->cr |= AVR32_TWIS_CR_ACK_MASK;
	// Disable all interrupts
	twis->idr = ~0UL;
	// Clear all status
	twis->scr = ~0UL;
	// Enable Slave Address Match Interrupt
	twis->ier = AVR32_TWIS_IER_SAM_MASK;
	// If callback is desired, go to the stop condition callback function
	if (stop_callback) {
		twis_slave_fct.stop();
	}
}
/**
 * \internal
 * \brief TWIS interrupt handler
 */
ISR(twis_slave_interrupt_handler,CONF_TWIS_IRQ_GROUP,CONF_TWIS_IRQ_LEVEL)
{
	// Get status and interrupt mask register values
	unsigned long status  = twis_inst_slave->sr;
	unsigned long enabled = twis_inst_slave->imr;
	unsigned long pending = status & enabled;

	// An error has occurred, set only address match active and return
	if (status & AVR32_TWIS_SR_ERROR_MASK) {
		twis_inst_slave->idr = ~0UL;
		twis_inst_slave->scr = ~0UL;
		twis_inst_slave->ier = AVR32_TWIS_IER_SAM_MASK;

		twis_slave_fct.stop();

		return;
	}

	// Check if the slave address match flag is raised
	if (pending & AVR32_TWIS_IER_SAM_MASK) {
		// Ignore repeated start and transmission complete flags
		if (pending & (AVR32_TWIS_SR_REP_MASK | AVR32_TWIS_SR_TCOMP_MASK)) {
			twis_inst_slave->scr = (AVR32_TWIS_SCR_REP_MASK |
					AVR32_TWIS_SCR_TCOMP_MASK);
			twis_inst_slave->idr = (AVR32_TWIS_IDR_REP_MASK |
					AVR32_TWIS_IDR_TCOMP_MASK);
		}
		pending &= ~(AVR32_TWIS_SR_REP_MASK | AVR32_TWIS_SR_TCOMP_MASK);

		// Enable error handling
		twis_inst_slave->ier = AVR32_TWIS_SR_ERROR_MASK;

		// Check if the slave should be in receive or transmit mode
		if (status & AVR32_TWIS_SR_TRA_MASK) {
			// Transmit mode
			twis_inst_slave->scr = AVR32_TWIS_SR_BTF_MASK;
			twis_inst_slave->ier = AVR32_TWIS_IER_BTF_MASK
				| AVR32_TWIS_IER_TCOMP_MASK;
			twis_inst_slave->thr = twis_slave_fct.tx();
		} else {
			// Receive mode
			twis_inst_slave->ier = AVR32_TWIS_IER_RXRDY_MASK
				| AVR32_TWIS_IER_TCOMP_MASK
				| AVR32_TWIS_IER_REP_MASK;
		}
	}

	// Check if there is data ready to be read in the data receive register
	if (pending & AVR32_TWIS_IER_RXRDY_MASK) {
		// Call user specific receive function
		twis_slave_fct.rx(twis_inst_slave->rhr);
	}

	// Check if the transmit ready flag is raised
	if (pending & AVR32_TWIS_SR_BTF_MASK) {
		if (status & AVR32_TWIS_SR_NAK_MASK) {
			twis_inst_slave->idr = AVR32_TWIS_IDR_BTF_MASK;
			twis_inst_slave->scr = AVR32_TWIS_SCR_BTF_MASK;
			twis_inst_slave->ier = AVR32_TWIS_IER_TCOMP_MASK
				| AVR32_TWIS_IER_REP_MASK;
			// Clear the NAK
			twis_inst_slave->scr = AVR32_TWIS_SCR_NAK_MASK;
		} else {
			twis_inst_slave->thr = twis_slave_fct.tx();
		}
	}

	// Check if the transmission complete or repeated start flags raised
	if (pending & (AVR32_TWIS_SR_TCOMP_MASK | AVR32_TWIS_SR_REP_MASK)) {
		// Clear transmit complete and repeated start flags
		twis_inst_slave->scr = AVR32_TWIS_SCR_TCOMP_MASK
			| AVR32_TWIS_SCR_REP_MASK;
		// Disable transmission ready interrupt
		twis_inst_slave->idr = AVR32_TWIS_IDR_BTF_MASK
			| AVR32_TWIS_IDR_RXRDY_MASK
			| AVR32_TWIS_IDR_TCOMP_MASK
			| AVR32_TWIS_IDR_REP_MASK;
		// Enable slave address match interrupt
		twis_inst_slave->ier = AVR32_TWIS_IER_SAM_MASK;
		// Call user specific stop function
		twis_slave_fct.stop();
	}
	/* Never clear the NAK mask without first receiving the appropriate
	 * BTF bit too.
	 *
	 * L4U  Errata 38.1.3.2:
	 * Clearing the NAK bit before the BTF bit is set locks up the TWI bus
	 * When the TWIS is in transmit mode, clearing the NAK Received (NAK)
	 * bit of the Status Register (SR) before the end of the
	 * Acknowledge/Not Acknowledge cycle will cause the TWIS to
	 * attempt to continue transmitting data, thus locking up the bus.
	 *
	 * Fix/Workaround
	 * Clear SR.NAK only after the Byte Transfer Finished (BTF) bit of the same register has been
	 * set.
	 */
	twis_inst_slave->scr = pending & (~AVR32_TWIS_SCR_NAK_MASK);
	return;
}
Example #3
0
/**
 * \internal
 * \brief TWIS interrupt handler
 */
ISR(twis_slave_interrupt_handler,CONF_TWIS_IRQ_GROUP,CONF_TWIS_IRQ_LEVEL)
{
	// Get status and interrupt mask register values
	unsigned long status  = twis_inst_slave->sr;
	unsigned long enabled = twis_inst_slave->imr;
	unsigned long pending = status & enabled;

	// An error has occurred, set only address match active and return
	if (status & AVR32_TWIS_SR_ERROR_MASK) {
		twis_inst_slave->idr = ~0UL;
		twis_inst_slave->scr = ~0UL;
		twis_inst_slave->ier = AVR32_TWIS_IER_SAM_MASK;

		twis_slave_fct.stop();

		return;
	}

	// Check if the slave address match flag is raised
	if (pending & AVR32_TWIS_IER_SAM_MASK) {
		// Ignore repeated start and transmission complete flags
		if (pending & AVR32_TWIS_SR_REP_MASK) {
			twis_inst_slave->scr = AVR32_TWIS_SCR_REP_MASK;
		}
		if (pending & AVR32_TWIS_SR_TCOMP_MASK) {
			twis_inst_slave->scr = AVR32_TWIS_SCR_TCOMP_MASK;
		}
		// Enable error handling
		twis_inst_slave->ier = AVR32_TWIS_SR_ERROR_MASK;

		// Check if the slave should be in receive or transmit mode
		if (status & AVR32_TWIS_SR_TRA_MASK) {
			// Transmit mode
			twis_inst_slave->scr = AVR32_TWIS_SR_BTF_MASK;
			twis_inst_slave->ier = AVR32_TWIS_IER_BTF_MASK
				| AVR32_TWIS_IER_TCOMP_MASK;
			twis_inst_slave->thr = twis_slave_fct.tx();
		} else {
			// Receive mode
			twis_inst_slave->ier = AVR32_TWIS_IER_RXRDY_MASK
				| AVR32_TWIS_IER_TCOMP_MASK
				| AVR32_TWIS_IER_REP_MASK;
		}
	}

	// Check if there is data ready to be read in the data receive register
	if (pending & AVR32_TWIS_IER_RXRDY_MASK) {
		// Call user specific receive function
		twis_slave_fct.rx(twis_inst_slave->rhr);
	}

	// Check if the transmit ready flag is raised
	if (pending & AVR32_TWIS_SR_BTF_MASK) {
		if (status & AVR32_TWIS_SR_NAK_MASK) {
			twis_inst_slave->idr = AVR32_TWIS_IDR_BTF_MASK;
			twis_inst_slave->scr = AVR32_TWIS_SCR_BTF_MASK;
			twis_inst_slave->ier = AVR32_TWIS_IER_TCOMP_MASK
				| AVR32_TWIS_IER_REP_MASK;
			// Clear the NAK
			twis_inst_slave->scr = AVR32_TWIS_SCR_NAK_MASK;
		} else {
			twis_inst_slave->thr = twis_slave_fct.tx();
		}
	}

	// Check if the transmission complete or repeated start flags raised
	if (pending & (AVR32_TWIS_IER_TCOMP_MASK | AVR32_TWIS_IER_REP_MASK)) {
		// Clear transmit complete and repeated start flags
		twis_inst_slave->scr = AVR32_TWIS_SCR_TCOMP_MASK
			| AVR32_TWIS_SCR_REP_MASK | AVR32_TWIS_SCR_NAK_MASK;
		// Disable transmission ready interrupt
		twis_inst_slave->idr = AVR32_TWIS_IDR_BTF_MASK
			| AVR32_TWIS_IDR_RXRDY_MASK
			| AVR32_TWIS_IDR_TCOMP_MASK
			| AVR32_TWIS_IDR_REP_MASK;
		// Enable slave address match interrupt
		twis_inst_slave->ier = AVR32_TWIS_IER_SAM_MASK;
		// Call user specific stop function
		twis_slave_fct.stop();
	}
	twis_inst_slave->scr = pending;
	return;
}