CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

I2C best practices? Example template?
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
allenhuffman



Joined: 17 Jun 2019
Posts: 537
Location: Des Moines, Iowa, USA

View user's profile Send private message Visit poster's website

PostPosted: Mon Oct 28, 2019 2:31 pm     Reply with quote

gaugeguy wrote:
Check the assembly code. If the bit in CCS is labeled PCIE for both I2C1CON and I2C2CON then your code is probably setting the bit in the wrong register.
You may need to use getenv to get the address for I2C2CONH and then do a #bit for the PCIE in that register manually.


Thanks... I should have noticed by the description using I2CxCONH. I changed it to:
Code:

// I2C2CONH - PCIE enable/disable bit, then P and S bits for status.
#word I2C2CONH = getenv("SFR:I2C2CONH")

#bit PCIE = I2C2CONH.6              // bit 6 - enable/disable

Now I see the bit set. I'm now working thru the interrupts to see if the Start and Stop IRQs will do what I want to do.
_________________
Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?
allenhuffman



Joined: 17 Jun 2019
Posts: 537
Location: Des Moines, Iowa, USA

View user's profile Send private message Visit poster's website

PostPosted: Mon Oct 28, 2019 3:10 pm     Reply with quote

Looks like this wasn't what I was looking for. I am now exploring this:
Code:
#bit MXMT = I2C2STAT.14              // bit 14 - TRSTAT master xmit status

When the master is done with the write, this clears to 0. I made my ISR check for this, and use it to flag that a message has been received. It is working great, but I'm not confident this is a proper way to do this. I don't know if I2C messages can be fragmented... Does this toggle between multiple write() commands on the Master? Or only at the end of a stop()?

Time to hook the scope back up...
_________________
Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Oct 28, 2019 4:54 pm     Reply with quote

Could you tell us what chip you're using, and whether this is for a Master
or Slave ? The reason is, if I Google the following I get no hits at all.
Quote:
MXMT I2C2STAT
Ttelmah



Joined: 11 Mar 2010
Posts: 19221

View user's profile Send private message

PostPosted: Tue Oct 29, 2019 1:46 am     Reply with quote

The reason is he has given the bit his own name. It is the TRSTAT bit.
Ttelmah



Joined: 11 Mar 2010
Posts: 19221

View user's profile Send private message

PostPosted: Tue Oct 29, 2019 7:42 am     Reply with quote

It's worth perhaps understanding that the standard I2C usage allows any size
'block' to be handled (up to 128 bytes). The only reason for needing to
detect 'stop', is if you want to apply some form of 'post processing' when
a block is received. Normally this is actually done by simply having an
'action' bit that the master sets to say to perform this, rather than trying
to do it automatically.
allenhuffman



Joined: 17 Jun 2019
Posts: 537
Location: Des Moines, Iowa, USA

View user's profile Send private message Visit poster's website

PostPosted: Tue Oct 29, 2019 8:44 am     Reply with quote

Ttelmah wrote:
It's worth perhaps understanding that the standard I2C usage allows any size
'block' to be handled (up to 128 bytes). The only reason for needing to
detect 'stop', is if you want to apply some form of 'post processing' when
a block is received. Normally this is actually done by simply having an
'action' bit that the master sets to say to perform this, rather than trying
to do it automatically.


Yes. I am trying to implement this, rather than how our pre-existing code does it by looking at specific bytes in a payload for the length, and knowing it is done when that many have been received. I just want to make something more flexible and generic than the pre-existing hard-coded approach currently in place.

The ISR is servicing a byte at a time, and I want to detect when the master has written a message so it can then be processed.

Our system has about five unique boards with variations of PIC24, and we end up talking to stacks of other boards via a multiplexer that receives I2C commands and then passes them out on a secondary I2C bus to 8 more units. Lots and lots of things stacked together :-) The original design from several years ago was not written with this in mind, so I'm hoping to help rewrite it to be a bit more flexible and easy to modify.
_________________
Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?


Last edited by allenhuffman on Tue Oct 29, 2019 8:52 am; edited 1 time in total
allenhuffman



Joined: 17 Jun 2019
Posts: 537
Location: Des Moines, Iowa, USA

View user's profile Send private message Visit poster's website

PostPosted: Tue Oct 29, 2019 8:48 am     Reply with quote

PCM programmer wrote:
Could you tell us what chip you're using, and whether this is for a Master
or Slave ? The reason is, if I Google the following I get no hits at all.
Quote:
MXMT I2C2STAT


I called it M XMT for Master Transmit. If I get to refactor, I will probably "clean code" it and make long, descriptive names like MasterTransmitStatus or something Smile
_________________
Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?
Ttelmah



Joined: 11 Mar 2010
Posts: 19221

View user's profile Send private message

PostPosted: Tue Oct 29, 2019 9:11 am     Reply with quote

So, in which case just use the normal way. Change the setup to enable
interrupt on start/stop, and before doing the normal I2C handling check
for start (exit if seen), and stop (trigger your end of block code). Follow
with the standard I2C code.
The TRSTAT bit is not meant to be used for this. It is defined for master
only, and does sometimes seem to work on slave, but not guaranteed.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Oct 29, 2019 10:27 am     Reply with quote

Also, changing the names of register bits makes the code much harder
to maintain. It's best to use the actual name and then add a comment
to clarify it, if necessary.

Notice how I was mystified by your bit name ? I googled it and got a
nothing-burger. A future maintainer of your code will have a hard time.
allenhuffman



Joined: 17 Jun 2019
Posts: 537
Location: Des Moines, Iowa, USA

View user's profile Send private message Visit poster's website

PostPosted: Tue Oct 29, 2019 11:49 am     Reply with quote

Ttelmah wrote:
The TRSTAT bit is not meant to be used for this. It is defined for master only, and does sometimes seem to work on slave, but not guaranteed.


Is there any existing CCS code that I can use to do this? How is one supposed to even know that the master is done writing X bytes with their API?
_________________
Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?
allenhuffman



Joined: 17 Jun 2019
Posts: 537
Location: Des Moines, Iowa, USA

View user's profile Send private message Visit poster's website

PostPosted: Tue Oct 29, 2019 11:51 am     Reply with quote

PCM programmer wrote:
Notice how I was mystified by your bit name ? I googled it and got a nothing-burger. A future maintainer of your code will have a hard time.


Excatly. That's why I would personally call it MasterTransmitStatus or something verbose. Techies love to use alphabet soup but that makes understanding code difficult -- have to consult datasheets, etc.

If you've never looked into it, check out https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882. I had never heard of this concept until my previous job, and after going in kicking in screaming for months, it finally changed my outlook on what code can be.

It's tough to honor in embedded if you are low on flash storage or clock cycles, but when that's not a barrier, it makes a great amount of sense.

Some day, I'll go back through all my GitHub stuff and "clean code" it all. Talk about alphabet soup...
_________________
Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?
Ttelmah



Joined: 11 Mar 2010
Posts: 19221

View user's profile Send private message

PostPosted: Tue Oct 29, 2019 1:29 pm     Reply with quote

Just use the P & S bits. These say whether the transfer that triggers the
interrupt was a start or stop.
Ttelmah



Joined: 11 Mar 2010
Posts: 19221

View user's profile Send private message

PostPosted: Thu Oct 31, 2019 1:30 am     Reply with quote

The way I have handled this in the past, which is simple, and works, is:

Setup standard slave interrupt.
Use standard slave interrupt handler.

Then in main code loop, test for the 'P' bit from the I2C. If this is set, call
your 'end of packet' handler code.

Nothing more is needed.
allenhuffman



Joined: 17 Jun 2019
Posts: 537
Location: Des Moines, Iowa, USA

View user's profile Send private message Visit poster's website

PostPosted: Thu Nov 07, 2019 2:18 pm     Reply with quote

(Edit to remove the code I found. After looking into it more, I am uncomfortable with how it mixes library calls and direct register access.)
_________________
Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?
allenhuffman



Joined: 17 Jun 2019
Posts: 537
Location: Des Moines, Iowa, USA

View user's profile Send private message Visit poster's website

PostPosted: Thu Nov 07, 2019 3:28 pm     Reply with quote

Ttelmah wrote:
The way I have handled this in the past, which is simple, and works, is:

Setup standard slave interrupt.
Use standard slave interrupt handler.

Then in main code loop, test for the 'P' bit from the I2C. If this is set, call
your 'end of packet' handler code.

Nothing more is needed.


I found some polled Slave code that I was working with, and it was reading the P in the loop to know when to stop. It worked well, but once I tried to remove some of the other direct register reads, the P stopped working. The original author had their own i2cRead() routine that looked like a standard C read/write (buffer pointer, size to read/write).

I was trying to do this in polled mode, but I can't get the P to work. When I had other code in earlier that also checked RBF and DA bits, then the P was good. So maybe something about reading those other bits is necessary when no interrupts are in use.

Code:

    // IC2C3STAT - sto(P) and (S)tart bits for status.
    #word I2C3STAT = getenv("SFR:I2C3STAT")
    #bit DA = I2C3STAT.5                // bit 5 - data/address bit
    #bit P = I2C3STAT.4                 // bit 4 - stop
    #bit S = I2C3STAT.3                 // bit 3 - start
    #bit RW = I2C3STAT.2                // bit 2 - read/write bit
    #bit RBF = I2C3STAT.1               // bit 1 - RBF receive buffer status bit



    while (1) // Read incoming bytes.
    {
        buffer[bytesRead++] = i2c_read(SYSTEM_BUS);

        if (bytesRead > size)
        {
            break;
        }

        if (P == 1) // Stop?
        {
            break;
        }
    }

_________________
Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
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