Using the same semaphores across multiple .c files

Hallo!
I want to synchronise ethernet functionality across an application. I understand that I have to use a semaphore to guarantee exclusive access, but I also need to keep the code divided into several .c files - the tasks are defined in various files, and all are included in the main.c.

My problem is that I don’t really understand how to pass the semaphore to different tasks in different files.
I started with an approach where semaphore would be passed to different task within task paramaters’ list. Like this:

main.c

     #include "LWIP.h"
    (...)
    int main(void)
    /* generate a struct with paramaters for the init function, and place it on the heap
    taskParams *initParams;
    initParams = (taskParams*) pvPortMalloc(sizeof(taskParams));
    SemaphoreHandle_t ptr_binary_sem;
    ptr_binary_sem = xSemaphoreCreateBinary();
    initParams->binary_sem_ptr = ptr_binary_sem;
    (...)
    xTaskCreate(vUDPpingpong, "UDPpingpong", 256U, (void*)(initParams), 9, NULL);
    vTaskStartScheduler();
   }

LWIP.c

    vUDPpingpong(void* pvParameters){
    
   /* get the paramaters */
   SemaphoreHandle_t init_sem;
   taskParams* ParamsPtr;
   ParamsPtr = (taskParams*)pvParamaters;
   init_sem = ParamsPtr->binary_sem_ptr;
      (...)
  }

Later on I have seen that this approach is wrong - one doesn’t have to pass the parameters to get the semaphores working.
I would like to use this possibility, however I don’t know how to synchronise the semaphores accross many files.
I need to define the semaphore with binary_sem = xCreateSemaphoreBinary() in main.c, to make it availible in different .c files. As to my understadnig, to make it possible to use the variable in different file I need to declare it as ‘extern’ in the other .c files. Unfortunturnatally this doesn’t work - the linker gives me back error for “undefined reference to `binary_sem’”

this is what I tried
main.c:

             #include "LWIP.h"
            (...)
            int main(){
            SemaphoreHandle_t binary_sem
            binary_sem = xSemaphoreCreateBinary();
            (...)
            xTaskCreate(vUDPpingpong, "UDPpingpong", 256U, NULL, 9, NULL);
            }

LWIP.c

         extern SemaphoreHandle_t binary_sem;

does anybody have any idea why the linker cannot find the semaphore? I could ‘fix’ the problem by declaring a variable without the ‘extern’ keyword, but in this way I would be just creating a new variable in the scope of the LWIP.c -this is not what I want to do. I need the read the same semaphore also in other files.
Thanks for any suggestions!

If it is accessed in many files, why not make it global:

main.c

/* Global declaration. */
SemaphoreHandle_t ptr_binary_sem;

int main( void )
{
    /* Create here. */
    ptr_binary_sem = xSemaphoreCreateBinary();

    /* Now create all the tasks which will access the semaphore. This is
     * to ensure that the semaphore is not accessed before creation. */
}

lwip.c

/* Extern declaration. */
extern SemaphoreHandle_t ptr_binary_sem;

vUDPpingpong(void* pvParameters)
{
    /* Access ptr_binary_sem here. */
}

Thanks.

1 Like

First, one warning, do NOT put things you want to use within a FreeRTOS application in main, as several of the ports will reuse the main stack for the ISR stack, and thus overwrite those variables.

I generally put things like Semaphore handles as global variables as Peter says, or they are file local variables or struct members and access is done in one file, with that file providing ‘API’ functions that other files will use to access the resource (things like device drivers so various tasks access the device through an API, and inside that API the queues/semaphores are used.