From eb2c0981974ef5d93e6315880973c4c256c89dc3 Mon Sep 17 00:00:00 2001 From: bernard Date: Tue, 31 Jan 2017 13:19:18 +0800 Subject: [PATCH] [C++] Add C++ interface for RT-Thread kernel. --- components/cplusplus/Lock.h | 42 ++++++++++++ components/cplusplus/Mail.h | 95 ++++++++++++++++++++++++++ components/cplusplus/Mutex.cpp | 35 ++++++++++ components/cplusplus/Mutex.h | 60 +++++++++++++++++ components/cplusplus/Queue.h | 88 ++++++++++++++++++++++++ components/cplusplus/SConscript | 1 + components/cplusplus/Semaphore.cpp | 30 +++++++++ components/cplusplus/Semaphore.h | 56 ++++++++++++++++ components/cplusplus/Thread.cpp | 103 +++++++++++++++++++++++++++++ components/cplusplus/Thread.h | 82 +++++++++++++++++++++++ 10 files changed, 592 insertions(+) create mode 100644 components/cplusplus/Lock.h create mode 100644 components/cplusplus/Mail.h create mode 100644 components/cplusplus/Mutex.cpp create mode 100644 components/cplusplus/Mutex.h create mode 100644 components/cplusplus/Queue.h create mode 100644 components/cplusplus/Semaphore.cpp create mode 100644 components/cplusplus/Semaphore.h create mode 100644 components/cplusplus/Thread.cpp create mode 100644 components/cplusplus/Thread.h diff --git a/components/cplusplus/Lock.h b/components/cplusplus/Lock.h new file mode 100644 index 0000000000..2d8cbe5895 --- /dev/null +++ b/components/cplusplus/Lock.h @@ -0,0 +1,42 @@ +/* + * File : Lock.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2016, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2016/10/1 Bernard The first version + */ + +#pragma once + +#include +#include + +namespace rtthread { + +class Lock +{ +public: + Lock(Mutex& mutex) : m(mutex) {m.lock();} + ~Lock() {m.unlock();} + +protected: + Mutex &m; +}; + +} diff --git a/components/cplusplus/Mail.h b/components/cplusplus/Mail.h new file mode 100644 index 0000000000..c812aa0bd7 --- /dev/null +++ b/components/cplusplus/Mail.h @@ -0,0 +1,95 @@ +/* + * File : Mail.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2016, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2016/10/1 Bernard The first version + */ + +#pragma once + +#include +#include + +#include + +namespace rtthread { + +/** + * The Mail class allow to control, send, receive, or wait for mail. + * A mail is a memory block that is send to a thread or interrupt service routine. + * @param T data type of a single message element. + * @param queue_sz maximum number of messages in queue. + */ + +template +class Mail { +public: + /** Create and Initialise Mail queue. */ + Mail(const char* name = "") + { + rt_mb_init(&mID, name, mPool, queue_sz, RT_IPC_FLAG_FIFO); + } + + ~Mail() + { + rt_mb_detach(&mID); + } + + /** Put a mail in the queue. + @param mptr memory block previously allocated with Mail::alloc or Mail::calloc. + @return status code that indicates the execution status of the function. + */ + bool put(T *mptr, int32_t millisec = 0) + { + rt_int32_t tick; + + if (millisec < 0) + tick = -1; + else + tick = rt_tick_from_millisecond(millisec); + + return rt_mb_send_wait(&mID, (rt_uint32_t)mptr, tick) == RT_EOK; + } + + /** Get a mail from a queue. + @param millisec timeout value or 0 in case of no time-out. (default: osWaitForever). + @return event that contains mail information or error code. + */ + T* get(int32_t millisec = -1) + { + T *t = NULL; + rt_int32_t tick; + + if (millisec < 0) + tick = -1; + else + tick = rt_tick_from_millisecond(millisec); + + rt_mb_recv(&mID, &t, tick); + + return t; + } + +private: + struct rt_mailbox mID; + T* mPool[queue_sz]; +}; + +} diff --git a/components/cplusplus/Mutex.cpp b/components/cplusplus/Mutex.cpp new file mode 100644 index 0000000000..c8dbbe6598 --- /dev/null +++ b/components/cplusplus/Mutex.cpp @@ -0,0 +1,35 @@ +#include "Mutex.h" + +using namespace rtthread; + +Mutex::Mutex(const char *name) +{ + rt_mutex_init(&mID, name, RT_IPC_FLAG_FIFO); +} + +bool Mutex::lock(int32_t millisec) +{ + rt_int32_t tick; + + if (millisec < 0) + tick = -1; + else + tick = rt_tick_from_millisecond(millisec); + + return rt_mutex_take(&mID, tick) == RT_EOK; +} + +bool Mutex::trylock() +{ + return lock(0); +} + +void Mutex::unlock() +{ + rt_mutex_release(&mID); +} + +Mutex::~Mutex() +{ + rt_mutex_detach(&mID); +} diff --git a/components/cplusplus/Mutex.h b/components/cplusplus/Mutex.h new file mode 100644 index 0000000000..b4109751e5 --- /dev/null +++ b/components/cplusplus/Mutex.h @@ -0,0 +1,60 @@ +/* + * File : Mutex.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2016, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2016/10/1 Bernard The first version + */ + +#pragma once + +#include +#include + +namespace rtthread { + +/** The Mutex class is used to synchronise the execution of threads. + This is for example used to protect access to a shared resource. +*/ +class Mutex { +public: + /** Create and Initialize a Mutex object */ + Mutex(const char* name = "mutex"); + ~Mutex(); + + /** Wait until a Mutex becomes available. + @param millisec timeout value or 0 in case of no time-out. (default: WaitForever) + @return true if the mutex was acquired, false otherwise. + */ + bool lock(int32_t millisec = -1); + + /** Try to lock the mutex, and return immediately + @return true if the mutex was acquired, false otherwise. + */ + bool trylock(); + + /** Unlock the mutex that has previously been locked by the same thread + */ + void unlock(); + +private: + struct rt_mutex mID; +}; + +} diff --git a/components/cplusplus/Queue.h b/components/cplusplus/Queue.h new file mode 100644 index 0000000000..b011dd5d28 --- /dev/null +++ b/components/cplusplus/Queue.h @@ -0,0 +1,88 @@ +/* + * File : Queue.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2016, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2016/10/1 Bernard The first version + */ + +#pragma once + +#include +#include + +#include + +namespace rtthread { + +/** + * The Queue class allow to control, send, receive, or wait for messages. + * A message can be a integer or pointer value to a certain type T that is send + * to a thread or interrupt service routine. + * @param T data type of a single message element. + * @param queue_sz maximum number of messages in queue. + */ +template +class Queue +{ +public: + /** Create and initialise a message Queue. */ + Queue() + { + rt_mq_init(&mID, "mq", mPool, sizeof(T), sizeof(mPool), RT_IPC_FLAG_FIFO); + }; + + ~Queue() + { + rt_mq_detach(&mID); + }; + + /** Put a message in a Queue. + @param data message pointer. + @param millisec timeout value or 0 in case of no time-out. (default: 0) + @return status code that indicates the execution status of the function. + */ + rt_err_t put(T& data, int32_t millisec = 0) + { + return rt_mq_send(&mID, &data, sizeof(data)); + } + + /** Get a message or Wait for a message from a Queue. + @param millisec timeout value or 0 in case of no time-out. (default: osWaitForever). + @return bool . + */ + bool get(T& data, int32_t millisec = WAIT_FOREVER) + { + rt_int32_t tick; + + if (millisec < 0) + tick = -1; + else + tick = rt_tick_from_millisecond(millisec); + + return rt_mq_recv(&mID, &data, sizeof(data), tick) == RT_EOK; + } + +private: + struct rt_messagequeue mID; + + char mPool[(sizeof(struct rt_messagequeue)+sizeof(T)) * queue_sz]; +}; + +} diff --git a/components/cplusplus/SConscript b/components/cplusplus/SConscript index 63f68ec3d8..4f7fab9b9d 100644 --- a/components/cplusplus/SConscript +++ b/components/cplusplus/SConscript @@ -4,6 +4,7 @@ from building import * cwd = GetCurrentDir() src = Glob('*.cpp') + Glob('*.c') + CPPPATH = [cwd] group = DefineGroup('CPlusPlus', src, depend = ['RT_USING_CPLUSPLUS'], CPPPATH = CPPPATH) diff --git a/components/cplusplus/Semaphore.cpp b/components/cplusplus/Semaphore.cpp new file mode 100644 index 0000000000..2579bcb041 --- /dev/null +++ b/components/cplusplus/Semaphore.cpp @@ -0,0 +1,30 @@ +#include "Semaphore.h" + +using namespace rtthread; + +Semaphore::Semaphore(const char *name, int32_t count) +{ + rt_sem_init(&mID, name, count, RT_IPC_FLAG_FIFO); +} + +bool Semaphore::wait(int32_t millisec) +{ + rt_int32_t tick; + + if (millisec < 0) + tick = -1; + else + tick = rt_tick_from_millisecond(millisec); + + return rt_sem_take(&mID, tick) == RT_EOK; +} + +void Semaphore::release(void) +{ + rt_sem_release(&mID); +} + +Semaphore::~Semaphore() +{ + rt_sem_detach(&mID); +} diff --git a/components/cplusplus/Semaphore.h b/components/cplusplus/Semaphore.h new file mode 100644 index 0000000000..6c09b198c6 --- /dev/null +++ b/components/cplusplus/Semaphore.h @@ -0,0 +1,56 @@ +/* + * File : Semaphore.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2016, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2016/10/1 Bernard The first version + */ + +#pragma once + +#include +#include + +namespace rtthread { + +/** The Semaphore class is used to manage and protect access to a set of shared resources. */ +class Semaphore +{ +public: + /** Create and Initialize a Semaphore object used for managing resources. + @param number of available resources; maximum index value is (count-1). + */ + Semaphore(const char *name = "sem", int32_t count = 0); + ~Semaphore(); + + /** Wait until a Semaphore resource becomes available. + @param millisec timeout value or 0 in case of no time-out. + @return true on success. + */ + bool wait(int32_t millisec = -1); + + /** Release a Semaphore resource that was obtain with Semaphore::wait. + */ + void release(void); + +private: + struct rt_semaphore mID; +}; + +} diff --git a/components/cplusplus/Thread.cpp b/components/cplusplus/Thread.cpp new file mode 100644 index 0000000000..4d2d8a59ea --- /dev/null +++ b/components/cplusplus/Thread.cpp @@ -0,0 +1,103 @@ +#include "Thread.h" + +using namespace rtthread; + +Thread::Thread(rt_uint32_t stack_size, + rt_uint8_t priority, + rt_uint32_t tick, + const char *name) +: _entry(RT_NULL), started(false) +{ + rt_event_init(&_event, name, 0); + + _thread = rt_thread_create(name, + (thread_func_t)func, + this, + stack_size, + priority, + tick); +} + +Thread::Thread(void (*entry)(void *p), + void *p, + rt_uint32_t stack_size, + rt_uint8_t priority, + rt_uint32_t tick, + const char *name) +: _entry(RT_NULL), started(false), _param(p) +{ + rt_event_init(&_event, name, 0); + + _thread = rt_thread_create(name, + (thread_func_t)func, + this, + stack_size, + priority, + tick); +} + +Thread::~Thread() +{ + rt_thread_delete(_thread); +} + +bool Thread::start() +{ + if (rt_thread_startup(_thread) == RT_EOK) + { + started = true; + } + + return started; +} + +void Thread::sleep(int32_t millisec) +{ + rt_int32_t tick; + + if (millisec < 0) + tick = 1; + else + tick = rt_tick_from_millisecond(millisec); + + rt_thread_delay(tick); +} + +void Thread::func(Thread *pThis) +{ + if (pThis->_entry != RT_NULL) + { + pThis->_entry(pThis->_param); + } + else + { + pThis->run(); + } + + rt_event_send(&pThis->_event, 1); +} + +void Thread::run() +{ + /* please overload this method */ +} + +void Thread::wait(int32_t millisec) +{ + join(millisec); +} + +void Thread::join(int32_t millisec) +{ + if (started) + { + rt_int32_t tick; + + if (millisec < 0) + tick = -1; + else + tick = rt_tick_from_millisecond(millisec); + + rt_event_recv(&_event, 1, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, tick, RT_NULL); + } +} diff --git a/components/cplusplus/Thread.h b/components/cplusplus/Thread.h new file mode 100644 index 0000000000..78bbd77d1f --- /dev/null +++ b/components/cplusplus/Thread.h @@ -0,0 +1,82 @@ +/* + * File : Thread.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2016, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2016/10/1 Bernard The first version + */ + +#pragma once + +#include +#include + +namespace rtthread +{ + +/** The Thread class allow defining, creating, and controlling thread functions in the system. */ +class Thread +{ +public: + typedef void (*thread_func_t) (void *param); + + /** Allocate a new thread without starting execution + @param priority initial priority of the thread function. (default: osPriorityNormal). + @param stack_size stack size (in bytes) requirements for the thread function. (default: DEFAULT_STACK_SIZE). + @param stack_pointer pointer to the stack area to be used by this thread (default: NULL). + */ + Thread(rt_uint32_t stack_size = 2048, + rt_uint8_t priority = (RT_THREAD_PRIORITY_MAX * 2)/3, + rt_uint32_t tick = 20, + const char *name = "th"); + + Thread(void (*entry)(void *p), + void *p = RT_NULL, + rt_uint32_t stack_size = 2048, + rt_uint8_t priority = (RT_THREAD_PRIORITY_MAX * 2)/3, + rt_uint32_t tick = 20, + const char *name = "th"); + + virtual ~Thread(); + + bool start(); + + static void sleep(int32_t millisec); + + void wait(int32_t millisec); + void join(int32_t millisec = -1); + +protected: + virtual void run(); + +private: + static void func(Thread *pThis); + +private: + rt_thread_t _thread; + + thread_func_t _entry; + void *_param; + + /* event for thread join */ + struct rt_event _event; + bool started; +}; + +} -- GitLab