Page 1 of 1

Execution halts when writing Flash via EFC0 from Flash0

Posted: Mon Jan 09, 2017 6:07 am
by crayfellow
We have a simple program on a SAM3U4C with a firmware update routine that runs from Flash0 with the main app running from Flash1.

I am able to write to Flash0 while running from Flash1 (from the app).

I am able to write to Flash1 while running from Flash0 (from the firmware update routine).

However, when I attempt to write to Flash0 while running from Flash0, while I can see later that the write succeeds, execution halts. This occurs not only when I write to a page in Flash, but also when I attempt to set a GPNVM bit (bit 2, for boot selecting between Flash0 and Flash1).

Any thoughts?

Cheers all!

Re: Execution halts when writing Flash via EFC0 from Flash0

Posted: Mon Jan 09, 2017 3:50 pm
by tsvoipio
You're hitting yourself into the head - the flash bank is unreadable during write and your code cannot run from it. The ASF drivers have solved this by copying the core of the programming code into RAM and running from there. Of course, the code must be linked to be able to run in the RAM location.

Re: Execution halts when writing Flash via EFC0 from Flash0

Posted: Mon Jan 09, 2017 8:52 pm
by crayfellow
tsvoipio wrote:You're hitting yourself into the head - the flash bank is unreadable during write and your code cannot run from it. The ASF drivers have solved this by copying the core of the programming code into RAM and running from there. Of course, the code must be linked to be able to run in the RAM location.
Thanks for your response! This is code that once ran fine on a 2C, which only has 1 Flash bank. It would have been writing to the same bank it is running from, every time. So I know the basic mechanics 'should' be OK.

Here is the function:

Code: Select all

__attribute__ ((section (".ramfunc"))) uint32_t start__do_eefc_command
(
    uint32_t cmd,
	uint8_t efc_index
)
{
    uint32_t fsr = 0;

    if (efc_index > 1) {
		return fsr;
	}

    __disable_irq();

    if (efc_index == 1) {
	    AT91C_BASE_EFC1->EFC_FCR = cmd;
	} else {
		AT91C_BASE_EFC0->EFC_FCR = cmd;
	}

    for (;;)
    {
		if (efc_index == 1) {
            fsr = AT91C_BASE_EFC1->EFC_FSR;
		} else {
		    fsr = AT91C_BASE_EFC0->EFC_FSR;
		}
        if (fsr & AT91C_EFC_FRDY) break;
    }

	if (fsr & AT91C_EFC_LOCKE || fsr & AT91C_EFC_FCMDE)
	{
		iprintf("Write to locked region attempted");
	}		
    __enable_irq();


    return fsr;
}
So somehow in the linker script update for 4C the .ramfunc must no longer be mapping the function into RAM - right? Here is a portion from the linker script:

Code: Select all

.relocate : AT (_etext)
    {
        . = ALIGN(4);
        _srelocate = .;
        *(.ramfunc .ramfunc.*);
        *(.data .data.*);
        . = ALIGN(4);
        _erelocate = .;
    } > ram
and memory spaces listed thusly:

Code: Select all

MEMORY
{
	flash0 (rx) : ORIGIN = 0x00080000, LENGTH = 0x00020000 /* Flash0, 128K */
	flash1 (rx) : ORIGIN = 0x00100000, LENGTH = 0x00020000 /* Flash1, 128K */

	flash_boot		(rx)    : ORIGIN = 0x00080000, LENGTH = 3K /* Flash0, 128K */
	flash_config	(rx)    : ORIGIN = 0x00080C00, LENGTH = 1K /* Flash0, 128K */
	flash_fwup		(rx)    : ORIGIN = 0x00081000, LENGTH = 124K /* Flash0, 128K */
	flash_app		(rx)    : ORIGIN = 0x00100000, LENGTH = 128K /* Flash1, 128K */
	ram             (rwx)   : ORIGIN = 0x20078000, LENGTH = 48K /* Sram, 48K */
}
does anything stand out here that would explain how the function might not actually be getting mapped into RAM?

Re: Execution halts when writing Flash via EFC0 from Flash0

Posted: Mon Jan 09, 2017 9:25 pm
by tsvoipio
It looks like the code in ASF, should be OK.

Check from the linker map where the code goes. On the GCC command line
-Wl,-Map=mycode.map
gets the map to mycode.map.

If the protection error trips, it seems suspect to print the error message when interrupts are off.

Re: Execution halts when writing Flash via EFC0 from Flash0

Posted: Mon Jan 09, 2017 9:48 pm
by crayfellow
tsvoipio wrote:It looks like the code in ASF, should be OK.

Check from the linker map where the code goes. On the GCC command line
-Wl,-Map=mycode.map
gets the map to mycode.map.
what should I look for in the map file? start__do_eefc_command should be there, no? (it's not)
tsvoipio wrote:If the protection error trips, it seems suspect to print the error message when interrupts are off.
I agree, but a previous developer did that so I'm trying to change as little as possible from the formerly working project in the process of getting this going on 4C.

Re: Execution halts when writing Flash via EFC0 from Flash0

Posted: Mon Jan 09, 2017 10:55 pm
by tsvoipio
You may have been bitten by the compiler optimization, if your function has been inlined.

I'm using my macro RAMFUNC for the RAM-located code callable from ROM:

/* Shorthands for attributes */

#define LONGCALL __attribute__((long_call))
#define NOINLINE __attribute__((noinline))
#define RAMCODE __attribute__((section(".ramcode")))

#define RAMFUNC NOINLINE LONGCALL RAMCODE

To check, add the switch
-Wa,-ahlms=myfile.lst
to the GCC compilation line and read the listing.

Re: Execution halts when writing Flash via EFC0 from Flash0

Posted: Tue Jan 10, 2017 4:47 am
by crayfellow
tsvoipio wrote:You may have been bitten by the compiler optimization, if your function has been inlined.

I'm using my macro RAMFUNC for the RAM-located code callable from ROM:

/* Shorthands for attributes */

#define LONGCALL __attribute__((long_call))
#define NOINLINE __attribute__((noinline))
#define RAMCODE __attribute__((section(".ramcode")))

#define RAMFUNC NOINLINE LONGCALL RAMCODE

To check, add the switch
-Wa,-ahlms=myfile.lst
to the GCC compilation line and read the listing.
that was it! I used this verbatim, only changing .ramcode to .ramfunc based on the naming in our linker script. I had thought I tried long_call but maybe I never did. I think that is what was missing, which seems crazy, but it is working now.

Thank you!! Cheers.