This is the mail archive of the
ecos-discuss@sources.redhat.com
mailing list for the eCos project.
Re: flash v2 program problem
- From: Bart Veer <bartv at ecoscentric dot com>
- To: gruber dot m at utanet dot at
- Cc: ecos-discuss at sources dot redhat dot com
- Date: Fri, 1 Jul 2005 23:54:42 +0100 (BST)
- Subject: Re: [ECOS] flash v2 program problem
- References: <200507011523.14520.gruber.m@utanet.at>
>>>>> "Manfred" == Manfred Gruber <gruber.m@utanet.at> writes:
Manfred> I use flash_v2 branch and have a problem on program my
Manfred> device. I use a AM29LV256, 2 x 16 bit devices on a 32 bit
Manfred> bus . On testing I found out that Toggle Bit DQ6
Manfred> functionality fails sometimes on my hardware. I had done
Manfred> a quick dirty hack, with that it works. can someone tell
Manfred> me why?
Manfred> // Quick dirty hack
Manfred> do {
Manfred> current = addr[i];
Manfred> if ((current & AM29_STATUS_DQ7) == masked_datum) {
Manfred> break;
Manfred> }
Manfred> if (0 != (current & AM29_STATUS_DQ5)) {
Manfred> continue;
Manfred> }
Manfred> } while (retries-- > 0);
This code looks wrong. While a program operation is in progress DQ7
will be inverted relative to the value being programmed, DQ6 will
toggle, and DQ5 will remain clear unless there is a serious error. On
completion the value read back will be the same as the value
programmed, so DQ7 will now match and DQ6 will cease toggling. Things
get somewhat complicated when there are parallel devices which may
complete at different times. The test
if ((current & AM29_STATUS_DQ7) == masked_datum)
checks for completion: the DQ7 bits of all the chips match the
values being programmed. If one of the chips has finished but the
other is still busy then the test will fail. The next test,
if (0 != (current & AM29_STATUS_DQ5)) {
continue;
}
does not achieve anything useful. Usually DQ5 will be clear so the
test will fail and we just go around the loop again. If there is ever
a serious error and DQ5 gets set, we just continue around the loop
again. You are no longer testing for errors, only for completion.
Now for the original:
Manfred> do {
Manfred> current = addr[i];
Manfred> if ((current & AM29_STATUS_DQ7) == masked_datum) {
Manfred> break;
Manfred> }
Manfred> if (0 != (current & AM29_STATUS_DQ5)) {
Manfred> current2 = addr[i];
--> Sometimes my devices fail here ....
Manfred> if ((((current ^ current2) & AM29_STATUS_DQ6) >> 1) & current) {
Manfred> block_start[AM29_OFFSET_COMMAND] = AM29_COMMAND_RESET;
Manfred> return;
Manfred> }
Manfred> }
Manfred> } while (retries-- > 0);
Manfred> #endif
The DQ7 test again checks for completion. The DQ5 test can trigger in
two situations: either there is a real error, or one of the chips has
completed before the other and the value being written happens to have
bit 5 set. If a chip is still busy programming then DQ6 will be
toggling, so bit 6 of current and current2 will be different. The
expression "(current ^ current2)" detects changing bits, masking with
DQ6 means we are only interested in that bit toggling, the ">> 1"
moves to DQ5, and finally "& current" gives us the error condition.
There are actually three cases:
1) both current and current2 were read while the chip was busy
programming. DQ6 will have toggled. If DQ5 is set then we have an
error.
2) current was read while the chip was busy toggling but current2 was
read after completion. DQ6 may or may not have toggled depending on
the value being written. But if DQ5 was set in current then there
was an error.
3) both current and current2 were read after completion so DQ6 will
have stopped toggling and (current ^ current2) always evaluates to
0. Hence the "if" test fails and we go around the loop again.
Manfred> for example it fails with this values:
Manfred> am29xxxxx_hw_programm:
Manfred> current 0xff847abf
Manfred> current2 0xffc45a5a
Manfred> AM_STATUS 400040
Manfred> ((((current ^ current2) & AM29_STATUS_DQ6) >> 1) & current) --> 200020
Looking at the top 16 bits first we have (with ? == don't care):
current ???????? 10000100
current2 ???????? 11000100
so DQ6 is toggling, i.e. the chip is still busy, DQ5 is clear
indicating no error, and presumably the value being written has bit 7
clear so it is currently being read inverted as 1. This is all as
expected.
Now for the bottom 16 bits:
current ???????? 10111111
current2 ???????? 01011010
This does not make a whole lot of sense. DQ7 has changed, so
programming cannot have completed before current was read. Instead it
looks like programming was still in progress when current was read but
had completed for current2. The value being written to these 16 bits
must have been 0x5a5a.
Current has DQ5 set indicating an error. In theory this can happen
when trying to program a 0 back to a 1, but at the start of the
am29_hw_program() loop there is a mask operation to prevent this. The
only other circumstance I know of under which DQ5 can be set is if the
chip has an internal timeout, which is pretty much a fatal error
condition. If so then DQ5 should continue reading back as 1 until
there is a reset command. However current2 has DQ5 clear, yet there
has not been a reset command.
Manfred> I tried to use the toggle bit algorithm from my am29lv256
Manfred> documentation, but without sucess. maybe some flash_v2
Manfred> developer has a mor information for me what goes wrong?
AFAIK the driver code is correct. I do not see how a standard am29
chip can give these results.
Bart
--
Bart Veer eCos Configuration Architect
http://www.ecoscentric.com/ The eCos and RedBoot experts
--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss