I2C bus not running correctly after multiple thread access

I've got a project that is running on SDK1.7.5 (modified by https://community.renesas.com/mcu-mpu/embedded-system-platform/f/forum/16286/riic-sclk-rate-is-screwy) on an S5D9.  This project was updated from SDK1.5.0-RC1 and is giving me some problems.

It has two threads that access a shared I2C bus with multiple peripherals on it, some of which happen on the one thread and some of which are on the other thread.  This is set up using the normal SDK framework of shared I2C bus structure. Running one thread or the other I don't have problems on this bus. Running two of them, at some point soon, I get the SDA line messed up which causes the bus to stop working.

Prior to having bus problems, the SDA line looks like this:

   Note the starting down how sharp the slope is on this.  It allows a start marker quite well.. Pretty quickly however we run into some sort of oddball collision or other and the SDA line looks like this:

Note the leading edge has a slope that is very much slower and it overlaps the SCL incorrectly which makes for illegal start markers.  It'll go like this till a power reset with nothing on that bus able to be addressed. 

So, what could be the problem here? This is some sort of driver issue here but I don't know what settings this is messing up..

I've got another project using this same I2C code and it doesn't do this at all on the same board...  I haven't been able to find a difference in the projects yet.

Any hints?

Top Replies

  • Hi,

    This module guide might help.

    I²C Framework Module Guide - Application Project (renesas.com)

    Are you locking access to the bus before making an access? It sounds like the two threads are accessing the bus at the same time. Try using the locking feature (which internally uses a mutex) to lock the bus access so only one thread is able to access the bus at a time.

    Ian.

  • I'll give this a look.  I'm guessing this is what is happening BUT...

    a) isn't this framework already doing that? I mean it's showing as a shared framework so isn't is supposed to be locking?  In fact the r_iic.c is using R_BSP_SoftwareLock() in the reads/writes.

    b) I've got another project that is quite close to this project and I just don't have the problem in it.  Timing is a bit different for the one thread but I've stopped accessing I2C in the one thread and have had the problem as well.

    Still, it's the only stone I've got so I'll see what I can see with it by turning it over.  I was thinking that maybe I'll have to do something along those lines myself.

  • It's better with this (using lock and unlock), but not completely right.  I still get the thing hosing the I2C line at some point although not as quickly and not always.

    The odd thing is that when it does hose the I2C, it's always got that illegal SDA transition and the only way out of that is to power cycle it. I have yet to catch exactly that transition but it only happens when I've got traffic from the other thread.

  • I've got something really, really, screwy going on in this code here.  First, I think that the above solution has fixed some things and so is the solution for this particular partial problem sort of.

    BUT

    I've got other things going on that somehow impact the SDA line there.  I've got a screen that I've been going to using GUIX that when I execute (in a separate thread from either of the ones talking on that I2C bus):

    gx_prompt_text_set(&((WINDOW_PRACTICE_C_CONTROL_BLOCK *)p_window_PracticeC)->window_practice_C_CompRate, "--");

    (i.e. putting a "--" in a text control) it kills the I2C lines.  Other control s that I'm filling in at the SHOW event don't cause the problem at all.

    It must be something to do with timing of something but I haven't been able to locate just what is the root cause of this.  Take this line out and things run fine. Put it back in and it goes wild the next time I hit up the I2C bus with a request for write.

    Well, the second time I do it.

    What I'm seeing is that I've got a pair of write/restart/read statements that have a 10mS wait between them usually and repeated every 50mS.  This can go on all day without problems until I hit this GUIX line.  Once that happens, the next time it requests the I2C lines, the gap between the write/restart/read is changed to ~900uS and things go out to lunch from there as shown on the scope with subsequent attempts at the write it gets a NAK. (not surprising)

    I am not clear on who is hanging up the bus (although I have suspicions), but from that point on, it is hung until a reset happens.

    What I'm guessing is going on is that there is some sort of forcing a context switch back to the thread that's doing the 10mS wait before it should and that's forcing some sort of I2C error along the way.  But that's just a guess right now.

  • Hello !
    Have you made any progress on this issue? Kindly let us know if there's any update.

    Regards,
    Jayesh

    If this response, or one provided by another user, answers your question, please verify the answer. Thank you!
    Renesas Engineering Community Moderators
    https://community.renesas.com/
    https://academy.renesas.com/
    en-support.renesas.com/.../

  • I've had to put this project aside for a bit due to other priorities.  I think I've found a workaround of sorts with this but I've got a ton of unanswered questions at the same time.  I'm leaning towards multiple problems all ganging up on me.  Some hardware, some firmware at various levels.  The deeper levels of the firmware are going to be interesting.

    The thing that's kicking up at least some of the hardware issue is this timing thing.  What apparently is happening is that a 1 tick wait (tx_thread_sleep (1)) is coming back whenever it feel like coming back instead of *at least* 1 tick.  I have not tracked down why that is at this point; it could be a driver problem of sorts or a ThreadX problem of another sort. 

    I *do* have some unexplained hardware problem going on as well here that the vendor in question isn't shedding a lot of light on at this point.

    Interesting enough I can clear the problem if I go talk to a different peripheral on the same bus. So something is watching what's going on and clearing itself, thus clearing the bus. 

    It'll be some time before I can come back to this problem however so hold it in your thoughts for a bit.

    Best Regards

  • Hi RJL,

    The tx_thread_sleep(1) will expire on the next systick.  The amount of time the thread will suspend depends on when the sleep is issued relative to the systick clock.  You can get a minimum of no delay to 1 systick delay.  If you use tx_thread_sleep(2) you will get between 1 and 2 ticks of delay.  If you need more precise delays, you can use the hardware timers and set a semaphore in the timer callback and have your thread pend on the semaphore.

    -Gary 

  • Ah, that would sort of explain it. I always have right around that time happen normally, but the switch between screens might perturb the timing of when we get to something enough to knock the implicit synchronization.. I'll have to look into that one. wasy enough to check the theory anyway.

    Might have to go with the timer thing as I don't know I can handle the 20mS time frame... 10mS is forever these days as it is..

    thanx