Monday, January 22nd 2018, 11:10am UTC+1

You are not logged in.

  • Login
  • Register

iurly

Beginner

Date of registration: Jan 2nd 2018

Posts: 2

1

Wednesday, January 3rd 2018, 1:55pm

J-Link won't reprogram a page with all 1's on STM32L4

Hi,

I have an issue with JLinkExe/J-Flash on an STM32L433CC, which I suspect is due to some JLink flash access optimization.
TL;DR
if you programatically and explicitly write a flash page (2KB) with all-1's (from within your firmware code), J-Link won't be able to reprogram it unless you erase the whole flash first!

Long story (after several hours of debugging):

I am implementing a simple bootloader to allow for on-the-field firmware upgrade. I have two separate binaries: a small bootloader firmware (flashed at the reset address location, 0x08000000) and the actual application firmware (stored at 0x08020000).
I use J-Link/GDB under Eclipse with the appropriate settings so that I can quickly program and debug both the bootloader and the application with a single mouse
click, which I find very convenient.

For the on-the-field upgrade, it goes like this: you flash the new application code starting at 0x08004000 and set a flag in the flash and then reboot.
The bootloader then checks for the flag and if it is set, it erases the flash area containing the current firmware and overwrites it with the new one before jumping to it. Pretty simple.
To test the bootloader code, I tried downloading an empty firmware (all-0xFF's) in the special area and setting the flag. The bootloader then just copies it over in the application-dedicated area, 0x08020000, (remember, it's all FF's!).

After that, I can't reprogram the flash pages starting at 0x08020000 using J-Link/GDB anymore. The error message (or lack thereof) varies depending on the tool/OS I use.

What's worse, GDB will just behave as if everything had been OK!
See the output here (GDB/Linux):

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
SEGGER J-Link GDB Server V6.22d Command Line Version

JLinkARM.dll V6.22d (DLL compiled Dec 14 2017 18:34:21)

Command
 line: -if swd -device STM32L433CC -endian little -speed 1000 -port 2331
 -swoport 2332 -telnetport 2333 -vd -ir -localhostonly 1 -singlerun 
-strict -timeout 0 -nogui
-----GDB Server start settings-----
GDBInit file:              	none
GDB Server Listening port: 	2331
SWO raw output listening port: 2332
Terminal I/O port:         	2333
Accept remote connection:  	localhost only
Generate logfile:          	off
Verify download:           	on
Init regs on start:        	on
Silent mode:               	off
Single run mode:           	on
Target connection timeout: 	0 ms
------J-Link related settings------
J-Link Host interface:     	USB
J-Link script:             	none
J-Link settings file:      	none
------Target related settings------
Target device:             	STM32L433CC
Target interface:          	SWD
Target interface speed:    	1000kHz
Target endian:             	little

Connecting to J-Link...
J-Link is connected.
Firmware: J-Trace Cortex-M Rev.3 compiled Nov 23 2017 16:43:50
Hardware: V3.10
S/N: <cut>
Feature(s): RDI, FlashBP, FlashDL, JFlash, GDB
Checking target voltage...
Target voltage: 3.27 V
Listening on TCP/IP port 2331Connecting to target...Connected to target
Waiting for GDB connection...Connected to 127.0.0.1
Reading all registers
Read 4 bytes @ address 0x00000000 (Data = 0x2000C000)
Read 2 bytes @ address 0x00000000 (Data = 0xC000)
Received monitor command: speed 1000
Target interface speed set to 1000 kHz
Received monitor command: clrbp
Received monitor command: reset
Resetting target
Received monitor command: halt
Halting target CPU...
...Target halted (PC = 0x08001F24)
Received monitor command: regs
R0 = 00000000, R1 = 00000000, R2 = 00000000, R3 = 00000000
R4 = 00000000, R5 = 00000000, R6 = 00000000, R7 = 00000000
R8 = 00000000, R9 = 00000000, R10= 00000000, R11= 00000000
R12= 00000000, R13= 2000C000, MSP= 2000C000, PSP= 00000000
R14(LR) = FFFFFFFF, R15(PC) = 08001F24
XPSR 01000000, APSR 00000000, EPSR 01000000, IPSR 00000000
CFBP 00000000, CONTROL 00, FAULTMASK 00, BASEPRI 00, PRIMASK 00
Reading all registers
Read 4 bytes @ address 0x08001F24 (Data = 0xD034F8DF)
Read 2 bytes @ address 0x08001F24 (Data = 0xF8DF)
Received monitor command: speed auto
Select auto target interface speed (2000 kHz)
Received monitor command: flash breakpoints 1
Flash breakpoints enabled
Read 4 bytes @ address 0x08001F24 (Data = 0xD034F8DF)
Read 2 bytes @ address 0x08001F24 (Data = 0xF8DF)
Downloading 120 bytes @ address 0x08020000 - Verified OK
......cut.....
Downloading 856 bytes @ address 0x08030808 - Verified OK
Comparing flash   [....................] Done.
Erasing flash 	[....................] Done.
Programming flash [....................] Done.
Verifying flash   [....................] Done.
Writing register (PC = 0x0802BBBC)
Read 4 bytes @ address 0x0802BBBC (Data = 0xFFFFFFFF)
Read 2 bytes @ address 0x080212EA (Data = 0xFFFF)
Read 2 bytes @ address 0x080212E8 (Data = 0xFFFF)
Read 2 bytes @ address 0x0802B4D4 (Data = 0xFFFF)
Read 2 bytes @ address 0x080212EA (Data = 0xFFFF)
Read 2 bytes @ address 0x080212E8 (Data = 0xFFFF)
Received monitor command: clrbp
Received monitor command: reset
Resetting target
Received monitor command: halt
Halting target CPU...
...Target halted (PC = 0x08001F24)
Read 2 bytes @ address 0x0802B4D4 (Data = 0xFFFF)
Received monitor command: regs
R0 = 00000000, R1 = 00000000, R2 = 00000000, R3 = 00000000
R4 = 00000000, R5 = 00000000, R6 = 00000000, R7 = 00000000
R8 = 00000000, R9 = 00000000, R10= 00000000, R11= 00000000
R12= 00000000, R13= 2000C000, MSP= 2000C000, PSP= 00000000
R14(LR) = FFFFFFFF, R15(PC) = 08001F24
XPSR 01000000, APSR 00000000, EPSR 01000000, IPSR 00000000
CFBP 00000000, CONTROL 00, FAULTMASK 00, BASEPRI 00, PRIMASK 00
Reading all registers
Read 4 bytes @ address 0x08001F24 (Data = 0xD034F8DF)
Read 2 bytes @ address 0x08001F24 (Data = 0xF8DF)
Setting breakpoint @ address 0x080212E8, Size = 2, BPHandle = 0x0001
Setting breakpoint @ address 0x0802B4D4, Size = 2, BPHandle = 0x0002
Starting target CPU...

However, when reading back the area at 0x08020000 (where the application should have been), I read all FF's.
If I do the same operation on the CLI tool JLinkExe/Linux, I at least get some hint that something went wrong:

Source code

1
2
3
4
5
6
7
Comparing flash   [100%] Done.
Erasing flash 	[100%] Done.
Programming flash [100%] Done.
Verifying flash   [100%] Done.
J-Link: Flash download: Restarting flash programming due to program error (possibly skipped erasure of half-way erased sector).
J-Link: Flash download: Skip optimizations disabled for second try.
Error while programming flash: Programming failed.



Almost in despair, I also tried using J-Flash (under Windows):

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
Erasing selected sectors ...
 - 1 of 128 sectors selected, 1 range, 0x8020000 - 0x80207FF
 - Start of preparing flash programming
 - End of preparing flash programming
 - Start of determining dirty areas in flash cache
 - End of determining dirty areas
 - CPU speed could not be measured.
 - Start of erasing sectors
 - Start of blank checking
 - End of blank checking
 - End of erasing sectors
 - Start of restoring
 - End of restoring
 - Erase operation completed successfully - Completed after 0.156 sec
Checking if selected data fits into selected flash sectors.
Programming target (8 bytes, 1 range) ...
 - Start of preparing flash programming
 - End of preparing flash programming
 - Start of determining dirty areas in flash cache
 - End of determining dirty areas
 - CPU speed could not be measured.
 - Start of erasing sectors
 - Start of blank checking
 - End of blank checking
 - End of erasing sectors
 - Start of flash programming
 - Programming range 0x08020000 - 0x080207FF (001 Sector, 2 KB)
 - End of flash programming
 - Flash programming performed for 1 range (2048 bytes)
 - 0x8020000 - 0x80207FF (001 Sector, 2 KB)
 - Start of restoring
 - ERROR: Programming failed @ address 0x08020008 (program error)
 - ERROR: Failed to restore target. RAMCode never stops
 - End of restoring
 - ERROR: Failed to program target
Disconnecting ...
 - Disconnected


After performing a mass erase actually everything goes back to normal.
Also, programmatically erasing the incriminated pages seems to also fix the situation.

So while I can't be 100% sure it's J-Link's fault, it looks like its optimization logic gets somehow deceived by this use case (albeit a pretty unique one, I admit).
The root cause is perhaps to be found within the STM32L4 internal flash implementation with its out-of-band ECC making an empty/erased flash page look indistinguishable from a page programmed with all 1's, even though the former can be reprogrammed at will, while the latter must be erased first.

For now I worked around the issue by adding an explicit check in the flash programming routine which refrains from explicitly writing a 64-bit double word if it's all 1's.

Nevertheless, it's quite unnerving how:
1) GDB incorrectly reports that programming was successful even though that was absolutely not the case!
2) JLinkExe tries to disable its internal optimization, without much success though
3) J-Flash reports "Erase operation completed successfully" (while apparently nothing was erased)
4) I found no way to explicitly and unconditionally erase a single page!

Could anyone please confirm whether my suspicion makes any sense at all or maybe I'm doing something wrong somewhere else?
Is there any better way to deal with this?
Any chance this could be fixed so that real errors are reported?

Thank you!

SEGGER - Nino

Super Moderator

Date of registration: Jan 2nd 2017

Posts: 567

2

Thursday, January 4th 2018, 5:28pm

Hello,

Thank you for your inquiry.

We were able to reproduce the issue with a STM32L4 board and J-Flash.
For this particular device family it seems that the flash can only be programmed once after erase.
Now programming all 0xFF also counts as programming once for the STM32L4.
If you try to program again on top of that J-Link will read all 0xFF and due to optimization think it was already erased and try to program the same flash cells a second time without erasing beforehand which results in a "confused" state of the target device. Thus no operations afterwards work properly until a software or power on reset.
As it is not feasible for us to remove optimizations for such a special case we can only offer workarounds in that matter:

- Try to use other testdata than 0xFF to avoid the erase optimization, for this you can use e.g. J-Flash and there under Target->Test->Generate Test data... and generate data which creates code for an application that is a simple branch loop onto itself which is not harmful to Cortex-M devices.
- Skip automatic flash compare, then an erase of the affected area will always be executed and thus you make sure that particular sector gets erased each time. For this you can use exec command "SetCompareMode" which sets the compare mode for the current session. Set this to "Skip" and you should no longer have any of the described issues.
For more information consult the J-Link User Manual.

Quoted

I found no way to explicitly and unconditionally erase a single page!

To do this specifically only J-Flash can be used as for all other cases the J-Link Software takes automatically care of only erasing affected sectors to increase the longevity of the users flash memory.

Best regards,
Nino

iurly

Beginner

Date of registration: Jan 2nd 2018

Posts: 2

3

Sunday, January 7th 2018, 12:26am

Thank you for you reply, see my comments inline.

Hello,

Thank you for your inquiry.

We were able to reproduce the issue with a STM32L4 board and J-Flash.
For this particular device family it seems that the flash can only be programmed once after erase.
Now programming all 0xFF also counts as programming once for the STM32L4.
If you try to program again on top of that J-Link will read all 0xFF and due to optimization think it was already erased and try to program the same flash cells a second time without erasing beforehand which results in a "confused" state of the target device. Thus no operations afterwards work properly until a software or power on reset.

Actually a power on reset or even a power cycle, does not seem to help either.

Quoted


As it is not feasible for us to remove optimizations for such a special case we can only offer workarounds in that matter:

- Try to use other testdata than 0xFF to avoid the erase optimization, for this you can use e.g. J-Flash and there under Target->Test->Generate Test data... and generate data which creates code for an application that is a simple branch loop onto itself which is not harmful to Cortex-M devices.
- Skip automatic flash compare, then an erase of the affected area will always be executed and thus you make sure that particular sector gets erased each time. For this you can use exec command "SetCompareMode" which sets the compare mode for the current session. Set this to "Skip" and you should no longer have any of the described issues.
For more information consult the J-Link User Manual.

OK, I'll give it a try.

Quoted


Quoted

I found no way to explicitly and unconditionally erase a single page!

To do this specifically only J-Flash can be used as for all other cases the J-Link Software takes automatically care of only erasing affected sectors to increase the longevity of the users flash memory.



Well, the above workaround should be enough.
The last thing I don't understand though, is how J-Link GDB server does not report any error at all. I see a pretty reassuring line:

Source code

1
Verifying flash   [....................] Done.


which is somehow misleading. This would suggest that programming was succesful as a later comparison would provide a match. Yet this is certainly not the case.
Could you please elaborate? What does line refer to?

Thank you!