Onsunsl 发表于 2012-8-23 08:51:15

Keil RTX4.20 for STM32学习(官方已公开源码)

本帖最后由 Onsunsl 于 2012-8-23 16:39 编辑

keil 里玩TRX的人好像比较少,RTX是一个不错的os,体积很好,它的优缺点可以google

RTX在keil默认是不提供os的源码的,除非你购买,为了学习从网的找了RL-ARM V420,安装后就有源码文件了,其实这个包里含:os、fs、ip、usb等代码和例程




对使用RTX的起动过程做了个分析,细读代码会发现比ucos结构简单。
STM32F10x.S-114 Reset_Handler()
main.c-57   main()
HL_CM3.c-42 os_set_env() //切换模式
HAL_CM3.c-96 SVC_Handler()//系统调用
               |- rt_Task.c-268 rt_sys_init()//系统初始化   
               |                     |- rt_MemBox.c-25 _init_box(mp_tcb)//任务控制块链表化
               |                     |- rt_MemBox.c-25 _init_box(mp_stk)//任务栈块链表化
               |                     |- rt_MemBox.c-25 _init_box(m_tmr)//任务定时器块链表化
               |                     |- rt_Task.c-50    rt_init_context(os_idle_TCB)//空闲任务上下文初始化
               |                     |                        |- rt_MemBox.c-71 rt_alloc_box()//分配栈
               |                     |                        \- HAL_CM3-218    rt_init_stack()//写控制块和寄存器
               |                     |- HAL_CM3.c-34    rt_set_PSP()//设置线程栈
               |                     |- rt_Task.c-308 rt_tmr_init()//CM3硬件定时器初始化
               |                     |- rt_Robin.c-32    rt_init_robin()//任务轮调
               |                     |- rt_Task.c-197    rt_tsk_create()//创建init任务
               |                                             |- rt_MemBox.c-71 rt_alloc_box()//分配任务控制块
               |                                             |- rt_Task.c-50    rt_init_context()//init任务上下文初始化
               |                                             |                        |- rt_MemBox.c-71 rt_alloc_box()//分配栈
               |                                             |                         \- HAL_CM3-218    rt_init_stack()//写控制块和寄存器
               |                                             |- rt_Task.c-36   rt_get_TID()//获取任务ID并写入活动任务列表里
               |                                             \- rt_Task.c-86   rt_dispatch()//分派任务
               |                                                                     |- rt_List.c-95 rt_put_rdy_first()//抢占正运行任务
               |                                                                     \- rt_Task.c-76 rt_switch_req()//切换任务
               |- rt_System.c-142 rt_stk_check()//栈溢出检测
               |- main.c-48   __task init()//运行init任务
                |                     |- rt_Task.c-197    rt_tsk_create(A)//创建任务A
               |                         |                     |- rt_MemBox.c-71 rt_alloc_box()//分配任务控制块
               |                         |                     |- rt_Task.c-50    rt_init_context()//A任务上下文初始化
               |                         |                     |                        |- rt_MemBox.c-71 rt_alloc_box()//分配栈
               |                         |                     |                         \- HAL_CM3-218    rt_init_stack()//写控制块和寄存器
               |                         |                     |- rt_Task.c-36    rt_get_TID()//获取任务ID并写入活动任务列表里
               |                         |                     \- rt_Task.c-86    rt_dispatch()//分派任务
               |                         |                                             \- rt_List.c-37 rt_put_prio()
               |                     |- rt_Task.c-197    rt_tsk_create(B)//创建任务A
               |                         |                     |- rt_MemBox.c-71 rt_alloc_box()
               |                         |                     |- rt_Task.c-50    rt_init_context()
               |                         |                     |                        |- rt_MemBox.c-71 rt_alloc_box()
               |                         |                     |                         \- HAL_CM3-218    rt_init_stack()
               |                         |                     |- rt_Task.c-36    rt_get_TID()
               |                         |                     \- rt_Task.c-86    rt_dispatch()
               |                         |                                             \- rt_List.c-37 rt_put_prio()
               |                         \- rt_Task.c-231 rt_tsk_delete()//删除init任务
               |                                             |- rt_MemBox.c 117 rt_free_box(mp_stk)//init任务释放栈
               |                                             |- rt_MemBox.c 117 rt_free_box(mp_tcb)//init任务控制块
               |                                             \- rt_Task.c 86    rt_dispatch()
               |                                                                         |- rt_get_first()
               |                                                                         \- rt_switch_req()
               |- rt_System.c-142 rt_stk_check()
               |- main.c-36      __task phaseA()//运行A任务
               |                            \- rt_time.c-32 rt_dly_wait(1)//延时
               |                                             |- rt_Task.c-113 rt_block()
               |                                                                |- rt_List.c-147 rt_put_dly()//把当前任务入延时列表中
               |                                                             |- rt_List.c-72 rt_get_first()//取出就绪任务
               |                                                             \- rt_Task.c-76 rt_switch_req()//切换任务


Onsunsl 发表于 2012-8-23 08:57:37

如果单存为了使用,不学习os源码的话,直接使用RTX库也可以的
例程简单对IO的翻转

liurangzhou 发表于 2012-8-23 08:58:47

现在RTX的源码是开放的,只是那些中间件不开放

Onsunsl 发表于 2012-8-23 09:05:14

哦?我out man了,
我用的是keil 420,安装了450后真是直接开放源码了



Onsunsl 发表于 2012-8-23 09:06:40

liurangzhou 发表于 2012-8-23 08:58 static/image/common/back.gif
现在RTX的源码是开放的,只是那些中间件不开放

中间件指示是RTX调试插件?
我是初学者,请大侠多多指教
{:lol:} {:handshake:}

bbs2009 发表于 2012-8-23 09:27:53

Onsunsl 发表于 2012-8-23 09:31:41

bbs2009 发表于 2012-8-23 09:27 static/image/common/back.gif
USB_CM3.lib, RTX_CM3.lib之类貌似没有源码,   算是中间件吧。

嗯,IP也没有源码,楼上在用RTX吗?

_yuming 发表于 2012-8-23 09:49:14

bbs2009 发表于 2012-8-23 09:27 static/image/common/back.gif
USB_CM3.lib, RTX_CM3.lib之类貌似没有源码,   算是中间件吧。

RTX_CM3.lib这个是有源码的,你可以自己生成RTX_CM3.lib。

Onsunsl 发表于 2012-8-23 10:21:33

本帖最后由 Onsunsl 于 2012-8-23 10:24 编辑

对RTX系统任务栈内存池定义有点不理解:

RTX_lib.c-62行
#define _declare_box8(pool,size,cnt)U64 pool[(((size)+7)/8)*(cnt) + 2]
_declare_box8 (mp_stk, OS_STKSIZE*4, OS_TASKCNT-OS_PRIVCNT+1);

展开后:
U64 mp_stk[(((OS_STKSIZE*4)+7)/8)*(OS_TASKCNT-OS_PRIVCNT+1) + 2]

OS_STKSIZE*4   -------------- ?
+7)/8               ---------------8字节对齐处理
OS_TASKCNT    --------------   任务数
+1                   --------------   空闲任务
OS_PRIVCNT    --------------   用户提供的栈数?

jordonwu 发表于 2012-8-23 10:42:39

mark.......

Onsunsl 发表于 2012-8-23 11:03:10

本帖最后由 Onsunsl 于 2012-8-23 16:32 编辑

1.RTX_lib.c-74行
void *os_active_TCB;//活动任务队列指针
+----------------+
|   P_TCB 0|
|   P_TCB 1|
|   P_TCB 2|
|   P_TCB .|
|   P_TCB .|
|   P_TCB .|
|   P_TCB n |
+---------------+
n = OS_TASKCNT - 1
void类型的指针指向在活的任务TCB

2.RTX_lib.c-58行
U32 mp_tcb[(((OS_TCB_SIZE)+3)/4)*(OS_TASKCNT) + 3]//任务控制块内存池,4字节对齐


3.RTX_lib.c-62行
#define _declare_box8(pool,size,cnt)U64 pool[(((size)+7)/8)*(cnt) + 2]
_declare_box8 (mp_stk, OS_STKSIZE*4, OS_TASKCNT-OS_PRIVCNT+1);

展开后:
U64 mp_stk[(((OS_STKSIZE*4)+7)/8)*(OS_TASKCNT-OS_PRIVCNT+1) + 2]//系统任务栈内存池


4.RTX_lib.c-82行
U32 const *m_tmr = NULL;//定时器
   +-------------------+
   | U16*m_tmr |
   +-------------------+


5.rt_Task.c-29行
struct OS_TCB os_idle_TCB; //空闲任务TCB
   +---------------------------+
   | U8cb_type          |
   | U8state            |
   | U8prio                |
   | U8task_id            |
   | OS_TCB * p_lnk   |
   | OS_TCB * p_rlnk    |
   | OS_TCB * p_dlnk   |
   | OS_TCB * p_plnk   |
   | U16delta_time   |
   | U16interval_time|
   | u16events          |
   | U16waits            |
   | void ** msg          |
   | U8   ret_val          |
   +--------------------------+

6.rt_Liat.c-25行
struct OS_XCBos_rdy;//就绪任务列表表头
   +------------------------+
   | U8cb_type       |
   | OS_TCB * p_lnk|
   | OS_TCB * p_rlnk |
   | OS_TCB * p_dlnk|
   | OS_TCB * p_plnk|
   | U16delta_time|
   +------------------------+

7.rt_Liat.c-27行
struct OS_XCBos_dly;//延时任务列表表头
   +-------------------------+
   | U8cb_type      |
   | OS_TCB * p_lnk   |
   | OS_TCB * p_rlnk|
   | OS_TCB * p_dlnk |
   | OS_TCB * p_plnk |
   | U16delta_time   |
   +-------------------------+


8.rt_Task-26行
struct OS_TSK os_tsk;//正在运行的任务
   +-------------------+
   | P_TCBrun    |
   | P_TCBnew|
   +-------------------+

9.RTX_lib
U32 os_fifo;//ISR请求队列
   +--------------------+
   | U8first         |
   | U8last          |
   | U8count      |
   | U8count      |
   | +--------------+|
   | | void * id   ||
   | | U32arg   ||
   | +--------------+|
   |                     |
   |                     |
   |                     |
   |                     |
   |                     |
   |                     |
   |                     |
   |                     |
   |                     |
   |                     |
   |                     |
   +-------------------+

10.rt_Robin.c-23行
struct OS_ROBIN os_robin; //轮调度变量
   +-------------------+
   | P_TCBtask   |
   | U16time      |
   | U16tout      |
   +-------------------+



















lryxr2507 发表于 2012-8-23 12:04:56

下来学习,顶一个!

bbs2009 发表于 2012-8-23 12:24:27

Onsunsl 发表于 2012-8-23 12:35:01

bbs2009 发表于 2012-8-23 12:24 static/image/common/back.gif
请教:
      RTX_CM3源码 在哪?我在 4.5 下没有搜到。
      USB_CM3有源码吗? 我在 4.5 下没有 ...

如果keil默认方式安装的的话应该是:
C:\Keil\ARM\RL\RTX\SRC\CM

_yuming 发表于 2012-8-23 14:00:46

本帖最后由 _yuming 于 2012-8-23 14:02 编辑

USB_CM3没有

我只是告诉你RTX_CM3有源码

路径C:\Keil\ARM\RL\RTX工程项目名称 RTX_Lib_CM

这说明你看东西很不仔细。。。。

buxinshan 发表于 2012-8-23 14:34:39

之前用了RTX_CAN,MDK所提供的驱动用的都是寄存器方式

Onsunsl 发表于 2012-8-23 16:11:16

buxinshan 发表于 2012-8-23 14:34 static/image/common/back.gif
之前用了RTX_CAN,MDK所提供的驱动用的都是寄存器方式

你可以楼主位的例程,都是用的st库


buxinshan 发表于 2012-8-24 08:29:53

Onsunsl 发表于 2012-8-23 16:11 static/image/common/back.gif
你可以楼主位的例程,都是用的st库

资源非常好,感谢了!!

liurangzhou 发表于 2012-8-24 08:31:30

Onsunsl 发表于 2012-8-23 09:06 static/image/common/back.gif
中间件指示是RTX调试插件?
我是初学者,请大侠多多指教
   ...

我是指CAN,USB,网络等这些个东东,没有开放源码

Onsunsl 发表于 2012-8-24 09:16:29

CAN,USB,网络的确是没有放出来

Onsunsl 发表于 2012-8-24 09:18:36

本帖最后由 Onsunsl 于 2012-8-24 09:20 编辑

对RTX的栈操作,不知道理解的对不对:

/*--------------------------- rt_init_stack ---------------------------------*/
/* 功能:栈初始化
* 参数:p_TCB 任务控制块指针
*   task_body 任务函数指针
*/
void rt_init_stack (P_TCB p_TCB, FUNCP task_body) {
/* Prepare TCB and saved context for a first time start of a task. */
U32 *stk,i,size;

/* Prepare a complete interrupt frame for first task start */
    //栈大小以是字节数表示,而用户是以4字节提供,所以除以4
size = p_TCB->priv_stack >> 2;   
if (size == 0) { //os_stackinfo的低16bit为系统默认栈尺寸
    size = (U16)os_stackinfo >> 2;
}

/* Write to the top of stack. */
stk = &p_TCB->stack[size];

/* Auto correct to 8-byte ARM stack alignment. */
if ((U32)stk & 0x04) {         //-1把不对齐部分跳过
    stk--;
}

stk -= 16;
// stk /* xPSR                                              */
// stk /* Entry Point                                    */
// stk /* R14 (LR) (init value will cause fault if ever used)*/
// stk /* R12                                                */
// stk /* R3                                                 */
// stk /* R2                                                 */
// stk /* R1                                                 */
// stk /* R0 : argument                                 */
//Remaining registers saved on process stack         
// stk /* R11                                                */
// stk /* R10                                                */
// stk /* R9                                                 */
// stk /* R8                                                 */
// stk /* R7                                                 */
// stk /* R6                                                 */
// stk /* R5                                                 */
// stk /* R4                                                 */
/* Default xPSR and initial PC */
stk[15] = INITIAL_xPSR;            //xPSR
stk[14] = (U32)task_body;         //PC?

/* Clear R1-R12,LR registers. */
for (i = 0; i < 14; i++) {                      //R0~R13
    stk[i] = 0;
}

/* Assign a void pointer to R0. */
stk[8] = (U32)p_TCB->msg;

/* Initial Task stack pointer. */
p_TCB->tsk_stack = (U32)stk;            //任务栈起始位置

/* Task entry point. */
p_TCB->ptask = task_body;                  //任务函数体

/* Set a magic word for checking of stack overflow. */
p_TCB->stack[0] = MAGIC_WORD;      //栈溢出测量字
}

dami 发表于 2012-8-24 09:33:56

好东西。

lovelywwei 发表于 2012-8-24 09:56:32

没用过这个的说。

Onsunsl 发表于 2012-8-24 10:12:41

读RTX的代码会发现一些奥妙:

手册提供给用户的接口:
OS_TID os_tsk_create (
    void (*task)(void),    /* Task to create */
    U8    priority );      /* Task priority (1-254) */


源码实现:
OS_TID rt_tsk_create (FUNCP task, U32 prio_stksz, void *stk, void *argv)

而且部分变量是用的

Onsunsl 发表于 2012-8-24 17:28:17

Onsunsl 发表于 2012-8-24 17:31:12

nazily215 发表于 2012-8-24 18:09:52

我印象中是CMSIS-RTX才是源码开放,但MDK内部的RTX还是要授权的哦?
我也喜欢用MDK内部的RTX,喜欢它的一个事件量,虽然在其它的OS中依然可以用SEM信号量代替,但这也是它一个特色,特别是OR和AND事件

Onsunsl 发表于 2012-8-24 18:15:44

nazily215 发表于 2012-8-24 18:09 static/image/common/back.gif
我印象中是CMSIS-RTX才是源码开放,但MDK内部的RTX还是要授权的哦?
我也喜欢用MDK内部的RTX,喜欢它的一个 ...

楼上说的授权指的是?

richards 发表于 2012-8-24 20:27:43

貌似还不错呢。。。

vigour 发表于 2012-8-24 20:28:15

一直在用,不错的{:lol:}{:lol:}{:lol:}{:lol:}

nazily215 发表于 2012-8-25 00:35:21

Onsunsl 发表于 2012-8-24 18:15 static/image/common/back.gif
楼上说的授权指的是?

CMSIS-RTX可以免費商用,MDK內置的RTX不可以,需要購買,聽人家說4W好像

xizi 发表于 2012-8-25 00:46:48

不懂CMSIS-RTX与MDK內置的RTX的区别?其中一个是指中间件吗?,如USB,TCP/IP?

Onsunsl 发表于 2012-8-25 15:31:39

nazily215 发表于 2012-8-25 00:35 static/image/common/back.gif
CMSIS-RTX可以免費商用,MDK內置的RTX不可以,需要購買,聽人家說4W好像

我又out了,CMSIS-RTX是哪出的?
MDK 的RTX肯定是收费的

nazily215 发表于 2012-8-25 16:01:24

Onsunsl 发表于 2012-8-25 15:31 static/image/common/back.gif
我又out了,CMSIS-RTX是哪出的?
MDK 的RTX肯定是收费的

應該也是KEIL公司出的,在主頁可以查到相關的信息,它是GPL許可以。兩個的區別也有,從代碼來看,CMSIS-RTX其中的一個特點是它的信號量收發是通過SW中斷,匯編編寫,非C語言,這個效率可能會高一些。移植性也高。接口基本上和RTX的有相同點,事件等待取消了OR和AND等待,當1個的時候就OR,當>1個的時候就AND,不過你可以改掉回原來的,還有一個GET_EVENT的時候有個BUG,GET的時候是錯的(CMSIS-RTX里),之后的沒怎么研究了
至于可不可以結合MDK的RTX可視化DEBUG進行調試,我只試過一次可以,之后就不可以了,不知道WHY

skyfight 发表于 2012-8-25 16:55:33

支持一下

Onsunsl 发表于 2012-8-26 09:38:39

nazily215 发表于 2012-8-25 16:01 static/image/common/back.gif
應該也是KEIL公司出的,在主頁可以查到相關的信息,它是GPL許可以。兩個的區別也有,從代碼來看,CMSIS-R ...

大侠肯定是深入研究过RTX

arm版本和Cortex版本明显的区别是:在给用户提供的接口上重新定义、cortex-m每次系统调用都通过__SVC_0切换模式

// rtx for cortex-M
#define os_sys_init(tsk)             os_set_env();                         \
                                     _os_sys_init((U32)rt_sys_init,tsk,0,NULL)

//rtx for ARM
#define os_sys_init(tsk)             os_sys_init0(tsk,0,NULL)

以上两个os_sys_init()最后都会调用rt_sys_init(),搜遍整个工程目录,没发现它两之间有什么联系

mon51 发表于 2012-8-26 11:40:55

一直使用它,不用UCOS。

kneken 发表于 2012-8-26 13:08:00

学习!!!!!

hncjs 发表于 2012-8-26 13:59:28

不错呀!

163fit 发表于 2012-8-26 14:43:25

有这么好的。

loveskangaroo 发表于 2012-8-30 17:22:14

{:lol:}正在使用中

y732770755 发表于 2012-9-15 14:14:28

本帖最后由 y732770755 于 2012-9-15 15:46 编辑

弱弱问一下,使用RL-RTX系统时,main函数调用的os_sys_init函数,在RTL.h定义为
#define os_sys_init(tsk)             os_set_env();                         \
                                     _os_sys_init((U32)rt_sys_init,tsk,0,NULL)
但是
extern void      _os_sys_init(U32 p, void (*task)(void), U32 prio_stksz,
                                     void *stk)                        __SVC_0;
定义系统切换模式, _os_sys_init函数的具体定义,找不到!!

zhang8198 发表于 2012-9-21 14:01:16

{:smile:}{:smile:}{:smile:}{:smile:}{:smile:}{:smile:}

nazily215 发表于 2012-9-21 15:40:41

Onsunsl 发表于 2012-8-26 09:38 static/image/common/back.gif
大侠肯定是深入研究过RTX

arm版本和Cortex版本明显的区别是:在给用户提供的接口上重新定义、cortex-m每 ...

敬請關注一下:
1)extern void      _os_sys_init(U32 p, void (*task)(void), U32 prio_stksz,
                                     void *stk)                        __SVC_0;
2)#define __SVC_0         __svc_indirect(0)

其中,__svc_indirect(0),是編譯器支持的一個語法,意思是有這個標誌的話,就使用SVC0語法編譯,不妨參考一下:
http://infocenter.arm.com/help/topic/com.arm.doc.dui0491c/BABHGCCB.html
這裏寫了,把某一些參數堆進R12寄存器等之類的操作,其中也可能會涉及多個參數,這時可能會用到R1,R2等等,
編譯器一看到這句話的時候,就會編譯成LDR語句,然後進行SVC中斷,
最後,在SVC中斷那裏執行任務的切換就可以了,其中的任務指針按約定的那裏取出就行,
所以在這裏,只需要加個__SVC_0的宏,即__svc_indirect(0)就可以了,編譯就按語法進行編譯。

3)至於_os_sys_init,這只是個名字,ONLY A NAME,隨你喜歡怎麼改。編譯時只會取出其中的參數,跟這名字沒關係。
4)所以它是通過SVC來進行好多任務操作。

nazily215 发表于 2012-9-21 15:41:17

y732770755 发表于 2012-9-15 14:14 static/image/common/back.gif
弱弱问一下,使用RL-RTX系统时,main函数调用的os_sys_init函数,在RTL.h定义为
#define os_sys_init(tsk)...

敬請關注一下:
1)extern void      _os_sys_init(U32 p, void (*task)(void), U32 prio_stksz,
                                     void *stk)                        __SVC_0;
2)#define __SVC_0         __svc_indirect(0)

其中,__svc_indirect(0),是編譯器支持的一個語法,意思是有這個標誌的話,就使用SVC0語法編譯,不妨參考一下:
http://infocenter.arm.com/help/topic/com.arm.doc.dui0491c/BABHGCCB.html
這裏寫了,把某一些參數堆進R12寄存器等之類的操作,其中也可能會涉及多個參數,這時可能會用到R1,R2等等,
編譯器一看到這句話的時候,就會編譯成LDR語句,然後進行SVC中斷,
最後,在SVC中斷那裏執行任務的切換就可以了,其中的任務指針按約定的那裏取出就行,
所以在這裏,只需要加個__SVC_0的宏,即__svc_indirect(0)就可以了,編譯就按語法進行編譯。

3)至於_os_sys_init,這只是個名字,ONLY A NAME,隨你喜歡怎麼改。編譯時只會取出其中的參數,跟這名字沒關係。
4)所以它是通過SVC來進行好多任務操作。

zhang8198 发表于 2012-9-22 11:35:12

{:smile:}{:smile:}{:smile:}{:smile:}{:smile:}

luoyiming1984 发表于 2012-10-18 13:48:11

USB和TCPIP怎么用?

cooleaf 发表于 2012-10-18 15:46:32

哦,RTX目前还没用上过,有空得试试,只用过uCos.

linjinming 发表于 2012-10-18 18:00:24

还不如用uCOS-III

huangxuankui 发表于 2012-10-18 21:35:46

学习了。

sz1199 发表于 2012-10-19 10:18:26

mark{:smile:}

znyu2009 发表于 2013-5-29 11:05:00

好吧,真的开源了。

baiyunfeikf 发表于 2013-5-29 13:40:56

学习了,打算好好学习一下rtx

licheng0620 发表于 2013-9-12 11:22:22

mark,有空看看

yeksw206 发表于 2013-10-8 11:45:30

学习!!!!!!!!!

jj632856828 发表于 2013-10-27 12:09:15

开始学习

hyf88 发表于 2015-10-14 18:54:45

mark,免费的话,可以试试,中间件需要收费的吗?、

yangpeng012 发表于 2015-10-14 18:56:35

很关注它里面的flash-fs的文件系统!曾经用过,但是性能好像一般般,这个代码能开源就好了!

magicoctoier1 发表于 2016-3-27 08:53:47

正在学习中。。。

lcmdw 发表于 2022-2-24 11:11:36

学习,谢谢。

liang16888 发表于 2022-2-24 21:41:14

think you !!!
页: [1]
查看完整版本: Keil RTX4.20 for STM32学习(官方已公开源码)