This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

semaphore problems on CM3

I have a program that reads from SPI eeprom (25AA1024). It does this by
1) getting a semaphore for the SPI
2) initiating a SPI sequence.
3) using an os_evt_wait to allow the rest to be done with interrupts.
4) Once the IRQs are done, they issue a itv_evt_set to restart the calling task.
5) It may either restart at #2 if there is more to read / write or proceed to 6.
6) Return the semaphore.

This has been used previously with a STR73 micro without problems. The SPI semaphore is gathering extra value causing conflicts on the STM build. The SPI file catches that it is busy and indicates that problems exist. It behaves for a period of time – a few seconds to a minute before having problems. For test purposes, a thread was added that reads a few hundred bytes every 5 to 10 ms.

Obviously the chip specific SPI code is different. Stm32 transfer and interrupts are via DMA vs SPI FIFO interrupts with str7.

After looking over many things, the os_sem_wait and os_sem_send calls for the eeprom were replaced with specific wait and send functions that separately kept track of gets and sends. This indicated it was sending more semaphores than it got.

The newly added functions were then selectively compiled with versions that used a volatile u16 counter to keep track of status and done so with interrupts turned OFF. The real semaphore version failed quickly while the manual method experiment has worked well with few timeouts on the E2 exercise task and none on the others.

Problem Code:

volatile  s16    E2SemStatus;
volatile  OS_TID LastSuccessfulTask;
volatile  OS_TID NextLastSuccessfulTask;

volatile  OS_TID LastReturnTask;
#if 0

OS_RESULT E2GetE2Semaphore( u16  timeout )
{

              OS_RESULT E2SemResult;
    volatile  OS_TID    E2SemCallingTask;


    E2SemCallingTask = os_tsk_self( );
    E2SemResult      = os_sem_wait( sem_eeprom, timeout );      /*   request semaphore.                           */
    if( E2SemResult != OS_R_TMO )                               /*   did we get it?                               */
    {
        GlobalInterruptDisable;
        E2SemStatus++;                                          /*     keep track of checked out items.           */
        NextLastSuccessfulTask = LastSuccessfulTask;            /*     and tasks.                                 */
        LastSuccessfulTask     = E2SemCallingTask;
        if( E2SemStatus != 1 )                                  /*     if this is != 1, something is wrong.       */
            while( 1 );
        GlobalInterruptEnable;

        if( sem_eeprom[ 0 ] & 0xffff0000 )                      /*     is upper 1/2 of [0] index not zero? if so, */
                                                                /*      too many got returned.                    */
        {
            while( 1 );
        }

    }

    return E2SemResult;
}

OS_RESULT E2ReturnE2Semaphore( void )
{
    GlobalInterruptDisable;
    E2SemStatus--;                                              /*   one checked out.                             */

    if( E2SemStatus )                                           /*   if nonzero ... one got lost.                 */
        while( 1 )
        {
        }
    GlobalInterruptEnable;
    LastReturnTask = os_tsk_self( );
    os_sem_send( sem_eeprom );
    return ( OS_R_OK );
}

and the functioning code


#else OS_RESULT E2GetE2Semaphore( u16 timeout ) /*< duplicate os_sem_wait(semphore, max delay) */ /* for a gives semaphore. > */ {
volatile OS_TID E2SemCallingTask;
E2SemCallingTask = os_tsk_self( ); /* keep track of the calling task. */
while( 1 ) { GlobalInterruptDisable; /* kill IRQ. */ if( E2SemStatus == 0 ) /* if value is 0, no one has checked it */ /* out... */
{ E2SemStatus++; /* Take it. */ GlobalInterruptEnable; NextLastSuccessfulTask = LastSuccessfulTask; /* keep track of tasks */ LastSuccessfulTask = E2SemCallingTask;
return OS_R_OK; /* get out. */
} else /* not available. */ { GlobalInterruptEnable; /* turn on IRQ. */ if( timeout && timeout != 0xffff ) /* if timeout is not 0xffff or 0, decrement */ /* it . */ { timeout--; }
if( timeout ) /* if any timeouts left ... */ { os_dly_wait( 1 ); /* for now, use OS delay. */ } else { return OS_R_TMO; /* if timeouts have gone away - return */ /* timed out. */ } } } }
OS_RESULT E2ReturnE2Semaphore( void ) /*< duplicate a os_sem_send(semaphore) .*/ { GlobalInterruptDisable; E2SemStatus--; /* one returned. */
if( E2SemStatus ) /* if nonzero ... one got lost. */ while( 1 ) { } GlobalInterruptEnable; LastReturnTask = os_tsk_self( ); /* for debugging, keep track of the last task */ /* to return an item. */ return ( OS_R_OK ); /* while not used, return a value. */ }
#endif

The task recording is for debugging.

This leads to the belief there is something funny in the get and / or send of the semaphore operation on the CMx Rtos. I don’t see any problems on simulation for the STM32 just real hardware on stm32. Any suggestions where to look if it is my problem?

Thanks,
Chad

0