请从 【 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 ----