This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
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:
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
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:
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)
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.
I thought that maybe there is no need to move the flash_addr to the register and to use "m" constraint, like this:
__asm__ __volatile__ ("clrx %0"::"m"(flash_addr));
But it does not work either, the most important disassembly part looks this way:
unsigned long flash_addr = 0x1c400; 4454: b4 40 00 c4 mov #-15360,-8(r4) ;#0xc400, 0xfff8(r4) 4458: f8 ff 445a: 94 43 fa ff mov #1, -6(r4) ;r3 As==01, 0xfffa(r4) [...cut...] __asm__ __volatile__ ("clrx %0"::"m"(flash_addr)); // dummy write 0 (or clrx) to the address contained in the reg 4482: 4f 18 84 43 clrx -8(r4) ;0xffff8(r4) 4486: f8 ff
This time it looks like clrx gets stack contents at -8(r4) but I am not sure if it reaches the contents of -6(r4) so to produce the corect 0x1c400 address.
Do you have any idea where do I make it wrong?
Best Regards,
tml
OK, the problem is narrowed down to the difference between:
__asm__ __volatile__ ("movx #0, @%0"::"r"(flash));
versus
char Byte = 0;
__asm__ __volatile__ ("movx.b %1, @%0":"=r"(flash):"m"(Byte));
The first one causes the program to mess up the flash bank A from where I run the code and erase from address 0xc400 instead of 0x1c400.
The latter one works ok.
They seem to me to be the same, why they are not? It does not matter if I use movx.b or movx (where word is applied).
**Attention** This is a public forum