Can't write to P-Flash?

Status
Not open for further replies.
Howdy forum,

I have encountered a strange bug where I cannot seem to write to P-Flash.

First, I set the FlexRam to act as normal RAM

Code:
// wait for ready
while ((FTFL_FSTAT & FTFL_FSTAT_CCIF) != FTFL_FSTAT_CCIF) {};  
	
// Set flexram command
FTFL_FCCOB0 = SET_FLEXRAM_FUNCTION;
FTFL_FCCOB1 = 0xFF;

// Clear error flags
FTFL_FSTAT = FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL | FTFL_FSTAT_RDCOLERR;
	
// Launch command
FTFL_FSTAT = FTFL_FSTAT_CCIF;

// wait for ready
while ((FTFL_FSTAT & FTFL_FSTAT_CCIF) != FTFL_FSTAT_CCIF) {};

Which seems to work, as my blinky LED test does not fire

Code:
if (FTFL_FSTAT & FTFL_FSTAT_ACCERR) {
       while (1) {
       led_toggle();
            for (long j = 1000000; j; --j) {
	            watchdog_refresh();
            }
        }
}

But now, when I try to erase a sector,

Code:
// erase sector
uint32_t address = 0x4000;	
FTFL_FCCOB0 = ERSSCR;
FTFL_FCCOB1 = (address >> 16) & 0xFF;
FTFL_FCCOB2 = (address >> 8) & 0xFF;
FTFL_FCCOB3 = address & 0xFF;

// Clear error flags
FTFL_FSTAT = FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL | FTFL_FSTAT_MGSTAT0;

// Launch command
FTFL_FSTAT = FTFL_FSTAT_CCIF;	

 // wait for ready
while ((FTFL_FSTAT & FTFL_FSTAT_CCIF) != FTFL_FSTAT_CCIF) {};

My script will hang indefinitely at the while loop.

If I comment out the while loop, I end up with an FTFL_FSTAT_ACCERR flag set.

My flash protection bits are very liberal, I am protecting only the first 8K of flash, which I am not writing to with my test script.

Code:
const uint8_t flashconfigbytes[16] =
{
    // Backdoor comparison key (disabled)
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,

    0xfe, 0xff, 0xff, 0xff,

    0xfe,       // Data flash protection (FDPROT)
    0xff,       // EEPROM protection (FEPROT)
    0xff,       // Flash nonvolatile option byte (FOPT)
    0x40        // Flash security byte (FSEC)
};


As well, I have defined the flexRam memory addresses in my linker script and they are read/writable. My clock is 48MHz, 48MHz bus, 24MHz flash.

Any ideas what I could be doing wrong? Perhaps there is some initialization features I missed?
 
I seem to have made some progress,

Executing the sector erase from RAM seems to successfully get a FTFL_STAT_CCIF bit set, and the command exits OK without access errors.

Code:
__attribute__ ((section(".fastrun"), noinline, noclone )) static void flashExec(volatile uint8_t *fstat) 								
{																					
	*fstat = FTFL_STAT_CCIF;
	while (!(*fstat & FTFL_STAT_CCIF)) {;}
}

Still, I am encountering an access error on sector write.
 
Please be careful.

If you both erase and write the sector with the flash config bytes, and you choose the wrong number you can permanently brick your Teensy.

The default security byte is programmed so you have to both change a 1 to 0 (only possible by programming) and a 0 to 1 (only possible by erasing). This is the best protection I can provide. If you do both these operations, you will be able to lock your Teensy and also configure for disabling mass erase. If mass erase is locked out, the bootloader can't access the chip and can't erase it to gain access again.
 
Don't worry, I have heard the warnings about the security bits!

I managed to successfully write to P-Flash a single word at a time.

Code:
	uint32_t flashData = 0x10101010;

	FTFL_FCCOB0 = FTFL_PROGRAM_LONG_WORD;
	FTFL_FCCOB1 = (flashAddress >> 16) & 0xFF;
	FTFL_FCCOB2 = (flashAddress >> 8) & 0xFF;
	FTFL_FCCOB3 = (flashAddress & 0xFF);
	FTFL_FCCOB4 = (unsigned char)((flashData >> 24) & 0xFF);
	FTFL_FCCOB5 = (unsigned char)((flashData >> 16) & 0xFF);
	FTFL_FCCOB6 = (unsigned char)((flashData >> 8) & 0xFF);
	FTFL_FCCOB7 = (unsigned char)(flashData & 0xFF);
	
	// Clear error flags
	FTFL_FSTAT = FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL | FTFL_FSTAT_MGSTAT0;

	__disable_irq();
	execute_flash_command(&FTFL_FSTAT);
	__enable_irq();

	// test 3
	if (FTFL_FSTAT & FTFL_FSTAT_ACCERR)
	{
		pulsePatternHigh();
	}
	
	uint32_t *memoryPointer = (uint32_t *)(flashAddress);
	
	// test passed?
	if (*memoryPointer == 0x10101010)
	{
		pulsePatternRegularFast();
	}	

	// test failed?
	pulsePatternRegularSlow();

This reliably lands at pulsePatternRegularFast().

So it would seem the issue lies somewhere in using the write sector command, aka, "buffer in FlexRAM to program half a flash sector at a time" feature of the K20 -- and not the security settings.

It would be an inconveniently slow solution to program the whole remaining 248K program flash space 4 bytes at a time, so the plot thickens...
 
Last edited:
It appears the flexNVM sector programmer is simply not behaving as anticipated.

My suspicion now is that the IVF / partition table has been previously configured in such a way that leads to this behavior, and my reading of both this forum and the datasheet would suggest that teensy loader does not wipe the whole flash, which I believe is needed to over-write the IVF configuration. Seeing as not too many people plan on using a JTAG with teensy 3.1, I suspect the write_sector command is just not usable --especially if you don't want to break the EEPROM library.
 
Status
Not open for further replies.
Back
Top