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
  • Here is 1 exammple - very specific to Keil's CMSIS RTOS implementation.

    namespace OsRTX
    {
        // uint32_t os_mutex_cb_##name[4] = { 0 }; becomes..
        struct Mutex { uint32_t _private_[4]; };
    }
    
    class OsMutex
    {
    private:
        OsRTX::Mutex m_rtxMutex;
        osMutexId m_MutexId;
    
        void Create()
        {
            osMutexDef_t temp; // Note: not all osDef_t items can be temporary
            temp.mutex = &m_rtxMutex;
            m_MutexId = osMutecCreate( (const osMutexDef_t *) &temp);
        }
    public:
        OsMutex()       { Create(); }  // Initialized at construction!
                                       // Note: not all os items can be initialized
                                       // before the OS is running.
        ~OsMutex() {}
        osStatus Wait(uint32_t millis) { return osMutexWait(m_MutexId, millis); }
        osStatus Release()             { return osMutexRelease(m_MutexId); }
    };
    
    // 2 Instances of Mutex Objects
    
    OsMutex Uart1Mutex;
    osMutex Uart2Mutex;
    
    // Usage
    
    status = Uart1Mutex.Wait(100);
    status = Uart1Mutex.Release();
    

    You can do something like this

    class Uart : public UartBase
    {
        UART* m_uart;
        OsMutex m_mutex;
    public:
        Uart(UART* uart) : m_uart(uart) {}
        ~Uart() {}
        osStatus Acquire(uint32_t millis) { return m_mutex.Wait(millis); }
        osStatus Release()
    };
    
    Uart GPS_Uart(UART1);
    Uart GSM_Uart(UART2);
    Uart Debug_Uart(UART3);
    

    Combining MANY items you can

    
    Class GenericObjectUsingTaskAndUart
    {
        static const uint32_t mbxitems = 10;
        UartBase *m_uart;
        OsThread A1;
        OsThread A2;
                        // Usually the object IS-A thread, but if you want multiple threads
                        // tied together, you would have the class contain them...
        OsMbx<mbxitems,DataType_t> InQueue// Mailbox with 10 entries of type DataType_t
    public:
        GenericObjectUsingTaskAndUart(UartBase *uart) : m_uart(uart) {}
        ~GenericObjectUsingTaskAndUart() {}
        osStatus InitTask() { // Init and start threads, other stuff, that must happen
                              // After OS is running.  Could break into InitTask and Start
                            }
    
        OsMbxBase<DataType_t> *GetInQueue() { return &InQueue; }
    };
    
    // We now have an object that contains what it needs and knows about then, but is not
    // specifically tied to something
    
    GenericObjectUsingTaskAndUart Gen1(UART1);
    GenericObjectUsingTaskAndUart Gen2(UART2);
    GenericObjectUsingTaskAndUart Gen3(UART3);
    
    

    You may create objects for every os item type (mailbox,message,timer,thread)
    They can be generically combined in any way imagined (for good or bad)

    This is just an example for thought. I am not suggesting that it is a way anyone should use it. Just posting it as an actual answer the original question. I am certainly not requesting any kind of critique.

Reply
  • Here is 1 exammple - very specific to Keil's CMSIS RTOS implementation.

    namespace OsRTX
    {
        // uint32_t os_mutex_cb_##name[4] = { 0 }; becomes..
        struct Mutex { uint32_t _private_[4]; };
    }
    
    class OsMutex
    {
    private:
        OsRTX::Mutex m_rtxMutex;
        osMutexId m_MutexId;
    
        void Create()
        {
            osMutexDef_t temp; // Note: not all osDef_t items can be temporary
            temp.mutex = &m_rtxMutex;
            m_MutexId = osMutecCreate( (const osMutexDef_t *) &temp);
        }
    public:
        OsMutex()       { Create(); }  // Initialized at construction!
                                       // Note: not all os items can be initialized
                                       // before the OS is running.
        ~OsMutex() {}
        osStatus Wait(uint32_t millis) { return osMutexWait(m_MutexId, millis); }
        osStatus Release()             { return osMutexRelease(m_MutexId); }
    };
    
    // 2 Instances of Mutex Objects
    
    OsMutex Uart1Mutex;
    osMutex Uart2Mutex;
    
    // Usage
    
    status = Uart1Mutex.Wait(100);
    status = Uart1Mutex.Release();
    

    You can do something like this

    class Uart : public UartBase
    {
        UART* m_uart;
        OsMutex m_mutex;
    public:
        Uart(UART* uart) : m_uart(uart) {}
        ~Uart() {}
        osStatus Acquire(uint32_t millis) { return m_mutex.Wait(millis); }
        osStatus Release()
    };
    
    Uart GPS_Uart(UART1);
    Uart GSM_Uart(UART2);
    Uart Debug_Uart(UART3);
    

    Combining MANY items you can

    
    Class GenericObjectUsingTaskAndUart
    {
        static const uint32_t mbxitems = 10;
        UartBase *m_uart;
        OsThread A1;
        OsThread A2;
                        // Usually the object IS-A thread, but if you want multiple threads
                        // tied together, you would have the class contain them...
        OsMbx<mbxitems,DataType_t> InQueue// Mailbox with 10 entries of type DataType_t
    public:
        GenericObjectUsingTaskAndUart(UartBase *uart) : m_uart(uart) {}
        ~GenericObjectUsingTaskAndUart() {}
        osStatus InitTask() { // Init and start threads, other stuff, that must happen
                              // After OS is running.  Could break into InitTask and Start
                            }
    
        OsMbxBase<DataType_t> *GetInQueue() { return &InQueue; }
    };
    
    // We now have an object that contains what it needs and knows about then, but is not
    // specifically tied to something
    
    GenericObjectUsingTaskAndUart Gen1(UART1);
    GenericObjectUsingTaskAndUart Gen2(UART2);
    GenericObjectUsingTaskAndUart Gen3(UART3);
    
    

    You may create objects for every os item type (mailbox,message,timer,thread)
    They can be generically combined in any way imagined (for good or bad)

    This is just an example for thought. I am not suggesting that it is a way anyone should use it. Just posting it as an actual answer the original question. I am certainly not requesting any kind of critique.

Children