@@ -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