I2CSlave test program. I2CSlave library has some improper behavior, so this program is able to watch that. The workaround for this behavior, only for NXP device, is wrote in 'I2CSlave_mod_NXP.cpp'.
I2CSlave_mod_NXP.cpp
00001 #include "I2CSlave_mod_NXP.h" 00002 00003 #define I2C_CONSET(x) (x->i2c->CONSET) 00004 #define I2C_CONCLR(x) (x->i2c->CONCLR) 00005 #define I2C_DAT(x) (x->i2c->DAT) 00006 #define I2C_STAT(x) (x->i2c->STAT) 00007 00008 static inline void i2c_conclr(i2c_t *obj, int start, int stop, int interrupt, int acknowledge) { 00009 I2C_CONCLR(obj) = (start << 5) 00010 | (stop << 4) 00011 | (interrupt << 3) 00012 | (acknowledge << 2); 00013 } 00014 00015 // Clear the Serial Interrupt (SI) 00016 static inline void i2c_clear_SI(i2c_t *obj) { 00017 i2c_conclr(obj, 0, 0, 1, 0); 00018 } 00019 00020 static inline int i2c_status(i2c_t *obj) { 00021 return I2C_STAT(obj); 00022 } 00023 00024 // Wait until the Serial Interrupt (SI) is set 00025 static int i2c_wait_SI(i2c_t *obj) { 00026 int timeout = 0; 00027 while (!(I2C_CONSET(obj) & (1 << 3))) { 00028 timeout++; 00029 if (timeout > 100000) return -1; 00030 } 00031 return 0; 00032 } 00033 00034 00035 I2CSlave_mod::I2CSlave_mod(PinName sda, PinName scl) : I2CSlave(sda, scl) { 00036 } 00037 00038 00039 int I2CSlave_mod::read(char *data, int length) { 00040 return i2c_slave_read_mod(&_i2c, data, length) != length; 00041 } 00042 00043 00044 int I2CSlave_mod::i2c_slave_read_mod(i2c_t *obj, char *data, int length) { 00045 int count = 0; 00046 int status; 00047 00048 do { 00049 if((status == 0x80) || (status == 0x90)) { 00050 data[count] = I2C_DAT(obj) & 0xFF; 00051 count++; 00052 } 00053 i2c_clear_SI(obj); 00054 i2c_wait_SI(obj); 00055 status = i2c_status(obj); 00056 } while (((status == 0x80) || (status == 0x90) || 00057 (status == 0x060) || (status == 0x70)) && (count < length)); 00058 00059 if(status != 0xA0) { 00060 i2c_stop(obj); 00061 } 00062 00063 i2c_clear_SI(obj); 00064 00065 return count; 00066 }
Generated on Tue Aug 16 2022 07:10:45 by 1.7.2