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.

MSP430 - Flash block write - need help!!

Hi,

I really want to find an Application Note or a sample about how to write into the flash in Block write mode.

I already read the SLAU144 document and found information on page 7-13.

"A block write cannot be initiated from within flash memory. The block write must be initiated from RAM only."

And i'm face an issue when i try to place my function in RAM. How can i do??

I try to put a "#pragma CODE_SECTION(copyBlock2Block, "RAM"), but it doesn't work....

Could you help me, please?

Bye.

  • I forgot, I'm using CCE 3-2-2-1-4and a MSP430F23x0.
  • Hi nross,

    The below code my colleague developed in-house which is a code example using block write mode. I'm not sure how to upload the file so it is pasted below. Let me know if you have any questions.

     

    //****************************************************************************
    //  MSP-FET430P140 Demo - Flash In-System Programming, BlockWrite
    //
    //  Description: This program first copies the FlashWrite routine to RAM, then
    //  erases flash seg A, then it increments all values in seg A using the 64
    //  byte block write mode.
    //
    //  Assumed default MCLK = DCO ~800 kHz.
    //
    //  ** Set Breakpoint on NOP in the Mainloop to avoid Stressing Flash **
    //
    //               MSP430F169
    //            -----------------
    //        /|\|              XIN|-
    //         | |                 |
    //         --|RST          XOUT|-
    //           |                 |
    //
    //  H. Grewal / L. Westlund
    //  Texas Instruments Inc.
    //  Jun 2006
    //  Built with IAR Embedded Workbench Version: 3.30A
    //******************************************************************************
    
    #include <msp430x16x.h>
    
    // Global variables
    char value = 0;                             // 8-bit value to write to segment A
    char* Flash_ptr;                            // Flash pointer
    char* RAM_ptr;                              // RAM pointer
    char* END_ptr;                              // End of FlashWrite routine
    
    // Function prototypes
    void FlashWrite();
    void CopyRoutine();
    void End_of_FlashWrite();
    
    void main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
    
      _DINT();                                  // Diable Interrupts
      CopyRoutine();                            // Copy FlashWrite routine to RAM
      _EINT();                                  // Enable Interrupts
    
      while(1)                                  // Repeat forever
      {
        Flash_ptr = (char *) 0x1000;            // Initialize Flash pointer
        FCTL2 = FWKEY + FSSEL1 + FN0;           // MCLK/2 for Flash Timing Generator
        FCTL1 = FWKEY + ERASE;                  // Set Erase bit
        FCTL3 = FWKEY;                          // Clear Lock bit
    
        *Flash_ptr = 0;                         // Dummy write to erase Flash segment
        while(!(FCTL3 & WAIT));                 // WAIT until Flash is ready
        asm("CALL #500h");                      // Execute FlashWrite from RAM
                                                // Inline Assembly
        value++;                                // Increment value
        _NOP();                                 // SET BREAKPOINT HERE
      }
    }
    
    void CopyRoutine()
    {
      Flash_ptr = (char*)FlashWrite;            // Set pointer to FlashWrite routine
      RAM_ptr = (char*)0x0500;                  // Set pointer to RAM
      END_ptr = (char*)End_of_FlashWrite;       // Set pointer to End_of_FlashWrite
    
      while(END_ptr != Flash_ptr)               // Check for end of FlashWrite
      {
        *RAM_ptr = *Flash_ptr;                  // Copy word to RAM
        Flash_ptr++;                            // Increment Flash pointer
        RAM_ptr++;                              // Increment RAM pointer
      }
    }
    
    void FlashWrite()
    {
      volatile int i;                           // Use as write counter
      Flash_ptr = (char*)0x1000;                // Initialize Flash pointer
      while(FCTL3 & BUSY);                      // Check Flash BUSY bit
      FCTL1 = FWKEY + BLKWRT + WRT;             // Enable block-write operation
      for(i = 0; i < 64; i++)
      {
        *Flash_ptr = value;                     // Write value to flash
        Flash_ptr++;                            // Double-increment Flash pointer
        while(!(FCTL3 & WAIT));                 // WAIT until Flash is ready
      }
      FCTL1 = FWKEY;                            // Clear BLKWRT & WRT bits
      while(FCTL3 & BUSY);                      // Check Flash BUSY bit
      FCTL3 = FWKEY + LOCK;                     // Reset LOCK bit
      return;                                   // Exits routine
    }
    
    void End_of_FlashWrite(){}                  // Marks end of FlashWrite
    
  • Hi,

    Here is another solution of achieving this by having the compiler handling the pointers of executing the function in RAM after it is copied from FLASH  to RAM.

     

    Name this filename as Running_from_RAM.c

    //******************************************************************************
    //  MSP430F22x4 Demo - Executing code from RAM
    //
    //  Description: This program demonstrates how a parts of a program can be
    //  executed from FLASH and RAM. First, the main program copies the function
    //  from Flash to RAM during runtime. The main program executes from Flash and
    //  it calls the RAM function and executes in RAM and finally jumps back to
    //  Flash. The function first erases flash seg C, then it increments all values
    //  in seg C, then it erases seg D, then copies seg C to seg D.
    //
    //  Important Notes:
    //
    //  1. CCE automatically generates a new copy of linker file in the project
    //     directory. The zip file has the attached required modified linker file.
    //     See below on what was added to the linker file.
    //
    //        MEMORY
    //        {
    //          ...
    //          RAM_MEM         : origin = 0x0200, length = 0x0200
    //          FLASH_MEM       : origin = 0x8000, length = 0x01FF
    //          ...
    //        }
    //
    //        SECTIONS
    //        {
    //          ...				    
    //          .FLASHCODE : load = FLASH_MEM, run = RAM_MEM
    //                                                /* CODE IN FLASH AND WILL BE COPIED
    //                                                   TO RAM AT EXECUTION HANDLED BY
    //                                                   USER                               */
    //          .RAMCODE   : load = FLASH_MEM         /* CODE WILL BE IN RAM                */
    //          ...
    //        }
    //
    //  2. Unlike IAR where it can calculate the code size through the segment 
    //     call functions, we have to define the allocated memory area that will
    //     be copied from FLASH to RAM. In this case, user has to manually define
    //     the start address of FLASH and RAM. These memory addresses has to be
    //     the same as defined in the linker file origin address of FLASH_MEM and
    //     RAM_MEM. The flash_code_size can be changed to however much the final
    //     compiled code size is.
    //
    //          #define flash_start_add 0x8000              // Flash code starting address
    //          #define flash_code_size 0x01ff              // Function segment size to be copied
    //          #define RAM_start_add   0x0200              // RAM code starting address
    //
    //
    //  3. Erasing and Writing to flash running from RAM requires a few checks of
    //     the BUSY flag. See the user guide for the flow diagram.
    //
    //     while(FCTL3&BUSY);
    //
    //  ACLK = n/a, MCLK = SMCLK = CALxxx_1MHZ = 1MHz
    //  //* Set Breakpoint on NOP in the Mainloop to avoid Stressing Flash *//
    //
    //
    //  W. Goh & M. Morales & A. Dannenberg
    //  Texas Instruments Inc.
    //  December 2008
    //  Built with CCE Version: 3.2.2.1.8
    //******************************************************************************
    
    #include "msp430x22x4.h"
    #include "string.h"
    
    // Define where the code is located in both Flash and RAM
    #define flash_start_add 0x8000              // Flash code starting address
    #define flash_code_size 0x01ff              // Function segment size to be copied
    #define RAM_start_add   0x0200              // RAM code starting address
    
    // Function prototypes
    void write_SegC (char value);
    void copy_C2D (void);
    
    char value;                                 // 8-bit value to write to seg C
    
    // This function is in flash to be copied to RAM
    #pragma CODE_SECTION(write_SegC,".FLASHCODE")
    void write_SegC (char value)
    {
      char *Flash_ptr;                          // Flash pointer
      unsigned int i;
      
      P1OUT ^= 0x02;
      
      Flash_ptr = (char *) 0x1040;              // Initialize Flash pointer
      while(FCTL3&BUSY);                        // Check BUSY flag; Important if running this code from RAM
      FCTL1 = FWKEY + ERASE;                    // Set Erase bit
      FCTL3 = FWKEY;                            // Clear Lock bit
      
      *Flash_ptr = 0;                           // Dummy write to erase Flash segment
      while(FCTL3&BUSY);                        // Check BUSY flag; Important if running this code from RAM
      FCTL1 = FWKEY + WRT;                      // Set WRT bit for write operation
    
      for (i=0; i<64; i++)
      {
        while(FCTL3&BUSY);                        // Check BUSY flag; Important if running this code from RAM
        *Flash_ptr++ = value;                   // Write value to flash
      }
    
      while(FCTL3&BUSY);                        // Check BUSY flag; Important if running this code from RAM
      FCTL1 = FWKEY;                            // Clear WRT bit
      FCTL3 = FWKEY + LOCK;                     // Set LOCK bit
    }
    
    
    // This function is in flash to be copied to RAM
    #pragma CODE_SECTION(copy_C2D,".FLASHCODE")
    void copy_C2D (void)
    {
      char *Flash_ptrC;                         // Segment C pointer
      char *Flash_ptrD;                         // Segment D pointer
      unsigned int i;
    
      Flash_ptrC = (char *) 0x1040;             // Initialize Flash segment C pointer
      Flash_ptrD = (char *) 0x1000;             // Initialize Flash segment D pointer
      while(FCTL3&BUSY);                        // Check BUSY flag; Important if running this code from RAM
      FCTL1 = FWKEY + ERASE;                    // Set Erase bit
      FCTL3 = FWKEY;                            // Clear Lock bit
      *Flash_ptrD = 0;                          // Dummy write to erase Flash segment D
      while(FCTL3&BUSY);                        // Check BUSY flag; Important if running this code from RAM
      FCTL1 = FWKEY + WRT;                      // Set WRT bit for write operation
    
      for (i=0; i<64; i++)
      {
        while(FCTL3&BUSY);                        // Check BUSY flag; Important if running this code from RAM
        *Flash_ptrD++ = *Flash_ptrC++;          // copy value segment C to segment D
      }
      
      while(FCTL3&BUSY);                        // Check BUSY flag; Important if running this code from RAM
      FCTL1 = FWKEY;                            // Clear WRT bit
      FCTL3 = FWKEY + LOCK;                     // Set LOCK bit
    }
    
    
    //Copy function from Flash to RAM
    void copy_flash_to_RAM(void)
    {
      unsigned char *flash_start_ptr;           // Initialize pointers
      unsigned char *RAM_start_ptr;
    
      flash_start_ptr = (unsigned char *)flash_start_add;
      RAM_start_ptr = (unsigned char *)RAM_start_add;
      
      // Copy flash function to RAM 
      memcpy(RAM_start_ptr,flash_start_ptr,flash_code_size);
    }
    
    
    void main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;                 // Stop WatchDog timer
      if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)                                     
      {  
        while(1);                               // If calibration constants erased
                                                // do not load, trap CPU!!
      }   
      BCSCTL1 = CALBC1_1MHZ;                    // Set DCO to 1MHz
      DCOCTL = CALDCO_1MHZ;
      FCTL2 = FWKEY + FSSEL_1 + FN1;            // MCLK/3 for Flash Timing Generator
      P1DIR |= 0x03;
      P1OUT |= 0x00;
      value = 0;
      
      copy_flash_to_RAM();                      // call function to copy from flash to RAM
        
      // Parts of this while loop executes from Flash. The write_SegC and copy_C2D
      // is executed from RAM. The program basically will execute from FLASH until
      // it calls write_SegC function which will jump the program to RAM.
      // After executing write_SegC in RAM, it will jump back to flash to continue
      // executing. When copy_C2D is called, it jumps to RAM and back to Flash when
      // done.
      while(1)
      {
      	  int i;
      	  
          P1OUT ^= 0x01;
          for(i=0;i<20000;i++);                 // This portion executes from FLASH
          write_SegC(value++);                  // This portion of the code is executed from RAM
          copy_C2D();                           // This portion of the code is executed from RAM
          __no_operation();                     // Jumps back to FLASH here. Set breakpoint here
      }
    }
    

     

    ---------------------------------------------------------------------------------------------------------------------------------------

    Here is the new Linker file that is required. You can name this as ******.cmd

    /******************************************************************************/
    /* lnk_msp430f2274.cmd - LINKER COMMAND FILE FOR LINKING MSP430F2274 PROGRAMS */
    /*                                                                            */
    /*  Ver | dd mmm yyyy | Who  | Description of changes                         */
    /* =====|=============|======|=============================================   */
    /*  0.01| 08 Mar 2004 | A.D. | First prototype                                */
    /*  0.02| 26 Mai 2004 | A.D. | Leading symbol underscores removed,            */
    /*      |             |      | Interrupt vector definition changed            */
    /*  0.03| 22 Jun 2004 | A.D. | File reformatted                               */
    /*                                                                            */
    /*   Usage:  lnk430     -o  -m  lnk.cmd     */
    /*           cl430   -z -o  -m  lnk.cmd     */
    /*                                                                            */
    /*----------------------------------------------------------------------------*/
    
    /* These linker options are for command line linking only.  For IDE linking,  */
    /* you should set your linker options in Project Properties                   */
    /* -c                                               LINK USING C CONVENTIONS  */
    /* -stack  0x0100                                   SOFTWARE STACK SIZE       */
    /* -heap   0x0100                                   HEAP AREA SIZE            */
    
    /*----------------------------------------------------------------------------*/
    /* 'Allocate' peripheral registers at given addresses                         */
    /*----------------------------------------------------------------------------*/
    
    /************************************************************
    * STANDARD BITS
    ************************************************************/
    /************************************************************
    * STATUS REGISTER BITS
    ************************************************************/
    /************************************************************
    * PERIPHERAL FILE MAP
    ************************************************************/
    /************************************************************
    * SPECIAL FUNCTION REGISTER ADDRESSES + CONTROL BITS
    ************************************************************/
    IE1                = 0x0000;
    IFG1               = 0x0002;
    IE2                = 0x0001;
    IFG2               = 0x0003;
    /************************************************************
    * ADC10
    ************************************************************/
    ADC10DTC0          = 0x0048;
    ADC10DTC1          = 0x0049;
    ADC10AE0           = 0x004A;
    ADC10AE1           = 0x004B;
    ADC10CTL0          = 0x01B0;
    ADC10CTL1          = 0x01B2;
    ADC10MEM           = 0x01B4;
    ADC10SA            = 0x01BC;
    /************************************************************
    * Basic Clock Module
    ************************************************************/
    DCOCTL             = 0x0056;
    BCSCTL1            = 0x0057;
    BCSCTL2            = 0x0058;
    BCSCTL3            = 0x0053;
                                                                                        
    /*************************************************************
    * Flash Memory
    *************************************************************/
    FCTL1              = 0x0128;
    FCTL2              = 0x012A;
    FCTL3              = 0x012C;
    /************************************************************
    * Operational Amplifier
    ************************************************************/
    OA0CTL0            = 0x00C0;
    OA0CTL1            = 0x00C1;
    OA1CTL0            = 0x00C2;
    OA1CTL1            = 0x00C3;
    /************************************************************
    * DIGITAL I/O Port1/2 Pull up / Pull down Resistors
    ************************************************************/
    P1IN               = 0x0020;
    P1OUT              = 0x0021;
    P1DIR              = 0x0022;
    P1IFG              = 0x0023;
    P1IES              = 0x0024;
    P1IE               = 0x0025;
    P1SEL              = 0x0026;
    P1REN              = 0x0027;
    P2IN               = 0x0028;
    P2OUT              = 0x0029;
    P2DIR              = 0x002A;
    P2IFG              = 0x002B;
    P2IES              = 0x002C;
    P2IE               = 0x002D;
    P2SEL              = 0x002E;
    P2REN              = 0x002F;
    /************************************************************
    * DIGITAL I/O Port3/4 Pull up / Pull down Resistors
    ************************************************************/
    P3IN               = 0x0018;
    P3OUT              = 0x0019;
    P3DIR              = 0x001A;
    P3SEL              = 0x001B;
    P3REN              = 0x0010;
    P4IN               = 0x001C;
    P4OUT              = 0x001D;
    P4DIR              = 0x001E;
    P4SEL              = 0x001F;
    P4REN              = 0x0011;
    /************************************************************
    * Timer A3
    ************************************************************/
    TAIV               = 0x012E;
    TACTL              = 0x0160;
    TACCTL0            = 0x0162;
    TACCTL1            = 0x0164;
    TACCTL2            = 0x0166;
    TAR                = 0x0170;
    TACCR0             = 0x0172;
    TACCR1             = 0x0174;
    TACCR2             = 0x0176;
    /************************************************************
    * Timer B3
    ************************************************************/
    TBIV               = 0x011E;
    TBCTL              = 0x0180;
    TBCCTL0            = 0x0182;
    TBCCTL1            = 0x0184;
    TBCCTL2            = 0x0186;
    TBR                = 0x0190;
    TBCCR0             = 0x0192;
    TBCCR1             = 0x0194;
    TBCCR2             = 0x0196;
    /************************************************************
    * USCI
    ************************************************************/
    UCA0CTL0           = 0x0060;
    UCA0CTL1           = 0x0061;
    UCA0BR0            = 0x0062;
    UCA0BR1            = 0x0063;
    UCA0MCTL           = 0x0064;
    UCA0STAT           = 0x0065;
    UCA0RXBUF          = 0x0066;
    UCA0TXBUF          = 0x0067;
    UCA0ABCTL          = 0x005D;
    UCA0IRTCTL         = 0x005E;
    UCA0IRRCTL         = 0x005F;
    UCB0CTL0           = 0x0068;
    UCB0CTL1           = 0x0069;
    UCB0BR0            = 0x006A;
    UCB0BR1            = 0x006B;
    UCB0I2CIE          = 0x006C;
    UCB0STAT           = 0x006D;
    UCB0RXBUF          = 0x006E;
    UCB0TXBUF          = 0x006F;
    UCB0I2COA          = 0x0118;
    UCB0I2CSA          = 0x011A;
    /************************************************************
    * WATCHDOG TIMER
    ************************************************************/
    WDTCTL             = 0x0120;
    /************************************************************
    * Calibration Data in Info Mem
    ************************************************************/
    CALDCO_16MHZ       = 0x10F8;
    CALBC1_16MHZ       = 0x10F9;
    CALDCO_12MHZ       = 0x10FA;
    CALBC1_12MHZ       = 0x10FB;
    CALDCO_8MHZ        = 0x10FC;
    CALBC1_8MHZ        = 0x10FD;
    CALDCO_1MHZ        = 0x10FE;
    CALBC1_1MHZ        = 0x10FF;
    /************************************************************
    * Interrupt Vectors (offset from 0xFFE0)
    ************************************************************/
    /************************************************************
    * End of Modules
    ************************************************************/
    
    /****************************************************************************/
    /* SPECIFY THE SYSTEM MEMORY MAP                                            */
    /****************************************************************************/
    
    MEMORY
    {
        SFR                     : origin = 0x0000, length = 0x0010
        PERIPHERALS_8BIT        : origin = 0x0010, length = 0x00F0
        PERIPHERALS_16BIT       : origin = 0x0100, length = 0x0100
        RAM_MEM									: origin = 0x0200, length = 0x0200
        RAM                     : origin = 0x0400, length = 0x0200
        INFOA                   : origin = 0x10C0, length = 0x0040
        INFOB                   : origin = 0x1080, length = 0x0040
        INFOC                   : origin = 0x1040, length = 0x0040
        INFOD                   : origin = 0x1000, length = 0x0040
        FLASH_MEM               : origin = 0x8000, length = 0x01FF
        FLASH                   : origin = 0x8200, length = 0x7DDE
        INT00                   : origin = 0xFFE0, length = 0x0002
        INT01                   : origin = 0xFFE2, length = 0x0002
        INT02                   : origin = 0xFFE4, length = 0x0002
        INT03                   : origin = 0xFFE6, length = 0x0002
        INT04                   : origin = 0xFFE8, length = 0x0002
        INT05                   : origin = 0xFFEA, length = 0x0002
        INT06                   : origin = 0xFFEC, length = 0x0002
        INT07                   : origin = 0xFFEE, length = 0x0002
        INT08                   : origin = 0xFFF0, length = 0x0002
        INT09                   : origin = 0xFFF2, length = 0x0002
        INT10                   : origin = 0xFFF4, length = 0x0002
        INT11                   : origin = 0xFFF6, length = 0x0002
        INT12                   : origin = 0xFFF8, length = 0x0002
        INT13                   : origin = 0xFFFA, length = 0x0002
        INT14                   : origin = 0xFFFC, length = 0x0002
        RESET                   : origin = 0xFFFE, length = 0x0002
    }
    
    /****************************************************************************/
    /* SPECIFY THE SECTIONS ALLOCATION INTO MEMORY                              */
    /****************************************************************************/
    
    SECTIONS
    {
        .bss       : {} > RAM                /* GLOBAL & STATIC VARS              */
        .sysmem    : {} > RAM                /* DYNAMIC MEMORY ALLOCATION AREA    */
        .stack     : {} > RAM (HIGH)         /* SOFTWARE SYSTEM STACK             */
    
        .text      : {} > FLASH              /* CODE                              */
        
        .FLASHCODE : load = FLASH_MEM, run = RAM_MEM
        																		 /* CODE IN FLASH AND WILL BE COPIED
        																		    TO RAM AT EXECUTION HANDLED BY
        																		    USER															*/
        .RAMCODE   : load = FLASH_MEM				 /* CODE WILL BE IN RAM								*/
        
        .cinit     : {} > FLASH              /* INITIALIZATION TABLES             */
        .const     : {} > FLASH              /* CONSTANT DATA                     */
        .cio       : {} > RAM                /* C I/O BUFFER                      */
    
        .pinit     : {} > FLASH              /* C++ CONSTRUCTOR TABLES            */
    
        .infoA     : {} > INFOA              /* MSP430 INFO FLASH MEMORY SEGMENTS */
        .infoB     : {} > INFOB
        .infoC     : {} > INFOC
        .infoD     : {} > INFOD
    
        .int00   : {} > INT00                /* MSP430 INTERRUPT VECTORS          */
        .int01   : {} > INT01
        .int02   : {} > INT02
        .int03   : {} > INT03
        .int04   : {} > INT04
        .int05   : {} > INT05
        .int06   : {} > INT06
        .int07   : {} > INT07
        .int08   : {} > INT08
        .int09   : {} > INT09
        .int10   : {} > INT10
        .int11   : {} > INT11
        .int12   : {} > INT12
        .int13   : {} > INT13
        .int14   : {} > INT14
        .reset   : {} > RESET              /* MSP430 RESET VECTOR               */ 
    }
    
    
  • Hi there,
    I see FCTL1 = FWKEY + BLKWRT + WRT statement in FlashWrite function. I guess it has to be
    just CTL1 = FWKEY + BLKWRT  for block write operations. 

    I'm I right?

    Thanks,
    Rahul
  • Rahul SU said:
    Hi there,
    I see FCTL1 = FWKEY + BLKWRT + WRT statement in FlashWrite function. I guess it has to be

    just CTL1 = FWKEY + BLKWRT for block write operations.

    I'm I right?



    No, you are not right. Block write is defined with FWKEY + BLKWRT + WRT. Double word write is defined with FWKEY + BLKWRT.

  • Thanks Soli,

    I did few experiments, what I found is 

    If I put this statement "FCTL1 = FWKEY + BLKWRT + WRT", I see only double word has been written into flash. rest all blank. But this statement "FCTL1 = FWKEY + BLKWRT " does writes all 64 bytes.

    What is your take on these results?

    Thanks,
    Rahul
  • Rahul SU said:

    I did few experiments, what I found is 

    If I put this statement "FCTL1 = FWKEY + BLKWRT + WRT", I see only double word has been written into flash. rest all blank. But this statement "FCTL1 = FWKEY + BLKWRT " does writes all 64 bytes.

    What is your take on these results?

    Thanks,
    Rahul

    Because you are not using block write on correct way. Block write is covered with code examples by 2xx / 5xx (slau144 / slau208) family users guide in flash section. I'm using block write executed from RAM in my flasher.

  • zrno soli said:
    I'm using block write executed from RAM in my flasher

    Well, using block write not from ram won’t work. Once the first (D)word is written, flash stops responding, so if not running form ram, the CPU can’t continue and do any more write.
    Which probably is what happened to Rahul.
    Dword write will allow to write multiple dwords as well (maybe just a misunderstanding of the name). Just that after each single write, the flash write system is shut down again and the CPU can continue from flash, doing the next write. Which makes the write process of course much slower.

    However, the thread was about 2x family flash write, which does not have a dword write mode. This explains the use of the bits: in 2x family, WRT was to be set for (byte/word) write in general, and for (byte/word) block write, BLKWRT was to be set in addition.
    on 5x family, the new dword write mode is initiated by only setting BLKWRT, while block write is always DWORD write (which doesn’t make a difference due to the ability of the flash controller to group byte or word writes toad word write)

**Attention** This is a public forum