Problems with erasing and programming PFlash on AURIX TriCore (tc0), TC277-DC

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Not applicable
Questions regarding use of Infineon - Memtool (v4.07.03) with TC277-DC:

1. After using the "Erase..." option to erase a sector of PFlash (PF0), if I subsequently use the "Read..." option to read and save that same sector to a (bin or hex) file, the data is *not* all zeroes. The sector becomes *mostly* zero, but several widely-spaced bytes are non-zero (usually contain 0x40, 0x20, 0x10, or 0x02).

Here is an example hex-dump (512 bytes) of an "erased" PF0, sector 1 (the offsets shown are from 0xA0004000, PF0-S1):

00000: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
00010: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
00020: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
00030: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
00040: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
00050: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
00060: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
00070: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
00080: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
00090: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
000A0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
000B0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
000C0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
000D0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
000E0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
000F0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
00100: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
00110: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
00120: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
00130: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
00140: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
00150: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
00160: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
00170: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
00180: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
00190: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
001A0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
001B0: 00 00 00 00 00 00 00 00 - 00 40 00 00 00 00 00 00 : .........@......
001C0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 20 00 00 : ............. ..
001D0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
001E0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................
001F0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 : ................

The Memtool Diagnostic Log reports no errors when erasing the sector.

According to the TC27x D-Step User Manual v3.8, section 10.5, an erased Flash cell should read as 0. Why is this not happening when I use the erase feature to erase PFlash sectors with Memtool?

2. If I use the Device->Test Empty menu option to test a previously erased PFlash sector, it reports "not empty". Why is this (presumably related to the first problem of non-zero values left after erasure)?

And BTW, I do not see either of these observations when erasing DFlash (DF_EEPROM) sectors using Memtool:
- the sector reads back as all zeroes after an erasure
- the "Test Empty" feature reports the sector as "empty"

Questions regarding the Infineon "FlashDemo":

1. As I reported in a separate unresolved posting, I'm unable to compile the Infineon ILLD demos (AURIX iLLD Demos v1.0.1.0.0.zip) using the Infineon supplied iLLD source and header files (AURIX iLLD Package v1.0.1.0.0.zip) with the TASKING tool chain (TASKING_TriCore-VX_v6.2r1).
At this time, I'm most interested in Infineon's FlashDemo (Aurix1G/FlashDemo) which supposedly can successfully write to both DFlash and PFlash from user code (the demo) running on the TriCore (tc0).

I *am* able to build this FlashDemo by using the iLLD source and header files included with the TASKING tool chain rather than the iLLD package supplied directly from Infineon. The iLLD files included with the TASKING tool chain appear to be iLLD v1.0.0.11.0 (older), where as the iLLD files supplied by Infineon are v1.0.1.0.0 (newer).

Anyway, the resulting FlashDemo executable built in this manner cannot successfully flash the PFlash.

A. If the sector was previously "erased" (i.e. using Memtool), then the PFlashDemo function fails the verification. When reading the sector (e.g. using Memtool), I see no evidence that the PFlashDemo->pFlashProgram actually changed the contents of the flash sector.

B. If the sector was previously "programmed" (i.e. using Memtool), then the PFlashDemo hangs in the "Verify the programmed data" loop (on the first read of the PFlash area).

Since I have to build the FlashDemo outside of the Eclipse IDE using a hand-written makefile, I've been unable to get the debugger to attach and provide more details for the reason of the hang. Is there a way to simply point the debugger to an already built hex or elf file and attach to the target debug it (without creating a building a C/C++ project within Eclipse)?

Now the IfxFlash.c/h files included with iLLD v1.0.1.0.0 are quite different from the ones in iLLD v1.0.0.11.0 - is this the reason for the difference in expected and observed behavior with FlashDemo?

For those that are curious, I successfully built the Infineon FlashDemo by flattening the directory structure (putting all the relevant files from Aurix1G/FlashDemo into a single directory):
Configuration.h
ConfigurationIsr.h
Cpu0_Main.c
Cpu0_Main.h
Cpu1_Main.c
Cpu2_Main.c
FlashDemo.c
FlashDemo.h

And then build with the attached GNU makefile (rename to Makefile or GNUmakefile).

-Rob
0 Likes
11 Replies
Not applicable
More details: building FlashDemo.hex using the IfxFlash.c/h from AURIX iLLD Package v1.0.1.0.0.zip -> iLLD_1_0_1_0_0\Src\BaseSw\iLLD\TC27D\Tricore\Flash\Std\ made no difference in the FlashDemo behavior from what I reported above. PFlashDemo will still either fail the PFlash write validation/comparison or hang when trying to read the PFlash after writing depending on whether I previously erased the sector by hand using Memtool.

In either case, reading the corresponding PFlash sector with Memtool after executing FlashDemo shows no evidence of data being changed in the sector by the PFlashDemo. I've experimented with PFlash sectors 1, 4, 20, 21, and 22 (careful to avoid sectors with BMHDs or for HSM use) with no observed difference in behavior between the PFlash sectors.

Has anyone confirmed that Infineon's FlashDemo actually works on a TC277 or provide any clues why it's not working for me?

Or why Infineon's Memtool cannot fully erase a PFlash sector?

Thanks,

-Rob
0 Likes
Not applicable
Here's another clue:
If I read the Flash Status Register (FSR) just before the read of the PFlash (where the PFlashDemo halts), I get the value 0x01002000, that's bits 24 (RES) and 13 (PROER) set.

This seems to be result of my removing the calls to IfxScuWdt_clear/setSafetyEndinitInline from the FlashDemo's PFlashErase function. I did this (temporarily, as a test), because this function was either halting or causing the board to reset (depending on how/where I add debug code to FlashDemo.c). Putting the PFlashErase() back the way it was (with the "Safety" calls), and I'm back to this function either halting or resetting the board.

😞

-Rob
0 Likes
Not applicable
Hi,

I have the same issue than the question 1, I'm using TC23XL, the memory is not all 0 after the Flash erase a sector, and reports no error.
Is the None-Zero byte some special byte?
0 Likes
Not applicable
I've whittled the code down from Infineon to just this little bit:

static void FlashDemo(void)
{
uint16 endinitSfty_pw;
uint32 sector_addr = 0xaf008000;

endinitSfty_pw = IfxScuWdt_getSafetyWatchdogPassword();

/* erase program flash */
IfxScuWdt_clearSafetyEndinit(endinitSfty_pw);
IfxFlash_eraseSector(sector_addr);
IfxScuWdt_setSafetyEndinit(endinitSfty_pw);
}

If you change the sector address from a Data Flash sector (somewhere in the 0xaf00xxxx range) to a Program Flash sector (somewhere in the 0xa0000xxxx range) then the code executes until the call to IfxFlash_eraseSector() and then resets the core (or jumps to the reset vector), executes the user code again and on the second invocation of IfxFlash_eraseSector(), the cores halt and the "RESET LED" (D604) lights red.

If the Flash address is within the Data Flash range, the code works fine.

If I copy this code to the PSPR first and execute from there, there is no difference in behavior.

If I use inline versions of the Set/ClearSafetyEndinit functions, there is no difference in behavior.

It appears something *else* must be done before you can erase or write to the Program Flash. Any one know what that is?

Thank you,

-Rob
0 Likes
Not applicable
Update:

By using the UDE Starterkit Debugger by PLS, I can now see that the Infineon FlashDemo code is entering trapcontext() when attempting to modify the PFlash sector.

Some time after successfully erasing the PFlash sector (again, not completely zeroed, but mostly), the code then jumps into the trap 3 handler:

0xA00F6060: 91 00 00 E8 MOVH.A a14,0x8000
0xA00F6064: D9 EE B6 61 LEA a14,[a14]0x19B6
0xA00F6068: DC 0E JI a14

Which subsequently calls _trapcontext():


0x800019B6: 0D 00 00 02 SVLCX
0x800019BA: 00 A0 DEBUG
0x800019BC: 8F 0F 43 41 OR d4,d15,0x30
0x800019C0: 6D FF E8 F3 CALL 0x80000190
0x800019C4: 0D 00 40 02 RSLCX
0x800019C8: 00 80 RFE
0x800019CA: 0D 00 00 02 SVLCX
0x800019CE: 00 A0 DEBUG
0x800019D0: 8F 0F 42 41 OR d4,d15,0x20
0x800019D4: 6D FF DE F3 CALL 0x80000190
0x800019D8: 0D 00 40 02 RSLCX

etc.

But upon executing the first instruction in _trapcontext() (SVLCX) the debugger loses step-control of the processor. If I break-in again, I end up back in the trap 3 handler. A look at the callstack shows these 2 addresses, like they're being called recursively:

0x800019B6
0x800019B6
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xA00F6080
0xC0000068
0x80000920
0x800007E8
0x8000062A
0x80001A6A
0x80001988

So I'm now reading TriCore Architecture Volume 1, section 6.3.4 Context Management (Trap Class 3). But if anyone has any tips, I'm all ears.

-Rob
0 Likes
Not applicable
Update:

I misspoke when I wrote "If I copy this code to the PSPR first and execute from there, there is no difference in behavior.". The code does have to be copied to and executed from PSPR or the failure symptoms are quite different.

The current state is: By copying the executing code to PSPR I can erase (mostly, not all zero as I've stated before) a PFlash sector, but while waiting for the PFlash to become "unbusy", the processor enters a trap condition (sometimes trap class 3 and sometimes class 4). The last line of code to execute successfully is from IfxFlash_waitUnbusy. The line that triggers the trap is:

while ((FLASH0_FSR.U & (1 << flashType))

This is the equivalent of:

while ((*(volatile uint32*)0xF8002010) & (1 << 3))

and indeed, if I just add a single line before this (reading the Flash Status Register), then that is where it will trap:

(void)*(volatile uint32*)0xF8002010;

The TIN value (stored in register D15) is always 0x00000004. This doesn't appear make any sense when reading the TriCore architecture document's description of trap class 3->TIN 4 or class 4->TIN 4.

HOWEVER: if I attach to the target using the UDE STK debugger and step through the relevant code an instruction at a time, it runs fine to completion, erasing and programming the PFlash sector successfully.

Any pointers would be extremely appreciated.

-Rob
0 Likes
Not applicable
Update:

I think I may have identified the problem (but not the solution). Here is the exact instruction at the location of a trap that occurs while erasing the PFlash from the TriCore PSPR (Program Scratch Pad RAM):

0x7010008E: 85 8F 38 00 LD.W d15,0x80000038

The value being loaded into the register (d15) is just a numeric constant used in the C source (not assigned to a variable). It doesn't really matter what numeric constant, it could be anything (e.g. the address of the FSR as used in IfxFlash.*), but in this case it's just a debug value and it was apparently given a location in PFlash and is always dereferenced from there (rather than placing it in the text segment along with the relevant code).

What's important is although the code is located in RAM (0x7xxxxxxx), the data being fetched (a simple numeric constant) is still located in Flash (0x8xxxxxxx).

Here's that data item in the .map file:

| Chip | Group | Section | Size (MAU) | Space addr | Chip addr | Alignment |
| mpe:pflash0 | | .zrodata.FlashDemo..11.cnt (194) | 0x00000004 | 0x80000038 | 0x00000038 | 0x00000002 |


My suspicion is that it's this data access from PFlash (while in the process or erasing or writing/programming the PFlash) that is the main issue with the Infineon FlashDemo.c. I think if I can relocate these constants to RAM (e.g. DSPR or PSPR) that may resolve the issue.

I've been trying to force these unnamed constant data items into DSPR (Data Scratch Pad RAM), without success, using a linker script like so:

#include "cpu.lsl"

section_layout mpe:vtc:linear
{
group (run_addr = mem:mpe:dspr0, copy )
{
select ".zrodata.FlashDemo.*"; // select sections for dspr0
}
}


This .lsl file does not move the location of the .zrodata.FlashDemo.* items to DSPR0, like I'd hoped. If I change to the "select" line to be more generic (e.g. *data*), it tries to copy items that "already has a copy" and the link fails.

Any help? Anyone? Hello?

-Rob
0 Likes
Not applicable
We received the following explanation from an engineer at Infineon with regards to the non-zero values in erased PFlash sectors:

The missing link here is that when you erase memory on the AURIX, both the data and the ECC bits are cleared to 0. Because the ECC calculation includes the address bits for each page of flash, the valid ECC for each page is non-zero. So, reading an erased page actually results in an uncorrectable memory error, rather than reading 0.

The reason Memtool shows occasional non-zero bits in erased memory is that when the ECC algorithm is overloaded with more than the 3 incorrect bits it can normally detect, it may alias the data into some other value.

This doesn’t apply to data flash, because the address isn’t part of the ECC calculation, and all 0s is a valid ECC pattern for a data flash page filled with 0.


Why Memtool reports these erased PFlash sectors as "not empty" is still unexplained, but likely just a bug in Memtool.

-Rob
0 Likes
Not applicable
More information:

I've tried "section renaming" to get these numeric constants (.zrodata.*) into the DSPR or PSPR by adding to FlashDemo.c:

#pragma section farrom dspr0
#pragma section nearrom dspr0

combined with this linker script:

#include "cpu.lsl"

section_layout mpe:vtc:linear // core vtc containing all address spaces
{ // of all cores
group dspr0 (run_addr = mem:mpe:dspr0, copy ) // tc0 memory dspr0
{
select "*.dspr0"; // select sections for dspr0
}
}


This successfully moved 71 bytes of "constant __far data" to PSPR0:

* Memory usage in bytes
========================
+--------------------------------------------------------------------+
| Memory | Code | Data | Reserved | Free | Total |
|====================================================================|
| mpe:brom | 0x0 | 0x0 | 0x008000 | 0x0 | 0x008000 |
| mpe:dflash0 | 0x0 | 0x0 | 0x064000 | 0x0 | 0x064000 |
| mpe:dflash1 | 0x0 | 0x0 | 0x010000 | 0x0 | 0x010000 |
| mpe:dspr0 | 0x0 | 0x000047 | 0x005400 | 0x016bb9 | 0x01c000 |


But left the problematic numeric constants (apparently "nearrom" since they're given the .zrodata prefix) in PFlash0. Example from .map file:

| Chip        | Group        | Section                                                                | Size (MAU) | Space addr | Chip addr  | Alignment  |
| mpe:pflash0 | | .zrodata.dspr0 (204) | 0x00000004 | 0x800000cc | 0x000000cc | 0x00000002 |


So at least I've successfully relocated *something* to DSPR, but not the data I needed to.

I've submitted a support request with TASKING (Altium) as well.

-Rob
0 Likes
Not applicable
Success!

I found this little blurb in the 1200 page TASKING tools manual:

#pragma section const_init
Sections with constant data are copied from ROM to RAM at program startup.

That's the line that was needed. It's not included in any of the Infineon or TASKING sample source code (I've scanned) and apparently there's no linker-script equivalent. But that's the "magic incantation" needed to force the constant data into the RAM rather than Flash (what they're calling "ROM" above) and now the Infineon flashing code consistently works.

Adding this one line (the #pragma above) before any #includes in FlashDemo.c allows it to work without exception/trapping.

-Rob
0 Likes
Not applicable
I also created an Altium/TASKING support request to see if there is a linker script equivalent and received this helpful response:

The reason for the trouble you experienced is that you used the 'wrong' section_Layout type for the copy assignment to near addressable sections. You used

mpe:vtc:linear

which is used for far addressable sections (.data, .text, .bss) but not for near addressable sections (.zdata, .zbss).

For near (abs18) addressed sections it needs to be

mpe:vtc:abs18

With this adjustment to the linker script, I can use that method of relocating the constant data to the DSPR as well:

#include "cpu.lsl"

section_layout mpe:vtc:abs18
{
group NEAR_CONST_DATA (run_addr = mem:mpe:dspr0, copy ) // tc0 memory dspr0
{
select ".zrodata.FlashDemo.*"; // select sections for dspr0
}
}


I also got this helpful tip from TASKING support:

Hint: Always use a group name e.g.:

group NEAR_CONST_DATA (run_addr = mem:mpe:dspr0, copy )

Then it is quite easy to determine whether the linker did what you expect it to do or it ignored your group entry for whatever reason. Just look at the generated map file in the locate result section. Here you can search for the

.zrodata.FlashDemo.*

sections and if the 'group' column beneath the entry is empty and does not show the assignment to group NEAR_CONST_DATA you know that the linker simply ignored you group assignment (but it does not complain since it is syntactically correct).


I hope this information helps other engineers with similar issues with regards to erasing/writing AURIX PFlash.

-Rob
0 Likes