• Resolved

RTOS/TMS320C6748: When is it safe to call Semaphore_pend() from main() ?

Part Number: TMS320C6748

Tool/software: TI-RTOS

Please don't say 'never' !!!

Clearly it would be reckless to call pend() from outside a task if it is going to block, but is it OK to call it provided the count is 1 or more so it will not block? Currently, I have a program doing this and it works, but I want to be sure it's safe and I'm not just being lucky.

If you're curious why anyone would do such a bizarre thing, this is how it came about. The program uses SPI1 to access two different devices (flash memory and an ADC) from two different tasks, and needs to guarantee exclusive access to the SPI so it uses a semaphore with an initial count of 1 as a mutex. So far, so good. Then it turns out we need to read something from the flash from main, before the call to BIOS_start(); The function  that reads the flash pends on a semaphore, reads flash, then posts the semaphore. So (without realising, initially) that function is called once from main, and then repeatedly later on from a task.

And it works! But should it?    Needless to say, I could restructure the program if I have to, but it's a huge upheaval at this stage.



  • If you use BIOS_NO_WAIT as the timeout, you can call Semaphore_pend from any thread (Task, Swi, or Hwi) and main().

  • In reply to ToddMullanix:

    Thanks Todd,
    I'm using BIOS_WAIT_FOREVER because I need the task to wait until the other task has finished and released the SPI.

    I must admit I read about using BIOS_NO_WAIT but didn't really understand it. Or rather I didn't understand how that would be useful. Presumably it decrements the semaphore count but never blocks the task, even if the count goes to zero?

    Problem is, I need it to be able to block the task, if it's called from a task. And not to block if it's called from main(). I can guarantee when it's called from main() the resource is always available, so it will never attempt to block. Is that sufficient?

    I realise this is a dodgy thing to ask. Maybe I should just bite the bullet and restructure.

  • In reply to Roy Jackson:

    Hi Roy,

    If you call Semphore_pend with BIOS_NO_WAIT, here is what can happen (for both binary and counting semaphores)
    1. The semaphore count is non-zero (e.g. it's available): Count is decremented by 1 and TRUE is returned. In other words, the caller obtains the semaphore.
    2. The semaphore count is zero (e.g. it's NOT available): Count is not decremented and FALSE is returned. In other words, the caller does not obtain the semaphore.

    You could add a call to determine what context you are in and use the corresponding timeout. The API is BIOS_getThreadType() and the returns are

    enum ThreadType {
    BIOS_ThreadType_Hwi, /*! Current thread is a Hwi */
    BIOS_ThreadType_Swi, /*! Current thread is a Swi */
    BIOS_ThreadType_Task, /*! Current thread is a Task */
    BIOS_ThreadType_Main /*! Current thread is Boot/Main */
  • In reply to ToddMullanix:

    Oh cool! Thanks.  I didn't know about BIOS_getThreadType()

    That is excellent, thanks, I can work with that.