• AVR Freaks

Helpful ReplyHot!I am totally discombobulated by MCC i2c code and examples.

Page: 12 > Showing page 1 of 2
Author
rwvb
Starting Member
  • Total Posts : 31
  • Reward points : 0
  • Joined: 2012/09/13 14:54:29
  • Location: NZ
  • Status: offline
2015/08/02 20:42:11 (permalink)
0

I am totally discombobulated by MCC i2c code and examples.

I love MCC's generated code in other modules like timers, usart and even eccp but then came i2c...
 
If the objective of code configurator is to make it easier to use 8-bit mcu's broad range of peripherals then in my experience thus far I would have to say you have succeeded. But (it seems there must always be a but) then I plummeted into i2c...
 
I have never used any of the eeproms so I'm unfamiliar with their i2c procedure. I am used to the plib i2c format like "signed char WriteI2C( unsigned char data_out )" etc, or even something like "void writeRegister(uint8_t reg, uint8_t value)" but to transition from here to "I2C Driver Transaction Request Blocks" is quite some leap. Then again, I know my c programming skills are lacking but trying to decode the examples presented has me throwing my toys all over the show!
 
Could someone kindly guide me from this code example back to the simplicity of passing an address byte and data byte to a function that inserts them into the SSPBUF after the appropriate ACK and error sequences have been checked?
 
I can see the value of microchip promoting their own products like eeproms by inserting code examples into MCC but I have to question the logic when it puts such a barrier in the way of those who want to use the module for it's intended purpose i.e. inter-integrated chip communication.
 
That's it. My rant ends and I'm back to the task at hand - getting i2c communication working between pic master and the slave IC.
enjoy,
Rich.
 
<code>
// excerpt from MCC's i2c.h //
/** Section: Interface Routines*//** @Summary Initializes the MSSP instance :
  @Description This routine initializes the i2c driver instance for : index, making it ready for clients to open and use it. This routine must be called before any other I2C routine is called. This routine should only be called once during system initialization.
  @Preconditions None.
  @Param None.
  @Returns None.
  @Example <code> #define SLAVE_I2C_GENERIC_RETRY_MAX 100 // initialize the module I2C_Initialize();
        // write to an EEPROM Device uint16_t dataAddress; uint8_t sourceData[16] = { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF }; uint8_t *pData; uint16_t nCount;
        uint8_t writeBuffer[3]; uint8_t *pD; uint16_t counter, timeOut;
        I2C_MESSAGE_STATUS status = I2C_MESSAGE_PENDING;
        dataAddress = 0x10; // starting EEPROM address pD = sourceData; // initialize the source of the data nCount = 16; // number of bytes to write
        for (counter = 0; counter < nCount; counter++) {
            // build the write buffer first // starting address of the EEPROM memory writeBuffer[0] = (dataAddress >> 8); // high address writeBuffer[1] = (uint8_t)(dataAddress); // low low address
            // data to be written writeBuffer[2] = *pD++;
            // Now it is possible that the slave device will be slow. // As a work around on these slaves, the application can // retry sending the transaction timeOut = 0; while(status != I2C_MESSAGE_FAIL) { // write one byte to EEPROM (3 is the number of bytes to write) I2C_MasterWrite( writeBuffer, 3, slaveDeviceAddress, &status);
                // wait for the message to be sent or status has changed. while(status == I2C_MESSAGE_PENDING);
                if (status == I2C_MESSAGE_COMPLETE) break;
                // if status is I2C_MESSAGE_ADDRESS_NO_ACK, // or I2C_DATA_NO_ACK, // The device may be busy and needs more time for the last // write so we can retry writing the data, this is why we // use a while loop here
                // check for max retry and skip this byte if (timeOut == SLAVE_I2C_GENERIC_RETRY_MAX) break; else timeOut++; }
            if (status == I2C_MESSAGE_FAIL) { break; } dataAddress++;
        }
    </code>

 
 
#1
cobusve
Super Member
  • Total Posts : 495
  • Reward points : 0
  • Joined: 2012/04/02 16:15:40
  • Location: Chandler
  • Status: offline
Re: I am totally discombobulated by MCC i2c code and examples. 2015/08/02 20:53:35 (permalink)
3.5 (2)
I agree that driver is pretty hard to use. We have been working on an improved version and have started testing it. If you would like to take a look at it send me a PM and I can send you a copy.
#2
Nikolay_Po
Super Member
  • Total Posts : 1939
  • Reward points : 0
  • Joined: 2012/04/01 13:49:27
  • Location: Russia, Novorossiysk
  • Status: offline
Re: I am totally discombobulated by MCC i2c code and examples. 2015/08/03 00:04:26 (permalink)
4.5 (2)
Hi, cobusve!
May be it worth to open an official "testing" or "beta" subsection on Microchip site where you'll be able to publish the versions under the testing? This way most proactive users will be able to test pre-released versions of MCC or another tools and give a feedback to developers before new version releasing.
#3
cobusve
Super Member
  • Total Posts : 495
  • Reward points : 0
  • Joined: 2012/04/02 16:15:40
  • Location: Chandler
  • Status: offline
Re: I am totally discombobulated by MCC i2c code and examples. 2015/08/03 00:08:50 (permalink)
0
Sounds like good advice :) Let me see what we can do.
#4
rwvb
Starting Member
  • Total Posts : 31
  • Reward points : 0
  • Joined: 2012/09/13 14:54:29
  • Location: NZ
  • Status: offline
Re: I am totally discombobulated by MCC i2c code and examples. 2015/08/03 13:41:57 (permalink)
0
Nothing is more gratifying than seeing the proactive response to my rant!
 
A huge thumbs up to the MCC team!
#5
n9wxu
Moderator
  • Total Posts : 63
  • Reward points : 0
  • Joined: 2008/11/06 17:00:50
  • Location: 0
  • Status: offline
Re: I am totally discombobulated by MCC i2c code and examples. 2015/08/03 18:48:04 (permalink) ☄ Helpfulby rwvb 2015/08/03 20:27:57
5 (1)
Consider this post a beta drop for the I2C master driver for MCC 3.0.
That driver is our least favorite driver followed closely by the I2C Slave.  I will be attacking the slave driver after Masters.
 
In the zip file please find 3 drivers for the PIC18F25K50 (it will run on ANYTHING with an MSSP)
i2c1_bb.<c,h> - Bit banged blocking driver for ANY PICmcu.  Depends upon the __delay_us(time) function.
i2c_mssp_blocking.c - implements the SAME api as i2c_bb.<c.h> only directly on an MSSP with wait loops.  I have not made a header file... consider that an exercise for the reader (or copy the i2c1_bb.h file and call it a day)
i2c_async.<c,h> - implements a fully async (interrupt driven) driver for the MSSP.  Makes heavy use of dependency injection (function pointers) on I2C events to allow user customization without changing the driver code.
i2c_blocking_async.<c,h> - not really a driver, simply an async implementation of the blocking drivers.  also serves as an example of the blocking code.
 
Also attached is 24lc014_async.c  - This is included as an example of using the function pointers to do NACK polling and short read continue operations.
 
You can expect the error codes in i2c_types.h and the API names to stabilize before it shows up in MCC 3.0 but I hope to clear the air on the existing driver by providing a beta release and soliciting feedback.
 
Lastly, remember the wisdom of Dr Donald Knuth: 
Beware of bugs in the above code; I have only proved it correct, not tried it. - Donald Knuth
 
Things are crazy here before Masters and I am still working on this code.  It should work but my test board just walked away.  Good Luck
#6
ric
Super Member
  • Total Posts : 26159
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: I am totally discombobulated by MCC i2c code and examples. 2015/08/03 19:53:40 (permalink)
4.5 (2)
n9wxu
...
It should work but my test board just walked away.

By itself?
Now that's a piggy-back board I want to hear about! ;)
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#7
rwvb
Starting Member
  • Total Posts : 31
  • Reward points : 0
  • Joined: 2012/09/13 14:54:29
  • Location: NZ
  • Status: offline
Re: I am totally discombobulated by MCC i2c code and examples. 2015/08/03 20:24:17 (permalink)
0
I think that board may have carried off the file "i2c_types.h" too!
#8
NKurzman
A Guy on the Net
  • Total Posts : 18424
  • Reward points : 0
  • Joined: 2008/01/16 19:33:48
  • Location: 0
  • Status: offline
Re: I am totally discombobulated by MCC i2c code and examples. 2015/08/04 07:04:59 (permalink)
0
The I2C slave should be interesting.
Since many I have seen are wreaks.
#9
cobusve
Super Member
  • Total Posts : 495
  • Reward points : 0
  • Joined: 2012/04/02 16:15:40
  • Location: Chandler
  • Status: offline
Re: I am totally discombobulated by MCC i2c code and examples. 2015/08/07 17:45:35 (permalink)
0
The slave will be awesome :) Watch this space !
#10
n9wxu
Moderator
  • Total Posts : 63
  • Reward points : 0
  • Joined: 2008/11/06 17:00:50
  • Location: 0
  • Status: offline
Re: I am totally discombobulated by MCC i2c code and examples. 2015/08/17 22:24:15 (permalink)
3 (1)
It is good to see so much interest in the new I2C master driver and I wanted to post an update.
 
Here is the update.  There are a great many changes but the key ones are as follows:
1) Driver operates in polled or interrupt mode.  Simply comment out the interrupt enable to trigger polled mode.
2) This driver has a single API for both modes.  The only thing that changes between modes is the time taken to execute the functions.
3) The i2c_simple.<c,h> provides a basic SMBus looking driver.  It sits on top of the i2c.<c,h> files.  It is a good example of using a data empty callback.
4) ALL the HW specific functions are in a separate file.  This allows a bit-banged, or new HW version to be implemented independently from the core driver.
This driver has been tested on the PIC18F25K50 and PIC16F1788 with only minor changes in the MSSP driver due to header file differences.
 
Masters is going on this week, so don't expect a slave driver anytime soon.
#11
rwvb
Starting Member
  • Total Posts : 31
  • Reward points : 0
  • Joined: 2012/09/13 14:54:29
  • Location: NZ
  • Status: offline
Re: I am totally discombobulated by MCC i2c code and examples. 2015/08/18 16:41:05 (permalink)
3 (1)
I like it! That was very swift considering Masters is on top of you  all.
 
I'm pleased to see the way you tidied up the callBack functions. This statement 
    <code>switch(i2c1_status.callbackTable[idx](i2c1_status.callbackPayload[idx]))</code>
from the function 
    <code>inline static uint8_t issueCallback(uint8_t idx, uint8_t thisState) {...}</code>
had me scratching my head so I'm pleased to see it gone!
 
Awesome work!!!
#12
n9wxu
Moderator
  • Total Posts : 63
  • Reward points : 0
  • Joined: 2008/11/06 17:00:50
  • Location: 0
  • Status: offline
Re: I am totally discombobulated by MCC i2c code and examples. 2015/08/18 22:15:26 (permalink)
0
Thank you to all the folks who have looked at the updated driver.
Please provide some feedback if you got the driver running and any issues that have been seen.
We are rapidly approaching a release on MCC 3.0 and it is not time to speak your mind.
#13
NKurzman
A Guy on the Net
  • Total Posts : 18424
  • Reward points : 0
  • Joined: 2008/01/16 19:33:48
  • Location: 0
  • Status: offline
Re: I am totally discombobulated by MCC i2c code and examples. 2015/08/19 07:35:11 (permalink)
3 (1)
Note that some of the Init code acts on the Port level instead of the Pins.
Aren't Callbacks a little heavy for PIC18 and especially PIC16.
#14
rwvb
Starting Member
  • Total Posts : 31
  • Reward points : 0
  • Joined: 2012/09/13 14:54:29
  • Location: NZ
  • Status: offline
Re: I am totally discombobulated by MCC i2c code and examples. 2015/08/19 18:31:21 (permalink)
0
So, after a  more thorough read of i2c.c I found my head scratching code IS still there!
 
Would someone like to explain to me how the compiler resolves op?
op = i2c1_status.callbackTable[i2c_dataComplete](i2c1_status.callbackPayload[i2c_dataComplete]);

 
enum i2c_dataComplete = 0
therefore
i2c1_status.callbackTable[0] (i2c1_status.callbackPayload[0])
 
It looks like a function call however that would be using an array name as a function name and  I'm pretty sure that is wrong! So what are the parenthesis  doing there?
 

case I2C_ADDRESS_NACK:
i2c1_status.addressNACKCheck = 0;
op = i2c1_status.callbackTable[i2c_addressNACK](i2c1_status.callbackPayload[i2c_addressNACK]);
i2c1_status.error = I2C_FAIL;
break;


// I2C Status Structure
typedef struct
{
unsigned busy:1;
unsigned inUse:1;
unsigned reading:1;
unsigned bufferFree:1;
unsigned addressNACKCheck:1;
i2c_address_t address; /// The I2C Address
uint8_t *data_ptr; /// pointer to a data buffer
size_t data_length; /// Bytes in the data buffer
uint8_t time_out; /// I2C Timeout Counter between I2C Events.
uint8_t time_out_value; /// Reload value for the timeouts
uint8_t state; /// Driver State
i2c_error_t error;
i2c_callback callbackTable[5];
void *callbackPayload[5]; // each callback can have a payload
} i2c_status_t;

#15
ric
Super Member
  • Total Posts : 26159
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: I am totally discombobulated by MCC i2c code and examples. 2015/08/19 18:39:24 (permalink)
3 (1)
rwvb
...
 
It looks like a function call however that would be using an array name as a function name and  I'm pretty sure that is wrong! So what are the parenthesis  doing there?
 

It IS a function call. It's perfectly legal in C to have an array of pointers to functions.
 
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#16
NKurzman
A Guy on the Net
  • Total Posts : 18424
  • Reward points : 0
  • Joined: 2008/01/16 19:33:48
  • Location: 0
  • Status: offline
Re: I am totally discombobulated by MCC i2c code and examples. 2015/08/19 18:59:34 (permalink)
4 (1)
Is an array of function pointers going to generate Poor Code in a PIC16 or 18?
I know they used to.  I am not sure about now.
In this case are not actually needed.  The Function can be named directly, or via a Macro.  In bigger chip why not.  They have indirection H/W and a real stack.
#17
rwvb
Starting Member
  • Total Posts : 31
  • Reward points : 0
  • Joined: 2012/09/13 14:54:29
  • Location: NZ
  • Status: offline
Re: I am totally discombobulated by MCC i2c code and examples. 2015/08/19 20:46:27 (permalink)
0
Okay, so let's see  if I can break it down...
op = i2c1_status.callbackTable[i2c_addressNACK](i2c1_status.callbackPayload[i2c_addressNACK]);

 
i2c1_status.callbackTable[i2c_addressNACK] is the name of the function. It is also a pointer
i2c1_status.callbackPayload[i2c_addressNACK] is the function parameter.
 
It is declared here
// I2C Status Structure
typedef struct
{
...
i2c_callback callbackTable[5];
void *callbackPayload[5]; // each callback can have a payload
} i2c_status_t;

 
and initialized here
bool i2c1_open(i2c_address_t address)
{
...
// set all the call backs to a default of sending stop
for(size_t x=0; x < sizeof(i2c1_status.callbackTable)/sizeof(*i2c1_status.callbackTable);x++)
{
i2c1_status.callbackTable[x]=returnStop;
i2c1_status.callbackPayload[x] = 0;
}

 
So when the function i2c1_status.callbackTable[] is called, the pointer is pointing at the [0] element of the array named callbackTable.
 
Is that element passed the pointer i2c1_status.callbackPayload[i2c_addressNACK]?
 
Is it basically saying point to element [0] of the callbackTable and change the value pointed to by the callbackPayload pointer to zero?
i2c_addressNACK = zero.
 
Or am I way off??
 
#18
NKurzman
A Guy on the Net
  • Total Posts : 18424
  • Reward points : 0
  • Joined: 2008/01/16 19:33:48
  • Location: 0
  • Status: offline
Re: I am totally discombobulated by MCC i2c code and examples. 2015/08/20 09:17:06 (permalink)
0
i2c1_status.callbackTable[i2c_dataComplete]  contains a pointer to a function
 
2c1_status.callbackTable[i2c_dataComplete] = &myfunction;  saves the address of myfunction in the pointer.
 
op = i2c1_status.callbackTable[i2c_dataComplete](i2c1_status.callbackPayload[i2c_dataComplete]);
is equivalent to
op = myfunction (i2c1_status.callbackPayload[i2c_dataComplete])
 
since status.callbackTable[i2c_dataComplete] contains a pointer to myfunction 
#19
rwvb
Starting Member
  • Total Posts : 31
  • Reward points : 0
  • Joined: 2012/09/13 14:54:29
  • Location: NZ
  • Status: offline
Re: I am totally discombobulated by MCC i2c code and examples. 2015/08/20 15:20:33 (permalink)
0
Thanks for clearing that up for me Nick, that's really helpful!
 
Now so far as the i2c driver is concerned my thoughts are as follows;
It works. I've tried it on 16F1938 and have had no issues. I haven't had to add extra delays to my code and that's a good thing. For writing and reading sequential registers the user code is succinct. (please ignore the lack of error checking)

// write 11 data bytes to sequential register starting at REGISTER_ADDRESS
uint8_t dataToWrite = {REGISTER_ADDRESS, 0x01,0x01,0x0E,0x00,0x01,0x05,0x01,0x00,0x00,0x00,0x00}; // 1 address byte plus 11 data bytes
writeDataPtr = &dataToWrite;    // set the write pointer
dataSize = 12;                         // set the number of bytes to write (includes 1 address byte)
// write dtatToWrite to i2c
opened = i2c1_open(7BIT_DEVICE_ADDRESS); // Open device specific i2c;
i2c1_setBuffer(writeDataPtr, dataSize);             // set buffer 
error = i2c1_masterWrite();                             // write data
closed = i2c1_close(MPR121_7BIT_ADDRESS);  // Close device specfic i2c

 
Probably with a little more thought it could be pared back even more.
However when it comes to writing to single non sequential configuration registers the code becomes somewhat clunky. After writing to twenty or thirty individual registers I'm back in my cot, I've thrown my toys and I'm screaming for attention because I've ripped of my nappy, thrown it  at the wall and want "them" to see it sliding down BEFORE it hits the floor!
MCC is a great opportunity to give users a leg up into embedded programming. Anyone who uses MCC is going to comb through the code that it produces and use it as  an example of how the "embedded experts" write their code. The code will be scrutinized to the n'th degree so you really need to take a step back and make sure you can truly justify your methods. When you do the final release add some documentation explaining why you have chosen to use the call back functions, hardware abstraction layers etc. Is it really the most efficient way to drive the MSSP module?
 
I want to see a simple function to write/read one byte to/from a configuration register. I don't want to have to write it! I would like to see functions that a year 12 school student can look at and say "yes, I can see how that works!" and "with this MCC tool I can do so much more than you can with your arduino!" I would also like to see comprehensive code commenting so that I can "learn" from the code.
 
Okay, that's my thoughts. I hope that someone can shoot me down in flames and point out that you've created a mean, lean i2c machine. Take heart, you have vastly improved the code when compared with the previous release!
 
I hope this is helpful. It's not very specific but then I'm no expert...
good luck,
Rich.
 
 
#20
Page: 12 > Showing page 1 of 2
Jump to:
© 2020 APG vNext Commercial Version 4.5