Looks like my code, except that in its current incarnation, I have declared the 
function "extern inline __attribute__((always_inline))". 
Makes it significantly faster than a real function call. And often allows for 
better optimization.
And I used plain int and not uintxx_t types.

For a word read, simply make result uint16_t and replace the movx.b by a movx.w.

A dword read may be more complex. I didn't check whether a mov @rx, 0(ry) does 
a real 32 bit transfer or only 20 bit.
My current implementation does 2*16 bit transfers and might be overly complex, 
so I won't post it.

However, writing is more compicated:

// may not be called from within ISR, as it takes ~48ms per segment
// segment 0 starts @ 0x10000. This function does NOT write below 64k.
int FlashWriteSegmentHigh (unsigned int segment, const unsigned int * source, 
unsigned int size){
  unsigned long i,j;
  unsigned int * flash;
  unsigned int register sr;
  i=segment +128;
  i<<=9;
  j=i+((unsigned long)size<<9);
  FCTL3=FWKEY;                                                                  
// clear lock bit
  while(i<j){
    // erase segment
    __asm__ __volatile__ ("mov    r2  , %0   \n":"=r"(sr));                     
// save old interrup tstate
    _DINT();                                                                    
// block IRQs
    FCTL1=FWKEY|SEGERASE;                                                       
// segment erase mode
    __asm__ __volatile__ ("movx.a %1,%0":"=r"(flash):"m"(i));                   
// 'm' type to ensure 20 bit load
    __asm__ __volatile__ ("movx #llo(0), @%0 "::"r"(flash));
    while(FCTL3&BUSY);                                                          
// wait for erase complete
    FCTL1=FWKEY;                                                                
// segment erase mode off
    __asm__ __volatile__ ("mov    %0  , r2   \n"::"r"(sr));                     
// allow IRQs, if enabled before, so an ISR has a chance.  (32ms have passed)
    _NOP();                                                                     
// give time for some interrupts
    _NOP();                                                                     
// give time for some interrupts
    do{
      _DINT();
      _NOP();                                                                   
// ensure INTs are disabled
      FCTL1=FWKEY|LWWRITE;
      __asm__ __volatile__ ("movx.a %1, %0":"=r"(flash):"m"(i));
      __asm__ __volatile__ ("movx %0, @%1"::"m"(*source),"r"(flash));
      __asm__ __volatile__ ("incd %0":"=r"(source):"0"(source));
      __asm__ __volatile__ ("incda %0":"=r"(flash):"0"(flash));
      __asm__ __volatile__ ("movx %0, @%1"::"m"(*source),"r"(flash));
      __asm__ __volatile__ ("incd %0":"=r"(source):"0"(source));
      __asm__ __volatile__ ("addx.a #llo(4), %0":"=m"(i):"m"(i));
      while(FCTL3&BUSY);                                                        
// wait for write complete
      FCTL1=FWKEY;
    __asm__ __volatile__ ("mov    %0  , r2   \n"::"r"(sr));                     
// allow IRQs, if enabled before, so an ISR has a chance.
    } while (i&0x1ff);
  }
  FCTL3=FWKEY|LOCK;                                                             
// set lock bit again
  return size;
}

My unified FlashWriteData function which writes any size on any place is not 
finished (I stopped working on this some time
ago when I was assigned to software development, and MSP work was reduced to 
bugfixing).
Doing such a function 'right' includes taking a backup of partially written, 
non-empty segments, different sized segments, handling of area overlap etc.

For a full sector read, you can use the following function. It has not been 
fully tested but should work:

void __attribute__ ((naked)) FlashReadData (unsigned long address, unsigned int 
* dest, unsigned int size){
  // R14/R15 = address, R12 = size, R13 = dest
  __asm__ __volatile__ ("add     #1,     r12       \n"
                      "  bic     #1,     r12       \n"                          
// ensure an even number of bytes (round up)
                      "  tst     r12               \n"
                      "  jnz     LP1               \n"                          
// at least one word to read
                      "  ret                       \n"
                      " LP1:                       \n"
                      "  push    r2                \n"
                      "  dint                     \n"                          
// disable interrupts (IRQs will clobber address bits 16..19)
                      "  and     #15,    r15       \n"
                      "  swpb    r15               \n"
                      "  rlam    #4,     r15       \n"
                      "  rlam.a  #4,     r15       \n"                          
// shift bit 16..19 of address into R15 bit 16..19
                      "  add     #1,     r14       \n"                          
// make it an even address
                      "  bic     #1,     r14       \n"
                      "  addx.a  r14,    r15       \n"                          
// move bit 0..15 of address into bit 0..15 of R15
                      "LP2:                        \n"
                      "  movx    @r15, @r13        \n"
                      "  incd    r13               \n"
                      "  incda   r15               \n"
                      "  decd    r12               \n"
                      "  jnz     LP2               \n"
                      "  pop     r2                \n"                          
// restore old interrupt state
                      "  ret                         "
                      ::);
}




----- Ursprüngliche Nachricht -----
Von: Matthias Ringwald
An: [email protected]
Gesendet am: 06 Aug 2011 10:30:24
Betreff: Re: [Mspgcc-users] How to access 20 bit peripheral registers...

Hi Alex

The MSP430s I've seen only have 16kB of RAM in the first 64kB, and of course 
you cannot just write to flash with a 
simple "mov".

However, the TI sample code for the MSP430x5438 Experimenter board has an 
example of recoding audio to flash. 
You may have a look there although their code uses IAR which supports 20 bit 
addresses in general.

Here's a working FlashReadByte(), which somebody on this list showed me a some 
time before.

Best 
Matthias

uint8_t FlashReadByte (uint32_t addr){
    uint8_t result;
    uint32_t register sr, flash;
    
    __asm__ __volatile__ (
    "mov    r2  , %1   \n"
    "bic    %3  , r2   \n"
    "nop               \n"
    "movx.a %4  , %2   \n"
    "movx.b @%2, %0    \n"
    "mov    %1 , r2    \n"
    :"=X"(result),"=r"(sr),"=r"(flash)
    :"i"(GIE),"m"(addr));

    return result;
}


On 05.08.2011, at 23:39, Alex Stefan wrote:

> Does anybody have some example routines for reading/writing to high addresses 
> in 
> the flash?
> 
> This is what I've written so far, but it's far from a working version:
> 
> static inline __attribute__((always_inline)) void
> flash_write_byte(uint32_t addr, uint8_t val)
> {
> 
>        __asm__ __volatile__ (
>                "dint \n"
>                "nop \n"
>                "mova %[addr], r15 \n"
>                "movx %[val], @r15 \n"
>                "eint \n"
>                :
>                :[addr] "r"(addr), [val] "m"(val)
>                );
> }
> static inline __attribute__((always_inline))  uint8_t
> flash_read_byte(uint32_t addr)
> {
> 
>        uint8_t result;
>        __asm__ __volatile__ (
>                "dint \n"
>                "nop \n"
>                "mova %[addr], r15 \n"
>                "movx @r15, %[result]  \n"
>                "eint \n"
>                :[result] "=m"(result)
>                :[addr] "r"(addr)
>                );
>        return result;
> }
> 
> The problem, from what I could tell, comes from the inlining of the functions 
> and the way the compiler generates their prologue. It would help me very much 
> if 
> I had fully working example to start from.
> 
> Alex
> 
> 
> ------------------------------------------------------------------------------
> BlackBerry&reg; DevCon Americas, Oct. 18-20, San Francisco, CA
> The must-attend event for mobile developers. Connect with experts. 
> Get tools for creating Super Apps. See the latest technologies.
> Sessions, hands-on labs, demos & much more. Register early & save!
> http://p.sf.net/sfu/rim-blackberry-1
> _______________________________________________
> Mspgcc-users mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/mspgcc-users


------------------------------------------------------------------------------
BlackBerry&reg; DevCon Americas, Oct. 18-20, San Francisco, CA
The must-attend event for mobile developers. Connect with experts. 
Get tools for creating Super Apps. See the latest technologies.
Sessions, hands-on labs, demos & much more. Register early & save!
http://p.sf.net/sfu/rim-blackberry-1
_______________________________________________
Mspgcc-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mspgcc-users


------------------------------------------------------------------------------
BlackBerry&reg; DevCon Americas, Oct. 18-20, San Francisco, CA
The must-attend event for mobile developers. Connect with experts. 
Get tools for creating Super Apps. See the latest technologies.
Sessions, hands-on labs, demos & much more. Register early & save!
http://p.sf.net/sfu/rim-blackberry-1
_______________________________________________
Mspgcc-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mspgcc-users

Reply via email to