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

 请从 【  https://sourceforge.net/u/m0slevin/profile/ 】    下载MARK3源码包,  如下图:

  和scmRTOS一样,因为是C++的,用的人很少很少,这个MARK3带个GUI,功能完善感觉比scmRTOS强一点,让我先来试试水吧。。。

  (scmRTOS相当于以前的UCOS II, 简单的OS,功能少点;Mark3旨在为对没有MMU的微控制器系统进行全面、易于使用的多任务处理

 

第一步:

打开Embedded_Studio按正常方式,建立一个STM32最小工程,并把main.c改为main.cpp,最终能编译通过的如下图:

  上图都是Embedded_Studio给工程创建的,必备的文件框架,完成这个步骤后,能编译和仿真!

 

第二步:

通过下载固件,取得STM32的固件库,我们只取三个就行了,如下图:

 

 因为Embedded_Studio已经有CMSIS和启动文件了,我们只要外设的x_conf.h和inc  src就可以了。

设置我们新加入的文件路经:

 

  完成这个步骤后,也要能编译和仿真!

 

第三步:

MARK3 RTOS是C++的,作者称完美支持C++11 C++14 C++17,编译后无警告  无错误;又因为一搬都是GCC文件

所以我们应当设置一下Embedded_Studio工程选项(GCC;  C11;  C++11就好):

 

  

 

 

 

 

 确认芯片型号和工具j-link:

  

第四步:

我们再移植MARK3 RTOS的内核文件,其他的暂时不要移植,移植好后如下图所示:

  example文件夹是我的工程目录,其实只要移植2个文件夹(lib和src),记得把相关路经加入工程中。

 

第五步:

来个简单又爆力的测试吧,把我们的main.cpp改变如下所示并编译,体积还算小吧:

----似乎打开了MAR3 RTOS的大门了,加油吧!!!

 

时间:2022-02-14

MAR3 RTOS在Embedded_Studio中,可以正常编译,但在接上STM32在线仿真后,就进入了HardFault_Handler错误,

想了好久,试了很多方法,在想要放弃时,终于搞定了。。我太难了!!

首先打开mark3cfg.h,这个是OS的用户配置文件,找到KERNEL_STACK_CHECK 配置为0,如下图:

/**
 * Enable kernel asserts at runtime.
 */
#define KERNEL_DEBUG (0)

/**
 * Perform stack-depth checks on threads at each context switch, which is useful
 * in detecting stack overflows / near overflows.  Near-overflow detection uses
 * thresholds defined in the target's portcfg.h.  Enabling this also adds the
 * Thread::GetStackSlack() method, which allows a thread's stack to be profiled
 * on-demand.
 *
 * Note:  When enabled, the additional stack checks result in a performance hit
 * to context switches and thread initialization.
 *
 */
#define KERNEL_STACK_CHECK (0)

上面俩个都是影响性能的,看描述是一些辅助功能,关掉后没事的!

 

然后再找到lib文件夹下的mark3c.cpp和mark3c.h,把它们进行删除,因为CHECK (0)了,不需要了,

留着会编译不通过。mark3c中的c应该是CHECK索写了。

 

最后我们接上STM32开发板,在线仿真。。官方的例程终于正常了!!

  通过这件事件,可以肯定的是:mark3cfg.h是给用户配置OS系统的,而portcfg.h是配置对应接口的,接口就是M3  M0  M4这些的!!

 

另外在ARM通用标准内核中,基本上mark3 rtos系统接管了如下资源:

  回顾一下知识点,ARM处理器有7种模式:

1---  user用户模式              2---  FIQ快速中断模式模式          3---  IRQ普通中断模式

4--- SVC管理模式              5---  Abort数据访问中止模式        6---  Und未定义指令中止模式

7---  SYS系统模式

 

话说为什么KERNEL_STACK_CHECK 配置为1打开后,就会出错呢?我觉得这是与Embedded_Studio兼容问题,

相信在用Cmake进行编译时,应该是可以正常使用的(优化参数问题,已经正常了)!!

 

时间:2022-02-15

在Embedded_Studio中,不同的优先级,会引发RTOS执行错误,经测试后保守参数为:

 

portcfg.h测试OK:

/*===========================================================================

    @file: portcfg.h
    @brief: CPU/端口的特定配置选项,每个芯片的专配

===========================================================================*/
#pragma once          // 防止make3cgf.h头文件重复包含
#include <stdint.h>   // 必要的C标准库

#define KERNEL_NUM_PRIORITIES (16)       // 线程优先级的数量:32种

/* 内核定时器线程运行的优先级。一般来说是最高的:31, 而空闲进程是最低的:0 */
#define KERNEL_TIMERS_THREAD_PRIORITY (KERNEL_NUM_PRIORITIES - 1)

#define THREAD_QUANTUM_DEFAULT     (4)   // 多个线程同优先级时,设置为时间片调度:4ms

#define KERNEL_STACK_GUARD_DEFAULT (8)  // words即32*2字节边界,剩余stack接近这个数量时,会有assert反馈

#define PORT_COROUTINE_PRIORITIES  (4)   // 设置协程调度器支持的优先级数:8个

#ifndef ARM
#define ARM (1)  // 定义一个宏,指示此端口所属的 CPU 架构
#endif

/*
    Define types that map to the CPU Architecture's default data-word and address
    size.
*/
#define K_WORD uint32_t //!< Size of a data word
#define K_ADDR uint32_t //!< Size of an address (pointer size)
#define K_INT   int32_t


/*
    Set a base datatype used to represent each element of the scheduler's
    priority bitmap.

    PORT_PRIO_MAP_WORD_SIZE should map to the *size* of an element of type
    PORT_PROI_TYPE.
*/
#define PORT_PRIO_TYPE uint32_t     //!< Type used for bitmap in the PriorityMap class
#define PORT_PRIO_MAP_WORD_SIZE (4) //!< size of PORT_PRIO_TYPE in bytes


#define PORT_SYSTEM_FREQ (72000000)                           // CPU工作频率,要和单片机主频一致
#define PORT_TIMER_FREQ ((uint32_t)(PORT_SYSTEM_FREQ / 1000)) // 计时器滴答1000次/秒

#define PORT_KERNEL_DEFAULT_STACK_SIZE ((K_ADDR)512)          // 默认线程堆栈大小(字节)
#define PORT_KERNEL_TIMERS_THREAD_STACK ((K_ADDR)512)         // 定义内核定时器线程栈的大小(如果配置了)

/* 定义对应于目标定时器硬件的计数器寄存器的本机类型 */
#define PORT_TIMER_COUNT_TYPE uint32_t //!< 32位定时器,STM32这种SYSYTICK都是24位,减数器

#define PORT_MIN_TIMER_TICKS  (0) // 任何延迟或睡眠的最小计时器滴答数,需要确保计时器无法初始化为负值
#define PORT_OVERLOAD_NEW     (1) // 将此设置为 1 以使用内核的分配器函数重载系统的 New/Free 函数

#define PORT_STACK_GROWS_DOWN (1) // 如果堆栈在目标架构中向下增长,则将其设置为1;如果堆栈向上增长,则设置为0
#define PORT_USE_HW_CLZ       (1) // 如果目标CPU/工具链支持优化的Count-leading-zeros指令,或count-leading-zeros内在指令,将此设置为1

 

mark3cfg.h测试OK:

/*===========================================================================

    @file: mark3cfg.h
    @brief: Mark3 内核配置

===========================================================================*/
#pragma once                           // 防止make3cgf.h头文件重复包含


#define KERNEL_DEBUG       (0)         // 在运行时启用内核asserts,影响性能
#define KERNEL_STACK_CHECK (1)         // 上下文切换时对堆栈深度检查,影响性能

/* 启用这个功能提供了Thread::SetName()和Thread::GetName(),
   传递给Thread::SetName()的字符串必须在该线程的生命周期内持续存在 */
#define KERNEL_NAMED_THREADS (1)

#define KERNEL_EVENT_FLAGS   (1)          // 该标志启用事件标志同步对象
#define KERNEL_CONTEXT_SWITCH_CALLOUT (1) // 可以定义一个回调,在上下文切换发生时执行,影响开销
#define KERNEL_THREAD_CREATE_CALLOUT  (1) // 用户自定义的内核回调,每当线程启动时就会执行
#define KERNEL_THREAD_EXIT_CALLOUT    (1) // 用户自定义的内核回调,每当线程被终止时就会执行

/* 每个优先级内启用循环调度,特殊的软件计时器用于管理正在运行的线程,影响性能 */
#define KERNEL_ROUND_ROBIN            (1)

/* 线程中提供特殊的数据指针,可用于向线程添加额外的上下文,通常这将用于实现线程本地存储 */
#define KERNEL_EXTENDED_CONTEXT       (1)

#include "portcfg.h" // 包括CPU/端口的特定配置选项,每个芯片的专配

 

这个RTOS使用空间,是真的小呀,编译仿真都正常的情况下:

  ---- END ----

posted on 2022-02-14 23:00  木子剑  阅读(410)  评论(0编辑  收藏  举报