Mark3的coroutines也相对比较简单,这次测试代码如下:
/*=========================================================================== 协作式多任务处理, 不需要抢占的任务系统,并且可以受益于拥有相对优先级 ===========================================================================*/ #include "mark3.h" /*=========================================================================== Lab Example 2: Exercise: - 添加一个由中断激活的协程 - 添加一个由定时器激活的协程 ===========================================================================*/ extern "C" { void __cxa_pure_virtual(void) {} void DebugPrint(const char* szString_); } namespace { using namespace Mark3; Thread clAppThread; // 申明线程 Thread clIdleThread; // K_WORD awAppStack[PORT_KERNEL_DEFAULT_STACK_SIZE / sizeof(K_WORD)]; // 栈大小 K_WORD awIdleStack[PORT_KERNEL_DEFAULT_STACK_SIZE / sizeof(K_WORD)]; void AppMain(void* unused_); // 回调函数申明 void IdleMain(void* unused_); // 3 个协程 Coroutine clCoroutine1; Coroutine clCoroutine2; Coroutine clCoroutine3; int iCounter1; int iCounter2; int iCounter3; // 3个回调函数之实现 void CoroutineTask1(Coroutine* pclCaller_, void* pvArg_) { Kernel::DebugPrint("Task1\n"); // 测试断点1 int* piCounter = static_cast<int*>(pvArg_); (*piCounter)++; } //--------------------------------------------------------------------------- void CoroutineTask2(Coroutine* pclCaller_, void* pvArg_) { Kernel::DebugPrint("Task2\n"); // 测试断点2 int* piCounter = static_cast<int*>(pvArg_); (*piCounter)++; } //--------------------------------------------------------------------------- void CoroutineTask3(Coroutine* pclCaller_, void* pvArg_) { Kernel::DebugPrint("Task3\n"); // 测试断点3 int* piCounter = static_cast<int*>(pvArg_); (*piCounter)++; } //--------------------------------------------------------------------------- void AppMain(void* unused_) // 用户线程 { // 在本例中,应用程序任务负责激活, 循环方式的各种协程。 while (1) { Thread::Sleep(100); clCoroutine1.Activate(); // 周期激活协程?? Thread::Sleep(100); clCoroutine2.Activate(); Thread::Sleep(100); clCoroutine3.Activate(); } } //--------------------------------------------------------------------------- void IdleMain(void* unused_) { while (1) { // 在这个例子中,使用 Idle 上下文来运行协程,因为它们被调度 auto* pclCoRoutine = CoScheduler::Schedule(); // 不断的运行协程?? if (pclCoRoutine != nullptr) { pclCoRoutine->Run(); } } } } // anonymous namespace using namespace Mark3; //--------------------------------------------------------------------------- int main(void) { Kernel::Init(); // Kernel::SetDebugPrintFunction(DebugPrint); 未实现 CoScheduler::Init(); // 初始化协程调度器 clCoroutine1.Init(1, CoroutineTask1, &iCounter1); clCoroutine2.Init(2, CoroutineTask2, &iCounter2); clCoroutine3.Init(3, CoroutineTask3, &iCounter3); clAppThread.Init(awAppStack, sizeof(awAppStack), 1, AppMain, 0); clIdleThread.Init(awIdleStack, sizeof(awIdleStack), 0, IdleMain, 0); clAppThread.Start(); clIdleThread.Start(); Kernel::Start(); return 0; }
C++就是不断新建类的对像过程,通过一些测试我们很容易,明白怎么使用Mark3的coroutines。
大概的工作原理: 申请并定义2个线程,再申明并定义3协程,当然它们都有对应的回调函数,
然后在MAIN中,进行初始化并加入OS内核调度中,这个例程在IdleMain中不断运行协程调度,
而在AppMain中不断的激活协程。这是因为协程只运行一次,所以要不断的激活。
时间:20220305
SEGGER Embedded Studio对C++支持不好, 不管选择GCC,CLANG,SEGGER哪一个,都有小毛病,
不同的优化级别,也会对MARK3 RTOS有影响,这个C++的OS玩不成了。还是老老实实用C吧。。。
时间:20220521
SEGGER Embedded Studio工程选项,设置如下:
assembler---gcc;
debugging---level 2;
Optimization-- level 1;
compiler---gcc;
C11 and C++11;
Runtime Library---embedded studio;
library Optimization--Balanced; 另外Runtime Memory Area全设为0 bytes.
经过测试确认,Mark3所有的example例程全部测试通过,这个回头草要吃了,要回归Mark3的C++怀抱!