![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
allenhuffman
Joined: 17 Jun 2019 Posts: 540 Location: Des Moines, Iowa, USA
|
Slave I2C code (no interrupts) showing read/respond. |
Posted: Thu Nov 07, 2019 2:07 pm |
|
|
I am trying to do an I2C SLAVE (PIC24) that does not use interrupts. I've found examples of how to do simple reads from the master, and they seem to work well.
All the examples I have found that show the Slave responding back have interrupt service routines handling this.
My ultimate goal is to implement our own I2C library that we will have source code to (we've had a ton of I2C issues lately). None of us have ever had to write an I2C driver, so I'm seeing how easy or difficult it might be.
From a PC program (one in C, one in C#), we have code we wrote that uses the FTDI library to write data and read back responses, so I am now trying to do a generic version of the Slave side for our PIC24s. _________________ 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 Fri Nov 08, 2019 11:30 am; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9178 Location: Greensville,Ontario
|
|
Posted: Thu Nov 07, 2019 3:26 pm |
|
|
CCS doesn't 'hide' the code for their I2C drivers. Have to ask why not use them ? If they are failing, then contact CCS and they will help !
Jay |
|
![](templates/subSilver/images/spacer.gif) |
allenhuffman
Joined: 17 Jun 2019 Posts: 540 Location: Des Moines, Iowa, USA
|
|
Posted: Thu Nov 07, 2019 3:29 pm |
|
|
temtronic wrote: | CCS doesn't 'hide' the code for their I2C drivers. Have to ask why not use them ? If they are failing, then contact CCS and they will help !
Jay |
I was told they don't release the source to all of it (though apparently some does ship with source) -- is this not correct? _________________ 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 ? |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9178 Location: Greensville,Ontario
|
|
Posted: Thu Nov 07, 2019 4:16 pm |
|
|
OK... technically the 'source' or C code isn't available BUT the assembler can be seen in the listings. When you consider there's fewer PIC instructions than fuses, reading ASM is easy. Actually every bit of every byte of code you compile can be seen, though some files may need the 'nolist' option removed.
Jay |
|
![](templates/subSilver/images/spacer.gif) |
allenhuffman
Joined: 17 Jun 2019 Posts: 540 Location: Des Moines, Iowa, USA
|
|
Posted: Thu Nov 07, 2019 4:20 pm |
|
|
temtronic wrote: | OK... technically the 'source' or C code isn't available BUT the assembler can be seen in the listings. When you consider there's fewer PIC instructions than fuses, reading ASM is easy. Actually every bit of every byte of code you compile can be seen, though some files may need the 'nolist' option removed.
Jay |
Ah, yeah, so we'd still be back to reimplementing. We wanted to take care of that global int8 that the compiler but was causing us crashes from. (Changing it to a 16-bit would have fixed that particular issue.) _________________ 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 ? |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19384
|
|
Posted: Fri Nov 08, 2019 1:28 am |
|
|
Remove the 'nolist' that is in the processor's include file, and the listing
will include the CCS functions.
Use the 'symbolic' setting for the project, and you will get a listing with
register names etc.
Result, nice and easy to see what the functions do. |
|
![](templates/subSilver/images/spacer.gif) |
allenhuffman
Joined: 17 Jun 2019 Posts: 540 Location: Des Moines, Iowa, USA
|
|
Posted: Fri Nov 08, 2019 8:39 am |
|
|
Ttelmah wrote: | Result, nice and easy to see what the functions do. |
True -- one of you let me know about that in an earlier post. But it wouldn't have let us work around the compiler bug unless we wanted to start being PIC assembly programmers.
Right now I'm trying to find a bi-directional CCS I2C example that does not use interrupts. I'm trying to replicate a bit of pre-existing I2C messaging code in an IRQ-free bootloader. _________________ 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 ? |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19384
|
|
Posted: Fri Nov 08, 2019 9:03 am |
|
|
Just use the same code as for interrupt driven, but leave the interrupt disabled
and test the interrupt flag bit. Exactly the same code can be used as is
inside the interrupt handler:
Instead of:
#INT_SSP //or whichever peripheral you are using, use:
if (interrupt_active(INT_SSP))
//Then have the INT_SSP code here.
Remember you will have to clear the interrupt at the end of the routine.
No other changes are needed. |
|
![](templates/subSilver/images/spacer.gif) |
allenhuffman
Joined: 17 Jun 2019 Posts: 540 Location: Des Moines, Iowa, USA
|
|
Posted: Fri Nov 08, 2019 11:28 am |
|
|
Ttelmah wrote: | Just use the same code as for interrupt driven, but leave the interrupt disabled
and test the interrupt flag bit. Exactly the same code can be used as is
inside the interrupt handler: |
Thanks. I did not know I could use i2c_isr_state() when not using an ISR.
I took some template I2C code and modified it. I'd now like to get the P - Stop bit" status implemented so the Slave can just read whatever size message comes in.
Our existing production code parses our message format inside the ISR looking for a size field and then stops at the end and toggles a state machine to let it know there is data to read.
A reply is stuffed into a transmit buffer and then it gets sent out by the same ISR.
I'm trying to make a much more generic I2C read routine that blocks until a message of any size is received, then lets the code parse that as needed and send a response back if needed.
I took the working ISR template code and added comments from the documentation and made it poll:
Code: | unsigned int i2cPoll (void *buffer, size_t size)
{
unsigned int state;
unsigned int value;
unsigned int address;
while (1)
{
if (SI2C3IF == 1) // I2C interrupt pending.
{
state = i2c_isr_state(SYSTEM_BUS);
value = (state & ~BIT(7)); // Mask off high bit.
// High bit (X0000000) indicates READ, else WRITE
if ((state & BIT(7)) == 0) // High bit CLEAR
{
if (value == 0x00)
{
// 0 - Address match received with R/W bit clear, perform
// i2c_read( ) to read the I2C address.
address = i2c_read (SYSTEM_BUS);
buffer[value] = i2c_read (SYSTEM_BUS);
}
else
{
// 1-0x7F - Master has written data; i2c_read() will immediately
// return the data
buffer[value] = i2c_read (SYSTEM_BUS);
}
}
else // High bit SET (Slave writing to Master)
{
if (value == 0x00)
{
// 0x80 - Address match received with R/W bit set; perform
// i2c_read( ) to read the I2C address, and use i2c_write( ) to
// pre-load the transmit buffer for the next transaction (next
// I2C read performed by master will read this byte).
//address = i2c_read (SYSTEM_BUS, 2);
i2c_write (SYSTEM_BUS, buffer[0]);
}
else
{
// 0x81-0xFF - Transmission completed and acknowledged; respond
// with i2c_write() to pre-load the transmit buffer for the next
// transition (the next I2C read performed by master will read
// this byte).
i2c_write (SYSTEM_BUS, buffer[value]);
}
// Stop when we've written as much as user wanted to write.
if (value > size)
{
break;
}
}
}
} // end of while (1)
return value;
} |
I commented out the receive "//address = i2c_read (SYSTEM_BUS);" part since it hangs there for me when running this polled code, but it was working in the ISR, so there are still bugs to squish.
NOTE: This code is one routine, where the call would block for data, then return how many bytes were received. Then if it's something we expect to reply to (Master would be waiting) we pass it a buffer which gets written out. I've been talking back and forth to a C# program to test this.
I'd like to implement the reading of the "P - Stop bit" status but that's being reset somewhere. The datasheet says "Hardware set or clear when Start, Repeated Start or Stop detected" so I'm likely doing it in the wrong place.
I'm enjoying digging into this. All the I2C stuff I've done in the past was just using existing APIs that did all this. Learning lots.
Thanks for your replies. _________________ 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 ? |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19384
|
|
Posted: Sat Nov 09, 2019 2:03 am |
|
|
There is no sign of you clearing SI2C3IF. Remember _you_ have to do this
if you are polling the interrupt.
In an ISR, the compiler clears this for you.
Problem therefore is that as posted, after the first time round this code
the routine will be being used, when the interrupt has not actually
happened again. So things like reads will hang, since data is not available.... |
|
![](templates/subSilver/images/spacer.gif) |
allenhuffman
Joined: 17 Jun 2019 Posts: 540 Location: Des Moines, Iowa, USA
|
|
Posted: Sat Nov 09, 2019 8:42 pm |
|
|
Ttelmah wrote: | There is no sign of you clearing SI2C3IF. Remember _you_ have to do this
if you are polling the interrupt. |
That makes sense. I am perplexed why it was returning to the caller at all.
If I can get the P (stop) figured out, I think that will go a long way. I've only had success when I was also reading other status register bits. It reminds me my old 8-bit days with a UARTs where reading status would clear other things. I expect it's just something like that I have to learn about the PIC internals. _________________ 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 ? |
|
![](templates/subSilver/images/spacer.gif) |
allenhuffman
Joined: 17 Jun 2019 Posts: 540 Location: Des Moines, Iowa, USA
|
|
Posted: Tue Nov 12, 2019 3:39 pm |
|
|
I have been working through some messages I found on the Microchip PIC24 forum where others are trying to do the same thing -- read I2C data until the Master is done writing.
From what I've read, it is possible to miss reading the P bit if polling. But the datasheet says it is only cleared when Start, Repeated Start or Stop is detected.
Stop bit is reset when a Stop is detected???
I am trying to find more documentation than what is in the datasheet. For example, "SI2CxIF" (Slave I2C X Event Interrupt Flag Status bit). What operations trigger this, other than an incoming byte?
Thanks for any pointers to more details docs. _________________ 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 ? |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Nov 13, 2019 4:07 am |
|
|
allenhuffman wrote: | I am trying to find more documentation than what is in the datasheet. For example, "SI2CxIF" (Slave I2C X Event Interrupt Flag Status bit). What operations trigger this, other than an incoming byte?
|
Look in the PIC24 Reference Manual on i2c. Look at page 18.
http://ww1.microchip.com/downloads/en/devicedoc/70000195f.pdf |
|
![](templates/subSilver/images/spacer.gif) |
gaugeguy
Joined: 05 Apr 2011 Posts: 298
|
|
Posted: Wed Nov 13, 2019 7:01 am |
|
|
It actually says "sets or clears", not "cleared"
P: Stop bit
1 = Indicates that a Stop bit has been detected last
0 = Stop bit was not detected last
Hardware sets or clears when Start, Repeated Start or Stop is detected.
Now if there are two separate messages that are extremely close to one another it may be possible to miss the stop bit when polling if it is very closely followed by a start bit for another message. A dead time between messages would prevent this. |
|
![](templates/subSilver/images/spacer.gif) |
allenhuffman
Joined: 17 Jun 2019 Posts: 540 Location: Des Moines, Iowa, USA
|
|
Posted: Wed Nov 13, 2019 9:26 am |
|
|
Great timing! My CEO just pointed me to that document as well. It is exactly what I was looking for. _________________ 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 ? |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|