• AVR Freaks

Hot!PIC18F47K42 I2C slave MCC bug?

Author
paulmtcuk
Starting Member
  • Total Posts : 43
  • Reward points : 0
  • Joined: 2007/08/23 05:16:51
  • Location: 0
  • Status: offline
2019/04/11 02:11:20 (permalink)
4 (1)

PIC18F47K42 I2C slave MCC bug?

Hello
 
I have had tremendous difficulty trying to get I2C slave working properly with PIC18F47K42 even just with the MCC generated code. This is about the problems I've been having with the MCC generated code, how I might be able to fix it without breaking it and to make sure it isn't just working in spite of itself.
 
I am using MPLAB 5.10, MCC 3.75, I2C Driver version 2.11, XC8 v 2.00
 
The main problem I am having is that after setting the register address to read, the first byte sent back form the slave is actually the next register address i.e.
 
[I2C address WRITE] [0x00] (I want to set eepromAddress to 0)
 
see TEK00109.jpg
https://pasteboard.co/I9Cp0QK.jpg
 
Ok, let's read from 0
 
see TEK00110.jpg
https://pasteboard.co/I9Cr2kh.jpg
 
What? I didn't get 0, it just started from 1 instead.
 
Let's continue reading
 
see TEK00111.jpg
https://pasteboard.co/I9CrdCT.jpg
 
What again? It has skipped the unsent 0x09 and moved to 0x0A
 
Let's try start reading from address 1 instead i.e.
 
[I2C address WRITE] [0x01] (I want to set eepromAddress to 1 and start reading from there)
 
see TEK00112.jpg
https://pasteboard.co/I9CrRhk.jpg
 
Ok well not surprising from what was going on above... it's skipped '0x01' and moved straight to '0x02' instead....
 
see TEK00113.jpg
https://pasteboard.co/I9Cs18B.jpg
 
So, what gives...??
 
BTW this is EEPROM_Buffer[]
 
 static uint8_t EEPROM_Buffer[] =
{
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,

 
So just so you know the address should match the data
 
(To get the code run MCC with PIC18F47K42 project and add I2C slave and generate.)
 
post edited by paulmtcuk - 2019/04/11 02:30:00

Attached Image(s)

#1

14 Replies Related Threads

    paulmtcuk
    Starting Member
    • Total Posts : 43
    • Reward points : 0
    • Joined: 2007/08/23 05:16:51
    • Location: 0
    • Status: offline
    Re: PIC18F47K42 I2C slave MCC bug? 2019/04/11 03:00:45 (permalink)
    +1 (1)
    Note that this is the code of the MMC generated I2C code and the steps it takes as I managed to debug with UART queue (hence queue_enqueue calls)
     
     

    void I2C1_ISR(void)
    {
    uint8_t I2C1_data = 0x55;
    if ((I2C1STAT1bits.RXBF) || (PIR2bits.I2C1RXIF))
    {
    PIR2bits.I2C1RXIF = 0;
    I2C1_data = I2C1RXB;
    queue_enqueue(&uart_queue, "1");
    }
    if (1 == I2C1STAT0bits.R)
    {
    if (I2C1PIRbits.PCIF)
    {
    I2C1PIRbits.PCIF = 0;
    PIR3bits.I2C1IF = 0;
    I2C1STAT1bits.CLRBF = 1; //clear I2C1TXB and TXBE
    I2C1CNT = 0xFF;
    queue_enqueue(&uart_queue, "2");
    }
    if (I2C1ERRbits.NACKIF)
    {
    I2C1ERRbits.NACKIF = 0;
    PIR3bits.I2C1EIF = 0;
    I2C1STAT1bits.CLRBF = 1; //clear I2C1TXB and TXBE
    I2C1_StatusCallback(I2C1_SLAVE_READ_COMPLETED);
    queue_enqueue(&uart_queue, "3");
    }
    else if (PIR3bits.I2C1TXIF)
    {
    PIR3bits.I2C1TXIF = 0;
    // callback routine should write data into I2C1TXB
    I2C1_StatusCallback(I2C1_SLAVE_READ_REQUEST);
    queue_enqueue(&uart_queue, "4");
    }
    if (I2C1PIRbits.ADRIF)
    {
    I2C1PIRbits.ADRIF = 0;
    PIR3bits.I2C1IF = 0;
    queue_enqueue(&uart_queue, "5");
    }
    }
    else if ((I2C1PIRbits.ADRIF))
    {
    I2C1PIRbits.ADRIF = 0;
    PIR3bits.I2C1IF = 0;
    // callback routine should prepare to receive data from the master
    I2C1_StatusCallback(I2C1_SLAVE_WRITE_REQUEST);
    queue_enqueue(&uart_queue, "6");
    }
    else
    {
    I2C1_slaveWriteData = I2C1_data;
    queue_enqueue(&uart_queue, "7");
    if (I2C1PIRbits.PCIF)
    {
    I2C1PIR = 0;
    PIR3bits.I2C1IF = 0;
    I2C1STAT1bits.CLRBF = 1;
    I2C1CNT = 0xFF;
    queue_enqueue(&uart_queue, "8");
    }
    // callback routine should process I2C1_slaveWriteData from the master
    I2C1_StatusCallback(I2C1_SLAVE_WRITE_COMPLETED);
    }
    I2C1CON0bits.CSTR = 0;
    }

     
    I noticed the UART is outputting:
     
    (WRITE) (0x00)
     
    6 (I2C1_SLAVE_WRITE_REQUEST)
    1 (I2C1_data = I2C1RXB)
    7 (I2C1_StatusCallback(I2C1_SLAVE_WRITE_COMPLETED))
    7 (I2C1_StatusCallback(I2C1_SLAVE_WRITE_COMPLETED))
    8 (WRITE STOP)
     
    thus it is reading a rouge data byte for some reason which would mean it would go into this code 
     

    case SLAVE_NORMAL_DATA:
    default:
    // the master has written data to store in the eeprom
    EEPROM_Buffer[eepromAddress++] = I2C1_slaveWriteData;

     
    incrementing eepromAddress twice when it should only be once.
     
    #2
    paulmtcuk
    Starting Member
    • Total Posts : 43
    • Reward points : 0
    • Joined: 2007/08/23 05:16:51
    • Location: 0
    • Status: offline
    Re: PIC18F47K42 I2C slave MCC bug? 2019/04/11 03:04:01 (permalink)
    +1 (1)
    sorry I meant--- thus it is reading a rouge data byte for some reason which would mean it would go into SLAVE_NORMAL_DATA in this code 
     

     
     
     
     
     
     
     
    switch (slaveWriteType)
    {
    case SLAVE_DATA_ADDRESS:
    eepromAddress = I2C1_slaveWriteData;
    break;
     
     
     

    case SLAVE_NORMAL_DATA:
    default:
    // the master has written data to store in the eeprom
    EEPROM_Buffer[eepromAddress++] = I2C1_slaveWriteData;
    if (sizeof (EEPROM_Buffer) <= eepromAddress)
    {
    eepromAddress = 0; // wrap to start of eeprom page
    }
    break;
     
     
     
    }
     
     
     

     
    incrementing eepromAddress when it should only go into SLAVE_DATA_ADDRESS
     
    The continuous read also has an issue incrementing the pointer by accident as I2C1_StatusCallback(I2C1_SLAVE_READ_REQUEST) is being called nine times instead of eight, why???
     
    ---- I cannot edit posts or post images in posts which is incredibly frustrating!!!!
    post edited by paulmtcuk - 2019/04/11 04:20:08
    #3
    paulmtcuk
    Starting Member
    • Total Posts : 43
    • Reward points : 0
    • Joined: 2007/08/23 05:16:51
    • Location: 0
    • Status: offline
    Re: PIC18F47K42 I2C slave MCC bug? 2019/04/11 05:16:25 (permalink)
    +1 (1)
    You can get around the receive bug by adding
     

    void I2C1_ISR(void)
    {
    uint8_t I2C1_data = 0x55;
    unsigned char byte_received = 0; // new line
    :
    else if ( byte_received ) // edited
    {
    I2C1_slaveWriteData = I2C1_data;

    // callback routine should process I2C1_slaveWriteData from the master
    I2C1_StatusCallback(I2C1_SLAVE_WRITE_COMPLETED);
    }
    else if (I2C1PIRbits.PCIF) // moved this out of the else if
    {
    I2C1PIR = 0;
    PIR3bits.I2C1IF = 0;
    I2C1STAT1bits.CLRBF = 1;
    PIR3bits.I2C1TXIF = 0;
    I2C1CNT = 0xFF;

    }


    [/code]but transmit still has an issue -- I've dumped MCC code entirely and using https://mplabxpress.microchip.com/mplabcloud/example/details/519 with no problem now.
    #4
    Mysil
    Super Member
    • Total Posts : 3354
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: offline
    Re: PIC18F47K42 I2C slave MCC bug? 2019/04/11 07:41:11 (permalink)
    0
    Hi Paul,
    I have experimented with I2C on several different PIC devices for some time,
    and PIC18F46K42 during the last couple of weeks.
    Bugs in MCC code, and especially in code for I2C is no surprise.
     
    The new I2C module in use in PI18__K42 have a lot of flags and options,
    and may generate several interrupts for each byte transferred,
    so may easily enough increment the array index, when it should not.
     
    I will try your problem, and the remedy suggested in message #4, when I get the opportunity.
    And also the code published by Chris Best. 
     
    But I usually end up making so many modifications,
    that corrections cannot easly be integrated back into MCC.
     
    This thread should really have been published in the MCC forum, where it could have been noticed by MCC developers.
     
    Also, if you publish a clearly stated problem, and a complete problem program with a precisely  documented correction, then there may be more possibility of the correction finding its way into a MCC release.
     
        Mysil
    post edited by Mysil - 2019/04/11 13:32:18
    #5
    paulmtcuk
    Starting Member
    • Total Posts : 43
    • Reward points : 0
    • Joined: 2007/08/23 05:16:51
    • Location: 0
    • Status: offline
    Re: PIC18F47K42 I2C slave MCC bug? 2019/04/11 12:40:42 (permalink)
    +1 (1)
    Thanks Mysil, I will post the details on the MCC forum perhaps in more detail, that said I'm suffering issues posting to the forum being unable to edit posts or upload images so I also made a post on stack exchange to allow that. Thanks again.
    #6
    Mysil
    Super Member
    • Total Posts : 3354
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: offline
    Re: PIC18F47K42 I2C slave MCC bug? 2019/04/11 13:46:30 (permalink)
    0
    Hi,
    The forum and servers running Microchip websites, have been pestered by spam,
    so there are various restrictions, especially for new members.
     
    When there are URL links in a message, it will be refused when the message is uploaded after editing.
    In the header of the Editor Window, there are several icons, including a 'broken link'.
    Select each URL link in sequence, and click the 'Unlink' button,
    before submitting an edited message.
     
        Mysil
     
    #7
    Mysil
    Super Member
    • Total Posts : 3354
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: offline
    Re: PIC18F47K42 I2C slave MCC bug? 2019/04/15 09:35:09 (permalink)
    0
    Hi,
    I have looked into the code published by Chris Best in the mplabxpress webpage indicated in message #5,
    and also the code as generated by MCC, using the same MCC library version.
    While the code published in: https://mplabxpress.microchip.com/mplabcloud/example/details/519
    have the directory structure of a MCC generated project, and all files have headers with MCC version identification.
    There is No Revision remark or clear comment that code is heavily modified from what was generated by MCC,
    but there are lots of changes, both in code, and additional comments.
     
    While code generated by MCC is made like 'library' code with a number of optional functions available,
    the 'mplabxpress' code have removed all functions that are not actually used in the specific example.
     
    For other devices, I2C code similar to MCC have example code doing only single byte updates of the emulated eeprom array. While this will work also for a real EEPROM device, it is a stupid thing to do if an array is to be stored in a real hardware EEPROM.
    It may seem that MCC code have never been tested with anything more than single byte updates.
     
    I2C master write operations to a EEPROM device, real or emulated, require the memory location to be transferred as first byte(s), before data bytes.
    In 'mplabxpress' code, this is solved by introducing another function, not provided by MCC:
        i2c1_writeNBytesRegister(SLAVE_ADDRESS, SLAVE_EE_ADD, &transArray[0], TRANS_CNT);    

    Note, that the TRANS_CNT argument, is the total size of the I2C transfer, (without the I2C address byte), and Not the number of bytes in 'transArray' argument.
    This seem illogical to me.
    If code were to be used with a real hardware I2C EEPROM device, the challenge will appear again,
    needing yet another function to transfer 2 memory index bytes before the data array.
     
    The I2C Slave code by MCC make wrong use of the: I2C1_StatusCallback(I2C1_SLAVE_WRITE_COMPLETED)
    Chris Best solve this problem by discarding the Callback concept entirely,
    but this is not a good solution either, it make a mixup of what could be general driver code, and application interface code in the callback functon.
    Here is my notes about state codes in the callback interface:
    /* @Remark   Inserted, Mysil
     *  Enumeration of I2C Slave Transfer Status is incomplete as generated by MCC
     *  There are 3 different States needed when Slave receive Write transfer from Master
     *
     *  Address Match is detected by slave hardware,
     *         it is start of new transfer, and do not have a Data byte.
     *         It have however received the Matching Address from Master,
     *         and this should be provided to the Callback routine,
     *         for the case when different addresses may be serviced by the same slave,
     *         by use of address masking or Slave with multiple address match registers.
     *
     *  Write Data Transfer, a.k.a. Slave Receiver,
     *         is Data byte received by Slave.
     *         Received data may be transferred to Callback function one byte at a time,
     *         but to prepare for DMA transfer using PIC18F__K42 I2C peripheral,
     *         a Buffer pointer, and maximum buffer size could be provided by the Callback function
     *         when transfer is initiated, or when driver is initialized.
     *
     *  Write Completed, a.k.a. Slave Receive Completed,
     *         is caused by a Stop condition signal.
     *         There is No Data update with this state, so transfer count or array index should not change.
     *         Callback function may use this state to act on the completed transfer.
     *
     *  Read Request, a.k.a Slave Transmit Request,
     *         is caused by Address Match detected with R bit set.
     *         It have the Matching Address available, and this should be provided to the Callback function.
     *         It is also a request to return the first Data byte.
     *
     *  Read Completed, a.k.a. Slave Transmit Complete,
     *         is caused by a NACK bit from Master  detected by the Slave.
     *         There is no more data wanted by master.
     *         Callback function may use this for transfer completed processing.
     *
     *  Callback interface, as implemented by MCC generated code is awkward.
     *  transferring data to the Callback function by Global Variable,
     *  not as a function argument, is a software design mistake.
     *  Also, Callback function manipulating hardware peripheral registers, is a bad solution,
     *  it make the callback into a hardware dependent part of the driver,
     *  not a interface to application code.
     *      Mysil, 2019-04-14.
     */  

    While correction suggested in message #4 may work,
    I think it may be the wrong cure to the problem.
     
    I may come back with some suggested code, but have noticed also some other strange effects,
    and want to test more.
     
    Regards,
        Mysil
     
    Btw. do not Edit previous messages, such that problem or mistakes disappear.
    It is usually better to make a new message in the same thread,
    such that the sequence of problem solving can be understood by readers.
        Mysil
    #8
    Mysil
    Super Member
    • Total Posts : 3354
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: offline
    Re: PIC18F47K42 I2C slave MCC bug? 2019/04/16 12:22:05 (permalink)
    0
    Hi,
    Have done some experiments based on the mplabxpress example 519,
    reproducing the example using current versions of MPLAB:
    MPLAB X v5.15, XC8 v2.05 in C99 mode,and current version of MCC.
     
    On PIC18F46K42, I2C1 and I2C2 are connected, RC3 to RB1, and RC4 to RB2.
    Code is generated by MCC, but then there are several corrections, especially the callback interface in Slave code.
    Changes are pointed out with my alias, and comments of the form: /* comment */ in column 41 and onwards are mine.
     
    Slave code is now using Vectored interrupts, as available on PIC18F__K42 family devices.
     
    post edited by Mysil - 2019/04/18 21:30:50
    #9
    paulmtcuk
    Starting Member
    • Total Posts : 43
    • Reward points : 0
    • Joined: 2007/08/23 05:16:51
    • Location: 0
    • Status: offline
    Re: PIC18F47K42 I2C slave MCC bug? 2019/04/30 08:48:04 (permalink)
    0
    Thanks Mysil for the code.
     
    Unfortunately I'm getting errors when reading (slave mode)
     
    9 times out of 10 I get the following error
     
    (when trying to read address 0x10 by doing a single write to address 0x28 and then 0x10 register with 8 byte reads)
    The code is sending the first byte correctly but after that it fails
     

     
     
     
     Time           Address   Data                                  Missing Ack
     
     
     
      -2.36E-05   Read 28   10 FE FE FE FE FE FE FF        X
     
     
     
     
     
    Continued read (without setting register with a write)
     

     
     
     
     Time           Address   Data                                  Missing Ack
     
     
     
      -2.36E-05   Read 28   12 FE FE FE FE FE FE FF        X
     
     
     
     

    Continued read (without setting register with a write) and so on

     
     
     
     Time           Address   Data                                  Missing Ack
     
     
     
      -2.36E-05   Read 28   14 FE FE FE FE FE FE FF        X
     
     
     
     X
     
     
     
     

     
     
    I changed the code to use I2C1 instead of I2C2 and I changed the address to 0x28 by doing the following
     

     
     
     
    #define I2C1_SLAVE_DEFAULT_ADDRESS          0x50    // This is the shifted address (actually 0x28)
     
     
     
     
     
    void I2C1_Initialize(void)
    {
     
     
     
    I2C1ADR0 = I2C1_SLAVE_DEFAULT_ADDRESS;
    I2C1ADR1 = 0;
    I2C1ADR2 = 0;
    I2C1ADR3 = 0;
     
     
     

     
    I had this problem with Chris Best's code too which I've been trying to work on today. Thought your code might have solved that but seems like it still suffers.
     
    when debugging I put a breakpoint at I2C1 at the point of transmit and it does go into the first and second byte TX OK, but after that it doesn't go into any more breakpoints.
     
    Any idea what might be going wrong?
    post edited by paulmtcuk - 2019/04/30 08:52:48
    #10
    Mysil
    Super Member
    • Total Posts : 3354
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: offline
    Re: PIC18F47K42 I2C slave MCC bug? 2019/04/30 10:10:53 (permalink)
    0
    Hi,
    Could you Package up the actual code you are now trying to test?
     
    The 'Package' facility is in the 'Projects' view, upper left quarter of MPLAB X window, 
    Point to root of project tree, the PDIP icon, and click righthand button, for the pop-up menu.
     
    Are you now using a real hardware EEPROM device? If that is the case, what type is it?
     
        Mysil
    #11
    paulmtcuk
    Starting Member
    • Total Posts : 43
    • Reward points : 0
    • Joined: 2007/08/23 05:16:51
    • Location: 0
    • Status: offline
    Re: PIC18F47K42 I2C slave MCC bug? 2019/05/01 01:26:41 (permalink)
    0
    Hi Mysil. Thanks for helping me  with this.
     
    I have packaged the source into a smaller project and I am actually getting different problems now depending on HF Internal Clock/Clock Divider settings.
     
    Setting HF Internal Clock to 4/8 MHz and Clock Divider to 4 (1/2 MHz)
    The SDA line is held low after first byte write which means the master cannot send a stop condition and PIC seems to think it is still in SMA mode. After another write it lets go of SDA. I have seen this happen some times and then it seems to work after a few reads/writes without changing code -- which means I can't rely on it.
     
    Setting HF Internal Clock to 32MHz and Clock Divider to 4 (8MHz)
    I can reproduce the read error problem described in my previous post (which is still strange as TXBE is 1 on transmit each time anyway)
     
    Setting HF Internal Clock to 32MHz and Clock Divider to 1 (32MHz)
    The code works fine.
     
    The I2C clock only seems to be about 20KHz -- didn't think this would cause such a problem with Fosc at 8MHz and clock stretching enabled? (Just saw your project had been set to 16MHz Clock Div 1)
     
    Also perhaps unrelated -- I also noticed that the code cleared the IE bits of I2CERR in Initialize() which I updated to:

     
     
     
     
     
     
     
        I2C1ERR &= 0x0F; // Ooops-- cleared the IE flag before
     
     
     
     
     
     
     

    (But doesn't appear to help the issue. in lower clocks)
     
    I am not using vectored interrupts (see interrupt_manager.c) I am using PIC18F47K42 on Curiosity HPC added 4.7K pullups on to SDA and SCL. Using MPLAB 5.15 and XC8 2.00. I am using the PIC as a slave on I2C1 just as the default "eeprom" (well actually RAM) example program as a test between a USB ISS module to laptop to confirm that I2C is working or not. Master is on I2C2. I am wanting to find out if we can use this family of PIC for projects that require I2C master and slave configuration.
      
    Thanks
     
    post edited by paulmtcuk - 2019/05/01 04:23:40
    #12
    paulmtcuk
    Starting Member
    • Total Posts : 43
    • Reward points : 0
    • Joined: 2007/08/23 05:16:51
    • Location: 0
    • Status: offline
    Re: PIC18F47K42 I2C slave MCC bug? 2019/05/02 09:44:33 (permalink)
    +1 (1)
    I have solved the issue, it appears my master did not support clock stretching. After supporting clock stretching, I2C clock at 100KHz at 8MHz HFINTOSC worked fine.
    #13
    meanilkp
    New Member
    • Total Posts : 4
    • Reward points : 0
    • Joined: 2018/08/19 22:12:10
    • Location: 0
    • Status: offline
    Re: PIC18F47K42 I2C slave MCC bug? 2019/06/18 00:58:11 (permalink)
    0
     
    You must select I2C specific input thresholds to work with lower frequency.
    /**
        RxyI2C registers
    /*      Slew rate limited,  Pull-up 2X, I2C specific input thresholds */
    RB1I2C = 0x51;
    RB2I2C = 0x51;
    RC3I2C = 0x51;
    RC4I2C = 0x51;
    RD0I2C = 0x51;
    RD1I2C = 0x51;
    #14
    meanilkp
    New Member
    • Total Posts : 4
    • Reward points : 0
    • Joined: 2018/08/19 22:12:10
    • Location: 0
    • Status: offline
    Re: PIC18F47K42 I2C slave MCC bug? 2019/06/18 00:58:11 (permalink)
    0
     
    You must select I2C specific input thresholds to work with lower frequency.
    /**
        RxyI2C registers
    /*      Slew rate limited,  Pull-up 2X, I2C specific input thresholds */
    RB1I2C = 0x51;
    RB2I2C = 0x51;
    RC3I2C = 0x51;
    RC4I2C = 0x51;
    RD0I2C = 0x51;
    RD1I2C = 0x51;
    #15
    Jump to:
    © 2019 APG vNext Commercial Version 4.5