Exemple #1
0
static inline int i2c_status(i2c_t *obj) {
    return I2C_STAT(obj);
}
Exemple #2
0
//==========================================================================
// The ISR does the actual work. It is not that much work to justify
// putting it in the DSR, and it is also not clear whether this would
// even work.  If an error occurs we try to leave the bus in the same
// state as we would if there was no error.
//==========================================================================
static cyg_uint32 lpc2xxx_i2c_isr(cyg_vector_t vec, cyg_addrword_t data)
{
    cyg_lpc2xxx_i2c_extra* extra = (cyg_lpc2xxx_i2c_extra*)data;
    cyg_uint8  status;
    
    I2C_R8(I2C_STAT(extra), status);
    switch(status) 
    {
    case 0x00: // bus error, stop transfer
         SET_CON(extra, CON_STO);
         extra->i2c_flag = I2C_FLAG_ERROR | I2C_FLAG_BUS;
         break;
         
    case 0x08: // START sent, send Addr+R/W
    case 0x10: // ReSTART sent, send Addr+R/W
         CLR_CON(extra, CON_STA);
         I2C_W8(I2C_DAT(extra), extra->i2c_addr);
         break;
      
    case 0x18: // Addr ACKed, send data
         if(extra->i2c_txbuf == NULL) 
         {
             extra->i2c_flag = I2C_FLAG_ERROR | I2C_FLAG_BUF;
             cyg_drv_interrupt_mask_intunsafe(vec);
             cyg_drv_interrupt_acknowledge(vec);
             return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR;
         }
         I2C_W8(I2C_DAT(extra), *extra->i2c_txbuf);
         extra->i2c_txbuf++;
         break;
         
    case 0x28: // Data ACKed, send more
         extra->i2c_count--;     
         if(extra->i2c_count == 0) 
         {
             extra->i2c_flag = I2C_FLAG_FINISH;
             cyg_drv_interrupt_mask_intunsafe(vec);
             cyg_drv_interrupt_acknowledge(vec);
             return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR;
         }
         I2C_W8(I2C_DAT(extra), *extra->i2c_txbuf);
         extra->i2c_txbuf++;
         break;
      
    case 0x50: // Data ACKed, receive more
    case 0x58: // Data not ACKed, end reception
         if(extra->i2c_rxbuf == NULL) 
         {
             extra->i2c_flag = I2C_FLAG_ERROR | I2C_FLAG_BUF;
             cyg_drv_interrupt_mask_intunsafe(vec);
             cyg_drv_interrupt_acknowledge(vec);
             return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR;
         }
      
         I2C_R8(I2C_DAT(extra), *extra->i2c_rxbuf);
         extra->i2c_rxbuf++;
         extra->i2c_count--;
         // fall through
         
    case 0x40: // Addr ACKed, receive data
         if(status == 0x58 || extra->i2c_count == 0) 
         {
             extra->i2c_flag = I2C_FLAG_FINISH;
             cyg_drv_interrupt_mask_intunsafe(vec);
             cyg_drv_interrupt_acknowledge(vec);
             return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR;
         }
      
         if((extra->i2c_count == 1) && extra->i2c_rxnak)
         {
             CLR_CON(extra, CON_AA);
         }
         else 
         {   
             SET_CON(extra, CON_AA);
         }
         break;
      
    case 0x20: // Addr not ACKed
    case 0x48: // Addr not ACKed
         SET_CON(extra, CON_STO); // tranfer failed - force stop
         extra->i2c_flag = I2C_FLAG_ERROR | I2C_FLAG_ADDR;
         cyg_drv_interrupt_mask_intunsafe(vec);
         cyg_drv_interrupt_acknowledge(vec);
         break;
         
    case 0x30: // Data not ACKed
         SET_CON(extra, CON_STO); // tranfer failed - force stop
         extra->i2c_count++;
         extra->i2c_txbuf--;
         extra->i2c_flag = I2C_FLAG_ERROR | I2C_FLAG_DATA;
         cyg_drv_interrupt_mask_intunsafe(vec);
         cyg_drv_interrupt_acknowledge(vec);
         return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR;
         break;
         
    case 0x38: // Arbitration lost
         extra->i2c_flag = I2C_FLAG_ERROR | I2C_FLAG_LOST;
         break;
         
    default: // lots of unused states
         extra->i2c_flag = I2C_FLAG_ERROR | I2C_FLAG_UNK;
         break;
    } // switch(status)
  
    CLR_CON(extra, CON_SI);
    cyg_drv_interrupt_acknowledge(vec);
    
    //
    // We need to call the DSR only if there is really something to signal,
    // that means only if extra->i2c_flag != 0
    //
    if (extra->i2c_flag)
    {
        return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR;
    }
    else
    {
        return CYG_ISR_HANDLED; 
    }
}