Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
11 years, 1 month ago.
What changed in mbed v63 of i2c (master mode) for the KL25Z ?
I just updated my mbed code for program KL25Z_MLX90620 from v62 to v64 and the i2c code stopped working. I pushed back to v63 and it was still broken. Pushed back to v62 and everything works again.
What changed?
thanks,
...kevin
1 Answer
11 years, 1 month ago.
Hi,
Have you tried to find out where does your code break with v63/v64?
Thanks,
Bogdan
EDIT: one more thing: does the problem go away if you run the interface at 100KHz instead of 400KHz?
EDIT2: I created a repository with a tentative fix here:
http://mbed.org/users/bogdanm/code/kl25z-i2c-fix/
Please let me know if it fixes the problem for you (this should work at 400KHz).
EDIT3: I'm having intermitent results with my fix; if it still doesn't work for you, try adding a small delay after the repeated start. Something like below:
temp = obj->i2c->F >> 6; obj->i2c->F &= 0x3F; obj->i2c->C1 |= 0x04; for (i = 0; i < 100; i ++) __NOP(); obj->i2c->F |= temp << 6;
Hi Bogdan,
EDIT: no, changing to 100KHz does not fix my problem.
EDIT2: Do you have an example on how to use your library?
EDIT3: I am using the higher level i2c commands. Example below:
unsigned short MLX90620::GetOscTrimReg() { RamCmmd[0] = 2; //command RamCmmd[1] = MLXTRIM; //address of register RamCmmd[2] = 0; //address step RamCmmd[3] = 1; //# of reads _i2c.write(0xc0, RamCmmd, 4, true); _i2c.read(0xc0, RamCmmd, 2); OscTrim = (RamCmmd[1] << 8) + RamCmmd[0]; return(OscTrim); }
EDIT3a. How would I insert the delay into the example above?
EDIT3b. Can I use a simple wait_us(100) instead of for (i = 0; i < 100; i ++) NOP(); ?
...kevin
posted by 06 Aug 2013Hi again Bogdan,
EDIT2: For grins, I imported your fix library, but made no references to it. I get a compiler error
""/extras/mbed_e3affc9e7238/TARGET_KL25Z/TOOLCHAIN_ARM_STD/MKL25Z4.sct", line 4 (column 9): Error: L6235E: More than one section matches selector - cannot all be FIRST/LAST." in file "/"
Cheers,
...kevin
posted by 06 Aug 2013I can answer that one at least. His library is a modified version of mbed-src. So delete your current mbed library, import his library.
posted by 06 Aug 2013Thanks Erik - that was easy,
Bogden,
I tried the library change, but there was no change in behavior.
...kevin
posted by 06 Aug 2013Thanks for your feedback. Did you try with the delay, but without the for, just as you suggested (wait_us(100)) ? The delay that I suggested is in the library code itself (function i2c_start in my library, file targets/hal/TARGET_Freescale/TARGET_KL25Z/i2c_api.c). Modify that function to look like this:
int i2c_start(i2c_t *obj) { uint8_t temp; volatile int i; // if we are in the middle of a transaction // activate the repeat_start flag if (obj->i2c->S & I2C_S_BUSY_MASK) { // KL25Z errata sheet: repeat start cannot be generated if the I2Cx_F[MULT] field is set to a non-zero value temp = obj->i2c->F >> 6; obj->i2c->F &= 0x3F; obj->i2c->C1 |= 0x04; for (i = 0; i < 200; i ++) __NOP(); obj->i2c->F |= temp << 6; } else { obj->i2c->C1 |= I2C_C1_MST_MASK; obj->i2c->C1 |= I2C_C1_TX_MASK; } first_read = 1; return 0; }
(notice the additional 'for' loop in the function which provides the delay).
posted by 06 Aug 2013That's the internal representation of the I2C interface. You shouldn't worry about that, the high level code (common/I2C.cpp) hides the HAl details from your code. Or maybe I didn't understand your question?
EDIT: by the way, you can simply update to my latest version of the code, compile and retry. I added the code for the wait in i2c_api.c on KL25Z.
posted by 06 Aug 2013It must need something. The compiler complains that there are too few arguments.
I'll try your latest update. I'll need a few minutes
posted by 06 Aug 2013I tried the latest kl25z-i2c-fix v16. No change. I'll go back to patching in the delay
posted by 06 Aug 2013This is the only error:
"Too few arguments in function call" in file "MLX90620MLX90620.cpp", Line: 88, Col: 1
line 88 is:
i2c_start_fix(); I had to add "_fix" to the name because i2c_start already exists.
int first_read = 0; int i2c_start_fix(i2c_t *obj) { uint8_t temp; volatile int i; // if we are in the middle of a transaction // activate the repeat_start flag if (obj->i2c->S & I2C_S_BUSY_MASK) { // KL25Z errata sheet: repeat start cannot be generated if the I2Cx_F[MULT] field is set to a non-zero value temp = obj->i2c->F >> 6; obj->i2c->F &= 0x3F; obj->i2c->C1 |= 0x04; for (i = 0; i < 200; i ++) __NOP(); obj->i2c->F |= temp << 6; } else { obj->i2c->C1 |= I2C_C1_MST_MASK; obj->i2c->C1 |= I2C_C1_TX_MASK; } first_read = 1; return 0; }
The calling routine (in progress)
int MLX90620::LoadEEPROM() { //clear out buffer first for(int i = 0; i < 256; i++) { EEbuf[i] = 0; } //load the entire EEPROM EEbuf[0] = 0; if(!_i2c.write(0xa0, EEbuf, 1, true)) { //0 returned is ok i2c_start_fix(); _i2c.write(0xa1); for(int i = 0; i < 256; i++) { EEbuf[i] = _i2c.read(1); } // _i2c.read(0xa0, EEbuf, 256); //load contents of EEPROM } else { _i2c.stop(); return(1); } _i2c.stop(); return(0); }
Line 10 in the calling routine is line 88 as far as the compiler is concerned
posted by 06 Aug 2013Again, no need to do that. Just update to my latest revision of the library and test it with your original code. My suggestion was to modify the i2c_api.c file that I've been talking about, not to add another function to your own code. In short:
1. update to my latest version of the code 2. test it with your _unmodified_ code 3. let me know if that works :)
HTH,
Bogdan
posted by 06 Aug 2013I did that. See my reply just before this latest one. There was no change in behavior
posted by 06 Aug 2013