This is the mail archive of the ecos-discuss@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: flash v2 program problem


>>>>> "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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]