TC399 Flash sequence for write pflash & dflash

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

cross mob
User19104
Level 3
Level 3
First like received
Hi,

I cannot find anywhere the correct sequence for writing the flash in the different regions:

  • pflash
  • dflash


Can anyone assist on this matter?
0 Likes
30 Replies
cwunder
Employee
Employee
5 likes given 50 likes received 50 solutions authored
Have you looked at this post to see if this helps you?
https://www.infineonforums.com/threads/11063-Aurix-TC387-Memory-Flash
0 Likes
User19104
Level 3
Level 3
First like received
Thanks cwunder.

I'm trying to write to address 0x80001000

So it, and followed it in writing my code:

/* Write either 32 bytes or 256 bytes per page. */
uint16 password = IfxScuWdt_getSafetyWatchdogPassword();
uint32 j = 0;

IfxFlash_clearStatus(0);
IfxFlash_enterPageMode(dest);
// Check for Page Mode status bit or error
while (!DMU_HF_STATUS.B.PFPAGE )
{
if (DMU_HF_ERRSR.B.SQER == 1 || DMU_HF_ERRSR.B.PROER == 1)
return 1;
}

for (j= 0; j < size; j++)
{
IfxFlash_loadPage2X32(0x0, *((uint64*) dest), ((uint64*)src));
*((uint64*) dest) = ((uint64*)src);
}
IfxScuWdt_clearSafetyEndinitInline(password);
IfxFlash_writePage(dest);
// Check for Program status bit or error
while (!DMU_HF_OPERATION.B.PROG)
{
if (DMU_HF_ERRSR.B.SQER == 1 || DMU_HF_ERRSR.B.PROER == 1)
return 1;
}
IfxScuWdt_setSafetyEndinitInline(password);
IfxFlash_waitUnbusy(0, IfxFlash_FlashType_P0);


although flash does not enter page mode.
4149.attach
and is stuck on the first while loop.
0 Likes
User19104
Level 3
Level 3
First like received
OK, understood the mirroring issue.

now can write to that region by writing to 0xa0000000.

just need to understand how to create the delay:
/*Wait for 2*1/fFSI ns (DFlash) or 3*1/fFSI + 8*1/fSRI ns (PFlash). */
0 Likes
cwunder
Employee
Employee
5 likes given 50 likes received 50 solutions authored
just need to understand how to create the delay:
/*Wait for 2*1/fFSI ns (DFlash) or 3*1/fFSI + 8*1/fSRI ns (PFlash). */


You can issue a simple for loop for the instruction cycles needed.

For A2G:
You need to review your PLL and CCUCONx settings.
Basically the maximum frequency of the FSI is 100 MHz, the maximum frequency for the SRI is 300 MHz.
Taking these values you need to delay 20ns for the DFlash or 6 cpu cycles, with the PFlash you need to delay 56.7ns or 17 cpu cycles.

You can just implement something like this in C and double check your execution time.
  for (volatile uint32 delay=10; delay--; )   
0 Likes
User19104
Level 3
Level 3
First like received
Adding a big loop after the while wait:
 
while (!DMU_HF_OPERATION.B.PROG)
{
if (DMU_HF_ERRSR.B.SQER == 1 || DMU_HF_ERRSR.B.PROER == 1)
return 1;
}
for (delay=100000; delay > 0; delay-- )
{ __asm__ volatile ("nop"); }


I'm getting an exception:
4151.attach

Just to point out, that if I'm debugging line by line it works without exception.
0 Likes
cwunder
Employee
Employee
5 likes given 50 likes received 50 solutions authored
Adding a big loop after the while wait:

Why? You only need to wait nanoseconds... For the BUSY bit to set before checking it.

What are your Watchdog timeouts?
In your code is the SAFETY ENDINIT open while you are performing the delay as it should not be

Realize that your delay is more than the "nop" instruction you also need to account for all of the other instructions to construct this delay loop.

Here is code I have tried for programming a "Program" flash page

/* TC38x delays are just to make sure the maximum times are satisfied
* They are not for optimal performance
*/
#define FLASH_PROG_PAGE_DELAY 34500
#define FLASH_EVENT_DELAY 100
#define FLASH_BUSY_DELAY 10
#define FLASH_PROG_PAGE_SIZE 4


/*! \fn uint8 Flash_WriteProgPage(uint64 *dst, uint64 *src, uint8 pxBusy)
* \brief write program flash page (64 bytes in PFlash)
* \param *dst: Address to write to NVM memory (start of the page)
* \param *src: Address to read data to be written to NVM memory
* \param *pxBusy: page write operation occurs on this PFlash block
* \return error: E_OK for no faults, E_NOT_OK when a timeout or error occurred
******************************************************************************/
__attribute__((asection(".cpu0_psram", "a=4", "f=xwc0")))
uint8 Flash_WriteProgPage(uint64 *dst, uint64 *src, uint8 pxBusy)
{
uint16 password = IfxScuWdt_getSafetyWatchdogPassword();
volatile uint32 timeout;
uint8 error = E_OK;


IfxFlash_clearStatus(IFXFLASH_NUM_MODULES);
IfxFlash_enterPageMode((uint32) dst);


timeout = FLASH_EVENT_DELAY;
while (--timeout && !DMU_HF_STATUS.B.PFPAGE)
{
if ((1 == DMU_HF_ERRSR.B.SQER) || (1 == DMU_HF_ERRSR.B.PROER))
{
error = E_NOT_OK;
continue;
}
}


if ((E_OK == error) && timeout)
{
for (uint32 j = 0; j < FLASH_PROG_PAGE_SIZE; j++)
{
/* loadPage 64 bits at a time */
*(uint64 *) (0xAF0055F0) = *src++;
__dsync();
}


IfxScuWdt_clearSafetyEndinitInline(password);
IfxFlash_writePage((uint32) dst);
IfxScuWdt_setSafetyEndinitInline(password);


/* Check for Program status bit or error */
timeout = FLASH_EVENT_DELAY;
while (--timeout && !DMU_HF_OPERATION.B.PROG)
{
if ((1 == DMU_HF_ERRSR.B.SQER) || (1 == DMU_HF_ERRSR.B.PROER))
{
error = E_NOT_OK;
continue;
}
}


/* no need to wait on a failure or timeout */
if ((E_OK == error) && timeout)
{
for (timeout=FLASH_BUSY_DELAY; timeout--; )
{
;
/* Wait for 2*1/fFSI ns (DFlash) or 3*1/fFSI + 8*1/fSRI ns (PFlash)
* fFSI = 100MHz, fSRI =300MHz
* then DFlash needs 6 cpu cycles, PFlash needs 17 cpu cycles)
* delay before checking the busy bit
*/
}


/* wait until HF_STATUSx.BUSY = 0*/
timeout = FLASH_PROG_PAGE_DELAY;
while (--timeout && (DMU_HF_STATUS.U & (1 << pxBusy)))
{
if (1 == DMU_HF_ERRSR.B.OPER)
{
error = E_NOT_OK;
continue;
}
}
}


if ((1 == DMU_HF_ERRSR.B.PVER) || (0 == timeout))
{
error = E_NOT_OK;
}
}
else
{
error = E_NOT_OK;
}


return error;
}
0 Likes
User19104
Level 3
Level 3
First like received
Hi,

Thanks for the reply, it might be the watchdog, and if so, why does it work on debug line by line?

doesn't IfxScuWdt_clearSafetyEndinitInline disable the wdt?

your driver also gets an exception, same as mine. 😕
0 Likes
cwunder
Employee
Employee
5 likes given 50 likes received 50 solutions authored
doesn't IfxScuWdt_clearSafetyEndinitInline disable the wdt?

Only for a short period to of time. This allows you a "window of time" to write SAFETY ENDINIT protected registers. Please review section "9.4.4 The Endinit Functions" in the AURIXTC3XX_UM_v1.4.pdf for more information on this.

Concerning an exception I would need to know what Trap you are entering and the relative details.

The code I posted does run without issues in my setup for a TC389. I am writing to PFlash 0
     flashStatus = Flash_WriteProgPage((uint64 *)0xA0038000, (uint64 *)&testArray[0], IfxFlash_FlashType_P0);


Here is the screenshot from the debugger
4154.attach
0 Likes
NeMa_4793301
Level 6
Level 6
10 likes received 10 solutions authored 5 solutions authored
Note that the AURIX does not support writing to PFLASH while anything is reading from the same PFLASH bank - including the CPU. If you want to write to PFLASH0, that means you either need to execute from some other PFLASH bank, or from RAM.
0 Likes
cwunder
Employee
Employee
5 likes given 50 likes received 50 solutions authored
Just to add to the comment by UC_wrangler please note in the code example that I posted, I have located the function Flash_WriteProgPage in the PSPR of CPU0.

I am using Gnuc toolchain
__attribute__((asection(".cpu0_psram", "a=4", "f=xwc0"))) uint8 Flash_WriteProgPage(uint64 *dst, uint64 *src, uint8 pxBusy)
0 Likes
User19104
Level 3
Level 3
First like received
I do not know which trap , but trap table starts at:
0x80000300

first_trap_table:
0x80000300 00 A0 DEBUG
0x80000302 BB 00 00 E0 MOV.U d14,0x0
0x80000306 42 FE ADD d14,d15
0x80000308 60 EE MOV.A a14,d14
0x8000030A 11 DE EA ED ADDIH.A a14,a14,0xDEAD
0x8000030E 1D 00 EC 05 J call_frame_dummy (0x80000EE6)
0x80000312 3C 00 J 0x80000312
0x80000314 00 00 NOP
0x80000316 00 80 RFE
0x80000318 00 00 NOP
0x8000031A 00 00 NOP
0x8000031C 00 00 NOP
0x8000031E 00 00 NOP
0x80000320 00 A0 DEBUG
0x80000322 BB 00 10 E0 MOV.U d14,0x100
0x80000326 42 FE ADD d14,d15
0x80000328 60 EE MOV.A a14,d14
0x8000032A 11 DE EA ED ADDIH.A a14,a14,0xDEAD
0x8000032E 1D 00 DC 05 J call_frame_dummy (0x80000EE6)
0x80000332 3C 00 J 0x80000332
0x80000334 00 00 NOP
0x80000336 00 80 RFE
0x80000338 00 00 NOP
0x8000033A 00 00 NOP
0x8000033C 00 00 NOP
0x8000033E 00 00 NOP
0x80000340 00 A0 DEBUG
0x80000342 BB 00 20 E0 MOV.U d14,0x200
0x80000346 42 FE ADD d14,d15
0x80000348 60 EE MOV.A a14,d14
0x8000034A 11 DE EA ED ADDIH.A a14,a14,0xDEAD
0x8000034E 1D 00 CC 05 J call_frame_dummy (0x80000EE6)
0x80000352 3C 00 J 0x80000352
0x80000354 00 00 NOP
0x80000356 00 80 RFE
0x80000358 00 00 NOP
0x8000035A 00 00 NOP
0x8000035C 00 00 NOP
0x8000035E 00 00 NOP
0x80000360 00 A0 DEBUG
0x80000362 BB 00 30 E0 MOV.U d14,0x300
0x80000366 42 FE ADD d14,d15
0x80000368 60 EE MOV.A a14,d14
0x8000036A 11 DE EA ED ADDIH.A a14,a14,0xDEAD
0x8000036E 1D 00 BC 05 J call_frame_dummy (0x80000EE6)
0x80000372 3C 00 J 0x80000372
0x80000374 00 00 NOP
0x80000376 00 80 RFE
0x80000378 00 00 NOP
0x8000037A 00 00 NOP
0x8000037C 00 00 NOP
0x8000037E 00 00 NOP
0x80000380 00 A0 DEBUG
0x80000382 BB 00 40 E0 MOV.U d14,0x400
0x80000386 42 FE ADD


Stack of traps:
4155.attach
0 Likes
User19104
Level 3
Level 3
First like received
I will point out that 1 page is written successfully
0 Likes
User19104
Level 3
Level 3
First like received
UC_wrangler wrote:
Note that the AURIX does not support writing to PFLASH while anything is reading from the same PFLASH bank - including the CPU. If you want to write to PFLASH0, that means you either need to execute from some other PFLASH bank, or from RAM.


So how come this works in step-by-step debug?

moreover, I use flash bank pf0 in the firs bank but write to the second, i.e 0xA0004000
0 Likes
cwunder
Employee
Employee
5 likes given 50 likes received 50 solutions authored
kfir wrote:
So how come this works in step-by-step debug?


A page write time of the PFlash only takes a maximum of 80us (5V) or 115us (3.3V). When single stepping the debugger it can recover when the flash is not available (for the flash operation) since I doubt you are able to press the step button faster than this.

kfir wrote:
moreover, I use flash bank pf0 in the firs bank but write to the second, i.e 0xA0004000


On the TC399 the Program Flash (16 MByte) is made up of 6 banks, the first five are 3 MBytes in size with the last bank being only 1 MByte in size.

PF0 is is defined between 0xA0000000 -- 0xA02FFFFF. I think you are confused in the flash terminology as you are talking about flash sectors (16 KByte) not banks.

Please provide the address address range for the code that you are executing the Flash operation on.

As stated previously the easiest is to run from the Program Scratch Pad Ram (PSPR).
If you want to execute the routines in PFlash to update PFlash then you cannot execute the flash command sequences in the same flash bank that you are running from.

From the user's manual:
Triggering an NVM operation using the command sequences takes the DMU into Command Mode. During its execution the Flash bank reports BUSY in DMU_HF_STATUS. In this mode read accesses to a Flash bank are refused with a bus error or the ready is suppressed until BUSY clears.
0 Likes
User19104
Level 3
Level 3
First like received
Thanks @cwunder and @UC_wrangler everything is working now.

Thanks vrey much for all the help.
0 Likes
User19104
Level 3
Level 3
First like received
One last question.....

Are the delays for erase different from write?
0 Likes
cwunder
Employee
Employee
5 likes given 50 likes received 50 solutions authored
kfir wrote:
Are the delays for erase different from write?

Yes, please consult the datasheet

You can see the erase time per logical sector or multi-sector command can take a maximum of 500ms.
While the program time for a page is measured in microseconds.
0 Likes
User19104
Level 3
Level 3
First like received
cwunder wrote:
Yes, please consult the datasheet

You can see the erase time per logical sector or multi-sector command can take a maximum of 500ms.
While the program time for a page is measured in microseconds.


I couldn't find in the documentation any reference to the different delays in in different checks of each bit in the AURIX_3XX manual, in section "Erase Logical Sector Range"
0 Likes
cwunder
Employee
Employee
5 likes given 50 likes received 50 solutions authored
If you are referring to the delay for the BUSY bit to be set during the command sequence then there is no difference.

This is defined as;
Wait for 2*1/fFSI ns (DFlash) or 3*1/fFSI + 8*1/fSRI ns (PFlash)
0 Likes
User19104
Level 3
Level 3
First like received
cwunder wrote:
If you are referring to the delay for the BUSY bit to be set during the command sequence then there is no difference.

This is defined as;


I have the code written as follows:
	uint32 N_sectors = 1;
uint16 password = al_IfxScuWdt_getSafetyWatchdogPassword();
volatile uint32 timeout;
uint8 error = 0;
uint8 flash_bank = get_flash_bank((uint64*) start_address);

if (((uint32)start_address & 0xff000000) == 0xa0000000) // program flash
{
N_sectors = size / 0x4000 +1; // size of 1 sector 16k for pflash
}
else if (((uint32)start_address & 0xff000000) == 0xaf000000) // data flash
{
N_sectors = size / 0x1000+1; // size of 1 sector 4 kb for dflash
}

IfxFlash_clearStatus(flash_bank);

IfxScuWdt_clearSafetyEndinitInline(password);
IfxFlash_eraseMultipleSectors((uint32)start_address, N_sectors);
IfxScuWdt_setSafetyEndinitInline(password);


timeout = FLASH_EVENT_DELAY;
while (--timeout && !DMU_HF_OPERATION.B.ERASE)
{
if ((1 == DMU_HF_ERRSR.B.SQER) || (1 == DMU_HF_ERRSR.B.PROER))
{
error = E_NOT_OK;
continue;
}
}

/* no need to wait on a failure or timeout */
if ((E_OK == error) && timeout)
{
for (timeout=FLASH_BUSY_DELAY; timeout--; )
{
;
/* Wait for 2*1/fFSI ns (DFlash) or 3*1/fFSI + 8*1/fSRI ns (PFlash)
* fFSI = 100MHz, fSRI =300MHz
* then DFlash needs 6 cpu cycles, PFlash needs 17 cpu cycles)
* delay before checking the busy bit
*/
}


/* wait until HF_STATUSx.BUSY = 0*/
timeout = FLASH_PAGE_DELAY;
while (--timeout && (DMU_HF_STATUS.U & (1 << flash_bank)))
{
if (1 == DMU_HF_ERRSR.B.OPER)
{
error = E_NOT_OK;
continue;
}
}
}

_dsync();

if ((1 == DMU_HF_ERRSR.B.PVER) || (0 == timeout))
{
error = E_NOT_OK;
}

return E_OK;
}


where the delays are:
#define FLASH_PAGE_DELAY 34500
#define FLASH_EVENT_DELAY 100
#define FLASH_BUSY_DELAY 10


after checking the following:
   while (--timeout && !DMU_HF_OPERATION.B.ERASE)
NeMa_4793301
Level 6
Level 6
10 likes received 10 solutions authored 5 solutions authored
N_sectors = size / 0x4000 +1; // size of 1 sector 16k for pflash

If size is 0x4000, your number of sectors will be 2. Consider this instead:
N_sectors = (size + 0x3FFF) / 0x4000; // size of 1 sector 16k for pflash
0 Likes
cwunder
Employee
Employee
5 likes given 50 likes received 50 solutions authored
The code snippet that I provided is not verified for a production environment that is up to you!

The maximum erase and program times are listed in the device datasheet under the "Flash Target Parameters"

Program Flash Erase Time per Multi-Sector Command can take a maximum of 0.5 seconds. You have to take into account the system behaviors (like checking the supply voltage and servicing watchdogs).

If you assume 300MHz CPU clock then a cycle takes 3.3nsec. To get a timeout of a 0.5s then you can 500ms/3.3ns = 150e6. However using this for a timeout will greatly exceed 0.5s as you also need to account for all of the instructions in the wait loop.
0 Likes
teoBits
Employee
Employee
5 sign-ins 100 replies posted 50 replies posted
Hello,

did you try porting the example Flash_Programming_1?

It is a very nice detailed example for the TC297, which can be easily ported to the TC399. It also comes with a detailed tutorial: Flash_Programming_1 tutorial.


If you are interested in other modules and you want to develop for AURIX™, you can get the new AURIX™ Development Studio and get inspired by numerous trainings from here: AURIX™ Trainings.
If you are not familiar with Eclipse based IDE’s checkout the Getting Started guide!

Hope it helps,
teoBits
0 Likes
User19104
Level 3
Level 3
First like received
teoBits wrote:
Hello,

did you try porting the example Flash_Programming_1?

It is a very nice detailed example for the TC297, which can be easily ported to the TC399. It also comes with a detailed tutorial: Flash_Programming_1 tutorial.


If you are interested in other modules and you want to develop for AURIX™, you can get the new AURIX™ Development Studio and get inspired by numerous trainings from here: AURIX™ Trainings.
If you are not familiar with Eclipse based IDE’s checkout the Getting Started guide!

Hope it helps,
teoBits


It's interesting that the code example is different from the manual...
While the manual states that the first thing is clear status, the example enters page mode 1st thing!

Also, n the example there are no delays as mentioned in the manual, why are there differences between the 2?
0 Likes
teoBits
Employee
Employee
5 sign-ins 100 replies posted 50 replies posted
kfir wrote:
It's interesting that the code example is different from the manual...
While the manual states that the first thing is clear status, the example enters page mode 1st thing!

Also, n the example there are no delays as mentioned in the manual, why are there differences between the 2?



Since the only operations carried out in the example are writing dummy data in the DFLASH and PFLASH, it is assumed that the status is already cleared, you can add the clear status operation on your code if you need to.

About the delays, the function waitUnbusy() waits for the needed time between the operations.

Best Regards,
teoBits
0 Likes
User19104
Level 3
Level 3
First like received
teoBits wrote:
Since the only operations carried out in the example are writing dummy data in the DFLASH and PFLASH, it is assumed that the status is already cleared, you can add the clear status operation on your code if you need to.

About the delays, the function waitUnbusy() waits for the needed time between the operations.

Best Regards,
teoBits


Te function waitUnbusy waits only for flash_busy bit on DMU_HF_STATUS, where the algorithm asks to wait on more bits than that.
0 Likes
teoBits
Employee
Employee
5 sign-ins 100 replies posted 50 replies posted
kfir wrote:
Te function waitUnbusy waits only for flash_busy bit on DMU_HF_STATUS, where the algorithm asks to wait on more bits than that.


Hello,

the waitUnbusy() function checks the Flash Status Register (FSR), which reflects the overall status of the Flash module after Reset and after reception of the different commands.
In particular, it checks the PxBUSY and DxBUSY bits, which are HW-controlled status flags and indicate the busy state of PFx/DFx because of active execution of an operation.
The other bits waited on the manual are for making sure that the procedure is correctly executed, e.g. after entering in page mode you check if the xFPAGE bit is set and the SQER and PROER bits are not.
About the PROG bit instead, if one BUSY flag is coincidently set, PROG indicates the type of busy state.

For simplicity, in the example these bits are not checked but, if you need to, you can add the instructions to check them in your code.

From the timing point of view, when the BUSY flags are reset, the flash memory is not subjected to operations, thus another operation can be started.

BR,
teoBits
0 Likes
User18665
Level 3
Level 3
UC_wrangler wrote:
Note that the AURIX does not support writing to PFLASH while anything is reading from the same PFLASH bank - including the CPU. If you want to write to PFLASH0, that means you either need to execute from some other PFLASH bank, or from RAM.


So, If I want to use in-application monitor for PFLASH writing, can I place it in RAM?
0 Likes
Darren_Galpin
Employee
Employee
First solution authored First like received
Yes you can. The CPU just cannot read from a PFLASH which is being written too concurrently.
0 Likes
User18665
Level 3
Level 3
Thanks a lot!
0 Likes