Write to data EEPROM hangs without delay

Enhanced mid-range devices. PIC12F1xxx and PIC16F1xxx

Write to data EEPROM hangs without delay

Postby tunelabguy » Tue Sep 23, 2014 5:29 am

My PIC is the 16F1823, and I am trying to write to data EEPROM. But the wait for the WR bit hangs for the second of two bytes I write, but only if I try to write the second byte immediately after writing the first byte. Here is the code (using the CCS compiler, but no CCS peripheral libraries):
Code: Select all
void WriteEEdata(unsigned int addr, unsigned int data)
{
   EEADR = addr;
   EEDATA = data;
   EECON1.EEPGD = 0;
   EECON1.CFGS = 0;
   EECON1.WREN = 1;
   INTCON.GIE = 0;         //..*** Interrupts Disabled ***
   EECON2 = 0x55;
   EECON2 = 0xaa;
   EECON1.WR = 1;         //..begins the write..
   INTCON.GIE = 1;         //..*** Interrupts Enabled ***
   while( EECON1.WR )  {;}   //..wait for write to finish
   EECON1.WREN = 0;
}


This code is called as follows:

Code: Select all
   WriteEEdata(0x04, MyAddress & 0xff);  //..this write always returns
   WriteEEdata(0x05, (MyAddress>>8) & 0xff);  //..this write hangs waiting for WR bit.

Here are some other interesting facts: I detect the fact that it hangs in the while loop by writing to an unused output pin before and after the loop. Even when it hangs, post mortem reading of data EEPROM through MPLAB confirms that both writes to addresses 0x04 and 0x05 were effective. If I add a time-wasting for loop between the two calls to WriteEEdata, then there are no hang-ups. This WriteEEdata function I have used successfully on previous projects.

Any idea what I might be doing wrong here?
User avatar
tunelabguy
Verified identity
 
Posts: 29
Joined: Sun Jul 20, 2014 9:41 pm
PIC experience: Professional 5+ years with MCHP products

Re: Write to data EEPROM hangs without delay

Postby jtemples » Tue Sep 23, 2014 7:24 am

What if you don't enable interrupts during the write?
jtemples
Verified identity
 
Posts: 173
Joined: Sun May 25, 2014 2:23 am
Location: The 805
PIC experience: Professional 5+ years with MCHP products

Re: Write to data EEPROM hangs without delay

Postby tunelabguy » Tue Sep 23, 2014 2:02 pm

jtemples wrote:What if you don't enable interrupts during the write?

Well, that is interesting. When I move the INTCON.GIE = 1 down to below the wait for WR, nothing hangs. But why should that be? The datasheet shows enabling interrupts immediately after setting WR. I suppose something in my ISR could touch the EEPROM registers, but my ISR does not seem to do that. I have no references to EEPROM registers in my ISR. Here is my ISR, which processes Tx, Rx, CCP1, and Timer1 overflow interrupts:
Code: Select all
   if(PIR1.RCIF)   //..RCREG1 is full.  RCIF will be cleared when RCREG is read
   {
      isrChar = RCREG;   //..this clears RCIF
      isrHandleRcvdChar();
   }

   if(TxNextToSend < TxEnd)
   {
      isrChar = TxBuf[TxNextToSend];
      {
         PIE1.TXIE = 1;      //..in case we got here because of some other interrupt..
         if(PIR1.TXIF)
         {
            TXREG = isrChar;
            TxNextToSend++;
         }
      }
   }
   else
   {
      PIE1.TXIE = 0;
   }
   

   if(PIR1.CCP1IF)      //..input capture event
   {
      if(mainState.firstCaptureDone == 0)
      {
         PrevCCPR1 = CCPR1;
         mainState.firstCaptureDone = 1;
         mainState.lastCaptureDone = 0;
      }
      else if (mainState.lastCaptureDone == 0)
      {
         PeriodDelta16 = CCPR1 - PrevCCPR1;   //..Every 256 x 16 oscillations.
         mainState.lastCaptureDone = 1;
      }
      PIR1.CCP1IF = 0;
   }   //..end of CCP capture interrupt..
   
   if(PIR1.TMR1IF)
   {
      PIR1.TMR1IF = 0;
      Timer1OverflowCount++;
      
   }      //..end of TMR1 overflow
#asm
   RETFIE      ;..fast return restores registers
#endasm


Edit update: Here is some new data. Instead of keeping all interrupts off during the entire write to EEPROM, I tried using the PIE1 register to selectively enable interrupts, as follows:
Code: Select all
void WriteEEdata(unsigned int addr, unsigned int data)
{
   int savedPIE;
   EEADR = addr;
   EEDATA = data;
   EECON1.EEPGD = 0;
   EECON1.CFGS = 0;
   EECON1.WREN = 1;
   INTCON.GIE = 0;         //..*** Interrupts Disabled ***
   savedPIE =    PIE1;
   PIE1 = 0;
   //PIE1.RCIE = 1;      //..THIS KILLS IT.

   EECON2 = 0x55;
   EECON2 = 0xaa;
   EECON1.WR = 1;         //..begins the write..
   INTCON.GIE = 1;         //..*** Interrupts Enabled ***
   EECON1.WREN = 0;
   while( EECON1.WR )  {;}   //..wait for write to finish
   PIE1 = savedPIE;
}

When I uncomment the PIE1.RCIE = 1, the second call to WriteEEdata hangs as before. And I know what might be causing that RC interrupt. The serial command that kicked off this write to EEPROM was sent from a terminal program that sends both a CR and the LF when I hit Enter. The PIC parses the CR as the command termination and begins the write to EEPROM. But the LF arrives shortly after (at 2400 baud). My ISR is supposed to discard characters that are not part of its protocol, so I don't know why an extra LF arriving should cause any problem to the WriteEEdata.
User avatar
tunelabguy
Verified identity
 
Posts: 29
Joined: Sun Jul 20, 2014 9:41 pm
PIC experience: Professional 5+ years with MCHP products

Re: Write to data EEPROM hangs without delay

Postby jtemples » Tue Sep 23, 2014 5:56 pm

But why should that be?

I don't know, but when I saw you were using CCS, my first thought was "compiler bug". Maybe something in the ISR context save/restore.
jtemples
Verified identity
 
Posts: 173
Joined: Sun May 25, 2014 2:23 am
Location: The 805
PIC experience: Professional 5+ years with MCHP products

Re: Write to data EEPROM hangs without delay

Postby tunelabguy » Tue Sep 23, 2014 9:41 pm

jtemples wrote:
But why should that be?

I don't know, but when I saw you were using CCS, my first thought was "compiler bug". Maybe something in the ISR context save/restore.

That was it. Careful examination of the compiler listing file showed that the beginning of the ISR did not set the bank select register, but just assumed it was 0. Therefore the first instruction, which was a test for PIR1.RCIF, was actually testing EEADRL.5, which just happened to always be 0. Therefore the ISR did not read RCREG, and the RCIF interrupt bit was not cleared, so when the ISR returned, it did an immediate interrupt, so the code would be perpetually interrupting, and the main program would hang.

My work-around was to insert an assembly-language "MOVLB 0" instruction at the top of the ISR. Now the EEPROM writes work just fine without hang-ups.
User avatar
tunelabguy
Verified identity
 
Posts: 29
Joined: Sun Jul 20, 2014 9:41 pm
PIC experience: Professional 5+ years with MCHP products

Re: Write to data EEPROM hangs without delay

Postby ric » Tue Sep 23, 2014 9:47 pm

Any particular reason you're using CCS?
Latest test project, an LED matrix display made from one reel of addressable LEDs. here
User avatar
ric
Verified identity
 
Posts: 453
Joined: Sat May 24, 2014 2:35 pm
Location: Melbourne, Australia
PIC experience: Professional 5+ years with MCHP products

Re: Write to data EEPROM hangs without delay

Postby tunelabguy » Wed Sep 24, 2014 12:48 am

ric wrote:Any particular reason you're using CCS?

I've used the CCS compiler for many years and I am comfortable with it.
User avatar
tunelabguy
Verified identity
 
Posts: 29
Joined: Sun Jul 20, 2014 9:41 pm
PIC experience: Professional 5+ years with MCHP products

Re: Write to data EEPROM hangs without delay

Postby ric » Wed Sep 24, 2014 1:12 am

Fair enough.
Not forcing bank 0 at the start of the ISR sounds like a pretty major bug, which I would have thought would have tripped up many people by now.
I wonder if it normally does it, but something unusual in your code made it think it didn't need to.

I'm guessing that when they extended the compiler to handle the 16F1xxx chips, they just removed the context saving code, which included selecting bank 0.
That would mean this bug would only occur on chips which have built in shadow registers.
Latest test project, an LED matrix display made from one reel of addressable LEDs. here
User avatar
ric
Verified identity
 
Posts: 453
Joined: Sat May 24, 2014 2:35 pm
Location: Melbourne, Australia
PIC experience: Professional 5+ years with MCHP products

Re: Write to data EEPROM hangs without delay

Postby tunelabguy » Wed Sep 24, 2014 2:30 am

ric wrote:Fair enough.
Not forcing bank 0 at the start of the ISR sounds like a pretty major bug, which I would have thought would have tripped up many people by now.
I wonder if it normally does it, but something unusual in your code made it think it didn't need to.

I'm guessing that when they extended the compiler to handle the 16F1xxx chips, they just removed the context saving code, which included selecting bank 0.
That would mean this bug would only occur on chips which have built in shadow registers.

The reason that others probably have not run into this bug is that most CCS users let the compiler handle the interrupt vectoring, supplying just the peripheral-specific ISRs as separate functions. This also ensures a more complete context saving and restoring. When the user writes his own #INT_GLOBAL, he takes full responsibility for all of that, which scares most people away from doing it. The reason I do it is because I have always liked having complete control of things like the exact sequence in which the various interrupts are serviced, especially if two different interrupts are functionally related, like a CCP capture interrupt and a Timer1 overflow interrupt for generating 32-bit captures. But I am an odd duck in this regard.
User avatar
tunelabguy
Verified identity
 
Posts: 29
Joined: Sun Jul 20, 2014 9:41 pm
PIC experience: Professional 5+ years with MCHP products


Return to 14-Bit Core (enhanced)

Who is online

Users browsing this forum: No registered users and 1 guest