|
|
View previous topic :: View next topic |
Author |
Message |
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
PIC24EP512 - Cross-device FW w/ or w/o I2C devices [CLOSED] |
Posted: Thu Jun 09, 2022 8:43 am |
|
|
Device: PIC24EP512GP806
Compiler: 5.026
Hi guys,
I will go through the documentation but I figured I'd run my questionning in here in the meantime.
I have a PIC24 FW that can run on two different HW revisions: on one device revision, there's a sensor tied to I2C but that sensor is not on the other revision. So on the device with the sensor, pin G2 is used for SCL and pin G3 is used for SDA. On the device w/o the sensor, these two pins are just left floating.
I want both devices to use the same PIC firmware but I need to prevent the I2C bus from hanging on the device without the sensor when the FW gets to the point where it will try to initialize the sensor. I guess the worst case scenario is that I could physicalyl solder a resistor on G2 and G3 to pull them low then read the pins prior to initializing it but ideally, I want to avoid having to make a HW modification.
So in the code, is there anything you think of that I can easily do? This code should also be done to take into account for a defective sensor for the version with the sensor so that if the sensor is present with both lines high via their pull-ups but the sensor itself is damaged or whatnot and not responding, then I need to be able to circumvent this as well to prevent the device from hanging at boot time.
If I find a solution on my own I will post it here.
Thanks!
Ben
[EDIT 1] I guess what I am after is a way to 'test' for the presence of the sensor without hanging the I2C....
[EDIT 2] Seems that there are configurable weak pull-ups and pull-downs on each pin? I guess that if I configure SDA and SCL by default at boot time to use weak pull-downs, then I could read these two pins and if both down, then the board does not have the sensor? Because on the other rev with the sensor present, then the lines will be pulled-up by the 2.4K resistors on the PCB. Any other suggestions or comments are welcome!
Last edited by benoitstjean on Tue Jun 21, 2022 8:39 am; edited 1 time in total |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1907
|
|
Posted: Thu Jun 09, 2022 9:40 am |
|
|
An option would be to first launch a timer to expire in x ms. Inside that timer's ISR, you disable the I2C. Once the timer is launched, you attempt to access the sensor via I2C. At the end of the function to access it, you kill the timer.
If the I2C hangs, you have an escape mechanism via the timer's ISR. If the sensor is present, just kill the timer. |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 303
|
|
Posted: Thu Jun 09, 2022 9:48 am |
|
|
If you have configurable weak pull downs then that would be a good option for checking for a floating pin. If you don't then you can still check it by driving the pin low, waiting breifly, changing it to an input, and then reading the value back. If a pullup is present the pin will go high based on the RC time constant. If it is floating the pin capacitance will keep it at the driven state reliably for a short time. Exact timing would need to be done by checking rise time of the pullup. |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Thu Jun 09, 2022 10:30 am |
|
|
Hi guys,
Ok thanks. So I did find @newguy other posts where you explain this. I will have to do some tests.
Question though: what flag in the PIC registers gets set/cleared in order for the I2C to hang when the I2C slave is not responding causing the transaction to fail?
As for the configurable weak pull-ups, I think that this is only on pins that can be configured as CN interrupts.
Was off working on PIC projects for a while so I have to get back into it and re-read docs...
Thanks!
Ben |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
Re: PIC24EP512 - Cross-device FW w/ or w/o I2C devices |
Posted: Thu Jun 09, 2022 11:40 am |
|
|
benoitstjean wrote: |
[EDIT 1] I guess what I am after is a way to 'test' for the presence of the
sensor without hanging the I2C....
|
"Ping" the i2c sensor board using the method shown in the i2c bus scanner
program. "Ping" the address of the sensor board only. See this link:
http://www.ccsinfo.com/forum/viewtopic.php?t=49713
benoitstjean wrote: |
[EDIT 2] Seems that there are configurable weak pull-ups and pull-downs on
each pin? I guess that if I configure SDA and SCL by default at boot time to
use weak pull-downs, then I could read these two pins and if both down, then
the board does not have the sensor? Because on the other rev with the
sensor present, then the lines will be pulled-up by the 2.4K resistors on the
PCB. Any other suggestions or comments are welcome! |
Another option for detecting if a remote board is connected, where in
the pull-ups are on the remote board (but not on the main board), is
given in this thread. It has suggestions by Ttelmah and me:
http://www.ccsinfo.com/forum/viewtopic.php?t=59630 |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Thu Jun 09, 2022 11:44 am |
|
|
It's not a sensor board tied to the circuit, it's a circuit I made where the first rev didn't have the I2C sensor then I made a second spin with an added sensor. I have a limited amount of these boards due to component shortage so now I want to make sure both boards work with the same firmware.
But I will have a look at the links you provided.
I like @newguy's solution but I'd just like to know "what" part of the I2C transaction causes the MCU to freeze.... What I2C registers/bits on the MCU used in the background by CCS during the transaction causes the bus to freeze since that/those bit(s) aren't cleared/set.
Ben |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Fri Jun 10, 2022 12:16 am |
|
|
You don't have to.
Just use PCM_programmers approach. As he says, look at how his
I2C scanner does this. The key point is that the I2C_write that sends
the device address, returns an ACK/NACK depending on whether the
device is there.. So you can use this to 'test for' a device, without hang
problems. The hang on I2C, only happens when you try to read a device,
or if the transaction actually gets broken.
On 'what hangs the I2C bus' for a master. Nothing!. _Except_ one critical
thing. I2C, in it's very first line for a new transaction, says:
1) Wait until no activity is seen on the I2C bus.
The internal peripheral on the PIC _will_ do this. This is indicated
by both lines being high.
So where you will get a problem, is if the master tries to start a
transaction, and the lines are not high.
In the case being talked about of an external device that may or may
not be there, You need to test (by simply reading), that both lines are
high _before_ you attempt any I2C transaction.
What 'hangs' an I2C master, is where the slave has gone into a state
holding the data line low, and you then try to launch a new transaction.
Disaster....
What you ideally should always do, is test that the lines are high before
launching a transaction. Fortunately on most PIC's, you can still read
the levels of the lines even when the peripheral is attached.
Now the sequence to 'unlock' a slave in this condition is to simply send
a number of pulses on the SCL line. You have to do this by turning off
the I2C peripheral (otherwise it'll wait for the lines to go high before
it'll start a new transaction), pulse the SCL line, and then re-test if both
lines are high,
Now the key thing here is whether the lines can be made to float high
even if the I2C board is not attached?. This could be done possibly
by enabling the PIC's internal pull-ups.
If this can be done, then you can simply test for ACK/NACK to find if
the I2C device is physically there. If not, then you need to be looking
at other tests before trying to use I2C. For example, if the lines may be
floating, then simply pulse them low, and a uSec later read them. If they
have gone high, then there are pull up resistors on them (so possibly I2C),
while if not, the lines are floating. If they both go high quickly, then you
can proceed to attempt a write and see if the slave chip does acknowledge
this. |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Mon Jun 13, 2022 7:25 am |
|
|
Alrighty, I think this is perfect. Thanks guys! Apprerciated!
Ben |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Mon Jun 13, 2022 9:22 am |
|
|
For the "old" rev without the I2C devices, then I cannot use the test because the PCB does not have pull-ups (since intially there weren't any I2C devices)...
The second option is to enable PIC internal pull-ups but I don't appear to be able to do this on G2 and G3.
So the last option I have is to pulse low the two lines and read back immediately.
Thanks again,
Ben |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Mon Jun 20, 2022 9:38 am |
|
|
Good morning guys,
So if I want to 'disable' I2C after its been configured in my header file through #use i2c( MASTER, FAST, sda=PIN_G3, scl=PIN_G2, FORCE_HW ), I guess I have to do it using assembly code or a direct register access to the I2CXCON Control Register through bit 15:
Code: | ON: I2C Enable bit(2)
1 = Enables the I2C module and configures the SDAx and SCLx pins as serial port pins
0 = Disables I2C module; all I2C pins are controlled by PORT functions
|
I haven't seen a straight CCS command in the docs...
Thanks!
Ben |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jun 20, 2022 10:12 am |
|
|
There are i2c functions in the CCS manual. They start with "i2c_".
Do a search for that in the manual. Then you find i2c_init().
The manual says:
Quote: | i2c_init( )
Syntax:
i2c_init([stream],baud);
Parameters:
stream – optional parameter specifying the stream defined in #USE I2C.
baud – if baud is 0, I2C peripheral will be disabled. If baud is 1,
I2C peripheral is initialized and enabled with baud rate specified in #USE
I2C directive. If baud is > 1 then I2C peripheral is initialized and enabled
to specified baud rate.
Returns: Undefined
-----
Purpose:
To initialize I2C peripheral at run time to specified baud rate.
Availability:
All Devices
Requires:
#USE I2C |
However, you may have to set the TRIS depending on your PIC.
You'll have to check for that. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Mon Jun 20, 2022 10:21 am |
|
|
Look at the keyword 'NOINIT' in the #use 12c.
If you use this the I2C will not be initialised until you use i2c_init. |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|