View previous topic :: View next topic |
Author |
Message |
Guest
|
write_eeprom and interrupts |
Posted: Mon Jan 26, 2004 4:56 am |
|
|
I'm using PCW3.178 and 18F458.
In my application INT_TIMER0 controls the multiplexing of
a 3-digit LED display, INT_RDA the incoming RS232 chars.
The program on the F458, after the power-up, displays
a startup message on the LED display, then send two times
the same information via RS232 and becomes operating
changing in the same time the displayed message.
One implemented feature allows to dowload from
a PC a set of parameters to be written into the EEPROM.
Such a "write parameters" routine is separated into two
blocks: the first-one receives the parameters from the
serial port and writes them into a RAM vector; the
second-one transfers the RAM content to the eeprom,
simply with a for-loop.
Sometimes (1 of 5) the write parameters routine fails:
the 18F458 reset itself, displays the startup
message, send one time only the message over RS232
and then remain hanged. What I can see is that the
INT_TIMER0 continue to work (the display is correctly
multiplexed).
INT_TIMER0 period is about 1.64ms.
Restarting the board, I can see that what has failed is the
write_eeprom: reading back the eeprom, at least one
location is corrupted (0xFF value).
Well, I tried to disable the interrupts before each
write_eeprom call and re-enable it after each-one:
it seems to fix the problem, never more problems.
I know the write_eeprom has inside the global interrupts
disabling, so adding a disable_interrupts(GLOBAL)
should not change the substance, but something
happened.
For example the LED display flickering during the eeprom
writing (about 40 locations) changes a lot. The flickering
can be explained by the interruptions on the multiplexing
due to the write eeprom times (~5ms versus the 1.64ms
of the mux time).
Before the fix there was a sort of indefinite visual shot,
something like an interruption in the multiplexing but very
short;
after the fix, there is some tenth of second of fickering
of all digits in the same way but not at the same time,
that seems more reasonable thinking that the write
parameter procedure takes 40x5ms = 200ms, more
or less.
What of different? The first, and for the moment unique,
thing is that in the disable_interrupts(GLOBAL)
.................... disable_interrupts(GLOBAL);
03E0: NOP(FFFF)
03E2: BCF FF2.6
03E4: BCF FF2.7 <-------
03E6: BTFSC FF2.7
03E8: GOTO 03E4
when the global bit is reset the program waits until
it is effectively reset (why?).
The write_eeprom has inside such a bit reset, but not
the following waiting loop
.................... write_eeprom(add, data);
0BCA: CLRF FAA
0BCC: MOVFF 18F,FA9
0BD0: MOVFF 190,FA8
0BD4: BCF FA6.6
0BD6: BCF FA6.7
0BD8: BSF FA6.2
0BDA: MOVF FF2,W
0BDC: MOVWF 00
0BDE: BCF FF2.7 <-----
0BE0: MOVLB F
0BE2: MOVLW 55
0BE4: MOVWF FA7
0BE6: MOVLW AA
0BE8: MOVWF FA7
0BEA: BSF FA6.1
0BEC: BTFSC FA6.1
0BEE: GOTO 0BEC
0BF2: BCF FA6.2
0BF4: MOVF 00,W
0BF6: IORWF FF2,F
Does someone know something more about that?
Thanks a lot
Fabio |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Mon Jan 26, 2004 7:52 am |
|
|
What would happen if an interrupt occurred while disabling the interrupts? Maybe it is possible that the interrupt would get serviced. However, the return from interrupt would set the bit back which is not what the user wanted. Maybe this is why but it is only my guess |
|
|
FabioPIC
Joined: 26 Jan 2004 Posts: 11
|
|
Posted: Mon Jan 26, 2004 9:16 am |
|
|
It could be, but in that case why Microchip suggests such a
way for eeprom writing (the same implemented by CCS)?
---
[/img] |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Mon Jan 26, 2004 9:29 am |
|
|
The disabling in the eeprom write routine is just to prevent anything from happening during the 55 AA WR part of the routine. The chance of 2 interrupts occurring so close together and one occuring on the disable instruction is very slim but it would still be possible in which case there would be an error. |
|
|
FabioPIC
Joined: 26 Jan 2004 Posts: 11
|
|
Posted: Tue Jan 27, 2004 2:33 am |
|
|
So, the question is: is the simple BCF FF2.7 "enough" or
we need instead
03E4: BCF FF2.7
03E6: BTFSC FF2.7
03E8: GOTO 03E4
?
If the simple bit clear is enough, why CCS implemented the
above bit test loop? Could it happen the bit doesn't get cleared
at the first attempt? Why? In that case, what could happen in the
write_eeprom when an interrupt occur, so bad to perform a
processor reset? |
|
|
Aart Guest
|
Eeprom Write |
Posted: Tue Jan 27, 2004 6:50 am |
|
|
Here is some code I wrote after running into a similar problem. This was a while ago but this is what I can remember:
The CCS code disables the global interrupt while its waiting for the write cycle to complete - waste.
void v_WrEemByte(int16 i16Addr, int8 i8Dat)
{
while (wr); //keep it here till finished (write flag) - other interrupts can still happen
EECON1 = 0x00;
EEADRH = make8(i16Addr,1);
EEADR = make8(i16Addr,0);
EEDATA = i8Dat;
wren = 1;
//the following sequence is defined in the documentation
disable_interrupts(global);
EECON2 = 0x55;
EECON2 = 0xAA;
wr = 1;
enable_interrupts(global);
}
//-------------------------------------
Aart |
|
|
FabioPIC
Joined: 26 Jan 2004 Posts: 11
|
|
Posted: Tue Jan 27, 2004 10:20 am |
|
|
OK Aart, so both we had the same problem and both found
the same solution (the CCS disable_interrupts(global)).
Still open my previous question about the loop necessity
to clear the GIE bit: where CCS did get the idea from?
---
Fabio |
|
|
Gerrit
Joined: 15 Sep 2003 Posts: 58
|
|
Posted: Tue Jan 27, 2004 12:29 pm |
|
|
FabioPIC,
CCS (and other) use this techniek to be sure the interupt is disabled.
Explanation:
When an interupt appears it will finisch the command that it is working
on and than serve the interrupt.
If the line disable interupt is running and an interrupt appears it will
finisch the disable interrupt and jumps to the interrupt, however you
cleared the global interrupt.
After the interrupt is finisched the interrupt will restore the global interupt
flag. and goto the line after you disabled the interrupt ( with no gloabal
interrupt disabled).
By checking for the global interrupt flag after you cleared it, you are
sure that it is disabled else there was an interrupt when you wanted to
disable it.
I hope I have explained you a little bit in my simple englisch?
Regards,
Gerrit |
|
|
FabioPIC
Joined: 26 Jan 2004 Posts: 11
|
|
Posted: Tue Jan 27, 2004 1:09 pm |
|
|
Hi Gerrit, and thanks for your explaination.
If what you say is correct, what Microchip suggest on the
data sheet about the write eeprom is wrong: they cannot
assure no interrupts will come during eeprom writing time
(several milliseconds) ... well, I suppose they want to do that.
Isn't it?
Fabio |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Tue Jan 27, 2004 2:08 pm |
|
|
Doesn't matter about the write time. They don't want any extra cycles between the 55 & AA sequence. |
|
|
Guest
|
|
Posted: Fri Feb 06, 2004 6:49 am |
|
|
Hi,
To be able to write to EEPROM you need to go through a special sequence. (standard procedure with a lot of EEPROM and flash devices) While executing that sequence, possible interrupts can have the effect that the code will execute but the EEPROM write action does not happen. Note you only have to disable the interupts for a couple of intructions - not the complete 4-5mS it takes to do the EEPROM write.
Aart |
|
|
FabioPIC
Joined: 26 Jan 2004 Posts: 11
|
|
Posted: Fri Feb 06, 2004 12:27 pm |
|
|
Hi Aart,
in your first reply you said you had a problem similar
to mine, and you solved it writing your own write_eeprom
code. The difference I can see between your code and the CCS's
one is the disable_interrupts(global) in place of the simple
GIE bit clear (you eliminated the wait for end of writing, but
this is not relevant for the case ... I suppose).
Have I understod correctly your first answer?
If yes, how the disable_interrupts(global) fixed the
problem we had?
Fabio |
|
|
|