Double freertos communicate using interrupt

Recently, I was doing an experiment of running two FreeRTOS with two CPU cores. I used two arm cortex-a7 CPU cores. I wanted to communicate between the two RTOS. I used software interrupts and shared memory to synchronize messages. However, since different interrupts need to be bound in both RTOS, the interrupt controller should be configured in both programs, which leads to the death of the first RTOS when the second RTOS is running. I really want to solve this problem,I will appreciate any help。

I’m afraid your question isn’t clear. Do you have two cores but only one interrupt controller, so both cores share the interrupt controller? Or do you have two cores and two interrupt controllers, so each core ahs its own interrupt controller?

We have some AMP (dual core) examples that might help as a reference: FreeRTOS - multicore (dual core) inter core communication example on STM32H745I Discovery board from ST

In fact, my board is similar to zynq. It has four cortex-a7 cores. Core 0 and core 1 are used to run Linux, and core 2 and core 3 are used to run two RTOS respectively. When I run Linux + one RTOS, they can run perfectly and communicate with each other. However, when I try to run Linux + two RTOS, the previous RTOS will always end. Four cores share an interrupt controller. I found that in my two RTOS programs, I both initialized the interrupt and bound the interrupt function。
However, if I do not initialize both programs with interrupts, one of the RTOS will not be able to communicate with Linux

If there is hardware shared between the cores, then something needs to be done to handle the sharing of the hardware. If the code doesn’t understand that sharing, you ARE going to have problems.

Can you share the code snippet? Is it possible that you are re-initializing your interrupt controller which you are supposed to do only once?

Status =  FGicPs_SetupInterruptSystem(&IntcInstance);
    if(Status!=GIC_SUCCESS)
    {
      fmsh_print("Gic setup failed\n\r");
      return GIC_FAILURE ;
    }
       
     Status = FGicPs_Connect(&IntcInstance, SGI_ID_CPU0_INFO_CPU1,
                (FMSH_InterruptHandler)SGI_15_hanlder, &IntcInstance);
          if (Status != GIC_SUCCESS) {
            return GIC_FAILURE;
           }      
          
     FMSH_ExceptionRegisterHandler(FMSH_EXCEPTION_ID_IRQ_INT,
        (FMSH_ExceptionHandler)FGicPs_InterruptHandler_IRQ,
              &IntcInstance);      
                      
      FGicPs_Enable(&IntcInstance, SGI_ID_CPU0_INFO_CPU2);

The above is the code of rtos1

Status =  FGicPs_SetupInterruptSystem(&IntcInstance);
    if(Status!=GIC_SUCCESS)
    {
      fmsh_print("Gic setup failed\n\r");
      return GIC_FAILURE ;
    }
       
     Status = FGicPs_Connect(&IntcInstance, SGI_ID_CPU0_INFO_CPU3,
                (FMSH_InterruptHandler)SGI_13_hanlder, &IntcInstance);
          if (Status != GIC_SUCCESS) {
            return GIC_FAILURE;
           }      
          
     FMSH_ExceptionRegisterHandler(FMSH_EXCEPTION_ID_IRQ_INT,
        (FMSH_ExceptionHandler)FGicPs_InterruptHandler_IRQ,
              &IntcInstance);      
                      
      FGicPs_Enable(&IntcInstance, SGI_ID_CPU0_INFO_CPU2);

The above is the code of rtos2

/******Interrupt Setup********/
u32  FGicPs_SetupInterruptSystem(FGicPs *InstancePtr)
{
	u32 RegValue1 = 0U;
	u32 Index;
	u32 Status;
        static FGicPs_Config* GicConfig; 
        
        GicConfig = FGicPs_LookupConfig(GIC_DEVICE_ID);
         if (NULL == GicConfig) {
            return GIC_FAILURE;
         }
         InstancePtr->Config = GicConfig;
	/*
	 * Read the ID registers.
	 */
	for(Index=0U; Index<=3U; Index++) {
		RegValue1 |= FGicPs_DistReadReg(InstancePtr,
			((u32)FGicPs_PCELLID_OFFSET + (Index * 4U))) << (Index * 8U);
	}

	if(FGicPs_PCELL_ID != RegValue1){
              return GIC_FAILURE;
	} 
        /*
        FGicPs_DistWriteReg(InstancePtr,
		FGicPs_INT_CFG_OFFSET_CALC(32U),
		0U);
        */
         {
            //int Status;
            Status = FGicPs_CfgInitialize(InstancePtr, GicConfig,
				GicConfig->CpuBaseAddress);
            if (Status != GIC_SUCCESS) {
		return GIC_FAILURE;
            }
	 }
   
        FMSH_ExceptionEnable();  
        return Status;
}

above is the code for initializing GIC

/*****************************************************************************/
/**
*
* CfgInitialize a specific interrupt controller instance/driver. The
* initialization entails:
*
* - Initialize fields of the FGicPs structure
* - Initial vector table with stub function calls
* - All interrupt sources are disabled
*
* @param	InstancePtr is a pointer to the FGicPs instance.
* @param	ConfigPtr is a pointer to a config table for the particular
*		device this driver is associated with.
* @param	EffectiveAddr is the device base address in the virtual memory
*		address space. The caller is responsible for keeping the address
*		mapping from EffectiveAddr to the device physical base address
*		unchanged once this function is invoked. Unexpected errors may
*		occur if the address mapping changes after this function is
*		called. If address translation is not used, use
*		Config->BaseAddress for this parameters, passing the physical
*		address instead.
*
* @return
*		- GIC_SUCCESS if initialization was successful
*
* @note		None.
*
******************************************************************************/
#define FMSH_CPU_ID = 0U;  
s32  FGicPs_CfgInitialize(FGicPs *InstancePtr,
				FGicPs_Config *ConfigPtr,
				u32 EffectiveAddr)
{
	u32 Int_Id;
	//u32 Cpu_Id = (u32)FPAR_CPU_ID + (u32)1;
        u32 Cpu_Id =(u32)1U;
	(void) EffectiveAddr;

	FMSH_ASSERT(InstancePtr != NULL);
	FMSH_ASSERT(ConfigPtr != NULL);

	if(InstancePtr->IsReady != COMPONENT_IS_READY ) {
		InstancePtr->IsReady = 0;
		InstancePtr->Config = ConfigPtr;


		for (Int_Id = 0U; Int_Id<FGicPs_MAX_NUM_INTR_INPUTS;Int_Id++) {
			/*
			* Initalize the handler to point to a stub to handle an
			* interrupt which has not been connected to a handler. Only
			* initialize it if the handler is 0 which means it was not
			* initialized statically by the tools/user. Set the callback
			* reference to this instance so that unhandled interrupts
			* can be tracked.
			*/
			if 	((InstancePtr->Config->HandlerTable[Int_Id].Handler == NULL)) {
				InstancePtr->Config->HandlerTable[Int_Id].Handler =
									StubHandler;
			}
			InstancePtr->Config->HandlerTable[Int_Id].CallBackRef =
								InstancePtr;
		}

		DistributorInit(InstancePtr, Cpu_Id);
		CPUInitialize(InstancePtr);

                InstancePtr->IsReady = COMPONENT_IS_READY;
	}

        return GIC_SUCCESS;
}
and this is the code of function "FGicPs_CfgInitialize()"

thanks everyone,I finally found the real problem. In fact, it was because I had problems setting the parameters of the xtaskcreate function on the two cores. The address of the stack in one RTOS covered the address of the stack in the other RTOS. After the modification, they can run well, and this is my negligence.

1 Like

Thank you for taking time to report your solution.