Can’t use EEFC on ATSAM4E when FreeRTOS is used

I am converting an existing application running on a ATSAM4E8E processor to use FreeRTOS. I am using the ARM_CM4F port of FreeRTOS 10.0.0.0 and static memory allocation. To get started, I am creating a single task in FreeRTOS that does everything. So the only FreeRTOS API calls I make are one call to xTaskCreateStatic() followed by a call to vTaskStartScheduler(). I have conditional code in my application so that I can compile with or without FreeRTOS. When I compile without FreeRTOS, the code works (and has done so for many months). When I compile with FreeRTOS, the code hangs when it tries to call Atmel Software Framework functions that access the EEFC (flash controller peripheral). For example, I have this code in the application startup sequence:
cpu_irq_disable();
const uint32_t rc = flash_read_unique_id(uniqueId, 4);
cpu_irq_enable();
Function flashreaduniqueid calls a RAMFUNC that accesses the EEFC. Disabling interrupts is necessary to prevent code in flash being executed due to an interrupt (in particular, SysTick) while the call is in progress. With FreeRTOS enabled (so that the code executes in the task), it hangs in that code. If I replace the call to flashreaduniqueid by the constant 1 then the code doesn’t hang, the initialisation completes and the firmware runs normally – until I do something that makes it try to use the EEFC again. Any ideas? I tried replacing cpuirqdisable/enable calls by taskENTERCRITICAL/EXITCRITICAL but it made no difference. I also tried varying the stack size – but as the code runs perfectly as long as I don’t access the EEFC and the flash functions use very little stack, it can’t be due to stack overflow anyway. For reference, here is the body of flashreadunique_id and the function it calls. I have verified that the RAMFUNC is allocated in RAM – in fact it is at the very start of RAM. uint32t flashreaduniqueid(uint32t *puldata, uint32t ulsize) { uint32t uidbuf[4]; uint32t ulidx;
if (FLASH_RC_OK != efc_perform_read_sequence(EFC, EFC_FCMD_STUI,
        EFC_FCMD_SPUI, uid_buf, 4)) {
    return FLASH_RC_ERROR;
}

if (ul_size > 4) {
    /* Only 4 dword to store unique ID */
    ul_size = 4;
}

for (ul_idx = 0; ul_idx < ul_size; ul_idx++) {
    pul_data[ul_idx] = uid_buf[ul_idx];
}

return FLASH_RC_OK;
} __noinline RAMFUNC uint32t efcperformreadsequence(Efc *pefc, uint32t ulcmdst, uint32t ulcmdsp, uint32t *pulbuf, uint32t ulsize) { volatile uint32t ulstatus; uint32t ul_cnt;

if (SAM3U4 || SAM3XA || SAM4SD16 || SAM4SD32 || SAM4C32 || SAM4CMS32|| SAM4CMP32)

uint32_t *p_ul_data =
        (uint32_t *) ((p_efc == EFC0) ?
        READ_BUFF_ADDR0 : READ_BUFF_ADDR1);

elif (SAM3S || SAM4S || SAM3N || SAM3U || SAM4E || SAM4N || SAM4C || SAMG ||

   SAM4CP || SAM4CM || SAMV71 || SAMV70 || SAMS70 || SAME70)
uint32_t *p_ul_data = (uint32_t *) READ_BUFF_ADDR;

else

return EFC_RC_NOT_SUPPORT;

endif

if (p_ul_buf == NULL) {
    return EFC_RC_INVALID;
}

p_efc->EEFC_FMR |= (0x1u << 16);

/* Send the Start Read command */

if (SAM4S || SAM4E || SAM4N || SAM4C || SAMG || SAM4CP || SAM4CM ||

 SAMV71 || SAMV70 || SAMS70 || SAME70)
p_efc->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FARG(0)
        | EEFC_FCR_FCMD(ul_cmd_st);

else

p_efc->EEFC_FCR = EEFC_FCR_FKEY(FWP_KEY) | EEFC_FCR_FARG(0)
        | EEFC_FCR_FCMD(ul_cmd_st);

endif

/* Wait for the FRDY bit in the Flash Programming Status Register
 * (EEFC_FSR) falls.
 */
do {
    ul_status = p_efc->EEFC_FSR;
} while ((ul_status & EEFC_FSR_FRDY) == EEFC_FSR_FRDY);

/* The data is located in the first address of the Flash
 * memory mapping.
 */
for (ul_cnt = 0; ul_cnt < ul_size; ul_cnt++) {
    p_ul_buf[ul_cnt] = p_ul_data[ul_cnt];
}

/* To stop the read mode */
p_efc->EEFC_FCR =

if (SAM4S || SAM4E || SAM4N || SAM4C || SAMG || SAM4CP || SAM4CM ||

 SAMV71 || SAMV70 || SAMS70 || SAME70)
        EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FARG(0) |
        EEFC_FCR_FCMD(ul_cmd_sp);

else

        EEFC_FCR_FKEY(FWP_KEY) | EEFC_FCR_FARG(0) |
        EEFC_FCR_FCMD(ul_cmd_sp);

endif

/* Wait for the FRDY bit in the Flash Programming Status Register (EEFC_FSR)
 * rises.
 */
do {
    ul_status = p_efc->EEFC_FSR;
} while ((ul_status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY);

p_efc->EEFC_FMR &= ~(0x1u << 16);

return EFC_RC_OK;
}

Can’t use EEFC on ATSAM4E when FreeRTOS is used

Can’t see any obvious reason for this. Is this code executing in the task or before you start the scheduler? Is anything else using the RAM occupied by the RAM function? Perhaps if there was a mistake in the linker script then without FreeRTOS it just happened that there were no clashed in RAM, but with FreeRTOS and having different memory requirements there is.

Can’t use EEFC on ATSAM4E when FreeRTOS is used

Hi Richard, thanks for responding. The code is executing within the task. I could move that particular piece of code to execute before I start the scheduler, but there are two other sections of code that need to use the EEFC (including one called from all the fatal exception handlers, to log the exception details to the user signature area of the flash) that also crash in the FreeRTOS build. The linker memory maps for RAM look identical up to the point where RAM variables for FreeRTOS are allocated. Where does FreeRTOS put the stack used by handlers? [EDIT: I think I found it in prvPortStartFirstTask(), it gets the top of stack from the first element of the vector table.] Is there anything different about the execution context when it is operating as a task? Obvously it’s using a different stack, but as far as I can tell from the FreeRTOS code it’s still running in privileged mode. I have not enabled the MPU.

Can’t use EEFC on ATSAM4E when FreeRTOS is used

Hi Richard, thanks for responding. The code is executing within the task. I could move that particular piece of code to execute before I start the scheduler, but there are two other sections of code that need to use the EEFC (including one called from all the fatal exception handlers, to log the exception details to the user signature area of the flash) that also crash in the FreeRTOS build.
I was not recommending moving it to before the scheduler is started, I was just wanting to know if it was simply adding the FreeRTOS code in that was causing the issue, or actually running in the context of a task that was the issue. The functions being called do not look alarming in any way so it is curious – we need to work out what the issue is though. Out of curiosity – if you were to create another RAM function that is not doing anything with the flash – does it still crash? If so, then it would seem to be just the act of running from RAM that was the issue.
Where does FreeRTOS put the stack used by handlers?
Handlers use the stack that is otherwise allocated to main() – otherwise that RAM is not recoverable after the scheduler has started – it does mean you loose any variables declared in main() though but there is no way of returning to main() anyway.

Can’t use EEFC on ATSAM4E when FreeRTOS is used

Thanks again. I made some progress: I added code to check whether the contents of the relocate segment in ram (which includes the ramfunc) still matches the original in flash that it is initialised from. It revealed that there is corruption in that memory area, starting with the very first byte of it (which is the very first byte of RAM). I also used vTaskGetInfo() to check that I am not running out of task stack, and added a separate check that there is plenty of handler stack space left. Now I just need to find the source of the memory corruption.

Can’t use EEFC on ATSAM4E when FreeRTOS is used

More data: the corruption is 3 dwords starting at the beginning of RAM: first dword is 1 second dword is the address of the array that provides the stack for the task I create third dword is the address of the StaticTask_t obkect that I provide for the main task

Can’t use EEFC on ATSAM4E when FreeRTOS is used

I found a solution. I noticed that the corruption matched the last 3 parameters passed to xTaskCreateStatic(). So it occurred to me that the compiler might be storing those parameters at the start of RAM instead of on the stack. I had declared the function that calls xTaskCreateStatic() and vTaskStartScheduler() with attribute “naked” on the grounds that it never returns, therefore it doesn’t need to save/restore any registers. I removed the “naked” attribute and the corruption is gone. I guess I don’t completely understand what that attribute does.

Can’t use EEFC on ATSAM4E when FreeRTOS is used

Thanks for reporting back. Using the naked attribute will prevent the compiler from inserting any function prelude code – the asm code that executes to set up a stack from before any of the function’s C code executes. That is definitely a bad thing if any stack is used at all, which is will be in the function, as stack accesses are then basically uninitialised.