xSemaphoreGive () зависает при использовании различными потоками - PullRequest
0 голосов
/ 26 февраля 2020

Я работаю на STM32F756ZG с FreeRTOS. У меня есть один сетевой поток, созданный с помощью osThreadDef (), который является частью CMSIS-RTOS API. У меня также выполняются другие задачи, созданные с помощью xTaskCreate (), который является частью API freeRTOS.

У меня есть семафор, который используется совместно с tempSensor и EEPROM. В сетевом потоке я пытаюсь получить значения для IP-адреса из EEPROM, используя протокол I2 C. Он успешно использует семафор с помощью xSemaphoreTake (), но когда пора отказаться от семафора с помощью xSemaphoreGive (), он теряется, а когда я нажимаю паузу, он остается в I2C_WaitOnFlagUntilTimeout (). В результате он никогда не загружает веб-страницу.

Другие задачи работают нормально, и датчик температуры, который также использует I2 c и sempahore, возвращает значения правильно.

Таким образом, мой вопрос заключается в том, создана ли эта проблема из-за использования семафора между двумя потоками, каждый из которых генерируется различным API ОС. Я действительно борюсь с этим, и любая помощь будет очень признательна. Большое спасибо!

Я добавляю сюда небольшой фрагмент кода.

/* Init networking thread */
osThreadDef(Start, StartNetworkThread, osPriorityNormal, 0, configMINIMAL_STACK_SIZE * 2);
osThreadCreate (osThread(Start), NULL);
start_threads(3);


HAL_ADC_Start_DMA(&hadc1, (uint32_t*) adc1vals, 1);
HAL_ADC_Start_DMA(&hadc2, (uint32_t*) adc2vals, 1);
xTaskCreate (vADC1, "vADC1", configMINIMAL_STACK_SIZE, NULL, uxPriority + 3, ( TaskHandle_t * ) NULL );
xTaskCreate (vADC2, "vADC2", configMINIMAL_STACK_SIZE, NULL, uxPriority + 3, ( TaskHandle_t * ) NULL );
xTaskCreate (vPIDloop, "vPIDloop", configMINIMAL_STACK_SIZE + 100, NULL, uxPriority + 2, ( TaskHandle_t * ) NULL );
xTaskCreate (vIO, "vIO", configMINIMAL_STACK_SIZE + 512, NULL, uxPriority + 1, ( TaskHandle_t * ) NULL ); //Run IO at least important priority
xTaskCreate (vControl, "vControl", configMINIMAL_STACK_SIZE + 512, NULL, uxPriority + 1, ( TaskHandle_t * ) NULL ); //Run control at least important priority

Вот как инициализируется мой семафор:

  // Initialize the semaphore that controls eeprom access
    xI2C3Semaphore = xSemaphoreCreateMutex();
    if( xI2C3Semaphore ==NULL)
    {
      while(1);
   }

Ниже приведен код, когда я читаю EEPROM:

int             result = 0;
NvVarsEeprom_t  eepromVar;    
memset( &eepromVar, 0xff, sizeof(eepromVar) );

if( xI2C3Semaphore != NULL )
{
    // Wait forever for semaphore
    if( xSemaphoreTake( xI2C3Semaphore, (TickType_t)10 ) == pdTRUE )
    {
     // count = uxSemaphoreGetCount(xI2C3Semaphore);

        // Read from EEPROM
        if( nvdata_read((char *)&eepromVar, sizeof(eepromVar), addr) != HAL_OK ) 
        {
            //vTaskDelay(5);
            if( nvdata_read((char *)&eepromVar, sizeof(eepromVar), addr) != HAL_OK ) 
            {
                return ERR_EEPROM;
            }
        }     
        //count = uxSemaphoreGetCount(xI2C3Semaphore);
        // Give up the semaphore
        if(xSemaphoreGive( xI2C3Semaphore ) != pdTRUE)
        {
          while(1);
        }
       // count = uxSemaphoreGetCount(xI2C3Semaphore);
    }
}

if( result == 0 )
{
    eepromVar.valid = NVP_VALID;
}

if( eepromVar.valid == NVP_VALID )
{
    strncpy( buf, eepromVar.str, EepromVarSize-1 );
    buf[EepromVarSize-1] = '\0';
}
else
{
    return ERR_EEPROM;    
}

return result;

Следующий фрагмент кода - это когда я читаю с датчика температуры:

int tempC = 0;

if( xI2C3Semaphore != NULL )
{
    // Wait forever for semaphore
    if( xSemaphoreTake( xI2C3Semaphore, (TickType_t)10 ) == pdTRUE )
    {
        // Read from I2C3
        tempC = heatSink_read();

        // Give up the semaphore
        if(xSemaphoreGive( xI2C3Semaphore ) != pdTRUE)
        {
          while(1);
        }
    }
}

return tempC;

Когда я прыгаю с загрузчика в приложение и пытаюсь прочитать значения из ЭСППЗУ, я могу взять Семафор, но я не возвращаю его с помощью xSemaphoreGive ().

1 Ответ

0 голосов
/ 26 февраля 2020

Прежде всего, убедитесь, что семафор правильно инициализирован, например:

if ((SemId_I2C1_Rx  = xSemaphoreCreateBinary()) == NULL) { goto InitFailed; };

Во-вторых, убедитесь, что вы используете правильную функцию для предоставления семафора.

Если оно дается от прерывания, вы должны использовать

xSemaphoreGiveFromISR(SemId_I2C1_Rx, NULL);
...