2008-10-11 11:04:36     flash write with interrupts

Document created by Aaronwu Employee on Sep 18, 2013
Version 1Show Document
  • View in full screen mode

2008-10-11 11:04:36     flash write with interrupts

Phil Wilshire (UNITED STATES)

Message: 63476   

 

Hi,

 

I am investigating running u-boot with interrupts running in the background .

 

With the latest version 2008R1.5 things are starting to work thanks to preemption now being enabled.

 

 

 

I expected some problems and found one with flash write.

 

 

 

The flash erase seemed to work but when attempting to write to the erased flash the function

 

flash_write_cfiword would incorrectly detect data other than  FFFF in the destination word.

 

With no interrupts all is OK. As soon as the interrupts are turned on I get these failures.

 

 

 

Having looked at quite a few different things

 

I decided to add "volatile" to the destination pointer as follows.

 

(In flash_write_cfiword in drivers/cfi_flash.c )

 

 

 

   volatile  cfiptr_t cptr;

 

The incorrect data from the destination flash went away. And flash writes started to work.

 

I have not looked in detail at the compiler output yet but I am interested in any comments on

 

what I have found. I dont quite understand it yet.

 

 

 

TIA Phil Wilshire

 

 

QuoteReplyEditDelete

 

 

2008-10-11 11:59:55     Re: flash write with interrupts

Mike Frysinger (UNITED STATES)

Message: 63479   

 

gcc (correctly) assumes that things are single threaded.  if you violate that assumption (by making the flash code threaded via interrupts), then you must mark shared data accordingly (like volatile).

QuoteReplyEditDelete

 

 

2008-10-11 22:02:05     Re: flash write with interrupts

Phil Wilshire (UNITED STATES)

Message: 63484   

 

Hi Mike,

If I shared the data I would understand.

In this case the data was not shared at all by the interrupt service routine.

The isr was working with a different data set altogether.

The only thing I can think of is a possibly missed register save / restore but I doubt it.

I am using the standard macro from the system.h header file.

The access to the flash data is via a union.

 

The volatile, I assume, forced a reread of the actual flash data.

I will, I think, have to take a deeper look at the assembler output.

 

The flash write failure, with the interrupt turned on, happened on a write after an  erase, and also when simply writing to that flash area after a few seconds delay after a  previous erase plus write attempt.

It would normally fail on the first word but not always.

I do, sometimes, get fkash write timeouts but I suspect some other problem there.

 

 

Checking the flash area showed that it was erased.

The system works, of course, 100% with no interrupts enabled.

 

Regards

   Phil

QuoteReplyEditDelete

 

 

2008-10-11 22:14:09     Re: flash write with interrupts

Mike Frysinger (UNITED STATES)

Message: 63485   

 

i'm not sure how well tested the save/restore macros are seeing as how the current u-boot doesnt use them at all (other than to push a set onto the stack to display) ... i would hook up jtag, and do a register file dump at the start of the ISR and at the end of the ISR to make sure everything was restored properly

QuoteReplyEditDelete

 

 

2008-10-11 23:16:33     Re: flash write with interrupts

Phil Wilshire (UNITED STATES)

Message: 63486   

 

Mike,

 

Here's a slight clue In the non volatile system we get this

 

info is in r0 and dest in r1 I presume

 

.type _flash_write_cfiword, STT_FUNC;

_flash_write_cfiword:

.LFB62:

        .loc 1 1253 0

.LVL90:

.LVL91:

.LVL92:

        [--sp] = ( r7:6 );

 

.LCFI38:

        [--SP] = P3;

.LCFI39:

        [--SP] = P4;

.LCFI40:

        P4 = R0;

        [--SP] = RETS; 

.LCFI41:

        SP += -16;

 

.LCFI42:

 

       .loc 1 1253 0

 

     [SP+44] = R2;

 

    P3 = R1;

 

 

[... stuff missing ...]

 

.LVL96:

.L170:

.LVL97:

        .loc 1 1268 0

        R1 = W [P3] (X);   << P3 used here to check for word erased

        R1 = R1 & R6;

        R0 = R6.L (Z);

        R1 = R1.L (Z);

        jump.s .L199;

 

 

Note the change in the system using volatile.

 

.type _flash_write_cfiword, STT_FUNC;

_flash_write_cfiword:

.LFB62:

        .loc 1 1253 0

.LVL90:

.LVL91:

.LVL92:

        [--sp] = ( r7:5 );

 

.LCFI38:

        [--SP] = P4;

.LCFI39:

        P4 = R0;

        [--SP] = RETS;

.LCFI40:

        SP += -20;

.LCFI41:

        .loc 1 1253 0

        [SP+48] = R2;

        R5 = R1;

.LBB146:

.LBB147:

        .loc 1 223 0

        R0 = B [P4+367] (Z);

.LBE147:

.LBE146:

        .loc 1 1263 0

        cc =R0==2;

        .loc 1 1253 0

        R6 = [SP+48];

        R7 = [SP+52];

        .loc 1 1259 0

        [SP+16] = R1;    << R1 saved here !!

        .loc 1 1263 0

        if cc jump .L170;

.LVL93:

 

[ ... stuff missing ...]

 

.LVL97:

.L170:

.LVL98:

        .loc 1 1268 0

        P2 = [SP+16];    < R1 recovered into P2 here

        R0 = R6.L (Z);

        R1 = W [P2] (X);

        R1 = R1 & R6;   << erase test

        R1 = R1.L (Z);

        jump.s .L199;

 

 

 

There was a slight difference in the volatile code

 

the flash address was carried in P3 for the non volatile code and saved on the

 

stack [SP+16] for the volatile code.

 

I cannot yet see anything obvious to explain the diference in behavior.

 

the save / restore macros in entry.h look just fine.

 

I assume that the register save

 

[sp--] =(R7:0, P5:0)

 

is matched by

 

(R7:0,P5:0) = [sp++];

 

 

 

My wrapper for the c function called by evt12 is this

 

        /* evt12 entry point  */

ENTRY(_evt_12)

        SAVE_ALL_SYS

        r0 = sp;        /* stack frame pt_regs pointer argument ==> r0 */

        sp += -12;

        call _bfin_evt12;

        sp += 12;

        RESTORE_ALL_SYS

        rti;

ENDPROC(_evt_12)

 

 

And bfin_evt12 just toggles a gpio and looks at timers.

 

So I guess its JTAG time.

 

 

 

  Phil

 

 

 

 

 

 

 

 

QuoteReplyEditDelete

 

 

2008-10-13 16:21:06     Re: flash write with interrupts

Phil Wilshire (UNITED STATES)

Message: 63583   

 

More information.

 

As I feared the use of the volatile statement only masked the situation.

 

The base u-boot timing has been moved to timer 3 to allow a high speed low latency core timer interrupt to execute.  In general, the new timer source is working but we are still testing it.

 

I am are seeing about 1 - 1.5 uSecs worst case latency with a typical latency of about 0.5 microseconds on a core timer interrupt which is excellent.

 

Sadly, the flash write error has come back in spades with the core timer running fast (every 60 uSecs).

 

I have added some debug to cfi_flash.c

 

Dest not erased dest 2010020a dest val 40 write val 4a

Dest not erased dest 20100366 dest val c0 write val 4c

Dest not erased dest 2010037e dest val 40 write val 18

 

This looks to me like the flash is in status mode.

 

Multiple write attempts will eventually correcty

 

A memory dump of the flash area shows the expected FFFF data.

 

This error occurs with both a combined erase and write and with individual write

 

up2 will upload a file, erase the flash and then write to the flash.

 

up2w simply repeats the flash write.

 

Here are the two env commands.

 

print up2                                                         

up2=tftpboot $(loadaddr) $(ubootfile);protect off 0x20100000 0x2013FFFF;erase 0

x20100000 0x2013FFFF;cp.b $(loadaddr) 0x20100000 $(filesize)

 

print up2w                                                        

up2w=cp.b $(loadaddr) 0x20100000 $(filesize)

 

After the data has been copied to flash a compare of sdram and flash is just fine

 

cmp.b $(loadaddr) 0x20100000 $(filesize)

 

I'll still keep looking.

 

  Phil

 

 

 

 

 

 

 

QuoteReplyEditDelete

 

 

2008-10-14 10:19:24     Re: flash write with interrupts

Robin Getz (UNITED STATES)

Message: 63653   

 

Phil:

 

I expect this is becuase reads on the Blackfin are speculative - and the U-Boot code does not work around this "feature", like the kernel does. for a more detailed description, see:

 

See blackfin/trunk/uClinux-dist/linux-2.6.x/arch/blackfin/lib/ins.S

 

-Robin

QuoteReplyEditDelete

 

 

2008-10-14 12:47:37     Re: flash write with interrupts

Phil Wilshire (UNITED STATES)

Message: 63660   

 

Hi Robin,

 

Thanks for the suggestion.

 

I had a suspicion that this may be some of the problem.

 

 

 

So we should protect the access to flash with  a cli /sti  . I did this to no avail.

 

==============================================

 

static int flash_write_cfiword (flash_info_t * info, ulong dest,

                                cfiword_t cword)

{

        cfiptr_t ctladdr;

        cfiptr_t cptr;

        int flag;

        unsigned long flags;

        volatile unsigned short tword;

 

        ctladdr.cp = flash_make_addr (info, 0, 0);

        local_irq_save(flags);     

        SSYNC();

        cptr.cp = (uchar *) dest;

        tword = *(unsigned short *) dest;

 

        /* Check if Flash is (sufficiently) erased */

        switch (info->portwidth) {

 

        case FLASH_CFI_16BIT:

                flag = ((cptr.wp[0] & cword.w) == cword.w);

                break;

 

        default:

                return 2;

        }

 

        local_irq_restore(flags);     

 

        if (!flag) {

                printf(" Flash error addr %p dest %x write %x flags %x tw %x\n"

                       , dest, cptr.cp[0], cword.c, flags , tword);

                return 2;

        }

======================================================

 

What is odd is that the first read access to flash fails. It is as if the flash

 

is in command mode.

 

 

 

I am doing a little work in the core timer service routine but not much.

 

Once the flash is written a memory compare between sdram and flash passes.

 

Still thinking

 

   Phil

 

 

 

 

 

QuoteReplyEditDelete

 

 

2008-10-14 17:20:56     Re: flash write with interrupts

Mike Frysinger (UNITED STATES)

Message: 63668   

 

perhaps it'd be useful to track every instruction that gets interrupted.  take a chunk of L1 data and in your interrupt entry point after saving all the registers, stick the interrupted PC there (RETI).  let the first word be the index into the array of actual saved PC values ...

QuoteReplyEditDelete

 

 

2008-10-15 06:15:42     Re: flash write with interrupts

Phil Wilshire (UNITED STATES)

Message: 63716   

 

Robin,

 

Do the Blackfin speculative reads affect MMRs or just the external bus ?

 

Am I correct in thinking that this sort of read operation may cause the flash to think it has been read but the actual CPU read was aborted due to an interrupt. The CPU will attempt repeat the read after the the interrupt has been processed. The affect on the flash would be two reads from the same location which may upset the flash in command mode.

 

Do we get the same sort of operation when doing a write to the extenal bus?

 

Can we solve this by turning off the interrupt and issuing a CSYNC before attempting the read ?

 

Sorry for all the questions

 

  Phil

 

 

 

 

 

 

 

 

 

 

 

 

QuoteReplyEditDelete

 

 

2008-10-15 21:33:17     Re: flash write with interrupts

Robin Getz (UNITED STATES)

Message: 63740   

 

Phil:

 

reads - Just the external bus. - internal things are protected. External things need to be protected like the kernel does things. See the examples there.

 

writes - are not speculative. The write is only issued out of the core when the intruction commits.

 

-Robin

Attachments

    Outcomes