world leader in high performance signal processing
Trace: » parallel-flash

Parallel NOR Flash and U-Boot

U-Boot is able to utilize parallel NOR flash hooked up to the Blackfin processor's asynchronous memory banks. Commands are provided for common flash operations such as:

  • reading sectors
  • erasing sectors
  • writing sectors
  • sector protecting

If the flash is CFI compliant, then common U-Boot code can handle detection of the flash automatically given a few board-specific defines (such as the location of the flash in the processor's address space).

If the flash is not CFI compliant, then you will need to write a board-specific driver. Doing so is beyond the scope of this documentation. Instead of wasting software development time, stop being cheap and just buy a CFI compliant flash.

Keep in mind that the size of the flash is limited to the asynchronous memory bank range which differs according to the processor variant. Some Blackfin processors can only support up to 4 megabytes while others can support up to 32 megabytes. Consult the datasheet for your variant for more information.


For CFI compliant flashes, you simply need the following defines in your board header file.

/* Board independent required settings */
#define CONFIG_SYS_FLASH_CFI                 /* Flash is CFI compliant */
#define CONFIG_FLASH_CFI_DRIVER              /* Use the common CFI flash driver */

/* Board dependent required settings */
#define CONFIGS_SYS_FLASH_BASE       0x20000000   /* Address flash is mapped */
/* Max number of banks -- can be greater than available, but cannot be smaller */
/* Max number of sectors -- can be greater than available, but cannot be smaller */

/* Optional settings */
#define CONFIG_SYS_FLASH_PROTECTION  1            /* Use hardware flash protection */

For more information, see the top level U-Boot README file.


Once U-Boot is running, you can query the flash information to make sure things are kosher. For example, the output on a BF537-STAMP board looks something like:

bfin> flinfo
Bank # 1: CFI conformant FLASH (16 x 16)  Size: 4 MB in 71 Sectors
 Erase timeout 8192 ms, write timeout 1 ms, buffer write timeout 1 ms, buffer size 1
  Sector Start Addresses:
    20000000 (RO) 20002000 (RO) 20004000 (RO) 20006000 (RO) 20008000 (RO)
    2000A000 (RO) 2000C000 (RO) 2000E000 (RO) 20010000 (RO) 20020000     
    20030000      20040000      20050000      20060000      20070000     
    20080000      20090000      200A0000      200B0000      200C0000     
    200D0000      200E0000      200F0000      20100000      20110000     
    20120000      20130000      20140000      20150000      20160000     
    20170000      20180000      20190000      201A0000      201B0000     
    201C0000      201D0000      201E0000      201F0000      20200000     
    20210000      20220000      20230000      20240000      20250000     
    20260000      20270000      20280000      20290000      202A0000     
    202B0000      202C0000      202D0000      202E0000      202F0000     
    20300000      20310000      20320000      20330000      20340000     
    20350000      20360000      20370000      20380000      20390000     
    203A0000      203B0000      203C0000      203D0000      203E0000     
    203F0000 (RO)

Here we can see a bottom boot 4 megabyte CFI compliant flash with 71 sectors.

The address of every sector found is displayed for easy reference. Any sector with (RO) after it means that U-Boot will prevent writing of the sector (see protection below for more information).


U-Boot offers write protection (in hardware or software) on a per-sector level for parallel flashes. Access to this protection is via the aptly named protect command.

bfin> help protect
protect on  start end
    - protect FLASH from addr 'start' to addr 'end'
protect on start +len
    - protect FLASH from addr 'start' to end of sect w/addr 'start'+'len'-1
protect on  N:SF[-SL]
    - protect sectors SF-SL in FLASH bank # N
protect on  bank N
    - protect FLASH bank # N
protect on  all
    - protect all FLASH banks
protect off start end
    - make FLASH from addr 'start' to addr 'end' writable
protect off start +len
    - make FLASH from addr 'start' to end of sect w/addr 'start'+'len'-1 wrtable
protect off N:SF[-SL]
    - make sectors SF-SL writable in FLASH bank # N
protect off bank N
    - make FLASH bank # N writable
protect off all
    - make all FLASH banks writable

By default, the Blackfin boards will set all the sectors that U-Boot itself lives in as read-only. You can of course control this behavior in your board-specific code.

For the lazy, you can make all sectors writable by simply using the protect off all command.

bfin> protect off all
Un-Protect Flash Bank # 1
....................................................................... done


Access to parallel flash is done via the standard U-Boot memory functions. That means you can simply read parallel flash directly like any other external memory location.

bfin> md.b 0x20000000 0x20
20000000: 0e e1 00 10 4e e1 b0 ff 90 61 10 3e 01 60 21 36    ....N....a.>.`!6
20000010: 29 36 31 36 39 36 01 3c 19 3c fc 31 00 e3 56 00    )61696.<.<.1..V.
bfin> cp.b 0x20000000 0 0x20
bfin> md.b 0 0x20
00000000: 0e e1 00 10 4e e1 b0 ff 90 61 10 3e 01 60 21 36    ....N....a.>.`!6
00000010: 29 36 31 36 39 36 01 3c 19 3c fc 31 00 e3 56 00    )61696.<.<.1..V.

Reading can be done at any offset independent of sector.


Due to the nature of flash technology, you obviously need to erase things before you can write them out. This is accomplished via the erase command and, again due to the nature of flash, must be done on sector boundaries.

bfin> help erase
erase start end
    - erase FLASH from addr 'start' to addr 'end'
erase start +len
    - erase FLASH from addr 'start' to the end of sect w/addr 'start'+'len'-1
erase N:SF[-SL]
    - erase sectors SF-SL in FLASH bank # N
erase bank N
    - erase FLASH bank # N
erase all
    - erase all FLASH banks

So to refer to the previous BF537-STAMP example, if we wish to erase a few sectors in the middle of the flash, we'd simply use a command like so:

bfin> erase 0x201C0000 0x2026FFFF
........... done
Erased 11 sectors

Notice that in the sector output from the flinfo command, the sector start addresses are shown. However, the end address is inclusive in the erased range, so we need to give the address of the first sector we don't want erased and subtract one from it.


Once again, due to the nature of flash technology, bits can written from 1 to 0 but not back again. Writes can also be done at the byte level rather than sector level. However, if you wish to change a 0 to a 1, you need to erase the sectors in question first.

To write flash, you need to use the cp U-Boot command. Load whatever data you wish to write to flash into some memory location (commonly via TFTP), and then copy it from that memory location into flash. Here we assume the sectors in question have already been erased and so we'll simply fill external memory with random bytes and then copy them into the flash.

bfin> md.b 0x201c0000
201c0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
201c0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
bfin> mw.b 0 0xee 0x20
bfin> md.b 0
00000000: ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee    ................
00000010: ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee    ................
bfin> cp.b 0 0x201c0000 10
Copy to Flash... done
bfin> md.b 0x201c0000
201c0000: ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee    ................
201c0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................

After writing, you can/should verify that the write was completed properly with the cmp (compare) command

bfin> help cmp
cmp - memory compare

cmp [.b, .w, .l] addr1 addr2 count
bfin> cmp.b 0 0x201c0000 10
Total of 16 bytes were the same

Disabling Support

Conversely, your board may not have any parallel flash at all so you want to disable support for it. Here are the things you need in your board configuration file.

  • do not define CONFIG_FLASH_CFI_DRIVER
  • do not define CONFIG_CMD_FLASH (undefine it if necessary)
  • do not define CONFIG_CMD_IMLS (undefine it if necessary)