木子剑
生命不熄,学习不止!

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++怀抱!

posted on 2022-02-28 08:41  木子剑  阅读(64)  评论(0编辑  收藏  举报