cancel
Showing results for 
Search instead for 
Did you mean: 

Semaphore in C++

LUrba.1
Associate II

I have a problem with operating the traffic light from the class method - every time the program crashes at that point.

Here is a simplified example for understanding what I'm writing about:

Class:

class IO_control
{
int num;
 
public:
   osSemaphoreId semaphoreHandle;
   int *outputs;  
   IO_control(int num,int outputs,osSemaphoreId semaphoreHandle);
   virtual ~IO_control();
 
   void SetOutputs();
   void UnsetOutputs();
};
 
 
/***********************************************/
 
 
IO_control::IO_control(int num, int *outputs,osSemaphoreId semaphoreHandle)
{
  this->num = num;
  this->outputs = outputs;
  this->semaphoreHandle = semaphoreHandle;
}
 
IO_control::~IO_control(){}
 
void IO_control::SetOutputs()
{
  osSemaphoreWait(semaphoreHandle, osWaitForever);
  *outputs |= num;
  osSemaphoreRelease(semaphoreHandle);
}
 
void IO_control::UnsetOutputs()
{
  osSemaphoreWait(semaphoreHandle, osWaitForever);
  *outputs &= ~(num);
  osSemaphoreRelease(semaphoreHandle);
}

I have three tasks that fight over one variable i_o_CAN.data_out, specifically four instances of the class + sending a message

two set it - the third copies it to the CAN message

typedef struct can_I_O_struct
  {
    union
    {
      int data_out;
      uint8_t out_arr[4];
    };
 
    union
    {
      int data_in;
      uint8_t in_arr[4];
    };
  } I_O_struct_can;
  
  
  I_O_struct_can i_o_CAN;
  
  osSemaphoreId CAN_IO_semaphoreHandle;
  
  IO_control out1(1,&i_o_CAN.data_out,CAN_IO_semaphoreHandle);
  IO_control out2(2,&i_o_CAN.data_out,CAN_IO_semaphoreHandle);
  IO_control out3(3,&i_o_CAN.data_out,CAN_IO_semaphoreHandle);
  IO_control out4(4,&i_o_CAN.data_out,CAN_IO_semaphoreHandle);
  
  void Task01(void const * argument)
  {
    for(;;)
    {
      out1.SetOutputs();
      osDelay(50);
      out1.UnsetOutputs();
      osDelay(1000);
      out2.SetOutputs();
      osDelay(50);
      out2.UnsetOutputs();
      osDelay(1000);
    }
  }
  
  
  void Task02(void const * argument)
  {
    for(;;)
    {
      out3.SetOutputs();
      osDelay(50);
      out3.UnsetOutputs();
      osDelay(2000);
      out4.SetOutputs();
      osDelay(50);
      out4.UnsetOutputs();
      osDelay(2000);
    }
  }
  
  void TaskCAN_Tx(void const * argument)
  {
    int tmp = 0;
      TxHeader2.StdId = 0x180;
    TxHeader2.DLC = 4;
    for(;;)
    {
      osSemaphoreWait(CAN_IO_semaphoreHandle, osWaitForever);
      if (i_o_CAN.data_out != tmp)
      {
      tmp = i_o_regs_can.data_out;
      TxData2[0] = i_o_CAN.out_arr[0];
      TxData2[1] = i_o_CAN.out_arr[1];
      TxData2[2] = i_o_CAN.out_arr[2];
      TxData2[3] = i_o_CAN.out_arr[3];      
      if (HAL_CAN_AddTxMessage (&hcan2, &TxHeader2, TxData2, &TxMailbox2)!= HAL_OK)
        {
          Error_Handler ();
        }      
      }
          osSemaphoreRelease(CAN_IO_semaphoreHandle);
    }
  }

when I adjust it so that I operate the traffic lights directly from the tasks, it works

void IO_control::SetOutputs()
{
  *outputs |= num;
}
 
void IO_control::UnsetOutputs()
{
  *outputs &= ~(num);
}
 
//////////////////////////////////////////////////////////////////////
  
  void Task01(void const * argument)
  {
    for(;;)
    {
      osSemaphoreWait(CAN_IO_semaphoreHandle, osWaitForever);
      out1.SetOutputs();
      osSemaphoreRelease(CAN_IO_semaphoreHandle);
      osDelay(50);
      osSemaphoreWait(CAN_IO_semaphoreHandle, osWaitForever);
      out1.UnsetOutputs();
      osSemaphoreRelease(CAN_IO_semaphoreHandle);
      osDelay(1000);
      osSemaphoreWait(CAN_IO_semaphoreHandle, osWaitForever);
      out2.SetOutputs();
      osSemaphoreRelease(CAN_IO_semaphoreHandle);
      osDelay(50);
      osSemaphoreWait(CAN_IO_semaphoreHandle, osWaitForever);
      out2.UnsetOutputs();
      osSemaphoreRelease(CAN_IO_semaphoreHandle);
      osDelay(1000);
    }
  }

but in reality it's not that simple and I need to access the traffic light from insatnaci - in addition, it's a lot of useless code

1 ACCEPTED SOLUTION

Accepted Solutions
LUrba.1
Associate II

STM32F205

but the problem is not related to hardware or freertos

I've found that it's a matter of C++ and bad passing of the reference to the class.

This is a functional solution:

class IO_control {
    int num;
 
  public:
    osSemaphoreId & semaphoreHandle;
    int * outputs;
    IO_control (int num, int * outputs, osSemaphoreId & semaphoreHandle);
    virtual ~IO_control();
 
    void SetOutputs();
    void UnsetOutputs();
};
/***********************************************/
IO_control::IO_control (int _num, int * _outputs, osSemaphoreId & _semaphoreHandle) :
  num(_num), semaphoreHandle(_semaphoreHandle), outputs(_outputs) {
}

View solution in original post

2 REPLIES 2
Amel NASRI
ST Employee

Hi @Luděk Urbani�?​ ,

Which product please?

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

LUrba.1
Associate II

STM32F205

but the problem is not related to hardware or freertos

I've found that it's a matter of C++ and bad passing of the reference to the class.

This is a functional solution:

class IO_control {
    int num;
 
  public:
    osSemaphoreId & semaphoreHandle;
    int * outputs;
    IO_control (int num, int * outputs, osSemaphoreId & semaphoreHandle);
    virtual ~IO_control();
 
    void SetOutputs();
    void UnsetOutputs();
};
/***********************************************/
IO_control::IO_control (int _num, int * _outputs, osSemaphoreId & _semaphoreHandle) :
  num(_num), semaphoreHandle(_semaphoreHandle), outputs(_outputs) {
}