2016年5月30日月曜日

mbedのRtosTimerをClassの中で使う。

クラスを定義して、メンバ関数をRtosTimerのtaskとして登録しようと思うと、

RtosTimer (void(*task)(void const *argument), os_timer_type type=osTimerPeriodic, void *argument=NULL)

の第一引数のtaskにメンバ関数をそのまま書くとコンパイルエラーになる。

staticなメンバ関数を一旦かましてやればビルド&実行OKだった。

参考:http://stackoverflow.com/questions/29007191/using-an-rtostimer-inside-a-class

#include "mbed.h"
#include "rtos.h"

class TestClass
{
public:
    TestClass(const char* _instanceName, uint32_t _updateTime) :
        updateTime(_updateTime),
        timer(&TestClass::threadHelper, osTimerPeriodic, (void *)this)
    {
        //NOTE: The RTOS hasn't started yet, so we can't create the internal thread here
        strncpy(instanceName, _instanceName, 20);
    }

    void run() {
        timer.start(updateTime);
    }

    void stop() {
        timer.stop();
    }

private:
    char instanceName[20];
    uint32_t updateTime;
    RtosTimer timer;

    static void threadHelper(const void* arg) {
        printf("In threadHelper()\r\n");

        //Cast the argument to a TestClass instance pointer
        TestClass* instance = (TestClass*)arg;

        //Call the thread method for the TestClass instance
        instance ->threadMethod();
    }

    void threadMethod() {
        printf("In threadMethod()\t%s\r\n", instanceName);
    }
};

int main()
{
    printf("\n\n\r** Using An RtosTimer inside a class test **\r\n");
    
    while (true) {
        printf("In main loop\r\n");
        TestClass test1("test1", 1000);
        TestClass test2("test2", 500);
        test1.run();
        test2.run();
        Thread::wait(10000);
        /*
        test1.stop();
        test2.stop();
        */
    }
}

ちょっとめんどくさいが、staticなメンバ関数をそのまま使うと、インスタンスごとのprivateなメンバ変数にアクセスできない。

mbed repository
https://developer.mbed.org/users/ryood/code/Nucleo_UsingAnRtosTimerInsideAClass_Test/