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()//切换任务
如果单存为了使用,不学习os源码的话,直接使用RTX库也可以的
例程简单对IO的翻转
现在RTX的源码是开放的,只是那些中间件不开放 哦?我out man了,
我用的是keil 420,安装了450后真是直接开放源码了
liurangzhou 发表于 2012-8-23 08:58 static/image/common/back.gif
现在RTX的源码是开放的,只是那些中间件不开放
中间件指示是RTX调试插件?
我是初学者,请大侠多多指教
{:lol:} {:handshake:} bbs2009 发表于 2012-8-23 09:27 static/image/common/back.gif
USB_CM3.lib, RTX_CM3.lib之类貌似没有源码, 算是中间件吧。
嗯,IP也没有源码,楼上在用RTX吗? 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: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 -------------- 用户提供的栈数?
mark....... 本帖最后由 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 |
+-------------------+
下来学习,顶一个! 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:02 编辑
USB_CM3没有
我只是告诉你RTX_CM3有源码
路径C:\Keil\ARM\RL\RTX工程项目名称 RTX_Lib_CM
这说明你看东西很不仔细。。。。 之前用了RTX_CAN,MDK所提供的驱动用的都是寄存器方式 buxinshan 发表于 2012-8-23 14:34 static/image/common/back.gif
之前用了RTX_CAN,MDK所提供的驱动用的都是寄存器方式
你可以楼主位的例程,都是用的st库
Onsunsl 发表于 2012-8-23 16:11 static/image/common/back.gif
你可以楼主位的例程,都是用的st库
资源非常好,感谢了!! Onsunsl 发表于 2012-8-23 09:06 static/image/common/back.gif
中间件指示是RTX调试插件?
我是初学者,请大侠多多指教
...
我是指CAN,USB,网络等这些个东东,没有开放源码 CAN,USB,网络的确是没有放出来 本帖最后由 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; //栈溢出测量字
} 好东西。 没用过这个的说。 读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)
而且部分变量是用的 我印象中是CMSIS-RTX才是源码开放,但MDK内部的RTX还是要授权的哦?
我也喜欢用MDK内部的RTX,喜欢它的一个事件量,虽然在其它的OS中依然可以用SEM信号量代替,但这也是它一个特色,特别是OR和AND事件 nazily215 发表于 2012-8-24 18:09 static/image/common/back.gif
我印象中是CMSIS-RTX才是源码开放,但MDK内部的RTX还是要授权的哦?
我也喜欢用MDK内部的RTX,喜欢它的一个 ...
楼上说的授权指的是? 貌似还不错呢。。。 一直在用,不错的{:lol:}{:lol:}{:lol:}{:lol:} Onsunsl 发表于 2012-8-24 18:15 static/image/common/back.gif
楼上说的授权指的是?
CMSIS-RTX可以免費商用,MDK內置的RTX不可以,需要購買,聽人家說4W好像 不懂CMSIS-RTX与MDK內置的RTX的区别?其中一个是指中间件吗?,如USB,TCP/IP? nazily215 发表于 2012-8-25 00:35 static/image/common/back.gif
CMSIS-RTX可以免費商用,MDK內置的RTX不可以,需要購買,聽人家說4W好像
我又out了,CMSIS-RTX是哪出的?
MDK 的RTX肯定是收费的 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
支持一下 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(),搜遍整个工程目录,没发现它两之间有什么联系
一直使用它,不用UCOS。 学习!!!!! 不错呀! 有这么好的。 {:lol:}正在使用中 本帖最后由 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函数的具体定义,找不到!! {:smile:}{:smile:}{:smile:}{:smile:}{:smile:}{:smile:} 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來進行好多任務操作。 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來進行好多任務操作。 {:smile:}{:smile:}{:smile:}{:smile:}{:smile:} USB和TCPIP怎么用? 哦,RTX目前还没用上过,有空得试试,只用过uCos. 还不如用uCOS-III 学习了。 mark{:smile:} 好吧,真的开源了。 学习了,打算好好学习一下rtx mark,有空看看 学习!!!!!!!!! 开始学习 mark,免费的话,可以试试,中间件需要收费的吗?、
很关注它里面的flash-fs的文件系统!曾经用过,但是性能好像一般般,这个代码能开源就好了! 正在学习中。。。 学习,谢谢。 think you !!!
页:
[1]