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 CCS Technical Support

Problem with Silicon Errata on PIC24FJ128GA705
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
PICmodule



Joined: 26 Oct 2021
Posts: 32

View user's profile Send private message

Problem with Silicon Errata on PIC24FJ128GA705
PostPosted: Tue Jun 20, 2023 6:49 am     Reply with quote

Hi,
I made a PCB based on the PIC24FJ128GA705 using I2C that is working with Raspberry Pi. We manufactured some hundreds of them and working perfectly. New production we done, used the same PIC24FJ128GA705 however seems different MARKING CODE. We realized that the I2C is not working. After a deep search, we decided that the problem is in the Silicon Errata on PIC24FJ128GA705.

https://ww1.microchip.com/downloads/aemDocuments/documents/MCU16/ProductDocuments/Errata/PIC24FJ256GA705-Family-Silicon-Errata-and-Data-Sheet-Clarification-DS80000718H.pdf

In order to avoid any misunderstanding, we de-soldered the microcontroller PIC24FJ128GA705 from the former (working well) boards and solder it to the new one and after that (with old microcontroller) works perfectly. Therefore this confirmed me that the reason is NOT PCB (it is exactly the same), but different LOT of micro controllers.

I'm trying to implement the Silicon Errata, but unsuccessfully because I do not have source of the i2c_isr_state and i2c_read

My Compiler Version is 5.115

I asked CCS info to provide it, but no luck.
Therefore I have 4 solutions:
1. Write from the scratch the new I2C Slave handler (difficult and take time for me).
2. Replace the i2c_isr_state and i2c_read by my (yours) own similar routines (this is what I m asking for).
3. Take the Microchip driver and convert to CCS (but their driver provided is very bad).
4. Use any ready and offered by you slave driver.

Any help would be very appreciated.
Below is simplified my I2C slave routine I'm using.


Code:

///////////////////////////////////////////////////////////////////////////////
///   DEFAULT:      0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F
///   NO_RTC:            0x69,       0x6B
///   ALTERNATE1: 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F
///   ALTERNATE2: 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F
///////////////////////////////////////////////////////////////////////////////

#INT_SI2C  LEVEL=7
void normal_SI2C_isr(void)
{
unsigned int8 dummy;
static unsigned int8 incoming, state;
static unsigned int8 MatchAddress; 
static unsigned int8 i2c_adr;

   run_status.i2c_running++;
   
   state=i2c_isr_state(RPI_I2C);
 
   if(state <= 0x80)                               //Master is sending data
   {
      if(state == 0x80)
      {
         incoming = i2c_read(RPI_I2C);             //Passing 2 as parameter, causes the function to read the SSPBUF without releasing the clock
      }
      else
      {
         incoming = i2c_read(RPI_I2C,2);
      }     
         
      if(state == 1)                               //First received byte is address
         i2c_adr = incoming;
     
                 
      if((state == 0) || (state == 0x80))
         MatchAddress = incoming;       
            
      if(state >= 2 && state != 0x80)           //Received byte is data
      {   
         switch(MatchAddress)
         {
            case   0xd0:               //0x68
               if(i2c_adr<=sizeof((struct _rtc)-1))
                  rtc.buffer[i2c_adr++]=incoming;
                  
               if(i2c_adr==sizeof((struct _rtc)-1))
               {
                  bcd_rtc_write();
                  rtc_rw_flag=WRITE;
               }
            break;
            
            case   0xd2:            //0x69
               if(i2c_adr<=sizeof(struct _stat)-1)
               {
                  stat.buffer[i2c_adr++] = incoming;                  
               }
               else
                  #asm
                     NOP;
                  #endasm           
            break;
            
         case   0xd4:            //0x6A   
            if(i2c_adr<=sizeof(struct _rtc)-1)
               rtc.buffer[i2c_adr++] = incoming;
            else
               #asm
                  NOP;
               #endasm             

         break;
         
         case   0xd6:            //0x6B   
            if(i2c_adr<=sizeof(struct _cmd)-1)
               cmd.buffer[i2c_adr++] = incoming;
            else
               #asm
                  NOP;
               #endasm           
         break;
         
         case   0xd8:               //0x6C
         case   0xda:               //0x6D   
         case   0xdc:               //0x6e
         case   0xde:               //0x6F   
            if(i2c_adr<=2)
               dummy=incoming;
            else
               #asm
                  NOP;
               #endasm             
         break;
         
         default:
         break;
         } 
      }
   }
 
   
   if(state >= 0x80)                            //RPi Master is requesting data
   {     
      switch(MatchAddress)
      {
         case   0xd1:                              //0x68
            if(i2c_adr<=sizeof(struct _rtc)-1)
               i2c_write_slave(RPI_I2C, rtc.buffer[i2c_adr++]);
            else
               i2c_write(RPI_I2C, 0x00); 
            
            break;
   
         case 0xd3:                              //0x69
            if(i2c_adr<=sizeof(struct _stat)-1)
            { 
               i2c_write_slave(RPI_I2C, stat.buffer[i2c_adr]);
               slaveWriteData=picostat.buffer[i2c_adr];
               i2c_adr++;
            }
            else
               i2c_write_slave(RPI_I2C, 0x00);

         
            break;
         
         case   0xd5:                           //0x6A
            if(i2c_adr<=sizeof(struct _rtc)-1)
            {   
               i2c_write_slave(RPI_I2C, rtc.buffer[i2c_adr++]);
            }
            else
               i2c_write_slave(RPI_I2C, 0x00);
               
            break;
         
         case 0xd7:                           //0x6B
            slaveWriteData=0x6B;
            if(i2c_adr<=sizeof(struct _cmd)-1)
            {              
               i2c_write_slave(RPI_I2C, cmd.buffer[i2c_adr++]);
            }
            else
               i2c_write_slave(RPI_I2C, 0x00); 
            break;
         
         case   0xd9:            //0x6C
         case   0xdb:            //0x6D
         case   0xdd:          //0x6E
         case   0xdf:            //0x6F
            if(i2c_adr<=2)
               i2c_write_slave(RPI_I2C, 0x00);
            else
               i2c_write_slave(RPI_I2C, 0x00);   
               
            break;
   
         default:
            break;
      }   
   }
}


Thank you in advance for your help !!
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Tue Jun 20, 2023 7:38 am     Reply with quote

First thing, what you post is very flawed. You are holding the bus when
it should not be held, and releasing it when it should be held.
Now a source for an extended I2C_ISR_state (designed to support
more than 256 bytes), was posted here (by me) a little while ago. Search
for i2c_isr_state16. If this is changed to use an int8 it gives the same code
as the supplied function.
Then, can you read the devid from the working and faulty chips? None
of the I2C errata apply to different versions. They all apply to all versions
of the chip, and checking with device editor, suggests that CCS have
already included fixes for the published errata. Two possibilities then
exist:
1) You have found a new erratum.
2) The chips you have are faulty.
I'd be very suspicious of the latter,
You should talk to Microchip, quoting the specific manufacture batch ID
and the devid. They may well simply replace the chips.
PICmodule



Joined: 26 Oct 2021
Posts: 32

View user's profile Send private message

PostPosted: Tue Jun 20, 2023 8:58 am     Reply with quote

Hi,
My answer is in the text


First thing, what you post is very flawed. You are holding the bus when
it should not be held, and releasing it when it should be held.

What do you mean, I followed examples provided by CCS, as also this (exactly this) routine was working with previous batch of micro-controller. Can you please explain what I'm making wrong

Now a source for an extended I2C_ISR_state (designed to support
more than 256 bytes), was posted here (by me) a little while ago. Search
for i2c_isr_state16. if this is changed to use an int8 it gives the same code
as the supplied function.

OK, I found it and study it. Thank you

Then, can you read the devid from the working and faulty chips. None
of the I2C errata apply to different versions. They all apply to all versions
of the chip, and checking with device editor,

OK. I will check. However it is not possible that IC are faulty and ONLY I2C is not working properly. More precise the first red is always good (after reset), also if I decrease dramatically the internal oscillator from 32 MHz to 2 MHz seems to be working.

1) You have found a new erratum.
2) The chips you have are faulty.
I'd be very suspicious of the latter,
You should talk to Microchip, quoting the specific manufacture batch ID
and the devid. They may well simply replace the chips.

Ad (1) I checked and seems this errata is the latest one, however check again.
Ad (2) As all other functions are fine, difficult to me to believe that I2C1 is faulty in 750 ICs. All of them I bought from the Microchip directly, I have another 3000 pcs


Please answer to the first remark you made, made this is the problem
Thank you very much
PICmodule



Joined: 26 Oct 2021
Posts: 32

View user's profile Send private message

PostPosted: Tue Jun 20, 2023 10:35 am     Reply with quote

I modified your function to 8bit
however the results are the same

Code:

pi@rpi:~ $ sudo i2cget -y 1 0x69 0x38
0x4e
pi@rpi:~ $ sudo i2cget -y 1 0x69 0x38
0x02
pi@rpi:~ $ sudo i2cget -y 1 0x69 0x38
0x08
pi@rpi:~ $ sudo i2cget -y 1 0x69 0x38
0x20
pi@rpi:~ $ sudo i2cget -y 1 0x69 0x38
0x80


The first read is proper each next is faulty, on this processor, on former one all are good


Last edited by PICmodule on Tue Jun 20, 2023 10:38 am; edited 1 time in total
PICmodule



Joined: 26 Oct 2021
Posts: 32

View user's profile Send private message

PostPosted: Tue Jun 20, 2023 10:37 am     Reply with quote

Can you please explain what do you mean with

First thing, what you post is very flawed. You are holding the bus when
it should not be held, and releasing it when it should be held.


This is working well with former processor, but not with current.
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Wed Jun 21, 2023 12:28 am     Reply with quote

You have the hold and release reversed:
Code:

   if(state <= 0x80)                               //Master is sending data
   {
      if(state == 0x80)
      {
         incoming = i2c_read(RPI_I2C);             //Passing 2 as parameter, causes the function to read the SSPBUF without releasing the clock
      }
      else
      {
         incoming = i2c_read(RPI_I2C,2);
      }     


Now look at the CCS example:
Code:

   if(state <= 0x80)                      //Master is sending data
   {
      if(state == 0x80)
         incoming = i2c_read(2);          //Passing 2 as parameter, causes the function to read the SSPBUF without releasing the clock
      else
         incoming = i2c_read();


You have it holding the clock on the transactions that don't want to hold
but not holding it on the one that does...

Exactly the opposite to what the example shows.
PICmodule



Joined: 26 Oct 2021
Posts: 32

View user's profile Send private message

PostPosted: Wed Jun 21, 2023 1:06 am     Reply with quote

Hi,
I already corrected it in the mean time, but still not working. More specifically working in the former micro controller without any problem (both versions) and NOT working on the new batch.
Actually, checking the driver from Microchip that seems to be more stable on both micro controllers, today expect to be back to you with more details or even solution. Lets hope
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Wed Jun 21, 2023 7:31 am     Reply with quote

OK.
Now if you study the errata, none of the I2C errata change between chip
versions, but a couple of the oscillator and CPU ones do.
Have you read the ID's.
What are the faulty chips actually doing?. I'm wondering if you have
perhaps got a problem like a slow rise time on the supply, and the chip
is actually triggering a brownout during boot, which is therefore causing
an issue if the new batch is one of the ones that does not correctly handle
the brownout reset. Have you got PUT enabled?. Have you got BROWNOUT
enabled?/
PICmodule



Joined: 26 Oct 2021
Posts: 32

View user's profile Send private message

PostPosted: Wed Jun 21, 2023 8:42 am     Reply with quote

Yes, the ID is the same on both batches 0x750B
If we use the CCS library, always the first read is proper after reset. ALWAYS.
Each next reading is damaged. In example first read is 0x4e, next is 0x02, then 0x08 etc. Doing Reset, again the first is 0x4e. I sent you simplified routine, without extra variables I m using for monitoring. Yes, it is next step to check OSC, this is what I'm using.

Quote:
#use delay(internal=32Mhz, pll_wait, AUX:crystal=32768Hz, clock=32768Hz, ACT=SOSC)


I realized that if decrease the OSC to 4 or better 2 MHz system is much more stable, and can get more reads (practically always). However it is not a solution.

The controller have typed the following:

OLD and good
FJ128GA705 2125 BTY

NEW and bad
FJ128GA705 1752 1HR
So definitely are not the same.

Yes, I have in mind that OSC can be problematic, however all other functions are working properly, tested many many times

Currently I'm testing the Microchip Library, and seems to be more stable, basically stable in read (always the same) but can not do write yet. In next hours will share with you the results.
Totally crazy situation.
Thank you for your help.
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Wed Jun 21, 2023 10:28 am     Reply with quote

Remove the ACT section.

The 2016 datasheet removed this option from the FRC oscillator.
Try without, and see what happens.
PICmodule



Joined: 26 Oct 2021
Posts: 32

View user's profile Send private message

PostPosted: Wed Jun 21, 2023 10:45 am     Reply with quote

yesss
PICmodule



Joined: 26 Oct 2021
Posts: 32

View user's profile Send private message

PostPosted: Wed Jun 21, 2023 1:32 pm     Reply with quote

Hi,
I ran the same software on both PCBs (first on the good processor, and then on the bad processor) with different results
See below what I ran

Clock setup

Code:

#use delay(internal=32MHz, AUX:crystal=32768Hz, clock=32768Hz)


Monitoring code
Code:

sprintf(printdata,"\n\r I2C1CONL:%X I2C1CONH:%X I2C1STAT:%X I2C1TRN:%X i2c_running:%X", I2C1CONL, I2C1CONH, I2C1STAT, I2C1_TRANSMIT_REG, run_status.i2c_running); debug_printing();
      sprintf(printdata,"\n\r\n\r ctr:%X slaveWriteData:%X slaveWriteData0:%X slaveWriteData1:%X", ctr, slaveWriteData, slaveWriteData0, slaveWriteData1); debug_printing();
      I2C1STAT_reg=I2C1STAT;

      sprintf(printdata,"\n\r\n\r I2C1STAT_reg.ACKSTAT:  %U", bit_test(I2C1STAT_reg, 15)); debug_printing();
      sprintf(printdata,"\n\r I2C1STAT_reg.TRSTAT:   %U", bit_test(I2C1STAT_reg, 14)); debug_printing();
      sprintf(printdata,"\n\r I2C1STAT_reg.ACKTIM:   %U", bit_test(I2C1STAT_reg, 13)); debug_printing();
      sprintf(printdata,"\n\r I2C1STAT_reg.BCL:      %U", bit_test(I2C1STAT_reg, 10)); debug_printing();
      sprintf(printdata,"\n\r I2C1STAT_reg.GCSTAT:   %U", bit_test(I2C1STAT_reg, 9)); debug_printing();   
      sprintf(printdata,"\n\r I2C1STAT_reg.ADD10:    %U", bit_test(I2C1STAT_reg, 8)); debug_printing();
      sprintf(printdata,"\n\r I2C1STAT_reg.IWCOL:    %U", bit_test(I2C1STAT_reg, 7)); debug_printing();
      sprintf(printdata,"\n\r I2C1STAT_reg.I2COV:    %U", bit_test(I2C1STAT_reg, 6)); debug_printing();
      sprintf(printdata,"\n\r I2C1STAT_reg.D_A:      %U", bit_test(I2C1STAT_reg, 5)); debug_printing();
      sprintf(printdata,"\n\r I2C1STAT_reg.P_BIT:    %U", bit_test(I2C1STAT_reg, 4)); debug_printing();
      sprintf(printdata,"\n\r I2C1STAT_reg.S_BIT:    %U", bit_test(I2C1STAT_reg, 3)); debug_printing();
      sprintf(printdata,"\n\r I2C1STAT_reg.R_W:      %U", bit_test(I2C1STAT_reg, 2)); debug_printing();
      sprintf(printdata,"\n\r I2C1STAT_reg.RBF:      %U", bit_test(I2C1STAT_reg, 1)); debug_printing();
      sprintf(printdata,"\n\r I2C1STAT_reg.TBF:      %U", bit_test(I2C1STAT_reg, 0)); debug_printing();
      sprintf(printdata,"\n\r\n\r ",); debug_printing();
   
      sprintf(printdata,"\n\r ",); debug_printing();
      for(q=0; q<32; q++)
      {
         sprintf(printdata,"%2X ", EMULATE_EEPROM_Memory[q]); debug_printing();
         restart_wdt();
      }
      
      sprintf(printdata,"\n\r ",); debug_printing();
      for(q=0; q<32; q++)
      {
         sprintf(printdata,"%2X ", q); debug_printing();
         restart_wdt();
      }

      sprintf(printdata,"\n\r -----------------------",); debug_printing();



and interrupt code

Code:


#INT_SI2C NOCLEAR LEVEL=7
void normal_SI2C_isr(void)
{
unsigned int8 dummy;
static unsigned int8 incoming, state;
static unsigned int8 MatchAddress; 
static unsigned int8 i2c_adr, adr_trn;

   run_status.i2c_running++;
      
   state=i2c_isr_state(RPI_I2C);
   
   if(flags.bit.LPR_enter_mode==ON)
      return;
 
   if(state <= 0x80)                                  //Master is sending data
   {
      if(state == 0x80)
      {
         incoming = i2c_read(RPI_I2C);             //Passing 2 as parameter, causes the function to read the SSPBUF without releasing the clock
      }
      else
      {
         incoming = i2c_read(RPI_I2C,2);
      }     

      EMULATE_EEPROM_Memory[ctr++]=incoming;
         
      if(state == 1)                                  //First received byte is address
         i2c_adr = incoming;
           
      adr_trn=i2c_adr;         
                 
      if((state == 0) || (state == 0x80))
         MatchAddress = incoming;       
            
      if(state >= 2 && state != 0x80)           //Received byte is data
      {   
         switch(MatchAddress)
         {
            case   0xd0:               //0x68
               if(i2c_adr<=sizeof((struct _rtc)-1))
                  rtc.buffer[i2c_adr++]=incoming;
                  
               if(i2c_adr==sizeof((struct _rtc)-1))
               {
                  bcd_rtc_write();
                  rtc_rw_flag=WRITE;
               }
            break;
            
            case   0xd2:            //0x69
               if(i2c_adr<=sizeof(struct _picostat)-1)
               {
                  picostat.buffer[i2c_adr++] = incoming;                  
               }
               else
                  #asm
                     NOP;
                  #endasm           
            break;
            
         case   0xd4:            //0x6A   
            if(i2c_adr<=sizeof(struct _rtc)-1)
               rtc.buffer[i2c_adr++] = incoming;
            else
               #asm
                  NOP;
               #endasm             

         break;
         
         case   0xd6:            //0x6B   
            if(i2c_adr<=sizeof(struct _picocmd)-1)
               picocmd.buffer[i2c_adr++] = incoming;
            else
               #asm
                  NOP;
               #endasm           
         break;
         
         case   0xd8:               //0x6C
         case   0xda:               //0x6D   
         case   0xdc:               //0x6e
         case   0xde:               //0x6F   
            if(i2c_adr<=2)
               dummy=incoming;
            else
               #asm
                  NOP;
               #endasm             
         break;
         
         default:
         break;
         } 
      }
   }
 
   
   if(state >= 0x80)                            //RPi Master is requesting data
   {      
      switch(MatchAddress)
      {

         case   0xd1:            //0x68
            if(i2c_adr<=sizeof(struct _rtc)-1)
               i2c_write_slave(RPI_I2C, rtc.buffer[i2c_adr++]);
            else
               i2c_write(RPI_I2C, 0x00); 
            
            break;

         case 0xd3:            //0x69
            if(adr_trn<=sizeof(buffer_Memory)-1)
            { 
               slaveWriteData=adr_trn;
               i2c_write_slave(RPI_I2C, picostat.buffer[adr_trn]);
               slaveWriteData0=picostat.buffer[adr_trn];
               adr_trn++;
               slaveWriteData1=adr_trn;
            }
            else
               i2c_write_slave(RPI_I2C, 0x00);
               
            break;
            
         case   0xd5:            //0x6A
            if(i2c_adr<=sizeof(struct _rtc)-1)
            {   
               i2c_write_slave(RPI_I2C, rtc.buffer[i2c_adr++]);
            }
            else
               i2c_write_slave(RPI_I2C, 0x00);
               
            break;
         
         case 0xd7:            //0x6B
            slaveWriteData=0x6B;
            if(i2c_adr<=sizeof(struct _picocmd)-1)
            {              
               i2c_write_slave(RPI_I2C, picocmd.buffer[i2c_adr++]);
            }
            else
               i2c_write_slave(RPI_I2C, 0x00); 
            break;
         
         case   0xd9:            //0x6C
         case   0xdb:            //0x6D
         case   0xdd:          //0x6E
         case   0xdf:            //0x6F
            if(i2c_adr<=2)
               i2c_write_slave(RPI_I2C, 0x00);
            else
               i2c_write_slave(RPI_I2C, 0x00);   
               
            break;
      
         default:
            i2c_write_slave(RPI_I2C, 0x00);
            break;
      }   

   }
   
   clear_interrupt(INT_SI2C);
}


I added some variables to monitor results. What I got:
GOOD processor

I2C1CONL:B3C0 I2C1CONH:0 I2C1STAT:8034 I2C1TRN:1 i2c_running:4

ctr:3 slaveWriteData:39 slaveWriteData0:1 slaveWriteData1:3A

I2C1STAT_reg.ACKSTAT: 1
I2C1STAT_reg.TRSTAT: 0
I2C1STAT_reg.ACKTIM: 0
I2C1STAT_reg.BCL: 0
I2C1STAT_reg.GCSTAT: 0
I2C1STAT_reg.ADD10: 0
I2C1STAT_reg.IWCOL: 0
I2C1STAT_reg.I2COV: 0
I2C1STAT_reg.D_A: 1
I2C1STAT_reg.P_BIT: 1
I2C1STAT_reg.S_BIT: 0
I2C1STAT_reg.R_W: 1
I2C1STAT_reg.RBF: 0
I2C1STAT_reg.TBF: 0

Stored incoming data
Code:
EMULATE_EEPROM_Memory[ctr++]=incoming;

D2 38 D3

BAD Processor
I2C1CONL:B3C0 I2C1CONH:0 I2C1STAT:802D I2C1TRN:1 i2c_running:4

ctr:3 slaveWriteData:39 slaveWriteData0:1 slaveWriteData1:3A

I2C1STAT_reg.ACKSTAT: 1
I2C1STAT_reg.TRSTAT: 0
I2C1STAT_reg.ACKTIM: 0
I2C1STAT_reg.BCL: 0
I2C1STAT_reg.GCSTAT: 0
I2C1STAT_reg.ADD10: 0
I2C1STAT_reg.IWCOL: 0
I2C1STAT_reg.I2COV: 0
I2C1STAT_reg.D_A: 1
I2C1STAT_reg.P_BIT: 0
I2C1STAT_reg.S_BIT: 1
I2C1STAT_reg.R_W: 1
I2C1STAT_reg.RBF: 0
I2C1STAT_reg.TBF: 1

Stored incoming data
Code:
EMULATE_EEPROM_Memory[ctr++]=incoming;

D2 38 D3

Now will decrease the clock to see
PICmodule



Joined: 26 Oct 2021
Posts: 32

View user's profile Send private message

PostPosted: Wed Jun 21, 2023 1:40 pm     Reply with quote

same results (even worst - as also the first byte is wrong)
with

Code:
#use delay(internal=4MHz, AUX:crystal=32768Hz, clock=32768Hz)

or
Code:
#use delay(internal=8MHz, AUX:crystal=32768Hz, clock=32768Hz)
PICmodule



Joined: 26 Oct 2021
Posts: 32

View user's profile Send private message

PostPosted: Wed Jun 21, 2023 4:53 pm     Reply with quote

No way with CCS, and the worst is that I d not know why.
So implementing the Microchip handler, where at least I can read values via I2C.
Now implementing the writing, also.
Code:


///////////////////////////////////////////////////////////////////////////////
///////////////            INTERRUPT SERVICE         /////////////////////////
///////////////////////////////////////////////////////////////////////////////

//NOCLEAR, LEVEL=n, HIGH, FAST, ALT, CLR_FIRST
#INT_SI2C NOCLEAR LEVEL=7
void mcsi2c_interrupt()
{
unsigned int8   dummy;
static int1      prior_address_match = false;
static int1      not_busy = true;

// NOTE: The slave driver will always acknowledge
//       any address match.
   
   run_status.i2c_running++;

   switch(i2c1_slave_state)
   {
      case S_SLAVE_IDLE:
      case S_SLAVE_RECEIVE_MODE:

      /* When at S_SLAVE_RECEIVE_MODE this mode there
      will be two types of incoming transactions:
      1. Data sent by master
      2. A restart or start detection

      But from the point of view of the firmware, there is
      no difference between S_SLAVE_IDLE and S_SLAVE_RECEIVE_MODE
      states, since the types of incoming transactions will be
      the same so we share the code here.
      */
         // case of 7-bit address detected
      if(((I2C1_10_BIT_ADDRESS_ENABLE_BIT == 0) && (I2C1_DATA_NOT_ADDRESS_STATUS_BIT == 0))
         || // case of general address call detected
         ((I2C1_GENERAL_CALL_ENABLE_BIT == 1) && (I2C1_GENERAL_CALL_ADDRESS_STATUS_BIT == 1)))
      {                           
         if (I2C1_READ_NOT_WRITE_STATUS_BIT == 0)
         {
            // it is a write, go to receive mode
/*         
            switch(I2C1_RECEIVE_REG)
            {
                  case 0xd0:                     //0x68 0x58 0x48   
                  //case 0xb0:
                  //case 0x90:
                     MatchAddressWSet=0x68;
                     break;
                  
                  case 0xd2:                     //0x69 0x59 0x49   
                  //case 0xb2:
                  //case 0x92:
                     MatchAddressWSet=0x69;
                     break;

                  case 0xd4:                     //0x6A 0x5A 0x4A
                  //case 0xb4:
                  //case 0x94:
                     MatchAddressWSet=0x6A;
                     break;

                  case 0xd6:                     //0x6B 0x5B 0x4B
                  //case 0xb6:
                  //case 0x96:
                     MatchAddressWSet=0x6B;
                     break;

                  default:
                     //MatchAddressWSet=0xAA;
                     break;
               }
*/            
               I2C1_StatusCallback(I2C1_SLAVE_RECEIVE_REQUEST_DETECTED);   
   
               // Receive the data if valid               
               I2C1_ReceiveProcess();
               i2c1_slave_state = S_SLAVE_RECEIVE_MODE;
            
            }
            else
            {
               // read the receive register only when
               // we are ready for the next transaction.
               // this one is a dummy read
               // it is a write, go to receive mode
/*               
               switch(I2C1_RECEIVE_REG)
               {
                  case 0xd0:                     //0x68 0x58 0x48   
                  //case 0xb0:
                  //case 0x90:
                     MatchAddressRGet=0x68;
                     break;
                  
                  case 0xd2:                     //0x69 0x59 0x49   
                  //case 0xb2:
                  //case 0x92:
                     MatchAddressRGet=0x69;
                     break;

                  case 0xd4:                     //0x6A 0x5A 0x4A
                  //case 0xb4:
                  //case 0x94:
                     MatchAddressRGet=0x6A;
                     break;

                  case 0xd6:                     //0x6B 0x5B 0x4B
                  //case 0xb6:
                  //case 0x96:
                     MatchAddressRGet=0x6B;
                     break;

                  default:
                     //MatchAddressRGet=0xAA;
                     break;
               }
*/
               dummy = I2C1_RECEIVE_REG;
   
               // it is a read, go to transmit mode
                   
               I2C1_StatusCallback(I2C1_SLAVE_TRANSMIT_REQUEST_DETECTED);

               // during this portion, the master is expecting the
               // slave for a reply. So the returned status of
               // the callback at this point cannot be used to
               // delay the reply if needed.
               // In other words, the slave has to reply to the master.
               // Therefore, the transmit will be performed.
                   
               I2C1_TransmitProcess();
               i2c1_slave_state = S_SLAVE_TRANSMIT_MODE;
            }

         }
         else if
         (
         // CASE of 10 - bit high address detected
         ((I2C1_10_BIT_ADDRESS_ENABLE_BIT  == 1) &&
          (I2C1_DATA_NOT_ADDRESS_STATUS_BIT == 0)
         ))
         {           
            
            if(I2C1_READ_NOT_WRITE_STATUS_BIT == 0)
            {
               // it is the detection of high byte address of
               // 10 - bit address, go to detection of low byte address
               prior_address_match = false;
               i2c1_slave_state = S_SLAVE_LOW_BYTE_ADDRESS_DETECT;
            }
            else // IF (I2C1_READ_NOT_WRITE_STATUS_BIT == 1)
            {
               if(prior_address_match == true)
               {
                  // it is the detection of high byte
                  // address of 10 - bit address, but the next
                  // transaction is read transaction (so it
                  // is a restart) .
                  // set the transmit REGISTER with the data
                  // to transmit then go to transmit mode
                  I2C1_StatusCallback (I2C1_SLAVE_TRANSMIT_REQUEST_DETECTED) ;
                  // during this portion, the master is expecting the
                  // slave FOR a reply. So the returned status of
                  // the callback at this point cannot be used to
                  // delay the reply IF needed.
                  // In other words, the slave has to reply to the master.
                  // Therefore, the transmit will be performed.
                  I2C1_TransmitProcess () ;
                  i2c1_slave_state = S_SLAVE_TRANSMIT_MODE;
               }
               else
               {
                  // it is the detection of high byte address of
                  // 10 - bit address, but next transaction is a write.
                  // go to detection of low byte address
                  prior_address_match = false;
                  i2c1_slave_state = S_SLAVE_LOW_BYTE_ADDRESS_DETECT;
               }
            }
            // dummy read is needed
            dummy = I2C1_RECEIVE_REG;
         }
   
         // this IF statement is to make sure we only save incoming
         // data when we are truly in receiving mode
         if(i2c1_slave_state == S_SLAVE_RECEIVE_MODE)
         {
         // CASE of data received
         if(I2C1_DATA_NOT_ADDRESS_STATUS_BIT == 1)
         {
            // check IF we are overflowing the receive buffer
            if (I2C1_RECEIVE_OVERFLOW_STATUS_BIT != 1)
            {
               I2C1_ReceiveProcess();
               not_busy = I2C1_StatusCallback(I2C1_SLAVE_RECEIVED_DATA_DETECTED);
            }
            else
            {
               // overflow detected!
               // read the buffer to reset the buffer full flag
               // and clear the overflow bit
               // then DO nothing so the master
               // will resend the data
               dummy = I2C1_RECEIVE_REG;
               I2C1_RECEIVE_OVERFLOW_STATUS_BIT = 0;
            }
         }
      }
      break;
     
      CASE S_SLAVE_LOW_BYTE_ADDRESS_DETECT:
      // Note that this state will only get
      // executed when 10 - bit address is set
      // we send receive request but we DO not actually know
      // IF the next one is a data from master since the
      // next one can be a restart with a transmit request.
      // When that happens, the next state will take care of it.
      // This is just the nature of i2c bus protocol.
      not_busy = I2C1_StatusCallback(I2C1_SLAVE_10BIT_RECEIVE_REQUEST_DETECTED);
      // set this flag to indicate we have
      // full 10 - bit address detection
      prior_address_match = true;
      if(not_busy)
      {
         // dummy read is needed
         dummy = I2C1_RECEIVE_REG;
      }

      i2c1_slave_state = S_SLAVE_RECEIVE_MODE;
      break;
     
      case S_SLAVE_TRANSMIT_MODE:
      // this is the state where an ACK or NACK is expected
      // to occur after the slave has placed data to the
      // transmit REGISTER.
      // IF the transaction was ACK'ed, more data needs to be sent
      // IF the transaction was NACK'ed then we don't need to send
      // more data
      if (I2C1_ACKNOWLEDGE_STATUS_BIT == 0)
      {
         // prepare next data
         I2C1_StatusCallback (I2C1_SLAVE_TRANSMIT_REQUEST_DETECTED) ;
         // transmit more data
         I2C1_TransmitProcess () ;
      }

      else //IF (I2C1_ACKNOWLEDGE_STATUS_BIT == 1)
      {
         // no more data to be sent so we go to idle state
         i2c1_slave_state = S_SLAVE_IDLE;
      }
      break;
     
      default:
         // should never happen, IF we ever get here stay here forever
         //   while(1);
      break;
   }

   I2C1_RELEASE_SCL_CLOCK_CONTROL_BIT = 1;
   // clear the slave interrupt flag
   clear_interrupt(INT_SI2C);
}



Code:
static unsigned int8 i2c1_slaveWriteData = 0xAA;

unsigned int1 I2C1_StatusCallback(I2C1_SLAVE_DRIVER_STATUS status)
{

                // this emulates the slave device memory where data written to slave
                // is placed and data read from slave is taken
               
static unsigned int8 address, addrByteCount;
static unsigned int1 addressState = true;

                switch(status)
                {
                    case I2C1_SLAVE_TRANSMIT_REQUEST_DETECTED:

                        // set up the slave driver buffer transmit pointer
                        I2C1_ReadPointerSet(&EMULATE_EEPROM_Memory[address]);
                        address++;
                        break;

                    case I2C1_SLAVE_RECEIVE_REQUEST_DETECTED:

                        addrByteCount = 0;
                        addressState = true;
                        //i2c_state_str='R';
                        // set up the slave driver buffer receive pointer
                        I2C1_WritePointerSet(&i2c1_slaveWriteData);
                        break;

                    case I2C1_SLAVE_RECEIVED_DATA_DETECTED:
                        slaveWriteData=0xAA;
                        if (addressState == true)
                        {
                            // get the address of the memory being written
                            if (addrByteCount == 0)
                            {
                                //address = (i2c1_slaveWriteData << 8) & 0xFF00;
                                addrByteCount++;
                            }
                            else if(addrByteCount == 1)
                            {
                                address = address | i2c1_slaveWriteData;
                                addrByteCount = 0;
                                addressState = false;
                            }
                        }
                        else if(addressState == false)
                        {
                            // set the memory with the received data
                            EMULATE_EEPROM_Memory[0] = 0xaa;   //i2c1_slaveWriteData;

                           
                        }
                        break;

                    case I2C1_SLAVE_10BIT_RECEIVE_REQUEST_DETECTED:
                        // do something here when 10-bit address is detected
                        // 10-bit address is detected
                        break;

                    default:
                        break;

      }

      return true;
}


This is working on both processors, tomorrow should be ready also the writing hopefully
PICmodule



Joined: 26 Oct 2021
Posts: 32

View user's profile Send private message

PostPosted: Thu Jun 22, 2023 4:09 pm     Reply with quote

I made finally procedure that is working fine for a read/write on both processors types

Code:
sudo i2cget -y 1 0x69 0x04

return 0x05

and after
Code:
sudo i2cset -y 1 0x69 0x04 0xaa

return 0xaa

Code:

/*
Function Name: SI2C1Interrupt
Description : This is the ISR for I2C1 Slave interrupt.
Arguments    : None
*/
//NOCLEAR, LEVEL=n, HIGH, FAST, ALT, CLR_FIRST
#INT_SI2C NOCLEAR LEVEL=7
void MCSI2C1Interrupt(void)
{
unsigned int8 dummy;   //used for dummy read
static unsigned int8 MatchAddress;
static unsigned int8 i2c_adr;
static unsigned int8 i2c_data;

   run_status.i2c_running++;

   if((I2C1_READ_NOT_WRITE_STATUS_BIT == 0)&&(I2C1_DATA_NOT_ADDRESS_STATUS_BIT == 0))   //Address matched
   {   
      MatchAddress = I2C1_RECEIVE_REG;                     //dummy read
      AddrFlag = 1;                                       //next byte will be address   
   }
   
   if((I2C1_READ_NOT_WRITE_STATUS_BIT == 0)&&(I2C1_DATA_NOT_ADDRESS_STATUS_BIT == 1))   //check for data
   {
      if(AddrFlag)
      {
         AddrFlag = 0;   
         DataFlag = 1;                                 //next byte is data
         i2c_adr=I2C1_RECEIVE_REG;
         I2C1_RELEASE_SCL_CLOCK_CONTROL_BIT = 1;      //Release SCL1 line         
      }
      else if(DataFlag)
      {
         i2c_data = (unsigned int8)I2C1_RECEIVE_REG;      // store data into RAM
         AddrFlag = 0;                                 //end of tx
         DataFlag = 0;
         EMULATE_EEPROM_Memory[i2c_adr]=i2c_data;   
         I2C1_RELEASE_SCL_CLOCK_CONTROL_BIT = 1;      //Release SCL1 line
      }
   }
   
   if((I2C1_READ_NOT_WRITE_STATUS_BIT == 1)&&(I2C1_DATA_NOT_ADDRESS_STATUS_BIT == 0))
   {   
      dummy = I2C1_RECEIVE_REG;
      I2C1_TRANSMIT_REG = EMULATE_EEPROM_Memory[i2c_adr];   //i2c_data;                     //Read data from RAM & send data to I2C master device
      I2C1_RELEASE_SCL_CLOCK_CONTROL_BIT = 1;               //Release SCL1 line
      while(I2C1_TRANSMITTER_BUFFER_STATUS_BIT);            //Wait till all
   }
   
   I2C1_RELEASE_SCL_CLOCK_CONTROL_BIT = 1;            //Release SCL1 line
   clear_interrupt(INT_SI2C);
}    


Can anyone comment it.
However this is not working when doing

Code:
sudo i2cget -y 1 0x69 0x04 w

return 0xff05

and here I do not know why, any ideas ?
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 1, 2  Next
Page 1 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