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 support@ccsinfo.com

Multitasking a EEPROM write using the eeprom interrupt?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Will Reeve
Guest







Multitasking a EEPROM write using the eeprom interrupt?
PostPosted: Thu Aug 21, 2003 3:41 am     Reply with quote

Hi guys,
I am trying to understand the CCS compiled code for a write_eeprom command. The reason I looked into it is the datasheet states interrupts should be disabled during an EEPROM write and I was checking up on the good people at CCS!

In fact this has thrown up a problem for me. I have a UART interrupt filling a circular buffer. The CCS code “hangs” the PIC while waiting for the EEPROM write to finish, that’s 8ms of time in my application, at 9600 baud I will miss 6 bytes!!!.

The CCS code uses the technique of waiting until the WR Write Control bit clears before continuing. As interrupts are off (correctly!) then no interrupt servicing happens!

According to the datasheet, their (Microchip’s) example is to set the WR Write Control to 1 then enable the interrupts and use the EEPROM write finished interrupt to clear WREN (EEPROM Write Enable bit).

Looking at the datasheet there is an interrupt that occurs when the EEPROM is finished but the ccs write_eeprom procedure doesn’t use it.

My question is this; the Microchip example puts the PIC into sleep while the write EEPROM completes, as the interrupt I want to catch doesn’t wake the PIC from SLEEP I plan to just carry on and effectively multitask the PIC while the write completes. I will check WREM on entry to my own eepromwrite routine to make sure the previous EEPROM write is complete (WREN will be reset by the finished write eeprom interrupt).

Has anyone had to do this on their project…is it safe practice? Why don’t CCS use this method?

Keep well all,


Will
___________________________
This message was ported from CCS's old forum
Original Post ID: 144517121
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

Re: Multitasking a EEPROM write using the eeprom interrupt?
PostPosted: Thu Aug 21, 2003 8:51 am     Reply with quote

CCS doesn't do this because it requires too much thinking and planning on the part of the programmer. The programmer has to be aware of these things which complicates the matter. If CCS didn't wait, you would have to do all this checking. The same goes for many of their other functions regarding outputting data using the "put" commands. Provide you do all the checking, there is no problem. If you are just worried about missing the data, you can simply enable ints and just watch the EEIF flag or the WR bit. Here is how I do it. Note the global_int() function is my own. It stores the current state if the int and then restores it so I don't have to keep track of it.

Code:

void Write_EEPROM(
  UINT8 data,            // byte written to eeprom
  UINT8 address)         // EEPROM address to write data
{
  PIR2bits.EEIF = 0;     // Make sure that the int flag is cleared
  EEADRH= 0;             // Load our address
  EEADR = address;       // Load our address
  EEDATA = data;         // Load our data
  EECON1bits.EEPGD = 0;  // Point to data memory
  EECON1bits.WREN = 1;   // Enable writes

  // Microchip recommends disabling ints here
  global_int(INT_DISABLED);
  EECON2 = 0x55;         // Write 0x55
  EECON2 = 0xAA;         // Write 0xAA
  EECON1bits.WR=1;       // Set WR to begin write
  _asm
    nop
  _endasm
  global_int(INT_RESTORE);
  while (!PIR2bits.EEIF); // Wait for write to complete

  PIR2bits.EEIF = 0;
  EECON1bits.WREN = 0;    // Disable writes
  return;
}

:=Hi guys,
:=I am trying to understand the CCS compiled code for a write_eeprom command. The reason I looked into it is the datasheet states interrupts should be disabled during an EEPROM write and I was checking up on the good people at CCS!
:=
:=In fact this has thrown up a problem for me. I have a UART interrupt filling a circular buffer. The CCS code ?hangs? the PIC while waiting for the EEPROM write to finish, that?s 8ms of time in my application, at 9600 baud I will miss 6 bytes!!!.
:=
:=The CCS code uses the technique of waiting until the WR Write Control bit clears before continuing. As interrupts are off (correctly!) then no interrupt servicing happens!
:=
:=According to the datasheet, their (Microchip?s) example is to set the WR Write Control to 1 then enable the interrupts and use the EEPROM write finished interrupt to clear WREN (EEPROM Write Enable bit).
:=
:=Looking at the datasheet there is an interrupt that occurs when the EEPROM is finished but the ccs write_eeprom procedure doesn?t use it.
:=
:=My question is this; the Microchip example puts the PIC into sleep while the write EEPROM completes, as the interrupt I want to catch doesn?t wake the PIC from SLEEP I plan to just carry on and effectively multitask the PIC while the write completes. I will check WREM on entry to my own eepromwrite routine to make sure the previous EEPROM write is complete (WREN will be reset by the finished write eeprom interrupt).
:=
:=Has anyone had to do this on their project?is it safe practice? Why don?t CCS use this method?
:=
:=Keep well all,
:=
:=
:=Will
___________________________
This message was ported from CCS's old forum
Original Post ID: 144517128
Will Reeve
Guest







Re: Multitasking a EEPROM write using the eeprom interrupt?
PostPosted: Wed Aug 27, 2003 9:24 am     Reply with quote

Hi guys,
I have updated your code to suit my application. It seems to work very well and doesn't hang the pic so allowing the USART to work while writing to a EEPROM location. Thanks.
I didn't have to use a #asm either!

Will


/*********************************************************************************
Library for implementing a multi-tasking EEPROM write arrangement

Syntax: mtask_write_eeprom(address, value)
Parameters: address is a 8 bit int, the range is device dependent, value
is a 8 bit int
Returns: undefined
Function: Write a byte to the specified data EEPROM address. This function
will initiate the write then release control back to the main
code. However further writes are not possible until the current
write has executed. This function has the advantage of not
holding the code up in the way the CCS built in function does. It
was written to all the UART to continue to fill a circular buffer.
Availability: This function is only available on devices with supporting hardware
on chip
Requires: The #INT_EEPROM interrupt to be enabled in calling code.



********************************************************************/

// register locations, this list is correct for 16F87x parts check for
// compatibility with target part!
#byte EEADRH = 0x10F
#byte EEADR = 0x10D
#byte EEDATA = 0x10C
#byte EECON2 = 0x18D
#bit EECON1_EEPGD = 0x18C.7
#bit EECON1_WREN = 0x18C.2
#bit EECON1_WR = 0x18C.1

/*******************************************************************
* void write_eeprom_finished(void)
* Purpose: This is called by an interrupt which occurs when a EEPROM
* write is completed.
*/
#INT_EEPROM
void write_eeprom_finished(void) {
EECON1_WREN = 0; // clear WREN to allow EPROM writes
} // eeprom_write_finished

/*****************************************************
* void mtask_write_eeprom(int8 loc,data)
* Purpose: Write 'data' to address 'loc' in the EEPROM
*/
void mtask_write_eeprom(int8 loc, data) {
while (EECON1_WREN); // wait until any current EEPROM write is finished
EEADRH = 0; // clear M EEADRH
EEADR = loc;
EEDATA = data;
EECON1_EEPGD = 0; // Point to DATA memory
EECON1_WREN = 1; // Enable writes
disable_interrupts(global); // Disable all interrupts
EECON2 = 0x55; //Write 55h
EECON2 = 0xAA; //Write AAh
EECON1_WR = 1; // Set WR to begin write
enable_interrupts(global); // Enable all interrupts
} // mtast_write_eeprom(int8 loc, data)
___________________________
This message was ported from CCS's old forum
Original Post ID: 144517327
rrb011270



Joined: 07 Sep 2003
Posts: 51

View user's profile Send private message Yahoo Messenger

Re: Multitasking a EEPROM write using the eeprom interrupt?
PostPosted: Thu Oct 09, 2003 6:32 pm     Reply with quote

Mabuhay!

How did u use mtask_write_eeprom(address, value) in ur program? would be also possible to have mtask_read_eeprom(address)? Anyone has done a code snippet mtask read function? Is their a change int #INT_EEPROM routine?

Thnx

Any help will do?

======

Will Reeve wrote:
Hi guys,
I have updated your code to suit my application. It seems to work very well and doesn't hang the pic so allowing the USART to work while writing to a EEPROM location. Thanks.
I didn't have to use a #asm either!

Will


/*********************************************************************************
Library for implementing a multi-tasking EEPROM write arrangement

Syntax: mtask_write_eeprom(address, value)
Parameters: address is a 8 bit int, the range is device dependent, value
is a 8 bit int
Returns: undefined
Function: Write a byte to the specified data EEPROM address. This function
will initiate the write then release control back to the main
code. However further writes are not possible until the current
write has executed. This function has the advantage of not
holding the code up in the way the CCS built in function does. It
was written to all the UART to continue to fill a circular buffer.
Availability: This function is only available on devices with supporting hardware
on chip
Requires: The #INT_EEPROM interrupt to be enabled in calling code.



********************************************************************/

// register locations, this list is correct for 16F87x parts check for
// compatibility with target part!
#byte EEADRH = 0x10F
#byte EEADR = 0x10D
#byte EEDATA = 0x10C
#byte EECON2 = 0x18D
#bit EECON1_EEPGD = 0x18C.7
#bit EECON1_WREN = 0x18C.2
#bit EECON1_WR = 0x18C.1

/*******************************************************************
* void write_eeprom_finished(void)
* Purpose: This is called by an interrupt which occurs when a EEPROM
* write is completed.
*/
#INT_EEPROM
void write_eeprom_finished(void) {
EECON1_WREN = 0; // clear WREN to allow EPROM writes
} // eeprom_write_finished

/*****************************************************
* void mtask_write_eeprom(int8 loc,data)
* Purpose: Write 'data' to address 'loc' in the EEPROM
*/
void mtask_write_eeprom(int8 loc, data) {
while (EECON1_WREN); // wait until any current EEPROM write is finished
EEADRH = 0; // clear M EEADRH
EEADR = loc;
EEDATA = data;
EECON1_EEPGD = 0; // Point to DATA memory
EECON1_WREN = 1; // Enable writes
disable_interrupts(global); // Disable all interrupts
EECON2 = 0x55; //Write 55h
EECON2 = 0xAA; //Write AAh
EECON1_WR = 1; // Set WR to begin write
enable_interrupts(global); // Enable all interrupts
} // mtast_write_eeprom(int8 loc, data)
___________________________
This message was ported from CCS's old forum
Original Post ID: 144517327
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Thu Oct 09, 2003 7:21 pm     Reply with quote

This is just a standard write routine. He didn't use the CCS one because he wanted to control the interrupts. He posted the code. Take a look at it and you will find it very similar to the code that I gave you as well as that in the eeprom section of the datasheet for the pic.
future



Joined: 14 May 2004
Posts: 330

View user's profile Send private message

PostPosted: Fri Jun 18, 2004 11:04 pm     Reply with quote

I modified the routine a little and it does not use interrupts.
Called from main() it will write a complete structure to eeprom. Each time it writes a single byte and exit, if called before last write is done it will skip.

Code:
int1 eewrite;//flag set in my int_RDA by command to save ram to eeprom

#byte      EECON1 = 0xFA6
#define   WR            1
#define   WREN        2
#define   EEPGD       7

#inline
void service_eeprom_wr(void) {
    if(!bit_test(EECON1,WR)) {      // was last byte wrote?
        if(eewrite) {         // if 1, save next byte
        if(eecnt<sizeof(cfg)) {
        EEADR = eecnt;
        EEDATA = *(&cfg+eecnt);
        bit_clear(EECON1,EEPGD);      // Point to DATA memory
        bit_set(EECON1,WREN);      // Enable writes
        disable_interrupts(global);      // Disable all interrupts
        EECON2 = 0x55;      // Write 55h
        EECON2 = 0xAA;      // Write AAh
        bit_set(EECON1,WR);      // Set WR to begin write
        enable_interrupts(global);      // Enable all interrupts
                eecnt++;
                        } else { eewrite=0; }
                }
        }
}
tu



Joined: 23 Aug 2005
Posts: 4

View user's profile Send private message

PostPosted: Tue Aug 23, 2005 11:59 pm     Reply with quote

hi, interesting, is it also possible to do this with flash program memory ?
Ttelmah
Guest







PostPosted: Wed Aug 24, 2005 4:14 am     Reply with quote

tu wrote:
hi, interesting, is it also possible to do this with flash program memory ?

Whenever you change the program memory, instruction execution has to stop during the write. Hence you cannot gain anything here.

Best Wishes
dpechman



Joined: 04 Dec 2007
Posts: 43

View user's profile Send private message Visit poster's website

PostPosted: Wed Sep 16, 2015 11:57 am     Reply with quote

those tips works great with pic 16, but i am having problems to make it work with pic 18f26k22 and address 1024 bytes

i have changed the address to int16 and splited it to EEADR and EEADRH

here my changes:

Code:

void multitask_write_eeprom(int16 loc, data)
{
   EEADRH = make8(loc,1);
   EEADR  = make8(loc,0);
   EEDATA = data;
   EECON1_WREN = 1;
   disable_interrupts(global);
   EECON2 = 0x55;
   EECON2 = 0xaa;
   EECON1_WR = 1;
   enable_interrupts(global);
   while(eecon1_wren);
}



what am i doing wrong?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Sep 16, 2015 1:03 pm     Reply with quote

Look at these two #device statements in the CCS manual:
Quote:
WRITE_EEPROM=ASYNC
Prevents WRITE_EEPROM from hanging while writing is
taking place. When used, do not write to EEPROM from both
ISR and outside ISR.

WRITE_EEPROM = NOINT
Allows interrupts to occur while the write_eeprom() operations
is polling the done bit to check if the write operations has
completed. Can be used as long as no EEPROM operations
are performed during an ISR.
dpechman



Joined: 04 Dec 2007
Posts: 43

View user's profile Send private message Visit poster's website

PostPosted: Wed Sep 16, 2015 4:05 pm     Reply with quote

tks, the code is working, i was reading the wrong address... Very Happy
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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