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

multiple instances of ITC objects in CMSIS-RTOS

Hello,

I'd like to write some reusabel code module to handle e.g. UART ports. Therefore I'd like to create a variable number (based on some kind of define...) of threads dealing with UART port 1,2,3 ... since it is possible to declare CMSIS-RTOS threads with a variable number of instances it could look like this:

#define UART_PORT_NUM 3

osThreadDef(uart_thread, osPriorityNormal, UART_PORT_NUM, 0)

my problem: If I need any kind of inter-thread communication (ITC) object, like mutexes or mail queues, for each of this threads I don't know how to declare them, since osMailQDef, osMutexDef and so on, are not designed with a "variable" number of instances...

Any suggestions?

Parents
  • Ok, that's what I need, thank you! I have to adapt it (I forgot to mention, that I am using C, the mentioned C++ thread was just to demonstrate, that there is a need for such an implementation)
    I was also thinking about avoiding the typical osXyzDef() macros and to do all the stuff manually.
    The only question, which you also have mentioned in your comment: Is it really save/recommendable to create the osXyzDef_t structures (e.g. osMutexDef_t) temporary? The macros are creating them as const, so I thought, the kernel needs it that way.

Reply
  • Ok, that's what I need, thank you! I have to adapt it (I forgot to mention, that I am using C, the mentioned C++ thread was just to demonstrate, that there is a need for such an implementation)
    I was also thinking about avoiding the typical osXyzDef() macros and to do all the stuff manually.
    The only question, which you also have mentioned in your comment: Is it really save/recommendable to create the osXyzDef_t structures (e.g. osMutexDef_t) temporary? The macros are creating them as const, so I thought, the kernel needs it that way.

Children
  • See my example for just supplying a struct to the tread, informing it what queues etc to associate with.

  • It is not at all safe to just make them temporary.

  • I had a similar need for reusable code involving mutexes. The way the macros are defined in
    cmsis_os.h make that difficult, but after some study it appears all that's needed is a
    control block of uint32_t[4] and a temporary pointer.

    The osMutexDef(x) goes away, as does osMutex(x). I've replaced those with:

    typedef struct _osMutexCb {
       uint32_t    cb[4];     // this is the actual control block
       void        *pCb;      // pointer to the control block. Only needed during osMutexCreate
    } osMutexCb_t;
    

    You should be able to allocate space for that statically or dynamically, as many of
    them as you need.

    I've created a wrapper for the create. This could also be done as a macro or inline, but I
    have some portability issues with the latter.

    osMutexId osMutexCreate2(osMutexCb_t *MutexCb) {
       MutexCb->pCb = (void *) MutexCb->cb;
       return osMutexCreate((const osMutexDef_t *) &MutexCb->pCb);
    }
    

    The other mutex functions only use the osMutexId (which is just a pointer to the control
    block, so why couldn't osMutexCreate just use it in the first place?). Duh.

    That's an awfully lot of monkey motion for a relatively simple thing. It's also a redundant
    level of indirection where we're sending osMutexCreate a pointer to a pointer. In the
    standard cmsis syntax using osMutexDef macro, that pointer space is only used once for the
    create. I tested this using an auto variable, demonstrating it does not need to be retained.

    The old Keil programmers would have never permanently wasted those 4 bytes, or the redundant
    level of indirection. They were careful of CPU clocks and space efficiency.

    I've seen some claims posted here that the standard osMutexDef() and osMutex() macros make
    code more readable. Nonsense. Wrapping a simple block of storage in a macro that references
    a typedef is less readable, not more. It took several hours to conclude that all you needed
    was 16 bytes of storage and send osMutexCreate a pointer to a pointer to that storage
    and you're finished.

    I'm at a loss to understand why Keil created these macros that make it difficult to write
    reusable code. The only reasonable answer might be that programmers will be less likely
    to "lose" control blocks by deallocating them from dynamic memory, or some other accident.

    Ok. But they could have easily protected dumb programmers by retaining the control block
    within OS static memory and allocating it during mutex create. Yes, that would mean a fixed
    number of mutexes would be allowed, but that's no different than the static memory allocated
    for the stack, or the fixed number of threads, etc.

    The bottom line is cmsis should have been similar to other OSes, and allow programmers
    to control their own mutexes and other OS objects. This would make portability and
    re-learning issues easier. I'm sure whomever designed this thing believes they were doing
    someone a favor. Sorry, no. It made things much more difficult, and in the end I've just
    rewritten a chunk of cmsis_os.h to let me do what I need to do. No doubt I'll rewrite
    more of it. That's time I've wasted merely because the convoluted multi-layer syntax in
    cmsis_os_h wouldn't allow me to do what is easily done with other OSes.