-
Notifications
You must be signed in to change notification settings - Fork 67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
XMC2Go: Wire.begin() sends I2C start condition #234
Comments
As this is FIRST use of a pin after CPU RESET, I suspect that what is needed is not ordering of lines, but a write to the output register to set both bits High, BEFORE configuring pin as output open drain. It looks like the internal GPIO register is cleared to 0 on power up/reset, so when the configuration is made the first thing that happens is the EXISTING state of the internal output register (0) is connected to the pin. This sort of mod would be required to BOTH types of beigin as Master and Slave. Also the pins are for some strange reinitialised to same settings in end() which is odd, as they should already be initialised before getting to end(). Suspect some tidy up there as well. A quick look, something like the following NOT TESTED but suggestion for you to try - XMC_GPIO_SetOutputLevel( , , XMC_GPIO_OUTPUT_LEVEL_HIGH ); For each pin probably with references to the references (uint8_t)XMC_I2C_config->scl.port Giving two extra line BEFORE the init of XMC_GPIO_SetOutputLevel( (uint8_t)XMC_I2C_config->scl.port, (uint8_t)XMC_I2C_config->scl.pin,, XMC_GPIO_OUTPUT_LEVEL_HIGH ); XMC_GPIO_SetOutputLevel( (uint8_t)XMC_I2C_config->sda.port, (uint8_t)XMC_I2C_config->sda.pin, XMC_GPIO_OUTPUT_LEVEL_HIGH ); In both begin() and begin(address) functions BEFORE the XMC_GPIO_Init(...) calls |
Wow, thank you for the super quick reply :) I tried the suggested solution, but it seems that it does not work.
directly before those two lines:
But unfortunately I still see the lines going LOW |
The initial value of the i2c lines is set to HIGH for all boards and configurations: So, maybe the reordering of the functions is enough for not falling into that start condition. But I would expect that such transient of sda and scl going low should not happen any time given that both are pulled-up to VDD, and the init is setting the HIGH as well. |
That is what should be happening, but I suspect the issue is order of configuring pins with I2C_init and I delved into gpio_init that appears to set level AFTER setting pin configuration, this may well be within th depths of XMCLIB In most cases this won't be noticed, it is noticeable in I2C due to state transitions by order of execution. In reality it should not be possible. Setting mode then setting default level is a problem on many platforms where people do not set level before configuring as output. In most cases the users or equipemnt does not notice the glitch when just driving an LED or similar. When configuring pins for interrupts it is often advisable to ensure pin is suitable state to avoid strange glitches. I will see if I can delve further into the code, between other things. |
From you analayser traces it lokks like the time between first edge going low and edge going high ias around 12 micro seconds, is this always a fixed time? Is the difference between the two edges going low always the same time? This suggests code execution timing, along with fact they both go high almost the same time when the I2C actually takes over |
I suspect the order of calls in Wire.cpp compared to what XMCLIB functions are doing especially with HWSEL (who has control of pins), as the XMC_GPIO_Init calls are in the middle of I2C config HWSEL may be being changed all over the place, and then set correct at last call in function XMC_I2C_CH_Start XMC_GPIO_Init does many things Two tests I would suggest
I suspect there is an interaction somewhere causing problems with many things possibly the HWSEL and changing things one pin ata time whilst the I2C hardware deasl with two pins simultaneously |
Thanks for doing those tests, as suspected the issue is how XMC_GPIO_Init is functioning, which is different order to the version of XMC1100 processor manual I have checked through which mentions orders to avoid glitches. See Reference manual for XMC1100AB, TPage 18-10 onwards Section 18.7 Initialization and System Dependencies, order is supposedly disable HWSEL before changing to input (clearing all bits for that pins mode). Manual states when setting utput to set HWSEL as one of the LAST things, there is no resetting of HWSEL before exit, even to what it was before.. So either the HWSEL disable is not working correctly or when USIC mode is set to I2C it over rides any form of HWSEL setting, the other cause is the source control in this function. There is no mention in these sections about source control which may be a major cause of issues as in init xmc_i2c_conf.c sets the source to XMC_INPUT_F and XMC_INPUT_E, where as in end they are set to XMC_INPUT_A. So the source is set to USIC pins, BEFORE the mode is configured, so if the USIC output is zero that is passed across to output regardless of output register (fine for SPI not for I2C). Doing what you are doing is LESS lkely to affect interrupts as these are defined by the I2C setup of the USIC and removing glitches lessens chnces of false interrupts. When under Hardware Control configurations of the port settings registers are NOT altered as the hardware control is after the registers, which is why I think the GPIO init in end is unnecessary. At the moment I fail to see that HWSEL is actually doing anything for I2C configuration, as it is not enabled by the time XMC_I2C_CH_Start, the hardware appears to takeover regardless. As your tests show, it does not matter where XMC_GPIO_Init is the I2C can work (with or without glitches. I would suggest, trying commenting out XMC_GPIO_Init calls in begin() of Wire.cpp, and test operations for start and communications. and checking that open drain gets configured by removing a pullup.. To ME it looks like at least with USIC configuration of pins it over rides probably ALL configuratuons of pin regardless, or at worst only the GPIO pins source needs changing AFTER starting I2C mode. Especially as you have things failing on the first transaction only. |
Sorry, I tried, but I'm not sure if I understood every part of your answer correctly. (I labeled by answer with numbers in order to structure it a little)
But when I looked into those functions I only see modifications to the USIC channel registers, not yet the GPIO/Port registers. So the pins are not affected as long as they are not set to HW-controlled via the HWSEL-bits, aren't they?
Aren't those "spikes" exactly what I observed?
|
The first problem is that HWSEL is being used funny, and I think that your fix that fixes a part of the problem is that XMC_I2C_CH_Start has grabbed some form of H/W control BEFORE XMC_GPIO_Init can do anything, and XMC_GPIO_Init "supposedly" ONLY DISABLES hardware control (in wrong order) and never reenables it. In Section 18.3 it states But nowhere could I find what aspects of hardware control it actually does for any pin or peripheral. Your tests
When setting a port you should ENABLE HWSEL as last action, this is NOT done, could be acheived by reading before disbling and rewriting saved value as last thin in XMC_GPIO_Init. This means reconfigurations later could be scuppered. 2/ We do not know from manual if ALL actions occur at XMC_I2C_CH_Start or part way through. 3/ Yes you are getting spikes, yes this is part of the solution. It has highlighted to me other potential issues like do we actually need to do XMC_GPIO_Init in Wire.end(), does this issue also occur in SPI, or other functions to do with timers, can the port be reconfigured after an end() correctly, also need to check versions of XMCLIB and see if better XMC_GPIO_Init exists in newer versions. 4/ What to do see if you can do a Pull Request for develop (V2.1x) and develop-1.x (V1.7x) a both versions exist and both have the SAME problem. I as a fellow contributor thank you for your willingness to do tests, and having a hardware setup to test this on, |
I have looked through code this problem affects XMC_GPIO_Init issues affect all boards HardwareSerial on end does NOT do some things like set the USIC channel to idle, and they HALF did the fix of moving one of the XMC_GPIO_init before XMC_UART_CH_Start not after it I will see what has to be done, when I get a few minutes. |
Now an important related update has been merged into develop I will try to find tiime to fix file for I2C,SPI, HardwareSerial and I2S. Later a fix for XMCLIB |
Thanks for keeping this topic alive and sorry for my delayed answer. I had a lot of other stuff going on the last few weeks and couldn't find the time to further work on this topic :/ |
Like you I have many things on including doing other Arduino based boards projects involving team of people and multiple customers in a long chain, taking up most of my time. If you can get I2C sorted for develop (V2.x branch) and develop-1.x (V1.7x +) branch it would help, and I can look t others later. Main things re
Basically in end we are duplicating what ws done in begin and if someone has externally changed the port pin config before calling end, either way will cause issues and it is unnecessary code. I will look at other iUSIC nterfaces and updating XMCLib version then change needed in there when I get some time, a few pull requests for that. |
Put the GPIO_Init() after CH_Start for SPI, I2C and HardwareSerial in order to avoid false pulses as described in issue Infineon#234
Put the GPIO_Init() after CH_Start for SPI, I2C and HardwareSerial in order to avoid false pulses as described in issue Infineon#234
Had a look and only minor thing missed was moving the sclk call to GPIO.init in HW_SPI.cpp |
Thanks @9Volts9er for highlighting this issue and also providing the fix. Thanks @techpaul for the support. |
Put the GPIO_Init() after CH_Start for SPI, I2C and HardwareSerial in order to avoid false pulses as described in issue #234
Hi,
I am using the XMC2Go and the Release 2.1.0 of XMC-for-Arduino in order to communicate with an I2C device.
There I have the issue that my device always ignored the first read/write command. I simply do not get an ACK. However, when I send the command a second time, it works. The issue only happens once after startup, so the first I2C communication after startup was ignored. Later commands were not affected.
So I had a closer look to this with a logic analyzer.
There I found that the Wire.begin() happens to pull down the SDA and SCL pins:
According to the I2C specification this can be interpreted as an I2C start condition, because the SDA is pulled LOW while SCL is idle (HIGH).
I traced this down to the following two code lines inside the Wire.begin():
Link to code
Those code lines seem to be responsible for pulling down at first SDA and then SCL.
A workaround for me was to exchange those lines with each other. Now the SCL gets pulled LOW, and then afterwards SDA, so this is not recognized as start condition anymore, and so the communication worked without any problems.
However, this is just a workaround, and maybe just for my specific case, it's not a really good solution. I'm still not sure, why the lines get pulled down in the first place...
Maybe someone with a better understanding of the code could help here?
Thanks a lot.
The text was updated successfully, but these errors were encountered: