Re: Accessing 20-bit memory range - issues with indirect addressing mode

Daniel Sulik <[email protected]>
Newsgroups gmane.comp.hardware.texas-instruments.msp430.gcc.user
Message-ID <[email protected]>
Hi Tomek,

Try the code snippet below. I am using 20-bit access for some time, 
targetting MSP430F2417/F2618
The code is part of my bootloader code. While bootloader is executed all 
IRQs are disabled.
I did not have much time to look closer at your code. Hope it helps.

/*
  * 20-bit write access to flash func
  */
static inline void FlashWriteByte (uint32 Address, uint8 Byte)
{
     unsigned int sr, flash;
     __asm__ __volatile__ ("mov r2,%0":"=r"(sr):);
     _DINT();
     __asm__ __volatile__ ("movx.a %1,%0":"=r"(flash):"m"(Address));
     __asm__ __volatile__ ("movx.b %1, @%0":"=r"(flash):"m"(Byte));
     __asm__ __volatile__ ("mov %0,r2"::"r"(sr));
}

...
     /*
      * Clear LOCK Bit
      * Set LOCKA bit
      */
     FCTL3 = FWKEY + LOCKA;
     FCTL1 = FWKEY + ERASE;
     /*
      * Dummy write to erase Flash segment
      */
     FlashWriteByte (Address + Start, 0);

     /*
      * Set WRT bit for byte write operation
      */
     FCTL1 = FWKEY + WRT;

     /*
      * Write value(s) to flash
      */
     uint8 *SrcPtr = (uint8*)Buffer;
     uint16 i;
     for (i = Start; i < Count; i++)
     {
         FlashWriteByte (Address + i, SrcPtr[i]);
     }

...

Regards
Dan
On 04/05/2014 00:00, Tomek Lorek wrote:
> Hi,
> I'm trying to figure out how to properly erase (and then to write, but
> this is the fist step to have anything working) flash region from high
> memory (over 64kB), thus using 20-bit mode.
>
> The erase procedure is quite straightforward:
>
> --start--
> unsigned long flash_addr = 0x1c400;
> unsigned long flash;
> unsigned int sr;
>
> FCTL3 = FWKEY; // Clear Lock bit
> while (FCTL3 & BUSY) ;
> FCTL1 = FWKEY + MERAS; // Set MERAS bit
>
> __asm__ __volatile__ ("mov r2,%0":"=r"(sr):); // save SR before disabling IRQ
> __dint();
> __asm__ __volatile__ ("movx.a %1,%0":"=r"(flash):"m"(flash_addr)); //
> move 20 bit flash address from variable to a register
> __asm__ __volatile__ ("clrx @%0"::"r"(flash));  // dummy write 0 (or
> clrx) to the address contained in the register
> __asm__ __volatile__ ("mov %0,r2"::"r"(sr)); // restore previous SR
> and IRQ state
> __eint();
>
> while (FCTL3 & BUSY) ; // test busy
> FCTL1 = FWKEY; // Clear MERAS bit
> FCTL3 = FWKEY + LOCK; // Set LOCK bit
> --stop--
>
> This code does not work, I've been struggling with it for a couple of
> hours and still miss what is wrong.
> Disassembly looks like this:
>
> --start--
> unsigned long flash_addr = 0x1c400;
>      4458: b4 40 00 c4 mov #-15360,-10(r4) ;#0xc400, 0xfff6(r4)
>      445c: f6 ff
>      445e: 94 43 f8 ff mov #1, -8(r4) ;r3 As==01, 0xfff8(r4)
> unsigned long flash;
> unsigned int sr;
>
> FCTL3 = FWKEY; // Clear Lock bit
>      4462: b2 40 00 a5 mov #-23296,&0x0144 ;#0xa500
>      4466: 44 01
> while (FCTL3 & BUSY) ;
>      4468: 03 43       nop
>      446a: 1f 42 44 01 mov &0x0144,r15
>      446e: 1f f3       and #1, r15 ;r3 As==01
>      4470: 4f 4f       mov.b r15, r15
>      4472: 4f 93       tst.b r15
>      4474: fa 23       jnz $-10     ;abs 0x446a
> FCTL1 = FWKEY + MERAS; // Set MERAS bit
>      4476: b2 40 04 a5 mov #-23292,&0x0140 ;#0xa504
>      447a: 40 01
>
> __asm__ __volatile__ ("mov r2,%0":"=r"(sr):); // save SR before disabling IRQ
>      447c: 0b 42       mov r2, r11
>      447e: 84 4b f0 ff mov r11, -16(r4) ;0xfff0(r4)
> __dint();
>      4482: 32 c2       dint
>      4484: 03 43       nop
> __asm__ __volatile__ ("movx.a %1,%0":"=r"(flash):"m"(flash_addr)); //
> mov 20-bit flash address from variable to a reg
>      4486: 80 1f 5a 44 movx.a -10(r4),r10 ;0xffff6(r4)
>      448a: f6 ff
>      448c: 84 4a f2 ff mov r10, -14(r4) ;0xfff2(r4)
>      4490: 84 4b f4 ff mov r11, -12(r4) ;0xfff4(r4)
> __asm__ __volatile__ ("clrx @%0"::"r"(flash)); // dummy write 0 (or
> clrx) to the address contained in the reg
>      4494: 1e 44 f2 ff mov -14(r4),r14 ;0xfff2(r4)
>      4498: 1f 44 f4 ff mov -12(r4),r15 ;0xfff4(r4)
>      449c: 40 18 8e 43 clrx 0(r14) ;0x00000(r14)
> --stop--
>
> The address 0x1c400 is properly stored on the stack in -10(r4) (4458
> and 445e). Then at 4486 it is mov'ed to r10, which is ok.
> What happens in 448c and 4490? What is expected at -14(r4) and why is
> the SR used in 4490 (mov'ed to r11 in 447c)? There is no C code
> accompanying it.
>
> I guess this is the problem as I can see in 448c and 4490 some strange
> data to be written to the stack and when the clrx is called at 449c it
> uses an indexed r14 with an offset of 0. I made a big mess :-)
> Where is the issue in my code?
>
> Using
> __asm__ __volatile__ ("movx #0,&0x1c400");
> works correctly, my goal was to make this address stored in a variable.
>
> Thanks in advance for a hint!
>
> Best Regards,
> Tomek
>
> ------------------------------------------------------------------------------
> "Accelerate Dev Cycles with Automated Cross-Browser Testing - For FREE
> Instantly run your Selenium tests across 300+ browser/OS combos.  Get
> unparalleled scalability from the best Selenium testing platform available.
> Simple to use. Nothing to install. Get started now for free."
> http://p.sf.net/sfu/SauceLabs
> _______________________________________________
> Mspgcc-users mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/mspgcc-users


------------------------------------------------------------------------------
"Accelerate Dev Cycles with Automated Cross-Browser Testing - For FREE
Instantly run your Selenium tests across 300+ browser/OS combos.  Get 
unparalleled scalability from the best Selenium testing platform available.
Simple to use. Nothing to install. Get started now for free."
http://p.sf.net/sfu/SauceLabs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.