@@ -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 ;
@@ -706,20 +705,26 @@ static void i2c_irq(i2c_t *obj)
706705        obj -> i2c .slaveaddr_state  =  WriteAddressed ;
707706        if  ((obj -> i2c .tran_ctrl  &  TRANCTRL_STARTED ) &&  obj -> i2c .tran_pos ) {
708707            if  (obj -> i2c .tran_pos  <  obj -> i2c .tran_end ) {
708+ 
709+                 // Did we receive any data? If so, receive it (if there is space in the buffer) and update tran_pos 
709710                if  (status  ==  0x80  ||  status  ==  0x88 ) {
710711                    if  (obj -> i2c .tran_ctrl  &  TRANCTRL_RECVDATA ) {
711-                         * obj -> i2c .tran_pos  ++  =  I2C_GET_DATA (i2c_base );
712+                         if (obj -> i2c .tran_pos  <  obj -> i2c .tran_end )
713+                         {
714+                             * obj -> i2c .tran_pos  ++  =  I2C_GET_DATA (i2c_base );
715+                         }
716+                         
712717                        obj -> i2c .tran_ctrl  &= ~TRANCTRL_RECVDATA ;
713718                    }
714719                }
715720
721+                 // Did we NACK this byte, ending the transaction?  
716722                if  (status  ==  0x88 ) {
717723                    obj -> i2c .slaveaddr_state  =  NoData ;
718724                    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  {
725+                 }
726+                 // Otherwise, tell the peripheral to receive the next byte 
727+                 else  {
723728                    uint32_t  i2c_ctl  =  I2C_CTL0_SI_Msk  | I2C_CTL0_AA_Msk ;
724729                    if  ((obj -> i2c .tran_end  -  obj -> i2c .tran_pos ) ==  1  && 
725730                            obj -> i2c .tran_ctrl  &  TRANCTRL_NAKLASTDATA ) {
@@ -738,7 +743,14 @@ static void i2c_irq(i2c_t *obj)
738743            i2c_disable_int (obj );
739744        }
740745        break ;
741-     //case 0xA0:  // Slave Receive Repeat Start or Stop 
746+ 
747+     case  0xA0 :  // Slave Operation Complete 
748+         // Master sent STOP condition, go back to idle state and end the operation 
749+         obj -> i2c .slaveaddr_state  =  NoData ;
750+         i2c_fsm_reset (obj , I2C_CTL0_SI_Msk  | I2C_CTL0_AA_Msk );
751+         obj -> i2c .tran_ctrl  &= ~TRANCTRL_STARTED ;
752+         i2c_disable_int (obj );
753+         break ;
742754
743755    // GC mode 
744756    //case 0xA0:  // GC mode Repeat Start or Stop 
@@ -903,6 +915,7 @@ uint32_t i2c_irq_handler_asynch(i2c_t *obj)
903915            uint8_t  * rx  =  (uint8_t  * ) obj -> rx_buff .buffer ;
904916            rx [obj -> rx_buff .pos  ++ ] =  I2C_GET_DATA (((I2C_T  * ) NU_MODBASE (obj -> i2c .i2c )));
905917        }
918+         // fall through 
906919    case  0x40 :  // Master Receive Address ACK 
907920        I2C_SET_CONTROL_REG (i2c_base , I2C_CTL0_SI_Msk  | ((obj -> rx_buff .pos  !=  obj -> rx_buff .length  -  1 ) ? I2C_CTL0_AA_Msk  : 0 ));
908921        break ;
@@ -915,11 +928,15 @@ uint32_t i2c_irq_handler_asynch(i2c_t *obj)
915928        break ;
916929
917930    case  0x58 :  // Master Receive Data NACK 
931+ 
932+         // We get here after the last byte was transferred in an async read. Save it into the buffer 
933+         // and end the transaction. 
918934        if  (obj -> rx_buff .buffer  &&  obj -> rx_buff .pos  <  obj -> rx_buff .length ) {
919935            uint8_t  * rx  =  (uint8_t  * ) obj -> rx_buff .buffer ;
920936            rx [obj -> rx_buff .pos  ++ ] =  I2C_GET_DATA (((I2C_T  * ) NU_MODBASE (obj -> i2c .i2c )));
921937        }
922-         I2C_SET_CONTROL_REG (i2c_base , I2C_CTL0_STA_Msk  | I2C_CTL0_SI_Msk );
938+         I2C_SET_CONTROL_REG (i2c_base , I2C_CTL0_STO_Msk  | I2C_CTL0_SI_Msk );
939+         event  =  I2C_EVENT_TRANSFER_COMPLETE ;
923940        break ;
924941
925942    case  0x00 :  // Bus error 
0 commit comments