Execution halts when writing Flash via EFC0 from Flash0

Discussion around product based on ARM Cortex M3 core.

Moderators: nferre, ncollot

crayfellow
Posts: 4
Joined: Mon Jan 09, 2017 5:55 am

Execution halts when writing Flash via EFC0 from Flash0

Mon Jan 09, 2017 6:07 am

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!
tsvoipio
Posts: 53
Joined: Wed Aug 19, 2015 9:44 pm

Re: Execution halts when writing Flash via EFC0 from Flash0

Mon Jan 09, 2017 3:50 pm

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.
crayfellow
Posts: 4
Joined: Mon Jan 09, 2017 5:55 am

Re: Execution halts when writing Flash via EFC0 from Flash0

Mon Jan 09, 2017 8:52 pm

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?
tsvoipio
Posts: 53
Joined: Wed Aug 19, 2015 9:44 pm

Re: Execution halts when writing Flash via EFC0 from Flash0

Mon Jan 09, 2017 9:25 pm

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.
crayfellow
Posts: 4
Joined: Mon Jan 09, 2017 5:55 am

Re: Execution halts when writing Flash via EFC0 from Flash0

Mon Jan 09, 2017 9:48 pm

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.
tsvoipio
Posts: 53
Joined: Wed Aug 19, 2015 9:44 pm

Re: Execution halts when writing Flash via EFC0 from Flash0

Mon Jan 09, 2017 10:55 pm

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.
crayfellow
Posts: 4
Joined: Mon Jan 09, 2017 5:55 am

Re: Execution halts when writing Flash via EFC0 from Flash0

Tue Jan 10, 2017 4:47 am

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.

Return to “SAM3 Cortex-M3 MCU”

Who is online

Users browsing this forum: No registered users and 2 guests