EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Does MAM settings affect IAP flash programming? (long)

Started by jayasooriah July 29, 2006
Hello,

Many have reported (some in this forum) unexplained crashes upon
invoking IAP call to erase flash. While experimenting with MAM
statistical registers on LPC2292, I believe I have stumbled on an
explanation.

The explanation requires a basic understanding of how MAM and FLASH
controller works. Although much of the information "Philips
Confidential" (and one needs Area 51 access to be able to conduct the
experiments I did) there are sufficient details already in the public
domain based on which the results can be interpreted.

Philips will not published details relating to MAM or flash
controller. I will try explain the specific problem in relation to my
experiments without going into Area 51.

For a good description of MAM internals, see Section 3.5 of Hitex
Insider Guide to Philips ARM7 Based Microcontollers by Trevor Martin.

While is no mention of any MAM bugs in latest errata for LPC2292
(version 2.1 dated 17-may-2006), the description of "MAM.1" bug in
errata for other variants like the LPC2146 is relevant.

The problem is stated as:


If code is running from on-chip Flash, a write to an SRAM location
followed by an immediate read from the same SRAM location corrupts the
data been read...


The solution is stated as:


User code should enable the MAM after Reset and before any RAM accesses...


This begs two salient questions:

Q1: What has MAM has got do with RAM accesses when it serves to
"provides accelerated execution from the on-chip flash at higher
frequencies".

Q2: Is MAM really disabled upon reset, or when MAMCR is set to zero?
Alternatively, does MAM affect memory accesses in the disabled state?
If so, how?

I crafted an experiment to demonstrate the issues. The code snippet
below is the core that does the following:

1/ start MAM statistics collection
2/ write the ERASE commend to flash controller
3/ wait for a given clock ticks using timer #1
4/ capture flash status register and memory
5/ freeze MAM statistical registers

> // start statistics
> _MAMS.ctrl = _MAMS_SRST | _MAMS_CODE | _MAMS_DATA;
>
> // issue command
> _LPC[6] = cmd;
>
> // delay before capture
> clk = _TIMER1.tc;
> while ((int) (_TIMER1.tc - clk) < del)
> ;
>
> // capture into buffer
> do
> {
> *--sp = _LPC[6];
> *--dp = *mp;
> } while (sp > sbuf);
>
> // freeze statistics
> _MAMS.ctrl = 0;

A dry run of the experiment yields the following:

R1:
> MAM 00000002 00000003
> DEL 00000000
> CMD 00
> OFF 00000000 00 28
> MEM 00000000 28
> FAC 00000001

The above indicate MAMCR = 2; MAMTIM = 3 (CLK = 14.7456 MHZ, PLL x4), 0 delay wait, null command (does not do anything, first capture
of flash register and memory is 0x00 and 0x28, respectively, memory
location captured is 0, and its final value is also 0x28, and the
flash access counter indicates only 1 access to memory was made for
even though the loop reads this location for 4K times.

When we run the same with MAM disabled in default state, we get what
we expect:

R2:
> MAM 00000000 00000007
> DEL 00000000
> CMD 00
> OFF 00000000 00 28
> MEM 00000000 28
> FAC 00001000

The flash memory access counter indicates MAM was not caching access
to flash.

If we now use the flash erase command (0x02), and wait for 500 ms, we
get the following which is as expected:

R3:
> MAM 00000002 00000003
> DEL 01c20000
> CMD 02
> OFF 00000000 00 28
> MEM 00000000 28
> FAC 00000001

Note that nothing is unusual, and that by the time we started reading
memory, the flash controller was ready. Lets look at what happens if
we tried to read the flash without waiting, when the flash controller
is busy:

R4:
> MAM 00000002 00000003
> DEL 00000000
> CMD 02
> OFF 00000000 02 ff
> OFF 00000001 00 ff
> MEM 00000000 ff
> FAC 00000001

Notice that the first read of the flash controller returned 0x02
meaning it was busy, and the read to memory returned 0xff instead of
0x28 because it was busy.

However, this caused the flash controller somehow to return a not busy
on the next read, while the memory still reads 0xff. Also, when we
wait for the full time it takes for the erase operation to complete
and read memory, it still shows up as 0xff, not 0x28. This is even
after the MAM is disabled.

Q3: Why is memory location zero reading 0xff and not 0x28 long after
the flash erase operation was complete?

Before we try to answer this and above questions, lets look at what
happens when we use a different delay parameter:

R5:
> MAM 00000002 00000003
> DEL 00000300
> CMD 02
> OFF 00000000 02 00
> OFF 00000020 02 ff
> OFF 00000026 00 ff
> MEM 00000000 ff
> FAC 00000001

Note that after we wait for about 5 usec (768+ cycles at 58.99 MHz),
the memory reads 0x00 when flash is busy, on the 32nd read changes to
0xff, and on the 40th read the flash controller becomes ready prematurely.

Still, the value of this location returns 0xff no matter what so long
as this bad value is stored in MAM buffers, and it does not matter
that we have disabled MAM when we are checking it and printing it on
the MEM line.

Q4: What value is returned when the FLASH is read while it is busy?

Q5: Does reading FLASH while it is busy affect flash operation in
progress?

What happens if MAM is disabled? Here is the result:

R6:
> MAM 00000000 00000007
> DEL 00000300
> CMD 02
> OFF 00000000 02 00
> OFF 0000001c 02 ff
> OFF 00000021 00 ff
> MEM 00000000 ff
> FAC 00001000

Note that the FAC indicates we have disabled MAM, the change in
offsets where we got 0x00 and 0xff changes as expected. However, note
that the caching effect of MEM is still there -- after the erase
operation is complete, the memory location still reads 0xff when it
should read 0x00. This begs the question of whether or not the MAM is
really disabled when MAMCR is zero.

Q6: Does setting MAMCR to zero disable MAM?

We do another experiment and change MAMTIM to what it would have been
when it was enabled to see if MAMTIM has any effect with MAMCR set to
disable MAM.

R7:
> MAM 00000000 00000003
> DEL 00000300
> CMD 02
> OFF 00000000 02 00
> OFF 00000020 02 ff
> OFF 00000026 00 ff
> MEM 00000000 ff
> FAC 00001000

Note that when MAM is disabled, with MAMTIM set to the value when it
was enabled, we get *exactly* the same results for memory reads, even
though MAM statistical register (FAC line) tells us that all accesses
were made direct to flash.

This last observation makes sense, considering the MAM.1 bug on some
of the devices (does this apply to LPC2292 too?) in that even though
MAM is disabled, MAMTIM value affects memory accesses in the same way
as if MAM was enabled, plus in the case of some parts, this also
affects access to RAM when it should not.

How do the findings and possible answers to the questions raised above
explain the unexplained crashes when IAP call is invoked to erase
flash? Here are my propositions as to what is happening.

P1: MAM controller makes accesses to FLASH as part of its pre-fetch
heuristics.

P2: When such an access to flash is made while erase operation is in
progress, this results in two problems: a) the erase operation is
prematurely terminated; and b) a bad value for pre-fetch is latched in
MAM buffers.

P3: When program accesses this memory location immediately on
returning to FLASH after doing the in-RAM flash erase wait, this bad
value is executed as an instruction resulting in "crash".

The above propositions IMO explain in relation to IAP erase calls, why:

a) it does not do the erase, and you need to do a blank check after
erase to be sure; and

b) call does not return and results in the application crashing.

As my code uses information from Area 51 in relation to MAM
statistical registers, I will not make this code public. However if
you can convince me you know something about MAM that is not public
knowledge (for example address of any of the statistical registers) I
would be happy to provide you with the full source and Makefile so
that you can conduct these experiments yourself to see if you can find
out something more that I have missed out.

Meanwhile, the news is not good for LPC users in that MAM is not what
it is made out to be -- it cannot be disabled fully and has nasty side
effects when it comes to flash write or erase operations.

You only hit this problem if it so happens that the bad value in MAM
buffers is used, and it is not clear how you can flush the MAM buffers
without knowing how exactly it is causing these problems.

Jaya

An Engineer's Guide to the LPC2100 Series

Hi Jaya,
I have two points you don't mention which might be relevent
to others understanding all the issues. My points come from
reading public information which might disagree with
the private information you have from Philips.
But the real answer is from the genuine measurements that
you are doing.

1) To fully disable the MAM on LPC2294 it is necessary to
set MAMTIM to one clock as well as MAM Mode to 0
according to the LPC2294 user manual:
> The MAM actually uses latched data if it is available,
> but mimics the timing of a Flash read operation.
> This saves power while resulting in the same execution
> timing. The MAM can truly be turned off by setting
> the fetch timing value in MAMTIM to one clock

2) The MAM on LPC214x is probably different from LPC2294
because on the LPC2148 it is a single 128-bit wide bank
(User Manual figure 12) but on LPC2294 it is two banks
(User Manual figure 18).
This makes it credible that MAM.1 was new for the
single-bank parts (consistent with the published errata).

Regards,
Danish
--- In l..., "Danish Ali" wrote:

> 1) To fully disable the MAM on LPC2294 it is necessary to
> set MAMTIM to one clock as well as MAM Mode to 0
> according to the LPC2294 user manual:
> > The MAM actually uses latched data if it is available,
> > but mimics the timing of a Flash read operation.
> > This saves power while resulting in the same execution
> > timing. The MAM can truly be turned off by setting
> > the fetch timing value in MAMTIM to one clock

I cannot seem to find this in my copies LPC2292/2294 DS or UM. Which
version are you looking at? Does this apply to LPC2292?

Not withstanding the above, comparing OFF lines in R5 and R7 shows
that timing with MAM enabled and disabled is identical.

I did a further experiment. repeating the last one with disabling MAM
as suggested above. The final value still remains 0xff.

I know how to flush it out but my question is what minimal operations
are necessary to do this.

This may be the cause of some nasty problems that has been reported:
boot loader corrupted after writes, opening debug window over system
registers leads to parts becoming unusable; flash writes failing
requiring blank checks; and flash writes causing application to crash.

> 2) The MAM on LPC214x is probably different from LPC2294
> because on the LPC2148 it is a single 128-bit wide bank
> (User Manual figure 12) but on LPC2294 it is two banks
> (User Manual figure 18).
> This makes it credible that MAM.1 was new for the
> single-bank parts (consistent with the published errata).

AFAIK single or dual bank only affects only interleaving. In both
cases it is logically 128-bit wide flash through MAM buffers.

Yes while MAM.1 bug may be peculiar to organisation, that does not
explain how it can affect RAM access given MAM has nothing to do at
all with access path to SRAM. Or does it?

Jaya
Thanks to Danish's posting on how to disable MAM fully on LPC2294, I
tried the same on LPC2292 and this produced a useful outcome:

If you disable MAM fully by setting MAMCR to 0 *and* setting MAMTIM to
1, MAM will not cause bad data to be returned from its buffers as a
result of reads to FLASH while it is locked out during the erase or
write operation.

This is evident from looking at the last two results, R8 and R8. I
have attached the full set for completeness.

Hence my advice to all is that whether or not this MAM bug is
documented for your part, it is better to disable MAM using the method
above before you attempt firmware updates.

Jaya

R1:
> MAM 00000002 00000003
> DEL 00000000
> CMD 00
> OFF 00000000 00 28
> MEM 00000000 28
> FAC 00000001

R2:
> MAM 00000000 00000007
> DEL 00000000
> CMD 00
> OFF 00000000 00 28
> MEM 00000000 28
> FAC 00001000

R3:
> MAM 00000002 00000003
> DEL 01c20000
> CMD 02
> OFF 00000000 00 28
> MEM 00000000 28
> FAC 00000001

R4:
> MAM 00000002 00000003
> DEL 00000000
> CMD 02
> OFF 00000000 02 ff
> OFF 00000001 00 ff
> MEM 00000000 ff
> FAC 00000001

R4:
> MAM 00000002 00000003
> DEL 00000300
> CMD 02
> OFF 00000000 02 00
> OFF 00000020 02 ff
> OFF 00000027 00 ff
> MEM 00000000 ff
> FAC 00000001

R6:
> MAM 00000000 00000007
> DEL 00000300
> CMD 02
> OFF 00000000 02 00
> OFF 0000001c 02 ff
> OFF 00000022 00 ff
> MEM 00000000 ff
> FAC 00001000

R7:
> MAM 00000000 00000003
> DEL 00000300
> CMD 02
> OFF 00000000 02 00
> OFF 00000020 02 ff
> OFF 00000027 00 ff
> MEM 00000000 ff
> FAC 00001000

R8:
> MAM 00000000 00000001
> DEL 00000300
> CMD 02
> OFF 00000000 02 00
> MEM 00000000 28
> FAC 00000000

R9:
> MAM 00000000 00000001
> DEL 00000000
> CMD 02
> OFF 00000000 02 00
> OFF 00000001 00 ff
> OFF 0000000d 00 00
> MEM 00000000 28
> FAC 00000000
Hi Jaya,
That quote was from the LPC2119/2129/2194/2292/2294 USER MANUAL
Preliminary 2004 May 03 on the bottom of page 92.
Regards,
Danish
--- In l..., "jayasooriah" wrote:
>
> --- In l..., "Danish Ali" wrote:
>
> > 1) To fully disable the MAM on LPC2294 it is necessary to
> > set MAMTIM to one clock as well as MAM Mode to 0
> > according to the LPC2294 user manual:
> > > The MAM actually uses latched data if it is available,
> > > but mimics the timing of a Flash read operation.
> > > This saves power while resulting in the same execution
> > > timing. The MAM can truly be turned off by setting
> > > the fetch timing value in MAMTIM to one clock
>
> I cannot seem to find this in my copies LPC2292/2294 DS or UM. Which
> version are you looking at? Does this apply to LPC2292?
--- In l..., "Danish Ali" wrote:

> That quote was from the LPC2119/2129/2194/2292/2294 USER MANUAL
> Preliminary 2004 May 03 on the bottom of page 92.
> Regards,

Thanks, I found it. This foot note for MAM off case clearly states
that while data may be returned from latches, it still "mimics timing
of a Flash read operation".

I did a variant of the same experiment, reading the same location in
FLASH 4K times and timing how long it takes. The results show it does
not mimic timing of FLASH read operations either:

> MAM 00000000 00000003
> CLK 0000c011
> FAC 00001000

> MAM 00000000 00000007
> CLK 00010011
> FAC 00001000

So clearly even with MAMCR set to zero, changing MAMTIM from 3 to 7
does make a difference to how many clock ticks it takes for the same
loop. I would like to know if this is a generic LPC problem or
something specific to LPC2292

One wonders what disabling MAM means other than showing pretend flash
access counts in the MAM statistical registers.

This explains why information about MAM statistical registers and
FLASH memory controller are not released to end users.

Jaya

The 2024 Embedded Online Conference