STR912:using binary semaphore between 2 tasks

Hello all,
I am using** STR912 comstick with freeRTOS to generate a **variable width PWM using TIM1.
Generation of variable width PWM is done. Now I have two tasks both generating PWM but of different variable widths.
I want to switch between these two tasks on some event – high or low on a GPIO. For that I need binary semaphore since I have one resource to share i.e TIM1.
If we use no semaphore with only one task it works fine.
When I use binary semaphore it dose not work . //global variables xSemaphoreHandle xSemaphore = NULL; const unsigned long ONArrayOC2R = {0x94CA,0x1982,0x0CBC,0x0CBC,0x0CBC,0x1982,0x0CBC,0x0CBC,0x0CBC,
                                     0x0CBC,0x0CBC,0x0CBC,0x0CBC,0x0CBC,0x0CBC,0x0CBC,0x0CBC,0x0CBC,
                                     0x0CBC,0x1982,0x1982,0x0CBC,0x1982,0x0CBC,0x0CBC,0x0CBC,0x1982,
                                     0x1982,0x1982,0xCBC};
const unsigned long ArrayOC1R = {0x64C3,0x075D,0x075D,0x075D,0x075D,0x075D,0x075D,0x075D,0x075D,
                                     0x075D,0x075D,0x075D,0x075D,0x075D,0x075D,0x075D,0x075D,0x075D,
                                     0x075D,0x075D,0x075D,0x075D,0x075D,0x075D,0x075D,0x075D,0x075D,
                                     0x075D,0x075D,0x75D}; const unsigned long OFFArrayOC2R = {0x94CA,0x1982,0x0CBC,0x0CBC,0x0CBC,0x1982,0x0CBC,0x0CBC,0x0CBC,
                                      0x1982,0x1982,0x0CBC,0x0CBC,0x0CBC,0x0CBC,0x0CBC,0x0CBC,0x0CBC,
                                      0x0CBC,0x0CBC,0x0CBC,0x0CBC,0x1982,0x0CBC,0x1982,0x0CBC,0x0CBC,
                                      0x0CBC,0x1982,0x0CBC}; static unsigned int PulseCount=0, RepeatSignal=0, ON_OFF_Flag; My main is – void main( void )
{
#ifdef DEBUG
debug();
#endif /* Setup any hardware that has not already been configured by the low
level init routines. */
prvSetupHardware();
    
          vSemaphoreCreateBinary( xSemaphore );   // create binary semaphore        /* Start either the uIP TCP/IP stack or the lwIP TCP/IP stack. */
      
#ifdef STACK_UIP
/* Finally, create the WEB server task. */
//xTaskCreate( vuIP_Task, “uIP”, configMINIMAL_STACK_SIZE * 3, NULL, mainCHECK_TASK_PRIORITY – 1, NULL );
                 xTaskCreate(  vPWM_ON_Task, “PWM_AC_ON”, configMINIMAL_STACK_SIZE * 3, NULL, mainCHECK_TASK_PRIORITY – 1,NULL);
                 xTaskCreate(  vPWM_OFF_Task, “PWM_AC_OFF”, configMINIMAL_STACK_SIZE * 3, NULL, mainCHECK_TASK_PRIORITY – 2,NULL);
#endif
         
#ifdef STACK_LWIP_130
vStartEthernetTasks(mainNET_TASK_BASE_PRIORITY);
#endif /* Start the scheduler. NOTE : Tasks run in system mode and the scheduler runs in Supervisor mode.
The processor MUST be in supervisor mode when vTaskStartScheduler is
called.  The demo applications included in the FreeRTOS.org download switch
to supervisor mode prior to main being called.  If you are not using one of
these demo application projects then ensure Supervisor mode is used here. */
        //portBASE_TYPE xHigherPriorityTaskWoken = 0;
vTaskStartScheduler(); /* We should never get here as control is now taken by the scheduler. */
for( ;; );
} then I have the task definitions as –
void vPWM_ON_Task(void)
{
          TIM_DeInit(TIM1);
          VIC_DeInit();
          TIM_ClearFlag(TIM1,TIM_FLAG_OC2); 
  
          portENTER_CRITICAL();
          {
                  VIC_Config(TIM1_ITLine,VIC_IRQ, 0);
                  VIC_ITCmd(TIM1_ITLine,ENABLE);
                  VIC_InitDefaultVectors();
                  TIM1->SR &= 0x0000;
                  VIC0->FSR = 0x0000;
          }
          portEXIT_CRITICAL();
         
          if(GPIO_ReadBit(GPIO4,GPIO_Pin_7)!= Bit_RESET)   //this is the event for loading particular array of variable widths in ISR
          {
            ON_OFF_Flag = 1;
            gpio9_led_on();
          }
          /*************************************************/
          TIM1->OC1R = 0x00FF;
          TIM1->CR2 = 0x0810;                                 //set prescaler and interrupt enable
          TIM1->CR1 = 0x8250;                                 //start the timer
          TIM1->OC2R = 0x0FFF;
          /*************************************************/
          xSemaphoreTake( xSemaphore, configTICK_RATE_HZ / 2 );
} The ISR is – void PWM_TIM1_IRQHandler(void)
{
  portBASE_TYPE xHigherPriorityTaskWoken = 0; /* Give the semaphore in case the uIP task needs waking. */
xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken );         /* Clear the interrupt. */
TIM1->SR = 0x0000;
        VIC0->FSR = 0x0000;
       
        if(ON_OFF_Flag ==0)
            TIM1->OC2R = OFFArrayOC2R;    //first array
        else
          TIM1->OC2R = ONArrayOC2R;      //second array
       
        TIM1->OC1R = ArrayOC1R;
        PulseCount++ ;
        if(PulseCount >= 30)  
        {
          RepeatSignal++;
          PulseCount = 0 ;
        }
       VIC0->VAR = 0;
       asm(”SUBS pc,lr,#4″);                        //returning from ISR
} Second task is- void vPWM_OFF_Task(void)
{
          TIM_DeInit(TIM1);
          VIC_DeInit();
          TIM_ClearFlag(TIM1,TIM_FLAG_OC2); 
  
          portENTER_CRITICAL();
          {
                  VIC_Config(TIM1_ITLine,VIC_IRQ, 0);
                  VIC_ITCmd(TIM1_ITLine,ENABLE);
                  VIC_InitDefaultVectors();
                  TIM1->SR &= 0x0000;
                  VIC0->FSR = 0x0000;
          }
          portEXIT_CRITICAL();
         
          if(GPIO_ReadBit(GPIO4,GPIO_Pin_7)== Bit_RESET)
          {
            ON_OFF_Flag = 0;
            gpio9_led_on();
          }
          /*************************************************/
          TIM1->OC1R = 0x00FF;
          TIM1->CR2 = 0x0810;
          TIM1->CR1 = 0x8250;
          TIM1->OC2R = 0x0FFF;
          /*************************************************/
          xSemaphoreTake( xSemaphore, configTICK_RATE_HZ / 2 );
} Is there something that I am doing wrong?
How to make use of binary semaphores to get it working

STR912:using binary semaphore between 2 tasks

If this is actually the code you are using then: - vPWM_ON_Task() has the wrong prototype to be a task.  It should take a void* parameter. - vPWM_ON_Task() must not exit just by dropping off the end of the function that implements the task.  A task must either run forever (typically in an infinite loop), or delete itself before it reaches the end of the function that implements it. Regards.

STR912:using binary semaphore between 2 tasks

Thank you we made the changes. But even after making the changing the changes it is not working.
Now is there any problem with semaphore?

STR912:using binary semaphore between 2 tasks

Your interrupt service routine does not exit correctly. Why have you manually written the return from the function in assembly language? Write your interrupts as documented for the port on the FreeRTOS web pages.

STR912:using binary semaphore between 2 tasks

Had one doubt: I am polling on One GPIO pin in void main() and created a task on some event on the GPIO (have one switch connected to it). If event detected -> create task -> go to task -> set some flags -> on Interrupt -> go to interrupt ->
serve it -> on completion -> delete task else keep polling the GPIO. so question is
1.on deletion of task where it will return ? 2. and can we pass a pointer to array to a TASK?

STR912:using binary semaphore between 2 tasks

You can pass a pointer to whatever you like to a task, as long as the code creating the task and the task itself agree on what the parameter points to. I don’t understand your scenario though. If you create a task from main(), then start the task by calling vTaskStartScheduler(), main() will never run again.  If you delete the task and there are no other tasks then the only code that will run (other than the kernel tick interrupt) is the Idle task. Regards.

STR912:using binary semaphore between 2 tasks

Thank you Richard,
That gave clue to the solution of problem,
I was just going through the documentation about task states. So if I want to poll on GPIO continuously I should do it in task only Right?? say taskA Now solution could be – void main() will create only this task(taskA) which will continuously poll GPIO and in-turn will create another task (taskB) on GPIO event (and now taskB can be deleted also since taskA is running continuously). But now I have one question how taskB will start / how it will switch to taskB?
or do I need to create taskB in suspended state and resume on GPIO event in taskA.

STR912:using binary semaphore between 2 tasks

And one more thing I just went through one of your replies richard: www.freertos.org/FreeRTOS_Support_Forum_Archive/May_2012/freertos_How_to_create_task_in_suspended_state_5262730.html This is a bit matching scenario which you explained in 2nd para. The conclusion is we can create a suspended task before vTaskStartScheduler() starts. I am a bit confused about starting taskB which is getting created (or resumed) on event on GPIO.
I need your comment on this.

STR912:using binary semaphore between 2 tasks

So if I want to poll on GPIO continuously I should do it in task only Right?? say taskA
Once the scheduler has been started, tasks, interrupts and software timers are the only things that execute.  There is no option to poll IO from main() as main() will never execute at that time. The only way of running tasks is to call vTaskStartScheduler().  You cannot call a task function.
Now solution could be – void main() will create only this task(taskA) which will continuously poll GPIO and in-turn will create another task (taskB) on GPIO event (and now taskB can be deleted also since taskA is running continuously).
You only need to create task B if task B needs to do something in parallel with task A.  If task A is just polling IO and creating task B when the IO changes then consider having the IO trigger an interrupt and having the interrupt service routine signal a task.  Generally repeatedly creating and deleting tasks is not necessary and wasteful.
But now I have one question how taskB will start / how it will switch to taskB?
or do I need to create taskB in suspended state and resume on GPIO event in taskA.
Task B can be created (if really necessary) at any time that you are not in a critical section (and don’t have the scheduler locked).  It will run immediately that it is the highest priority task to run.  Therefore, if Task A creates task B, and Task B has a higher priority than Task A, then Task B will start running immediately – before Task A has returned from the xTaskCreate() function even. Regards.