-1

我正在使用 FreeRTOS 开发 STM32F756ZG。我有一个使用 osThreadDef() 制作的网络线程,它是 CMSIS-RTOS API 的一部分。我还有其他正在运行的任务,这些任务是使用 xTaskCreate() 创建的,它是 freeRTOS API 的一部分。

我有一个由 tempSensor 和 EEPROM 共享的信号量。在网络线程中,我尝试使用 I2C 协议从 EEPROM 中获取 IP 地址的值。它使用 xSemaphoreTake() 成功获取了 Semaphore,但是当它使用 xSemaphoreGive() 放弃 Semaphore 时它会丢失,当我点击暂停时,它会停留在 I2C_WaitOnFlagUntilTimeout() 中。因此它永远不会加载网页。

其他任务运行良好,也使用 I2c 和信号量的温度传感器正确返回值。

所以我的问题是,如果这个问题是因为在两个线程之间使用信号量而产生的,每个线程都是由不同的 OS 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;

当我从引导加载程序跳转到应用程序并尝试从 EEPROM 中读取值时,我可以获取信号量,但我不会使用 xSemaphoreGive() 将其返回。

4

1 回答 1

0

首先,确保信号量已正确初始化,如下所示:

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

其次,确保您使用正确的函数来提供信号量。

如果它是从中断中给出的,则必须使用

xSemaphoreGiveFromISR(SemId_I2C1_Rx, NULL);
于 2020-02-26T16:41:07.603 回答