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 flash
readunique
id 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 flashread
uniqueid 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 cpu
irqdisable/enable calls by taskENTER
CRITICAL/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 flash
readunique_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.
uint32
t flashread
uniqueid(uint32
t *puldata, uint32
t ulsize)
{
uint32
t uidbuf[4];
uint32
t 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;
}
__no
inline
RAMFUNC
uint32t efc
performread
sequence(Efc *pefc,
uint32
t ulcmd
st, uint32t ul
cmdsp,
uint32
t *pul
buf, uint32t ul
size)
{
volatile uint32t ul
status;
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;
}