-1

I am working on STM32F756ZG with FreeRTOS. I have one network thread that is made using osThreadDef() which is a part of the CMSIS-RTOS API. I also have other tasks running that are created using xTaskCreate() which is a part of the freeRTOS API.

I have a Semaphore that is shared by a tempSensor and EEPROM. In the network thread, the I try to get the values for IP address from the EEPROM using I2C protocol. It successfully takes the Semaphore using xSemaphoreTake() but when its time to give up the Semaphore using xSemaphoreGive() it gets lost and when I hit pause it stays in I2C_WaitOnFlagUntilTimeout().As a result it never loads the webpage.

The other tasks run fine and the temp sensor that also uses I2c and sempahore returns the values correctly.

So my question is if this problem is created because of using semaphore between two threads each generated by different OS API. I am really struggling with this and any help would be really appreciated. Thanks a lot!

I am adding a little code snippet here.

/* 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

This is how my Semaphore is initialized:

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

Following is the code for when I am reading the 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;

The next code snippet is when I am reading from the temp sensor:

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;

When I jump from the bootloader to the application and try to read values from the EEPROM, I can take the Semaphore but I does not give it back using xSemaphoreGive().

Neharika
  • 21
  • 4
  • 1
    I do not see any relevant code. Question which casnnot be answered – 0___________ Feb 26 '20 at 21:38
  • what do you want to achieve? – 0___________ Feb 28 '20 at 19:06
  • @P__J__ I want to read values from the EEPROM so that I can get the IP addresses value and I can load the webpage. Now, I am able to get only the temp sensor or the Webage working and not both of them. So basically I have two threads, one to read value from EEPROM and start a webpage and the second one to get value from temp sensor. Both use I2c and share the same Semaphore. – Neharika Feb 28 '20 at 19:14
  • you do not need counting semaphore. You need the mutex or binary semaphore for that. – 0___________ Feb 28 '20 at 19:39
  • @P__J__ I am creating a Semaphore using xSemaphoreCreateMutex() and was using count for debugging. Also, if I run the application on its own using the debugger I can access EEPROM as well as the Temp Sensor. It is when I jump from bootloader, I cannot access both of them. My bootloader has its own webpage and also has access to the EEPROM using I2C. I am denitializing everything before jumping to the app. I have been stuck on this since a long time and I really appreciate any kind of help. Thank you! – Neharika Feb 28 '20 at 21:30

1 Answers1

1

First of all, make sure semaphore got initialized properly, like this:

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

Secondly, make sure you are using proper function for giving the semaphore.

If it is given from an Interrupt, you have to use

xSemaphoreGiveFromISR(SemId_I2C1_Rx, NULL);
Nik
  • 630
  • 1
  • 6
  • 17
  • What can you advice if you do not see any code related to semaphores. – 0___________ Feb 26 '20 at 21:39
  • thanks for discourage man, I will never waste my time for helping any one here again. – Nik Feb 27 '20 at 15:53
  • Just answer the questions asked the correct way. This question cannot be answered as there is no code & no actual question asked – 0___________ Feb 27 '20 at 16:03
  • Also, @P__J__ I am sorry for not asking the question properly. I have added a few more details.I would appreciate any help. Thanks!! – Neharika Feb 28 '20 at 19:02