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, 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.
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.