2 Replies Latest reply on Oct 15, 2016 7:43 AM by darius1

    Wiced sdk using freertos semaphore fundamental error

    darius1

      Problem:

      Wiced with freertos working incorectly, because using counting semaphore.

      Quick way to resolve in fuction hostinitsemaphore create mutex with xCreateSemaphoreBinary.

      And need remove 2 assert in hostsetsemaphore and it must allways return true.

       

      Example problem:

      1. Uart init semaphore and enable interupt

      2. Interupt occurs - counting semaphore increase self value to 1

      3. UartReceive fuction getsemaphore for waiting data - semaphore decrease it value to 0 but not block. Uart receive 0 bytes or not full pscket..

      4. Goto 2 point....

       

      After correction:

      1. Uart init semaphore and enable interupt

      2. Interupt occurs - unlock semaphore

      3. UartReceive fuction getsemaphore (lock) for waiting data  in block mode.

      4. Interupt fullrx occurs setsemaphore (unlock)  task in 3 point receive full packet.

       

      Similar scenarious can occurs anywhere.

        • 1. Re: Wiced sdk using freertos semaphore fundamental error
          axel.lin_1746341

          Do you mean change the implement of host_rtos_init_semaphore():

          to use xSemaphoreCreateBinary() instead of xSemaphoreCreateCounting()?

           

          The host_rtos_init_semaphore() is used in many places, you need to make sure

          it works for all users with your change.

           

          I don't quite understand that you mentioned:

          3. semaphore decrease it value to 0 but not block. Uart receive 0 bytes or not full pscket..

           

          BTW, any chance to post the code you changed?

          • 2. Re: Wiced sdk using freertos semaphore fundamental error
            darius1

            >The host_rtos_init_semaphore() is used in many places, you need to make sure

            >it works for all users with your change.

            Sorry, I can't guarantee nothing, but with this changes system with FreeRtos working Ok for me.  (some days)

             

            I found in one place inserted "brilliant" workaround code  in exmp.

            platform_result_t platform_uart_transmit_bytes( platform_uart_driver_t* driver, const uint8_t* data_out, uint32_t size )

            {......

                 host_rtos_get_semaphore( &driver->tx_complete, NEVER_TIMEOUT, WICED_TRUE );//darius posible not blocked

                 while ( ( driver->peripheral->port->SR & USART_SR_TC ) == 0 )//darius workaround - system polling state bit.... so system overloaded

                 {

                 }

             

            ......

            }

             

             

             

             

            >I don't quite understand that you mentioned:

            >>3. semaphore decrease it value to 0 but not block. Uart receive 0 bytes or not full pscket..  

            counting semaphore  will stay in block mode, when it counter is zero, and  user want take it.

            exmp.

            semaphore = xSemaphoreCreateCounting( (unsigned portBASE_TYPE) 0x7fffffff, (unsigned portBASE_TYPE) 0 );

            xSemaphoreGive( semaphore );  //blocked

             

             

            semaphore = xSemaphoreCreateCounting( (unsigned portBASE_TYPE) 0x7fffffff, (unsigned portBASE_TYPE) 0 );

            xSemaphoreTake(semaphore);//increment from 0 to 1

            xSemaphoreGive(semaphore );  ///not blocked  decrement from 1 to 0

            xSemaphoreGive( semaphore );  //blocked nothing to Give

             

             

             

            semaphore = xSemaphoreCreateCounting( (unsigned portBASE_TYPE) 0x7fffffff, (unsigned portBASE_TYPE) 0 );

            xSemaphoreTake(semaphore);//increment from 0 to 1

            xSemaphoreTake(semaphore);//increment from 1 to 2

            xSemaphoreGive(semaphore );  ///not blocked  decrement from 2 to 1

            xSemaphoreGive(semaphore );  ///not blocked  decrement from 1 to 0

            xSemaphoreGive( semaphore );  //blocked

             

            >>BTW, any chance to post the code you changed?

            No problem.

            wwd_result_t host_rtos_init_semaphore(  /*@special@*/ /*@out@*/ host_semaphore_type_t* semaphore ) /*@allocates *semaphore@*/  /*@defines **semaphore@*/

            {

                /*

                 Note that binary semaphores created using

                 * the vSemaphoreCreateBinary() macro are created in a state such that the

                 * first call to 'take' the semaphore would pass, whereas binary semaphores

                 * created using xSemaphoreCreateBinary() are created in a state such that the

                 * the semaphore must first be 'given' before it can be 'taken'.

                */

                *semaphore =xSemaphoreCreateBinary();

             

                //darius counting semaphore with not limited counter

                //*semaphore = xSemaphoreCreateCounting( (unsigned portBASE_TYPE) 0x7fffffff, (unsigned portBASE_TYPE) 0 );

             

                /*@-compdef@*/ /* Lint doesnt realise allocation has occurred */

                return ( *semaphore != NULL ) ? WWD_SUCCESS : WWD_SEMAPHORE_ERROR;

                /*@+compdef@*/

            }

            //darius need remove  2 asserts and allways return true

            wwd_result_t host_rtos_set_semaphore( host_semaphore_type_t* semaphore, wiced_bool_t called_from_ISR )

            {

            #if 0

                signed portBASE_TYPE result;

             

                if ( called_from_ISR == WICED_TRUE )

                {

                    signed portBASE_TYPE xHigherPriorityTaskWoken=pdFALSE;//darius darome init

                    result = xSemaphoreGiveFromISR( *semaphore, &xHigherPriorityTaskWoken );

                    wiced_assert( "Unable to set semaphore", result == pdTRUE );

             

                    /* If xSemaphoreGiveFromISR() unblocked a task, and the unblocked task has

                     * a higher priority than the currently executing task, then

                     * xHigherPriorityTaskWoken will have been set to pdTRUE and this ISR should

                     * return directly to the higher priority unblocked task.

                     */

                    portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );

                }

                else

                {

                    result = xSemaphoreGive( *semaphore );

             

                    wiced_assert( "Unable to set semaphore", result == pdTRUE );

             

                }

                return ( result == pdPASS )? WWD_SUCCESS : WWD_SEMAPHORE_ERROR;

             

             

            #else

             

                if ( called_from_ISR == WICED_TRUE )

                {

                    signed portBASE_TYPE xHigherPriorityTaskWoken=pdFALSE;//darius darome init

                    xSemaphoreGiveFromISR( *semaphore, &xHigherPriorityTaskWoken );

             

                    //wiced_assert( "Unable to set semaphore", result == pdTRUE );

             

                    /* If xSemaphoreGiveFromISR() unblocked a task, and the unblocked task has

                     * a higher priority than the currently executing task, then

                     * xHigherPriorityTaskWoken will have been set to pdTRUE and this ISR should

                     * return directly to the higher priority unblocked task.

                     */

                    portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );

                }

                else

                {

                    xSemaphoreGive( *semaphore );

                }

                //darius   if give more times  its  Ok

                return WWD_SUCCESS;

            #endif

            }