This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RTOS/LAUNCHXL-CC2650: Synchronization and Communication between tasks

Part Number: LAUNCHXL-CC2650
Other Parts Discussed in Thread: BLE-STACK

Tool/software: TI-RTOS

Hi everyone.

I need your help with the following scenario:

I'm running a ProjectZero-based application, which communicates via BLE with another device. When the application receives some data for bluetooth I have to wake up another task that collects data through the I2C protocol (call it the 'display' task), processes them and returns the result to the BLE task so that it sends it to the linked BLE device . Currently, each task meets its purpose well. My problem is to link them properly.
My doubts are:
1. How should I make the 'display' task remain in the locked state until no data has been entered by BLE, then run only once and then lock again?
2. What should be the priorities between the BLE task and the display?
3. How should I pass the information from one task to the other, considering it is a char array of 50 elements?
I have considered using a global variable, whose access is controlled by a binary semaphore, but it does not work for me.


Any ideas or suggestions are welcome.
Thank you very much.

  • Hello,

    1. I would recommend using a TI-RTOS Event. You can see examples of this in our SDK. In summary your BLE-stack enabled task would post an event to your display task. The display processes the task and then pends to wait for another. Until another event is posted by BLE, your display task will remain blocked.

    2. If by "BLE task" you mean your application (i.e. Project Zero task) then I would recommend the display task uses the same priority. The only rule is that the actual BLE-Stack (ICall) Task must have the highest priority. It is setup this way by default and I do not recommend changing this.

    3. You can use and RTOS mailbox or queue to pass a message, alongside a pointer to your data and its length.
  • I really apreciate your answer. Thank you. I will investigate about Events.

    About queue or Mailbox, would it be necessary to guarantee mutual exclusion considering that there will be only two accesses to the resource, one for writing and one for reading?

  • I'm using an Event just like you recommend me.

    When 'Project Zero task' proccess an incoming BLE msg, it does:

    Event_post(myEvent, Event_Id_00);

    On the other hand, 'display' task is doing:

    while(1){
    
    		/* Wait for the event */
    		events = Event_pend(myEvent, Event_Id_NONE,Event_Id_00,BIOS_WAIT_FOREVER);
    		/* Process all the events that have occurred */
    		if (events & Event_Id_00) {
    			I2CSlaveIntEnable(I2C0_BASE,I2C_SLAVE_INT_DATA); //Enable interrupts to capture data
    
    			if((peso_listo==true) && (precio_un_listo==true) && (precio_tot_listo==true)){ //If the data has been captured
    				I2CSlaveIntDisable(I2C0_BASE, I2C_SLAVE_INT_DATA); //Disable interrupts
    				//Decoding data
    				build_trama();
                                    //Reseting variables
    				clear_nuevo_producto(); //(BREAKPOINT HERE)
    			}
    		}

    The problem is that the execution only stops at the breakpoint half the times it should. Every two messages that the 'Project Zero task' receives, only 1 time the event mechanism works.

    Why is this happening?

  • I was trying to set up and use a Mailbox. The result is not good, the intended communication does not occur. I raised the priority of the 'task display' to 3, while the priority of 'Project Zero task' is 2.

    Here is what I did:

    In main.c:

    Error_Block eb;
    Event_Handle myEvent;
    Mailbox_Handle mbox;
    char decoded_main[50];
    
    int main()
    {
      //...
      Error_init(&eb);
      /* create an Event object. All events are binary */
      myEvent = Event_create(NULL, &eb);
      if (myEvent == NULL) {
    	  System_abort("Event create failed");
      }
    
      Mailbox_Params mboxParams;
      Mailbox_Params_init(&mboxParams);
    
      mbox = Mailbox_create(sizeof(decoded_main), 1, &mboxParams, &eb);
      if (mbox == NULL) {
    	  System_abort("Mailbox create failed");
      }
       //...
    }

    In 'Project Zero task' :

    static void user_processApplicationMessage(app_msg_t *pMsg){
    	
    	char_data_t *pCharData = (char_data_t *)pMsg->pdu;
    
    	switch (pMsg->type){
    		case APP_MSG_SERVICE_WRITE: /* Message about received value write */
    		  /* Call different handler per service */
    			switch(pCharData->svcUUID) {
    				case LED_SERVICE_SERV_UUID:
    					user_LedService_ValueChangeHandler(pCharData);
    					break;
    				case DATA_SERVICE_SERV_UUID:
    					user_DataService_ValueChangeHandler(pCharData);
    					//...
    					//After receiving and processing an incoming Bluetooth message
    					
    					Event_post(myEvent, Event_Id_00);
    					Mailbox_pend(mbox, &decoded_BLE, BIOS_WAIT_FOREVER);
    					DataService_SetParameter(DS_STRING_ID, sizeof(decoded_BLE), decoded_BLE);
    					
    					break;
    				}
    		break;
    		//...
    		
    	}
    }

    And in 'display' task:

    void display_balanza_taskFxn(UArg a0, UArg a1){
    	//Inicializamos todas las variables de la tarea
    	display_balanza_init();
    	uint8_t events;
    	
    	while(1){
    		/* Wait for the event */
    		events = Event_pend(myEvent, Event_Id_NONE,Event_Id_00,BIOS_WAIT_FOREVER);
    		/* Process all the events that have occurred */
    		if (events & Event_Id_00) {
    			I2CSlaveIntEnable(I2C0_BASE,I2C_SLAVE_INT_DATA); //Enable interrupts to capture data
    
    			if((peso_listo==true) && (precio_un_listo==true) && (precio_tot_listo==true)){ //If the data has been captured
    				I2CSlaveIntDisable(I2C0_BASE, I2C_SLAVE_INT_DATA); //Disable interrupts
    				//Decoding data
    				build_trama();
    				
    				Mailbox_post(mbox, &decoded, BIOS_WAIT_FOREVER); //Sending data trought mailbox
    				
    				//Reseting variables
    				clear_nuevo_producto(); //(BREAKPOINT HERE)
    			}
    		}
    	}
    }

    Is logic correct?