I have a function which updates the flash memory on a PIC24F device with new data. I have followed Microchip’s advice with regard to copying the old flash page to RAM, modifying the RAM copy, erasing the flash page and then writing the modified RAM copy back to the flash. When this routine is run on its own (no RTOS), all is fine and I can see the updated data in the flash.
The problem arises when I call this function from a FreeRTOS task which uses vTaskDelayUntil() to execute itself periodically every 4ms. The kernel tick time is set to 4ms, which is required so that I can have the aforementioned task execute every 4ms. The flash write operation, however, takes 40ms because writing to flash is a slow operation. So lots of ticks will be missed while this takes place. I have the flash algorithm in a critical section. When the program tries to execute vTaskDelayUntil() AFTER data has written back to the flash, configASSERT( ( xTimeIncrement > 0U ) ); triggers. The flash data updates correctly, so the FreeRTOS kernel must have been corrupted somehow. My question is why, and what can I do to fix it. The flash write operation uses Microchip’s
writeflash
word16(prog_addressT dst, int dat) function, which does modify interrupt priorities temporarily, but I don’t know if that is likely to cause a problem if it is done inside a critical section.
The code is as follows (I’ve stripped out some unrelated stuff to make it easier to read).
Task which executes every 4ms
void vSystemUSBTask( void pvParameters ) {
TickType_t xLastWakeTime;
// Initialise xLastWakeTime variable with current tick count.
xLastWakeTime = xTaskGetTickCount();
for(;;) {
USBDeviceTasks(); //Takes care of enumeration and other USB events
if((USBGetDeviceState() < CONFIGUREDSTATE) ||
(USBIsDeviceSuspended() == true))
{
continue;
}
else
{
vVendorConfig();
}
// Block for 4ms (1 tick period).
vTaskDelayUntil( &xLastWakeTime, pdMSTOTICKS(4) );
**configASSERT( (xTimeIncrement > 0U ) ) triggers here, but only after vVendorConfig() has run**
}
vVendorConfig() function
void vVendorConfig(void) {
…
taskENTERCRITICAL();
…
for(row = 0; row < FLASHROWSINPAGE; row++)
{
_writeflash16(flashRowAddress, (int )ramAddress);
flashRowAddress += FLASHROWINC;
// Increment ramBuffer (source) by same amount
ramAddress += RAMBUFFERINC;
}
taskEXITCRITICAL();
}
I know it is writeflashword16() causing the problem, as commenting it out prevents the configASSERT from being triggered. Furthermore, replacing writeflash16 with a simple for loop time delay of roughly the same time seems to eliminate the problem (obviously at the expense of not writing to the flash), so the problem must be something to do with writeflash16.
Any help as to why configASSERT( (xTimeIncrement > 0U ) ) triggers would be gratefully appreciated.
Many thanks in advance.
Andrew