Crash in Windows port

[moves from SouceForge forum]

I have found a crash in Windows port of FreeRTOS in port.c

I have found that pxCurrentTCB is NULL:

/* Obtain the state of the task now selected to enter the
                Running state. */
                pxThreadState = ( ThreadState_t * ) ( *( size_t *) pxCurrentTCB );

Callstack:

>   plugin_AeroSIMRC.dll!prvProcessSimulatedInterrupts()  Line 496 + 0x5 bytes  C
    plugin_AeroSIMRC.dll!xPortStartScheduler()  Line 362    C
    plugin_AeroSIMRC.dll!vTaskStartScheduler()  Line 1084   C

The proposed fix:

if(pxCurrentTCB != NULL)
                {
                  /* Obtain the state of the task now selected to enter the
                  Running state. */
                  pxThreadState = ( ThreadState_t * ) ( *( size_t *) pxCurrentTCB );

                  /* pxThreadState->pvThread can be NULL if the task deleted
                  itself - but a deleted task should never be resumed here. */
                  configASSERT( pxThreadState->pvThread != NULL );
                  ResumeThread( pxThreadState->pvThread );
                }

Please note that this crash was not immediate. It occurred after one hour of FreeRTOS app run.

I have investigated this problem and it might be a side effect of calling xSemaphoreGiveFromISR() from non FreeRTOS thread. I needed to simulate IRQ from something that cannot belong to FreeRTOS thread chunk.

This was originally reported here - FreeRTOS Real Time Kernel (RTOS) / Bugs / #203 Crash in prvProcessSimulatedInterrupts() in Windows port

Please elaborate on this, as it sounds like the route cause of your problem.

The Windows port creates a Windows thread each time you call xTaskCreate() (or its static equivalent). Those threads are under the control of FreeRTOS and, because FreeRTOS has a task control block for each created thread, are scheduled exactly like any other FreeRTOS port. Giving a semaphore can result in a context switch whereby the giving thread (or the thread running when a semaphore is given from an ISR) is placed on a ready list before the receiving task leaves the blocked state to become the running state task - the data structures necessary to do that are in the task control blocks of both the giving and receiving tasks. Windows threads that were not created by FreeRTOS have no task control block, so no data that can be manipulated by the scheduler to keep the system consistent - hence only threads created by the scheduler can use FreeRTOS objects such as semaphores.

Hi Richard Barry, I know all that you write, but it did not solve my problem.

I need to ABORT FreeRTOS and continue application. I have already proposed full workable fix to FreeRTOS here: I need to exit FreeRTOS without aborting whole Windows application

Why? I has been used Aerosim-RC (absolutelly no control over Aerosim threads) and a code from UAV MCU autopilot compilled to Windows: Autopilot for UAV's
and bind them together.

Nobody before me has been solved clean FreeRTOS shutdown to Windows. First I have wrong suspection, that there is only a minor bug in FreeRTOS, but the correct solution resulted to create bunch of a new code.

May be that this thread moved from Source Forge is just a duplicity.

I did not solve it 100% correct, but FreeRTOS finishes correctly in 99%. It is very good that I do
not need to restart Aerosimulator so often.

I just increased your forum privileges - you should be able to post the links now.

Links are updated in the previous post.
I appologise to use different username. I has been logged through google account now - I did not note it.

Data exchange between Aerosim and FreeRTOS based plugin has been also solved, I remember that I has been used global variables to transfer data without any locks. INT32 variables are moved atomically in x86 based CPUs.

On the true MCU platform, the sensor’s data are obtained from hardware during asynchronous IRQ. On Window platform I have found that no “virtual” IRQ is not possible from allien thread:

 void ControllerPhaseHookFromISR(BYTE event)
{
portBASE_TYPE xSwitchRequired = pdTRUE;
  gControllerEvents |= event;
  if((gControllerEvents & CTR_EVENT_MASK) == CTR_EVENT_MASK)
  {
    xSemaphoreGiveFromISR(Controller_Semaphore, &xSwitchRequired);
  }
}

void Acc_NewData_xyz(TAccelerometer *pAccelerometer, INT16 x, INT16 y, INT16 z)
{
  //portENTER_CRITICAL(); - removed
  WriteFloat(pAccelerometer->LinDtpId[pAccelerometer->RemapAccLin[0]&0x3], 
                      (x==Int16NAN) ? NAN : pAccelerometer->LinGain[0]*x);
  WriteFloat(pAccelerometer->LinDtpId[pAccelerometer->RemapAccLin[1]&0x3], 
                      (y==Int16NAN) ? NAN : pAccelerometer->LinGain[1]*y);
  WriteFloat(pAccelerometer->LinDtpId[pAccelerometer->RemapAccLin[2]&0x3], 
                      (z==Int16NAN) ? NAN : pAccelerometer->LinGain[2]*z);
  //portEXIT_CRITICAL(); - removed
  gControllerEvents|=CTR_EVT_ACC; GiveControllerSemaphore=1;
  //ControllerPhaseHookFromISR(CTR_EVT_ACC); - removed
}

It would be nice to have some chance to emit some event from allien non FreeRTOS thread.
I have found workable workaround in vApplicationIdleHook():

void vApplicationIdleHook(void)
{
    ................
    portBASE_TYPE xSwitchRequired = pdTRUE;
    GiveControllerSemaphore = 0;
    if((gControllerEvents & CTR_EVENT_MASK) == CTR_EVENT_MASK)
    {
      xSemaphoreGiveFromISR(Controller_Semaphore, &xSwitchRequired);
    }
  }
  .............
}