configASSERT( ( xTimeIncrement > 0U ) ); Problem on PIC24F Port

andrew-ar wrote on Tuesday, January 24, 2017:

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 _write_flash_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

rtel wrote on Tuesday, January 24, 2017:

That assert would seem to indicate the second parameter to
vTaskDelayUntil() is passed in as zero, but in your code it is passed in
as pdMSTOTICKS(4), which would seem to be a constant, so why does it
think it is 0?

edwards3 wrote on Wednesday, January 25, 2017:

Stack overflow?

andrew-ar wrote on Wednesday, January 25, 2017:

Thanks for the suggestions. If I put a breakpoint on taskEXITCRITICAL(), then step thorugh the code, the correct value is passed into the second parameter of vTaskDelayUntil() - pdMSTOTTICKS, which computes to 1 in this case. However, if I insert the following code into tasks.c (temporary modification), and put a breakpoint on the Nop(), it appears that “0” has been passed into the second parameter of vTaskDelayUntil(). Weird.

void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )
{
TickType_t xTimeToWake;
BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;

if( xTimeIncrement == 0) {
    Nop();
}

    configASSERT( pxPreviousWakeTime );
	configASSERT( ( xTimeIncrement > 0U ) );
	configASSERT( uxSchedulerSuspended == 0 );    
    
    ...
}

I have vApplicationStackOverflowHook() defined and configCHECK_FOR_STACK_OVERFLOW set to 2, and its not hitting those.

Maybe I am expecting too much to use flash writing calls with FreeRTOS. With some careful thinking I could make this application work without an RTOS, but I would prefer to use it if I can. I will post back here if I make any progress. Any further comments welcome.

andrew-ar wrote on Wednesday, January 25, 2017:

Update: When the problem occurs, it seems to think the first parameter to vTaskDelayUntil() is zero too.

rtel wrote on Wednesday, January 25, 2017:

As pointed out, this could be a stack issue. Does the library that
writes to flash use a lot of stack, or allocate large buffers?

andrew-ar wrote on Friday, January 27, 2017:

Thanks all for the help - I have now located and fixed the problem. Yes, the functions which write to flash use a lot of RAM for buffering (1K’s worth), which might have been causing a stack overflow but I doubt it given the memory allocation settings. More serious, however, was that when the relevant flash page was erased during the update procedure, a small amount of program code was erased with it…I admit to this being a stupid mistake on my part for not locating the objects to be updated elsewhere in program memory, well away from program code! Nonetheless, a stack overflow may be an issue as I use up more RAM during development. I have learnt the hard way, but at least I’ll not make the same mistake again. Apologies that this turned out not to be a FreeRTOS issue.

Many thanks - FreeRTOS is brilliant piece of engineering and usually makes life much easier!

Andrew