@@ -313,7 +313,7 @@ int i2c_slave_receive(i2c_t *obj)
313313
314314int i2c_slave_read (i2c_t * obj , char * data , int length )
315315{
316- return i2c_do_tran (obj , data , length , 1 , 1 );
316+ return i2c_do_tran (obj , data , length , 1 , 0 );
317317}
318318
319319int i2c_slave_write (i2c_t * obj , const char * data , int length )
@@ -691,7 +691,6 @@ static void i2c_irq(i2c_t *obj)
691691 }
692692 obj -> i2c .slaveaddr_state = ReadAddressed ;
693693 break ;
694- //case 0xA0: // Slave Transmit Repeat Start or Stop
695694 case 0xC0 : // Slave Transmit Data NACK
696695 case 0xC8 : // Slave Transmit Last Data ACK
697696 obj -> i2c .slaveaddr_state = NoData ;
@@ -705,40 +704,46 @@ static void i2c_irq(i2c_t *obj)
705704 case 0x68 : // Slave Receive Arbitration Lost
706705 obj -> i2c .slaveaddr_state = WriteAddressed ;
707706 if ((obj -> i2c .tran_ctrl & TRANCTRL_STARTED ) && obj -> i2c .tran_pos ) {
708- if (obj -> i2c .tran_pos < obj -> i2c .tran_end ) {
709- if (status == 0x80 || status == 0x88 ) {
710- if (obj -> i2c .tran_ctrl & TRANCTRL_RECVDATA ) {
707+ // Did we receive any data? If so, receive it (if there is space in the buffer) and update tran_pos
708+ if (status == 0x80 || status == 0x88 ) {
709+ if (obj -> i2c .tran_ctrl & TRANCTRL_RECVDATA ) {
710+ if (obj -> i2c .tran_pos < obj -> i2c .tran_end )
711+ {
711712 * obj -> i2c .tran_pos ++ = I2C_GET_DATA (i2c_base );
712- obj -> i2c .tran_ctrl &= ~TRANCTRL_RECVDATA ;
713713 }
714+
715+ obj -> i2c .tran_ctrl &= ~TRANCTRL_RECVDATA ;
714716 }
717+ }
715718
716- if (status == 0x88 ) {
717- obj -> i2c .slaveaddr_state = NoData ;
718- i2c_fsm_reset (obj , I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk );
719- } else if (obj -> i2c .tran_pos == obj -> i2c .tran_end ) {
720- obj -> i2c .tran_ctrl &= ~TRANCTRL_STARTED ;
721- i2c_disable_int (obj );
722- } else {
723- uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk ;
724- if ((obj -> i2c .tran_end - obj -> i2c .tran_pos ) == 1 &&
725- obj -> i2c .tran_ctrl & TRANCTRL_NAKLASTDATA ) {
726- // Last data
727- i2c_ctl &= ~I2C_CTL0_AA_Msk ;
728- }
729- I2C_SET_CONTROL_REG (i2c_base , i2c_ctl );
730- obj -> i2c .tran_ctrl |= TRANCTRL_RECVDATA ;
719+ // Did we NACK this byte, ending the transaction?
720+ if (status == 0x88 ) {
721+ obj -> i2c .slaveaddr_state = NoData ;
722+ i2c_fsm_reset (obj , I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk );
723+ }
724+ // Otherwise, tell the peripheral to receive the next byte
725+ else {
726+ uint32_t i2c_ctl = I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk ;
727+ if ((obj -> i2c .tran_end - obj -> i2c .tran_pos ) == 1 &&
728+ obj -> i2c .tran_ctrl & TRANCTRL_NAKLASTDATA ) {
729+ // Last data
730+ i2c_ctl &= ~I2C_CTL0_AA_Msk ;
731731 }
732- } else {
733- obj -> i2c .tran_ctrl &= ~TRANCTRL_STARTED ;
734- i2c_disable_int (obj );
735- break ;
732+ I2C_SET_CONTROL_REG (i2c_base , i2c_ctl );
733+ obj -> i2c .tran_ctrl |= TRANCTRL_RECVDATA ;
736734 }
737735 } else {
738736 i2c_disable_int (obj );
739737 }
740738 break ;
741- //case 0xA0: // Slave Receive Repeat Start or Stop
739+
740+ case 0xA0 : // Slave Operation Complete
741+ // Master sent STOP condition, go back to idle state and end the operation
742+ obj -> i2c .slaveaddr_state = NoData ;
743+ i2c_fsm_reset (obj , I2C_CTL0_SI_Msk | I2C_CTL0_AA_Msk );
744+ obj -> i2c .tran_ctrl &= ~TRANCTRL_STARTED ;
745+ i2c_disable_int (obj );
746+ break ;
742747
743748 // GC mode
744749 //case 0xA0: // GC mode Repeat Start or Stop
@@ -903,6 +908,7 @@ uint32_t i2c_irq_handler_asynch(i2c_t *obj)
903908 uint8_t * rx = (uint8_t * ) obj -> rx_buff .buffer ;
904909 rx [obj -> rx_buff .pos ++ ] = I2C_GET_DATA (((I2C_T * ) NU_MODBASE (obj -> i2c .i2c )));
905910 }
911+ // fall through
906912 case 0x40 : // Master Receive Address ACK
907913 I2C_SET_CONTROL_REG (i2c_base , I2C_CTL0_SI_Msk | ((obj -> rx_buff .pos != obj -> rx_buff .length - 1 ) ? I2C_CTL0_AA_Msk : 0 ));
908914 break ;
@@ -915,11 +921,15 @@ uint32_t i2c_irq_handler_asynch(i2c_t *obj)
915921 break ;
916922
917923 case 0x58 : // Master Receive Data NACK
924+
925+ // We get here after the last byte was transferred in an async read. Save it into the buffer
926+ // and end the transaction.
918927 if (obj -> rx_buff .buffer && obj -> rx_buff .pos < obj -> rx_buff .length ) {
919928 uint8_t * rx = (uint8_t * ) obj -> rx_buff .buffer ;
920929 rx [obj -> rx_buff .pos ++ ] = I2C_GET_DATA (((I2C_T * ) NU_MODBASE (obj -> i2c .i2c )));
921930 }
922- I2C_SET_CONTROL_REG (i2c_base , I2C_CTL0_STA_Msk | I2C_CTL0_SI_Msk );
931+ I2C_SET_CONTROL_REG (i2c_base , I2C_CTL0_STO_Msk | I2C_CTL0_SI_Msk );
932+ event = I2C_EVENT_TRANSFER_COMPLETE ;
923933 break ;
924934
925935 case 0x00 : // Bus error
0 commit comments