static int i2c_interrupt(int irq, FAR void *context) { uint16_t sr1 = rSR1; if (sr1 & (I2C_SR1_STOPF | I2C_SR1_AF | I2C_SR1_ADDR)) { if (sr1 & I2C_SR1_STOPF) { /* write to CR1 to clear STOPF */ (void)rSR1; /* as recommended, re-read SR1 */ rCR1 |= I2C_CR1_PE; } /* DMA never stops, so we should do that now */ switch (direction) { case DIR_TX: i2c_tx_complete(); break; case DIR_RX: i2c_rx_complete(); break; default: /* not currently transferring - must be a new txn */ break; } direction = DIR_NONE; } if (sr1 & I2C_SR1_ADDR) { /* clear ADDR to ack our selection and get direction */ (void)rSR1; /* as recommended, re-read SR1 */ uint16_t sr2 = rSR2; if (sr2 & I2C_SR2_TRA) { /* we are the transmitter */ direction = DIR_TX; } else { /* we are the receiver */ direction = DIR_RX; } } /* clear any errors that might need it (this handles AF as well */ if (sr1 & I2C_SR1_ERRORMASK) { rSR1 = 0; } return 0; }
/* * Receives a data byte from the slave-transmitter and returns it * @param delay_us Delay in microseconds following the read * @return Byte read from the line */ uint8_t i2c_rx_byte(int delay_us) { uint8_t ret = MCF_I2C0_I2DR; // Read, which generates SCL for the slave to transmit // Wait for transfer to finish while(!i2c_tx_complete()) { } MCF_I2C0_I2SR &= ~(MCF_I2C_I2SR_IIF); // Clear interrupt request flag // Delay for delay_us following the transfer dtim0_delay_us(delay_us); return ret; }
/* * Send a single byte of data to the slave * * @param data Byte to send * @param delay_us Microseconds to delay after the send */ void i2c_tx_byte(uint8_t data, int delay_us) { //asm_set_ipl(7); // Mask all interrupt levels !!! necessary? // Write data MCF_I2C0_I2DR = data; // Wait for data to finish transmitting while(!i2c_tx_complete()) { } MCF_I2C0_I2SR &= ~(MCF_I2C_I2SR_IIF); // Clear interrupt request flag //asm_set_ipl(0); // Unmask all interrupt levels !!! necessary? // Delay for delay_us following the transfer dtim0_delay_us(delay_us); }