View previous topic :: View next topic |
Author |
Message |
Will Reeve Guest
|
Multitasking a EEPROM write using the eeprom interrupt? |
Posted: Thu Aug 21, 2003 3:41 am |
|
|
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
|
Re: Multitasking a EEPROM write using the eeprom interrupt? |
Posted: Thu Aug 21, 2003 8:51 am |
|
|
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? |
Posted: Wed Aug 27, 2003 9:24 am |
|
|
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
|
Re: Multitasking a EEPROM write using the eeprom interrupt? |
Posted: Thu Oct 09, 2003 6:32 pm |
|
|
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
|
|
Posted: Thu Oct 09, 2003 7:21 pm |
|
|
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
|
|
Posted: Fri Jun 18, 2004 11:04 pm |
|
|
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
|
|
Posted: Tue Aug 23, 2005 11:59 pm |
|
|
hi, interesting, is it also possible to do this with flash program memory ? |
|
|
Ttelmah Guest
|
|
Posted: Wed Aug 24, 2005 4:14 am |
|
|
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
|
|
Posted: Wed Sep 16, 2015 11:57 am |
|
|
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
|
|
Posted: Wed Sep 16, 2015 1:03 pm |
|
|
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
|
|
Posted: Wed Sep 16, 2015 4:05 pm |
|
|
tks, the code is working, i was reading the wrong address... |
|
|
|