/** * \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; }
/** * \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; }