Flashing CFI devices?

Hello!

Anybody got flashing of CFI devices working? It seems to me that there’s a bug in openocd.

I have a sst39vf1601 on a 16bit bus. The command sequences for this device are listed at page 9 of the datasheet (http://www.rockbox.org/twiki/pub/Main/D … S71223.pdf).

With openocd/doc/configs/arm7_ft2232.cfg issuing the “flash probe 1” command, openocd tries to write 0x98 to 0x800000aa, which is simply not covered by the datasheet. So there’s no real surprise that probing fails. Instead the following sequence should be issued:

write 0xaa to 0x8000aaaa
write 0x55 to 0x80005554
write 0x98 to 0x8000aaaa

Note that the adresses given in the datasheet need to be doubled, since A0 is not connected on 16bit busses.

All CFI devices I ever seen require similar sequences. With this quick-n-dirty patch:

Index: src/flash/cfi.c
===================================================================
--- src/flash/cfi.c     (Revision 121)
+++ src/flash/cfi.c     (Arbeitskopie)
@@ -911,8 +911,12 @@
        u8 command[8];


+       cfi_command(bank, 0xaa, command);
+       target->type->write_memory(target, flash_address(bank, 0, 0x5555), bank->bus_width, 1, command);
+       cfi_command(bank, 0x55, command);
+       target->type->write_memory(target, flash_address(bank, 0, 0x2aaa), bank->bus_width, 1, command);
        cfi_command(bank, 0x98, command);
-       target->type->write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command);
+       target->type->write_memory(target, flash_address(bank, 0, 0x5555), bank->bus_width, 1, command);

        cfi_info->qry[0] = cfi_query_u8(bank, 0, 0x10);
        cfi_info->qry[1] = cfi_query_u8(bank, 0, 0x11);

the device can be found. Similar problems are with the other commands (erase, write, etc).

Is this a real bug or am I misunderstanding something here?

Currently only CFI flashes using the Intel commandset are supported, i.e. only the algorithms (read, write, erase, protect) for commandsets 1 and 3 are implemented.

The SST devices (as well as AMD/Spansion and a few others) seem to violate the CFI standard, which clearly states that (JEDEC Standard No. 68.01, p. 2):

Nonvolatile memory devices are assumed to power up in a read-only state. Independent of that assumption, the Query structure contents must be able to be read at the specific address locations following a single system write cycle where: 1) a 98h Query command code is written to 55h address location within the device s address space (in maximum device buswidth), and 2) the device is in any valid read state, such as Read Array or Read ID Data .

The CFI code automatically aligns writes depending on the bus configuration. For a 16-bit device on a 16-bit bus, the value 0x0098 is written to offset 0xaa (shifted to the left by one bit, to make up for the not-connected A0 line. The device thus sees 0x55 on its address lines).

I’d have to check other implementations of CFI probing code to see what sequence exists that a) allows SST and others to be identified and b) doesn’t harm the Intel devices that closely follow the JEDEC standard.

I’ve received several patches adding support for other CFI flashes (namely SST, iirc), but none were clean enough for inclusion, or didn’t make me fear they would break the existing supported devices.

Unfortunately I’ve never had access to a board using a non-Intel external flash chip, so I can’t test this myself.

Best regards,

Dominic

Dominic:
Currently only CFI flashes using the Intel commandset are supported, i.e. only the algorithms (read, write, erase, protect) for commandsets 1 and 3 are implemented.

The SST devices (as well as AMD/Spansion and a few others) seem to violate the CFI standard, which clearly states that (JEDEC Standard No. 68.01, p. 2):

I must admit that I haven’t read the JEDEC standard and I have never used intel flash devices. But OTOH, I see from the practice, that most vendors (Spansion(former AMD), Atmel, Fujitsu, ST, SST, just to name some) use the non-JEDEC-compatible procedure I described in my previous post.

I’d have to check other implementations of CFI probing code to see what sequence exists that a) allows SST and others to be identified and b) doesn’t harm the Intel devices that closely follow the JEDEC standard.

I think probing with different algorithms should be pretty safe. A device that don’t recognize its sequence simply remains in read-array-data mode. Therefore recognizing a wrong type of chip can only happen if vendor-id and chip-id is programmed into the chip on the location of the IDs.

An alternative would be to specify in the config file which algorithm to use.

Hello,

I also have problems programming a CFI flash device. I am using a self made board with STR720, Intel 28F640J3 flash and 32 MB SDRAM. Downloading and debugging programs into the 16 KByte internal RAM of the STR720 works well. But I have to program larger programs into flash. This works in principal but is dramatically slow.

If I don’t use a workspace programming succeeds but it lasts 630 s to program 78 KByte. It is not very funny to wait more than 10 minutes to find out that the program is still buggy.

When I define a workspace either in internal RAM or in the SDRAM after initialization it by a script, OpenOCD fails at the first byte. A status register value of 0xff is reported.

This is the end of the logfile, after 32 KByte has been transferred into the workspace at 0xA0000000:

  • Debug: embeddedice.c:253 embeddedice_write_reg(): 5: 0xe3550007

    Debug: embeddedice.c:253 embeddedice_write_reg(): 5: 0xe0866004

    Debug: embeddedice.c:253 embeddedice_write_reg(): 5: 0xe5828000

    Debug: embeddedice.c:253 embeddedice_write_reg(): 5: 0xe5824004

    Debug: embeddedice.c:253 embeddedice_write_reg(): 5: 0xe58d6680

    Debug: embeddedice.c:253 embeddedice_write_reg(): 5: 0xe58d567c

    Debug: embeddedice.c:253 embeddedice_write_reg(): 5: 0xd282c008

    Debug: embeddedice.c:253 embeddedice_write_reg(): 5: 0xdafffbd3

    Debug: arm7_9_common.c:838 arm7_9_halt(): target->state: debug_running

    Debug: embeddedice.c:253 embeddedice_write_reg(): 9: 0xffffffff

    Debug: embeddedice.c:253 embeddedice_write_reg(): 11: 0xffffffff

    Debug: embeddedice.c:253 embeddedice_write_reg(): 12: 0x00000100

    Debug: embeddedice.c:253 embeddedice_write_reg(): 13: 0x000000f7

    Debug: embeddedice.c:157 embeddedice_read_reg_w_check(): 1

    Debug: ft2232.c:915 ft2232_execute_queue(): ftd2xx buffer size reached, sending queued commands (first_unsent: c30020, cmd: d9ffe4)

    Debug: arm7_9_common.c:620 arm7_9_poll(): DBGACK set, dbg_state->value: 0x9

    Debug: embeddedice.c:253 embeddedice_write_reg(): 0: 0x00000005

    Debug: embeddedice.c:253 embeddedice_write_reg(): 12: 0x00000000

    Debug: arm7_9_common.c:944 arm7_9_debug_entry(): target entered debug from ARM state

    Debug: arm7_9_common.c:976 arm7_9_debug_entry(): target entered debug state in Undefined mode

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r0: 0xa0008000

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r1: 0x10000000

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r2: 0x00004000

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r3: 0x00220040

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r4: 0x003d8010

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r5: 0x00000308

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r6: 0xff4bff9f

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r7: 0xbb7ffb37

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r8: 0xfaffdfff

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r9: 0xbf7fffdf

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r10: 0xee7fef77

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r11: 0x60003f18

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r12: 0x60003f1c

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r13: 0x60003ffc

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r14: 0x00080028

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r15: 0xa0008000

    Debug: arm7_9_common.c:1011 arm7_9_debug_entry(): entered debug state at PC 0xa0008000

    Debug: target.c:442 target_call_event_callbacks(): target event 3

    Debug: arm7tdmi.c:506 arm7tdmi_write_xpsr_im8(): xpsr_im: d3, rot: 0, spsr: 0

    Debug: arm7tdmi.c:506 arm7tdmi_write_xpsr_im8(): xpsr_im: db, rot: 0, spsr: 0

    Debug: arm7tdmi.c:506 arm7tdmi_write_xpsr_im8(): xpsr_im: d3, rot: 0, spsr: 0

    Debug: arm7tdmi.c:506 arm7tdmi_write_xpsr_im8(): xpsr_im: db, rot: 0, spsr: 0

    Debug: arm7tdmi.c:506 arm7tdmi_write_xpsr_im8(): xpsr_im: d3, rot: 0, spsr: 0

    Debug: arm7tdmi.c:506 arm7tdmi_write_xpsr_im8(): xpsr_im: db, rot: 0, spsr: 0

    Debug: armv4_5.c:563 armv4_5_run_algorithm(): setting core_mode: 0x13

    Debug: breakpoints.c:93 breakpoint_add(): added hardware breakpoint at 0x003d0230 of length 0x00000004

    Debug: arm7_9_common.c:1328 arm7_9_resume():

    Debug: embeddedice.c:253 embeddedice_write_reg(): 8: 0x003d0230

    Debug: embeddedice.c:253 embeddedice_write_reg(): 9: 0x00000003

    Debug: embeddedice.c:253 embeddedice_write_reg(): 11: 0xffffffff

    Debug: embeddedice.c:253 embeddedice_write_reg(): 13: 0x000000f7

    Debug: embeddedice.c:253 embeddedice_write_reg(): 12: 0x00000100

    Debug: arm7_9_common.c:1127 arm7_9_restore_context():

    Debug: arm7_9_common.c:1143 arm7_9_restore_context(): examining User mode

    Debug: arm7_9_common.c:1157 arm7_9_restore_context(): examining dirty reg: r0

    Debug: arm7_9_common.c:1157 arm7_9_restore_context(): examining dirty reg: r1

    Debug: arm7_9_common.c:1157 arm7_9_restore_context(): examining dirty reg: r2

    Debug: arm7_9_common.c:1157 arm7_9_restore_context(): examining dirty reg: r3

    Debug: arm7_9_common.c:1157 arm7_9_restore_context(): examining dirty reg: r4

    Debug: arm7_9_common.c:1157 arm7_9_restore_context(): examining dirty reg: pc

    Debug: arm7_9_common.c:1157 arm7_9_restore_context(): examining dirty reg: cpsr

    Debug: arm7_9_common.c:1206 arm7_9_restore_context(): writing register 0 of mode User with value 0xa0000000

    Debug: arm7_9_common.c:1206 arm7_9_restore_context(): writing register 1 of mode User with value 0x40000000

    Debug: arm7_9_common.c:1206 arm7_9_restore_context(): writing register 2 of mode User with value 0x00004000

    Debug: arm7_9_common.c:1206 arm7_9_restore_context(): writing register 3 of mode User with value 0x00220040

    Debug: arm7_9_common.c:1206 arm7_9_restore_context(): writing register 4 of mode User with value 0x003d0550

    Debug: arm7_9_common.c:1143 arm7_9_restore_context(): examining FIQ mode

    Debug: arm7_9_common.c:1157 arm7_9_restore_context(): examining dirty reg: pc

    Debug: arm7_9_common.c:1143 arm7_9_restore_context(): examining IRQ mode

    Debug: arm7_9_common.c:1157 arm7_9_restore_context(): examining dirty reg: pc

    Debug: arm7_9_common.c:1143 arm7_9_restore_context(): examining Supervisor mode

    Debug: arm7_9_common.c:1157 arm7_9_restore_context(): examining dirty reg: pc

    Debug: arm7_9_common.c:1143 arm7_9_restore_context(): examining Abort mode

    Debug: arm7_9_common.c:1157 arm7_9_restore_context(): examining dirty reg: pc

    Debug: arm7_9_common.c:1143 arm7_9_restore_context(): examining Undefined mode

    Debug: arm7_9_common.c:1157 arm7_9_restore_context(): examining dirty reg: pc

    Debug: arm7_9_common.c:1239 arm7_9_restore_context(): writing cpsr with value 0x400000d3

    Debug: arm7tdmi.c:475 arm7tdmi_write_xpsr(): xpsr: 400000d3, spsr: 0

    Debug: arm7_9_common.c:1246 arm7_9_restore_context(): writing PC with value 0x003d0200

    Debug: embeddedice.c:253 embeddedice_write_reg(): 0: 0x00000004

    Debug: target.c:442 target_call_event_callbacks(): target event 4

    Debug: arm7_9_common.c:1431 arm7_9_resume(): target resumed

    Debug: embeddedice.c:157 embeddedice_read_reg_w_check(): 1

    Debug: arm7_9_common.c:620 arm7_9_poll(): DBGACK set, dbg_state->value: 0x9

    Debug: embeddedice.c:253 embeddedice_write_reg(): 0: 0x00000005

    Debug: embeddedice.c:253 embeddedice_write_reg(): 9: 0x00000003

    Debug: embeddedice.c:253 embeddedice_write_reg(): 11: 0xffffffff

    Debug: embeddedice.c:253 embeddedice_write_reg(): 13: 0x000000f7

    Debug: embeddedice.c:253 embeddedice_write_reg(): 12: 0x00000100

    Debug: arm7_9_common.c:944 arm7_9_debug_entry(): target entered debug from ARM state

    Debug: arm7_9_common.c:976 arm7_9_debug_entry(): target entered debug state in Supervisor mode

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r0: 0x40000000

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r1: 0x40000000

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r2: 0x00004000

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r3: 0x00220040

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r4: 0x003d0550

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r5: 0x00000308

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r6: 0xff4bff9f

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r7: 0xbb7ffb37

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r8: 0xfaffdfff

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r9: 0xbf7fffdf

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r10: 0xee7fef77

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r11: 0x60003f18

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r12: 0x60003f1c

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r13: 0x60003f5c

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r14: 0x00055af0

    Debug: arm7_9_common.c:1005 arm7_9_debug_entry(): r15: 0x003d0230

    Debug: arm7_9_common.c:1011 arm7_9_debug_entry(): entered debug state at PC 0x3d0230

    Debug: target.c:442 target_call_event_callbacks(): target event 3

    Debug: embeddedice.c:253 embeddedice_write_reg(): 12: 0x00000000

    Debug: armv4_5.c:633 armv4_5_run_algorithm(): restoring register r0 with value 0x40000000

    Debug: armv4_5.c:633 armv4_5_run_algorithm(): restoring register r1 with value 0x40000000

    Debug: armv4_5.c:633 armv4_5_run_algorithm(): restoring register r2 with value 0x00004000

    Debug: armv4_5.c:633 armv4_5_run_algorithm(): restoring register r3 with value 0x00220040

    Debug: armv4_5.c:633 armv4_5_run_algorithm(): restoring register r4 with value 0x003d0550

    Debug: armv4_5.c:633 armv4_5_run_algorithm(): restoring register r5 with value 0x00000308

    Debug: armv4_5.c:633 armv4_5_run_algorithm(): restoring register r6 with value 0xff4bff9f

    Debug: armv4_5.c:633 armv4_5_run_algorithm(): restoring register r7 with value 0xbb7ffb37

    Debug: armv4_5.c:633 armv4_5_run_algorithm(): restoring register r8 with value 0xfaffdfff

    Debug: armv4_5.c:633 armv4_5_run_algorithm(): restoring register r9 with value 0xbf7fffdf

    Debug: armv4_5.c:633 armv4_5_run_algorithm(): restoring register r10 with value 0xee7fef77

    Debug: armv4_5.c:633 armv4_5_run_algorithm(): restoring register r11 with value 0x60003f18

    Debug: armv4_5.c:633 armv4_5_run_algorithm(): restoring register r12 with value 0x60003f1c

    Debug: armv4_5.c:633 armv4_5_run_algorithm(): restoring register r13_svc with value 0x60003f5c

    Debug: armv4_5.c:633 armv4_5_run_algorithm(): restoring register lr_svc with value 0x00055af0

    Debug: armv4_5.c:633 armv4_5_run_algorithm(): restoring register pc with value 0x003d0230

    Debug: armv4_5.c:633 armv4_5_run_algorithm(): restoring register spsr_svc with value 0x400000d3

    Debug: arm7_9_common.c:1676 arm7_9_read_memory(): address: 0x40000000, size: 0x00000002, count: 0x00000001

    Debug: embeddedice.c:157 embeddedice_read_reg_w_check(): 1

    Debug: cfi.c:210 cfi_intel_wait_status_busy(): status: 0xff

    Error: cfi.c:214 cfi_intel_wait_status_busy(): status register: 0xff

    Error: cfi.c:216 cfi_intel_wait_status_busy(): Block Lock-Bit Detected, Operation Abort

    Error: cfi.c:218 cfi_intel_wait_status_busy(): Program suspended

    Error: cfi.c:220 cfi_intel_wait_status_busy(): Low Programming Voltage Detected, Operation Aborted

    Error: cfi.c:222 cfi_intel_wait_status_busy(): Program Error / Error in Setting Lock-Bit

    Error: cfi.c:224 cfi_intel_wait_status_busy(): Error in Block Erasure or Clear Lock-Bits

    Error: cfi.c:226 cfi_intel_wait_status_busy(): Block Erase Suspended

    Debug: arm7_9_common.c:1822 arm7_9_write_memory(): address: 0x40000000, size: 0x00000002, count: 0x00000001

    Debug: embeddedice.c:253 embeddedice_write_reg(): 0: 0x00000004

    Debug: embeddedice.c:157 embeddedice_read_reg_w_check(): 1

    Debug: embeddedice.c:253 embeddedice_write_reg(): 0: 0x00000005

    Debug: arm7_9_common.c:1822 arm7_9_write_memory(): address: 0x40000000, size: 0x00000002, count: 0x00000001

    Debug: embeddedice.c:253 embeddedice_write_reg(): 0: 0x00000004

    Debug: embeddedice.c:157 embeddedice_read_reg_w_check(): 1

    Debug: embeddedice.c:253 embeddedice_write_reg(): 0: 0x00000005

    Debug: target.c:1328 handle_reset_command():

    Debug: arm7_9_common.c:656 arm7_9_assert_reset(): target->state: halted

    Debug: jtag.c:247 jtag_call_event_callbacks(): jtag event: 0

    Debug: jtag.c:1096 jtag_reset_callback():

    Debug: jtag.c:247 jtag_call_event_callbacks(): jtag event: 1

    Debug: jtag.c:1096 jtag_reset_callback():

    Warning: arm7_9_common.c:683 arm7_9_assert_reset(): srst resets test logic, too

    Debug: jtag.c:247 jtag_call_event_callbacks(): jtag event: 0

    Debug: jtag.c:1096 jtag_reset_callback():

    Debug: jtag.c:247 jtag_call_event_callbacks(): jtag event: 1

    Debug: jtag.c:1096 jtag_reset_callback():

    Debug: ft2232.c:738 olimex_jtag_reset(): trst: 1, srst: 1, high_output: 0x0a, high_direction: 0x0f

    Debug: ft2232.c:738 olimex_jtag_reset(): trst: 1, srst: 1, high_output: 0x0a, high_direction: 0x0f

    Debug: arm7_9_common.c:722 arm7_9_deassert_reset(): target->state: reset

    Debug: jtag.c:247 jtag_call_event_callbacks(): jtag event: 2

    Debug: jtag.c:1096 jtag_reset_callback():

    Debug: ft2232.c:738 olimex_jtag_reset(): trst: 0, srst: 0, high_output: 0x01, high_direction: 0x0f



  • Can anyone give me a hint, what went wrong?

    Many thanks in advance,

    Sigi

    Could you give the config script you are using, as slow programming usually means you have not setup a target working area in ram.

    Not any help with your problem but the str720 was phased out by ST about 10 months ago, i hope this is not a new design ?

    Cheers

    Spen

    The slow download is indeed caused by a missing working area. My problem is that if I use a working area, which is either 16 KB in the integrated SRAM or 512 KB in external SDRAM, programming fails at the first byte. From the OpenOCD log file you can see that after transferring 32 KB data into the working area (the SDRAM version) OpenOCD fails with a busy status of 0xff. To me that looks as if an erased cell of the flash is read instead the status value. Something in the programming algorithm seems to fail. Maybe it is a timing problem? The processor core is operating at 24 MHz is this too fast? Shall I try to slow it down?

    Besides this I know that STR720 is no longer available. It board was designed as a student project. Since the processor is no longer valid only five boards exist and have no commercial use. I use this board privatly to learn more about programming of ARM7 designs. But with all my troubles so far I think I will move to a commercial board with an ARM7 processor from Atmel. For them there seems to be a lot of code and knowledge available in the internet.

    Sigi

    Dominic:
    I’ve received several patches adding support for other CFI flashes (namely SST, iirc), but none were clean enough for inclusion, or didn’t make me fear they would break the existing supported devices.

    Can you put them somewhere publically accessible so one can take that as a base for improvements? A note what's wrong with the patches would be fine, too :-)

    Dominic:
    The SST devices (as well as AMD/Spansion and a few others) seem to violate the CFI standard, which clearly states that (JEDEC Standard No. 68.01, p. 2):

    All of the modern(29lv160 and later) AMD/spansion flashes I know of adhere to the CFI standard with regard to probing. After all, AMD wrote the CFI spec. I have no idea about SST.

    I have patches tested against S29GL128N that use the cfi code to identfy the device. They don’t handle locking at all right now, but I believe I sent them to you quite a while back.

    Hello Andrew,

    I’ve put your patch into the patch tracking system at berlios a long time ago, and several people used it as a starting point. Back then you told me that it wasn’t ready yet, and that you wouldn’t have time to work on it in the near future, so I just put it there for people to work with.

    Since then I’ve received several patches, but most of them broke the existing Intel flash support, or were only meant to support one specific family, but not all flashes using primary OEM command set 0x2

    With regard to probing, we could add a config parameter (e.g. alt_probe) to make sure devices that adhere to the CFI standard don’t get irritated. Currently 0xaa and 0x55 aren’t used by any device whose datasheet I checked, but the config option shouldn’t hurt and would be a safeguard for future/unknown CFI flash memories.

    Regards,

    Dominic

    The U-Boot project has flash code for Intel and AMD devices that looks rather easy to move to the openocd project - it implements the CFI 2001 spec

    For those interested here are the links:

    Project Web site:

    http://u-boot.sourceforge.net/

    Download Page

    ftp://ftp.denx.de/pub/u-boot

    Hello Dominic

    I think I found a bug. I noticed that OPEN OCD does not use the CFI interface description byte (0x28) to determine the actual device mode. So for example if a x16/x8 capable device was strapped in x8 mode it would still require (by the CFI spec) that the addresses are doubled to use CFI commands. The bus_width and chip_width directives would have to be set incorrectly on such a device resulting in size calculations that are off by a factor two. I have verified this error on devices I am working with.

    References: CFI version 2.0, 2001

    “Table 3.1.1 Summary of Command Sequence as a function of device and mode”

    PS thanks for all of your hard work OPENOCD is a wonderful project!

    Hi,

    adyer:
    I have patches tested against S29GL128N that use the cfi code to identfy the device. They don’t handle locking at all right now, but I believe I sent them to you quite a while back.

    care to share those patches? (the only CFI related patch in the project patch tracker refers to an (unspecified) Atmel device and does not work with S29GL128N)

    Regards,

    Anders

    alarsen:
    care to share those patches? (the only CFI related patch in the project patch tracker refers to an (unspecified) Atmel device and does not work with S29GL128N)

    I was just in the process of sending an updated version to Dominic. Ask him in a hour or so :slight_smile:

    The U-Boot project has flash code for Intel and AMD devices that looks rather easy to move to the openocd project - it implements the CFI 2001 spec

    I find the u-boot cfi flash driver very difficult, and the linux code much easier to understand.

    I was just in the process of sending an updated version to Dominic. Ask him in a hour or so

    The new code sent by Andrew is going to add support for Spansion flashes, but not for Atmel flashes. Atmel reports the same CFI primary command set (0x2), and seems to use the same algorithm sequences, but uses a completely different CFI primary extended query table.

    The linux kernel uses fixups that are applied depending on the JEDEC manufacturer ID and device ID (where necessary). I’d like to implement something similar in the OpenOCD’s CFI driver, as this allows us to write cleaner code than u-boot’s driver for example.

    I have a board using Atmel’s AT49BV322A(T) here for testing, so I’ll be able to try the Atmel workarounds myself. Spansion seems to set the standard for command set 0x2, so we should use that as a base. If someone wants support for a different flash using command set 0x2 he’ll have to supply a patch that implements the fixups as shown by the Atmel example I’m going to write.

    I think I found a bug. I noticed that OPEN OCD does not use the CFI interface description byte (0x28) to determine the actual device mode. So for example if a x16/x8 capable device was strapped in x8 mode it would still require (by the CFI spec) that the addresses are doubled to use CFI commands. The bus_width and chip_width directives would have to be set incorrectly on such a device resulting in size calculations that are off by a factor two. I have verified this error on devices I am working with.

    This could be a real problem (but I haven't seen a board using a x16 chip in x8 mode yet - do you have one with which you could test?), because using the interface description byte wouldn't solve this issue - to be able to read that description byte we'd already have to know that we're working with a x16 device in x8 mode. I think an additional command line option would be appropriate for this.

    Regards,

    Dominic

    The U-Boot project has flash code for Intel and AMD devices that looks rather easy to move to the openocd project - it implements the CFI 2001

    This could be a real problem (but I haven’'t seen a board using a x16 chip in x8 mode yet - do you have one with which you could test?)

    Yes I do - I am using a Spansion S29GL064M90 part in my project (it is DNS-323 Dlink NAS) - the main update from the AMD patch is the x16/x8 mode which causes a factor of 2 scale factor in address depending on the settings in CFI 0x28 byte.

    Regarding the x16/x8 mode a simple solution I like is to loop through all possible bus and chip width value while examining the CFI response - then set the address scale values based on the results. It least their is no doubt once that step is done as to what values to use. I have added this to the current CFI code and it works fine - for me.

    because using the interface description byte wouldn’‘t solve this issue - to be able to read that description byte we’‘d already have to know that we’'re working with a x16 device in x8 mode. I think an additional command line option would be appropriate for this.

    Yes that would be ok

    Hi,

    Dominic:
    The new code sent by Andrew is going to add support for Spansion flashes

    I can confirm that the new code works with my Spansion S29GL128N flash chip :D

    Thanks Andrew (and Dominic, of course)

    Cheers

    Anders

    Hi alarsen,

    Can u share ur OpenOCD Config file. and How did u check the Spansion Flash i.e the commands u used to get flash info

    Regards

    Gururaja

    Hi,

    Can u share ur OpenOCD Config file

    sure (it's an Atmel AT91RM9200 (ARM920T) CPU):
    #daemon configuration
    telnet_port 4444
    gdb_port 3333
    
    #interface
    interface ft2232
    ft2232_device_desc "Olimex OpenOCD JTAG A"
    ft2232_layout "olimex-jtag"
    ft2232_vid_pid 0x15ba 0x0003
    jtag_speed 0
    jtag_nsrst_delay 500
    jtag_ntrst_delay 500
    
    reset_config trst_and_srst
    
    #jtag scan chain
    #format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE)
    jtag_device 4 0x1 0xf 0xe
    
    #target configuration
    daemon_startup reset
    
    #target <type> <startup mode>
    #target arm9tdmi <reset mode> <chainpos> <endianness> <variant>
    target arm9tdmi little reset_halt 0 arm920t
    target_script 0 reset cpu1.script
    working_area 0 0x30000000 0x40000 nobackup
    
    #flash configuration
    flash bank cfi 0x10000000 0x1000000 2 2 0
    

    cpu1.script:

    mww 0xffffff00 0x00000001	# cancel reset remapping
    mww 0xfffffc20 0x0000ff01	# PMC_MOR: Enable main oscillator, OSCOUNT = 0xff
    # Init flash
    mww 0xffffff10 0x00000000	# MC_PUIA[0]
    mww 0xffffff50 0x00000000	# MC_PUP
    mww 0xffffff54 0x00000000	# MC_PUER: Memory controller protection unit disable
    mww 0xffffff64 0x00000000	# EBI_CFGR
    mww 0xffffff70 0x00003284	# SMC_CSR[0]: 16bit, 2 TDF, 4 WS
    mww 0xffffff78 0x00003284	# SMC_CSR[2]: 16bit, 2 TDF, 4 WS
    mww 0xffffff8c 0x00004182	# SMC_CSR[7]:  8bit, 1 TDF, 2 WS
    # Init clocks
    mww 0xfffffc28 0x2026be04	# PLLAR: 179.712000 MHz for PCK
    sleep 10
    mww 0xfffffc2c 0x10483e0e	# PLLBR: 48.054857 MHz (divider by 2 for USB)
    sleep 10
    mww 0xfffffc30 0x00000202	# MCKR : PCK/3 = MCK Master Clock = 59.904000MHz from PLLA
    sleep 10
    # Init SDRAM
    mww 0xfffff870 0xffff0000	# PIOC_ASR: Configure PIOC as peripheral (D16/D31)
    mww 0xfffff874 0x00000000	# PIOC_BSR:
    mww 0xfffff804 0xffff0000	# PIOC_PDR:
    mww 0xffffff60 0x00000002	# EBI_CSA : CS1=SDRAM
    mww 0xffffff64 0x00000000	# EBI_CFGR:
    mww 0xffffff98 0x21914155	# SDRC_CR :
    mww 0xffffff90 0x00000002	# SDRC_MR : Precharge All
    mww 0x20000000 0x00000000	# access SDRAM
    mww 0xffffff90 0x00000004	# SDRC_MR : Refresh
    mww 0x20000000 0x00000000	# access SDRAM
    mww 0x20000000 0x00000000	# access SDRAM
    mww 0x20000000 0x00000000	# access SDRAM
    mww 0x20000000 0x00000000	# access SDRAM
    mww 0x20000000 0x00000000	# access SDRAM
    mww 0x20000000 0x00000000	# access SDRAM
    mww 0x20000000 0x00000000	# access SDRAM
    mww 0x20000000 0x00000000	# access SDRAM
    mww 0xffffff90 0x00000003	# SDRC_MR : Load Mode Register
    mww 0x20000080 0x00000000	# access SDRAM
    mww 0xffffff94 0x000002e0	# SDRC_TR : Write refresh rate
    mww 0x20000000 0x00000000	# access SDRAM
    mww 0xffffff90 0x00000000	# SDRC_MR : Normal Mode
    mww 0x20000000 0x00000000	# access SDRAM
    

    How did u check the Spansion Flash i.e the commands u used to get flash info

    like this:
    > reset run_and_init
    > flash banks
    #0: cfi at 0x10000000, size 0x01000000, buswidth 2, chipwidth 2
    > flash probe 0
    flash 'cfi' found at 0x10000000
    > flash info 0
    #1: cfi at 0x10000000, size 0x01000000, buswidth 2, chipwidth 2
    
    cfi information:
    
    mfr: 0x0001, id:0x227e
    qry: 'QRY', pri_id: 0x0002, pri_addr: 0x0040, alt_id: 0x0000, alt_addr: 0x0000
    Vcc min: 2.7, Vcc max: 3.6, Vpp min: 0.0, Vpp max: 0.0
    typ. word write timeout: 128, typ. buf write timeout: 128, typ. block erase timeout: 1024, typ. chip erase timeout: 1
    max. word write timeout: 1024, max. buf write timeout: 4096, max. block erase timeout: 16384, max. chip erase timeout: 1
    size: 0x1000000, interface desc: 2, max buffer write size: 5
    
    Spansion primary algorithm extend information:
    pri: 'PRI', version: 1.3
    Silicon Rev.: 0x4, Address Sensitive unlock: 0x0
    Erase Suspend: 0x2, Sector Protect: 0x1
    VppMin: 11.5, VppMax: 12.5
    

    Cheers

    Anders

    Hi,

    Thanks for the Config file & other relative details

    Regards

    Gururaja

    Hi,

    I am working on customized variant of arm versatile board. We have arm92ejs processor with S29GL128N Flash. At present i am able probe and get info and also erase with the flash commands but not able write any image/binary data. I get a error saing Error: cfi.c:888 cfi_protect(): cfi primary command set 2 unsupported

    Kindly help me to solve this. I heard there is a set of patches for this command set. Kindly care to share the links .

    TIA

    Regards

    Gururaja