你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

自制简单OS(仅任务调度) 精华  

[复制链接]
qianfan 发布时间:2015-6-28 15:36
本帖最后由 QianFan 于 2015-6-30 18:02 编辑
# Z; Z! C7 `+ |# h3 y5 y. `4 k4 C* T. O8 c4 O7 ^# `( T
    之前简单的学习了下ucos,仅仅是会用,并没有深究。毕竟平时用的不是很多。最近闲来无事,好好的阅读了一下ucos的源码,看了下任务调度的内部细节,感觉挺有意思。许多问题在QQ社区群请教了橙子大哥,感谢橙子大哥的不吝赐教。
: Z* i3 g( c0 u! @2 o, b! V; Z  h6 ~8 m" J0 U" ~4 I; x( y* c, a( d
    但是不满足于ucos的代码,太复杂,函数太长。虽然功能强大,但是像我这样的懒人,不想敲那么多次键盘。于是开始自己DIY一个任务调度器。目前只是简单的实现了任务调度。在今后还要添加其余的功能。但是毕竟一个人的能力太弱,自己DIY的仅供娱乐和学习,不能满足于商业化的使用。
1 O2 N9 b) z; U9 u7 N! ]% X; a8 f- e" n- l; \& P/ }
    在DIY的时候使用了303Nucleo,这个板子有80K的内存,所以给堆提供了10K的内存,这些足够malloc消遣了。所以有关任务的栈使用了malloc来进行分配。在测试的时候创建了两个任务(空闲任务除外),用来控制两个led灯。一个间隔1s闪烁,另一个间隔2s闪烁。视频效果可以点击这里查看:https://v.youku.com/v_show/id_XMTI3MjQ2NTQyNA==.html?firsttime=0&from=y1.4-2 请自觉忽略视频的声音,因为在录制的时候有人在讨论电源的问题。测试用的工程可以在附件中下载。* z- z5 |4 i* M
0 Y, C2 p4 f/ l! P! K/ K  G' V

1 {2 I* Y3 P: A, r, D2 |7 V
  1. #include "QSys.h"3 |" o. D8 b" t* Y) o
  2. #include "stm32f30x.h"
    ' S8 s9 F" e: V) C, M- h) a& V
  3. #include "stm32f30x_rcc.h"
    0 F" H2 b6 U, l, v% a' P
  4. #include "stm32f30x_gpio.h". }4 [$ N1 {$ N* [/ A% g3 k/ i
  5. ! d  N1 F/ u9 w- T! m% a
  6. GPIO_InitTypeDef ioIt = 8 r1 C- `& S5 s- o% F+ D# B1 r
  7. {
    % E3 R/ C* }3 L1 Z$ D
  8.         GPIO_Pin_5 | GPIO_Pin_6,
    7 `& C2 v4 Y* c+ E) t* R( H4 Z/ P
  9.         GPIO_Mode_OUT,GPIO_Speed_50MHz,
    ; h5 ~5 |/ u" U
  10.         GPIO_OType_PP,GPIO_PuPd_NOPULL,2 F! Z# i# O8 Y2 x9 `' V8 o
  11. };
    - l+ Y! p5 H/ K6 l$ ^9 P

  12. 9 N: x1 l, w+ T: f2 r$ x
  13. void PA5On(void);( Y+ A1 w8 y/ a- I3 ]. p6 p! e2 D
  14. void PA6On(void);
    % Y4 X. q( w4 ~0 D1 z! Y+ `

  15. ) V  j# T# m1 r3 h& i
  16. #define pidPA5                        5
    ( ?- T! z" `$ V1 X! q# E6 T3 ^
  17. #define pidPA6                        6
    . ^1 i# b( Q( x) M! U' k
  18.         
    # T; a- H7 K  x3 P& t
  19. int main(void)4 f# c* w3 P4 _! u. A6 k8 C) u
  20. {
    1 Q" f3 o4 S6 i: Q1 }; z! {9 v
  21.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);. J  F" q# }- l; a
  22.         GPIO_Init(GPIOA,&ioIt);% e6 k  g$ J' Q- ~, j
  23.         SysTick_Config(64000000 / 20  ); //50ms
    0 C  }7 g5 g8 D0 K4 O$ T
  24.         
    , s1 {( i& X3 q* V
  25.         taskCreate(pidPA5,PA5On,"PA5");
    , V8 f: y2 _$ x4 s! @3 x( c
  26.         taskCreate(pidPA6,PA6On,"PA6");
    7 {5 q, S9 V6 Z1 O/ g; t& K
  27.         
      y* z/ ^/ p5 ?# R9 \6 F$ Y) Q" H
  28.         QSysStart();: l5 \. s# P  L9 U4 c' r( M
  29. }
    ( t" q% g' U9 }- i6 L/ ]
  30. / P) Z: S2 B7 ]8 y- _4 e
  31. void PA5On(void)/ z8 W4 y$ a7 Z6 ~7 Q7 [/ o# @
  32. {9 D5 C; \' T- m8 `! y' Q
  33.         while(1)
    ' W4 q  F* |+ R. U
  34.         {7 O8 s& O6 \7 ~/ F7 s
  35.                 GPIO_SetBits(GPIOA,GPIO_Pin_5);7 y! u9 o* r( ]7 D; @! v' q
  36.                 delay(pidPA5,20);
    7 K4 R- ]" Z7 g9 k( \- D( l
  37.                 GPIO_ResetBits(GPIOA,GPIO_Pin_5);" ~: `! o/ U  {) T. N2 a% p
  38.                 delay(pidPA5,20);
    ( n+ S5 Z# t! }; c+ K5 Y6 o2 E8 H
  39.         }
    3 g9 g6 D/ R; G
  40. }, T4 W% Y- |* x! w
  41. * J4 {' o( Z" j- r! N! G1 e
  42. void PA6On(void)8 P1 v8 ^! D# {  Z
  43. {
    % X% s( T5 E& B; F7 y- A2 S7 n+ u
  44.         while(1)* j, i1 G6 s* C$ t' r* D- c
  45.         {
    - ~* \" x* Y1 g& t% L" r
  46.                 GPIO_SetBits(GPIOA,GPIO_Pin_6);
    ) O- c, e1 m' [9 H, o
  47.                 delay(pidPA6,40);
    # f5 ~: |; M4 |
  48.                 GPIO_ResetBits(GPIOA,GPIO_Pin_6);
    / q" u+ l4 n' A  {7 y
  49.                 delay(pidPA6,40);* d/ I, F% N7 M" W
  50.         }
    : J9 _2 K" q) C! Y7 w( G% C6 z( [7 s
  51. }8 T/ f9 ~5 H2 Z+ ^5 r6 Y
  52. / W6 b) M0 [( ~7 U( e* w% Y5 d
复制代码

+ |. ]3 a& F6 ~0 w$ s, `: wUpdate:0.0.2
8 s0 Z  G( y  F: H
  • 改进taskCreate,不再使用malloc和free进行自动内存分配。
  • 删除void delay(unsigned int pid,unsigned int ticks);
  • 新增函数void suspend(void),用于挂起任务本身。
  • 新增函数void resume(unsigned int pid),用于恢复已经被挂起的任务或者被sleep阻塞的任务。
    6 }6 s# P2 u8 p7 B3 j& H8 r2 s

% F: ~& Q- v3 r. V. Z! i, l/ E   Example:
$ y3 o9 T( H6 H8 r6 l$ ^5 v% }   将Nucleo的按键设置成为下降沿触发中断的方式。建立一个任务,每隔2s闪烁一次led,闪烁完1次之后将自身挂起,当按键按下的时候,在按键中断中 恢复任务。视频地址:https://v.youku.com/v_show/id_XMTI3MzUwMjQ4OA==.html1 l  L1 d3 b' ]$ \( E. v
在视频中可以看到,第一次按键的时候,亮的时间特别短。这个是按键有抖动导致的,另一方面,sleep这个函数做的也不行。即使任务被sleep阻塞了,resume也能够恢复它。这个也算是bug吧。在之后会继续改进的。
% m" w9 i; U- w( b+ E
  1. #include "QSys.h"
    / `8 ~7 w! {+ O; a
  2. #include "stm32f30x.h"
    # U) J: _# y. v
  3. #include "stm32f30x_rcc.h"# Z& T3 @5 b. T5 y+ H2 t- B
  4. #include "stm32f30x_gpio.h"
    2 A3 H) {2 w" h( d# i. H
  5. #include "stm32f30x_exti.h"* [; `3 [1 d; i: R& g: F
  6. #include "stm32f30x_syscfg.h"  C) `0 c9 d2 \8 M
  7. 3 b; i0 F/ w1 d: ?( F; Q$ K- P
  8. EXTI_InitTypeDef EXTI_InitStructure;
    6 R* O, [, O$ ^
  9. GPIO_InitTypeDef ioIt =
    1 G: h5 k! _' n. ?
  10. {& h) F, l* a% `9 ?2 E/ ~6 x
  11.         GPIO_Pin_5 | GPIO_Pin_6,* p: _. _6 a4 Y9 b" J
  12.         GPIO_Mode_OUT,GPIO_Speed_50MHz,$ y7 Z3 I; `5 w" ^1 }2 `8 ]5 w
  13.         GPIO_OType_PP,GPIO_PuPd_NOPULL,) C6 q! K; I. ]/ y0 Y- W
  14. };% a3 u  a5 `) c" o9 |

  15. 3 e0 f2 N& m( g  S& }
  16. void PA5On(void);6 ?1 `$ G! t! j9 |  i
  17. void PA6On(void);
    ( D: m& x4 T6 F9 m! s3 k
  18.   L: Z  X2 ]% t: p/ a0 R6 c
  19. #define pidPA5                        HIGHEST_PID
    0 y+ c% Z/ k3 i6 R( [0 L& X2 ]' d
  20. #define pidPA6                        LOWEST_PID
    0 m! ~5 Z$ p8 v) N6 r8 W

  21. 8 G7 w& f# N. K. h4 G8 S
  22. unsigned int spPA5[128];2 Z" q; M( l" L: b& v$ @
  23. unsigned int spPA6[128];
    0 v; ^" g) D6 Z, n+ {: c! R
  24. struct task taskPA5,taskPA6;/ a) F+ O1 A1 j" `7 U
  25.         
    7 H+ _& z" d% I( ]
  26. int main(void); p/ M4 c% `0 E8 a* f  d7 w
  27. {# K5 S) X/ D, I
  28.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);% ^* r. Z- K4 s) y
  29.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC,ENABLE);% ^5 a. {" C! s* y) Y7 i
  30.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);6 }' ^9 r1 p) a7 u5 l1 S
  31.         
    & _/ a, D+ A" t
  32.         GPIO_Init(GPIOA,&ioIt);4 P* @. C5 V% g
  33.         ioIt.GPIO_Pin = GPIO_Pin_13;
    % P$ x; K  f/ g2 u* X& Y( w
  34.         ioIt.GPIO_Mode = GPIO_Mode_IN;/ c+ |( ^- C4 |' p3 K/ g' v1 ~( E
  35.         GPIO_Init(GPIOC,&ioIt);
    6 s1 v% Z6 R( o! z( }( m: T
  36.         
    & I- l& w" X( v4 \
  37.         /* Connect EXTI13 Line to PC13 pin */+ o7 j0 n- ]* s2 N8 |
  38.   SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource13); $ H' o4 _4 T- a6 Q
  39.   
      |0 c- h* j# L. d! N
  40.   /* Configure EXTI13 line */' Q# m+ a  j* l  i: }
  41.   EXTI_InitStructure.EXTI_Line = EXTI_Line13;
    ' M: L% O% S! o! I8 y
  42.   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;' Y% w8 C, ]: P
  43.   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
    ' T8 L; A/ c) G$ G4 S, i- {& W8 l
  44.   EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    ! ^( `  t/ |+ j2 O- P
  45.   EXTI_Init(&EXTI_InitStructure);; a( b& z( K- ?7 x5 u+ G( z
  46.         8 R. i4 i  y  ]3 s+ I4 H- L& U) T$ |
  47.         NVIC_EnableIRQ(EXTI15_10_IRQn);
    7 A+ r+ A7 z  Y, q
  48.         SysTick_Config(64000000 / 20  ); //50ms
    2 C: ~2 @6 W1 _- R/ k
  49.         
    8 K0 \' U- J8 W# L/ i' ^6 M) g' z" q
  50.         taskCreate(&taskPA5,pidPA5,PA5On,spPA5,128,"PA5");* `3 q' \/ T7 |5 A) w% I
  51.         taskCreate(&taskPA6,pidPA6,PA6On,spPA6,128,"PA6");% t1 v  k( v! q& k" J
  52.         
    9 y9 N$ {9 B' Z) s  Z; b
  53.         QSysStart();
    $ W6 b/ Z5 Q" J; V  T. x3 [% j
  54. }' V) c$ y9 H7 s# _4 O8 {% X5 j
  55. * c1 x6 |" A: m6 {
  56. void PA5On(void)* u5 ]  `1 h: e' x0 F
  57. {. R9 P: E1 r- @+ c$ \
  58.         while(1)
    5 h3 E8 t* @/ k% [
  59.         {
    - x6 _! J+ s- c5 {4 h
  60.                 for(int i=0;i<2;i++)
    . x, x7 W+ [% K
  61.                 {  Q( }0 J. I" t( y7 g
  62.                         GPIO_SetBits(GPIOA,GPIO_Pin_5);. F! \  M; |* L1 Q) Y- U
  63.                         sleep(20);) T, e6 X( Y$ w0 {$ ~# V0 c8 m
  64.                         GPIO_ResetBits(GPIOA,GPIO_Pin_5);
    7 @& S$ g; V; c. L% c
  65.                         sleep(20);
    1 x1 V) U, t  q& i- L- a7 _
  66.                 }* {, ?7 K; q- C: g+ t5 f
  67.         }
    / {& w0 d. }. y- _
  68. }
    & Z% S+ E- }0 }: n. W
  69. 6 Y: L- Y5 l$ U+ U: J% r4 F
  70. void PA6On(void)& Y4 i5 t/ u, {: B1 d4 u9 w* p
  71. {
    4 }/ z$ _" B4 I7 y( _
  72.         suspend();3 ^6 a! r, T: d; [
  73.         while(1)
    & s4 h" ]' T7 P4 N% V% I! D0 A$ A; r; v
  74.         {
    & h; K% ~+ k. k* W+ |# x
  75.                 GPIO_SetBits(GPIOA,GPIO_Pin_6);
    $ @* s0 T) c; F4 `3 V
  76.                 sleep(40);5 D! v' R  p; o
  77.                 GPIO_ResetBits(GPIOA,GPIO_Pin_6);5 x1 ?) R( o: H  O, G& e1 X
  78.                 sleep(40);  c, I7 {. p4 r3 A( p1 H
  79.                
    & T# s6 {8 w2 P/ Z+ @
  80.                 suspend();//suspend itself,watting next exti interrupe
    % M) J, N" y  _4 U! n5 i6 ~
  81.         }
    3 z3 Q, a( m+ w# p# e* e, O
  82. }
    7 y* ^* I; E$ G% Y
  83. ) x& [) x5 `3 l6 L# M. G
  84. void EXTI15_10_IRQHandler(void)
    5 g) C, U0 q4 q  r
  85. {
    , f: m- {0 [( Q4 F+ I
  86.         resume(pidPA6);. @& c& }3 `+ g  l: T
  87.         EXTI_ClearITPendingBit(EXTI_Line13);
    ! L) q) j' r* `- U
  88. }, R6 {; X+ d" _" s& L
复制代码

+ F# H* N: w- @6 b1 D! P; _( f6 h) x" [7 a" m9 g) y
Bug Report:
0 _9 s6 }( [' O# u2 L||9 ?; N" V/ U, _2 m1 z( w1 E# Z2 s
||. M3 Q2 b7 p* c+ w* e& H  K2 c5 N
\\//
2 _7 f9 i% Q& t. x
\/( n/ M& h0 B8 n
# M. _+ H- G& w7 ^/ ^

5 Y1 p  z% d3 W. ^3 j

QSys.rar

下载

853.41 KB, 下载次数: 126

0.0.1

QSys.rar

下载

1 MB, 下载次数: 229

0.0.2

收藏 8 评论93 发布时间:2015-6-28 15:36

举报

93个回答
Mandelbrot_Set 最优答案 回答时间:2015-6-30 10:50:48
QianFan 发表于 2015-6-29 21:40
, F& ?. k6 \) R. s+ e/ T5 s% [" JUpdate:0.0.2
( z- x, U$ o; G) v% T
# F' Z$ P2 W# H: a8 l    改进taskCreate,不再使用malloc和free进行自动内存分配。

  B/ o8 L' h3 Q9 R  x3 \我又来了哈...* q3 i* m7 E! @
example1:$ X1 w: s: v: P* p: W, k
void sleep(int delayTicks)中- [! Q8 y$ q  M+ B" t* f7 o
在if((taskList[pid]==NULL)||(pid==IDLE_PID)||(delayTicks==0))
9 J1 c: }4 h4 u- T% Z9 t) D                return ;
2 O" Q8 Z8 G$ O8 S3 A  L之前taskSwOn();之后产生调度: D" X2 X# g- F, U% ]9 O! a
并不能确保taskList[pid]不是NULL(taskList[curpid]本不应该NULL.)9 K& U5 v4 S, ]$ _
(调度后来了个changePid).
9 [+ S8 Y2 h5 ]! `! Pexample2:& p& S9 x  @2 Y. Q% S! m
updateNextTask执行中产生调度,
( Q% k( x! ^6 m  {3 W每一个taskList[pid]都有被其它任务修改的可能,应该有风险.2 ]/ A; t/ b% z* f$ }
: r% `+ N& S4 s. ?
- d/ k" S$ Q4 F2 v7 p
qianfan 最优答案 回答时间:2015-6-30 12:45:21
Mandelbrot_Set 发表于 2015-6-30 10:50
, U' F, i" I/ z* l6 j, [( \) d, B. t我又来了哈...0 p' _" w% A' Y
example1:) ~/ m3 K- y+ R/ W: e+ u/ }
void sleep(int delayTicks)中

) D+ }; {/ V7 _! H请教个问题,比如当前OS的节拍数是100,有一个任务Task1,调用了自身的sleep,sleep的时间是1000个节拍。也就是到1100个节拍的时候这个任务应该被唤醒。
; {+ N7 I! c) Q: \' o
/ S; ]1 ^7 N0 o- h# h假设到了第200个OS节拍的时候,另一个任务Task2更改了Task1的优先级,将他的优先级提高了。你说这个时候是应该让Task1立即执行呢,还是到1100个节拍的时候才能再次执行?
Mandelbrot_Set 最优答案 回答时间:2015-6-30 13:23:06
QianFan 发表于 2015-6-30 12:45! O. k1 K4 P# O3 m1 P3 `& w
请教个问题,比如当前OS的节拍数是100,有一个任务Task1,调用了自身的sleep,sleep的时间是1000个节拍。 ...

( t& @- j3 ?3 q! s我觉得Task1既然sleep(1000)了,那就应该有sleep(1000)的样子,在1100节拍之前就不应该是就绪状态吧...
. P. J) f$ Z; t/ n- y' v% M
9 E) E. I9 y# L: v& B
Mandelbrot_Set 回答时间:2015-6-29 14:18:46
QianFan 发表于 2015-6-29 10:46' q# z. b, `" Z+ W& t) h0 f) I. R
如果是这样呢?
0 d1 [: y4 i% `  g; I# H
我觉得还有一个可能怀疑的就是malloc与free本身.
( m$ A; V1 n* n9 U设计上本身并不排除malloc,free执行一半调度到另一任务的malloc,free.0 F; y; |2 y9 L! q9 d1 e
examples:
1 x9 B2 s; q8 J8 ^  w8 J2 rA delete B  free了一半 调度到 B delete B3 D& \6 }  e2 w- {9 n+ D0 e7 }
A delete B  free了一半 调度到 C create D  p; p& m7 G+ [* d) ?7 I
。。。(这概率!)这总是让人不安,谁没用过malloc(应该包括new delete吧?)。( {% \' h9 B" x
(malloc不局限于嵌入式平台)于是有了下文先。
6 P6 t/ r6 S* O7 T9 ?暂时还没完全搞清楚,有点晕。有点简单问题复杂化的感脚。  s8 D% }' |6 {, g% J  P
(引用的帖子与博客不代表个人观点。。。)
0 a& ?' O4 A9 B7 x" K7 ?9 F, t
malloc free 的实现看上去好像不太靠普(其实没仔细看,不直观,看个大概..关键手册不详细,或没找到。)
" i. i8 M9 x, e; z% Z( t  H8 Hida F5生成(其中一个QSys.axf),仅供参考。4 J0 [% V, `. k5 V, G) p8 K
int __fastcall malloc(int a1)
7 I' o( M' y* P* I1 M/ v% c{" k* ]6 R  V, ^, z. p2 E2 w
  int v1; // r1@17 T0 J8 q6 C& `5 ?* L
  int i; // r2@2; v. n8 S, t0 Z$ N/ m
  unsigned int v3; // r3@3
& _$ e: h# M& |& X' K1 [4 B8 e  __int64 v4; // r6@5
4 j2 v" e4 |/ G) [1 b  int v5; // r3@59 T, ?8 J/ Z" Z
  int result; // r0@7
) D. Z) Q4 I3 j: Z/ [6 G  int v7; // r0@9
$ M3 d3 X5 Y* x1 C: N, }3 R7 ^# N0 C1 d; h
  v1 = (a1 + 11) & 0xFFFFFFF8;6 w* j0 l7 y  f" w; Q
  while ( 1 )
" W3 R7 }$ j2 J! S" p  {
  U* Y  Z! q2 G7 C) _% ~    for ( i = (int)&_microlib_freelist; ; i = v7 + 4 )
9 s1 \& }/ }; V6 g" `+ ^3 O- @    {1 o" ~" P" v7 @- ~% q
      v7 = *(_DWORD *)i;: R1 m# h9 y  u0 O! V
      if ( !*(_DWORD *)i )! B5 q" U+ F) d; E
      {
0 A: H' X1 @3 N* q        result = 0;
$ S" S7 T' z' i! G/ J) u        goto LABEL_11;, ?; z5 U! p% Z  x
      }( Q% P7 B8 c! b( |6 |9 I
      v3 = *(_DWORD *)v7;
; x: i, W; J1 [. V( _      if ( *(_DWORD *)v7 >= (unsigned int)v1 )5 C% m  f% @% y2 F* @/ C& |
        break;: E! j0 e/ p2 a  W0 m: E1 u1 E
    }
6 F* ^# E: J) _( ]" t0 f4 Y% Y1 g    if ( v3 <= v1 ): A7 f4 j: c2 r  H$ j
    {
+ S* H7 h! R7 B# o0 n      v5 = *(_DWORD *)(v7 + 4);% U) u+ x& I7 q( k# h' @7 c
    }7 ~& m: U  e* f9 G0 G
    else) o/ S& q# I6 I0 p7 G
    {
6 k- o2 m7 {" w1 Y8 y% r      LODWORD(v4) = v3 - v1;
& h  I: U/ M' W/ I# J      v5 = v7 + v1;
5 q0 i( `5 n; D& F3 B      HIDWORD(v4) = *(_DWORD *)(v7 + 4);# b* b7 x- `2 S3 A# N
      *(_QWORD *)(v7 + v1) = v4;
% h4 u! ^% c3 U    }7 E0 K9 d' r; w3 v  n( J
    *(_DWORD *)i = v5;
- ~5 c$ g. x, g    *(_DWORD *)v7 = v1;
) p! ^/ q& L' M% r5 r    result = v7 + 4;1 }* S- W7 L- t2 h' d# ^  @
LABEL_11:
& I1 ]$ q2 V  }9 i7 r    if ( result )
( p( B  G* ^& f) U) S      return result;, m2 E" \: S( e1 q" _
    if ( _microlib_freelist_initialised )
8 r1 @3 w( [# e      return 0;& Q7 L" W8 D: `% \0 Z  }
    _microlib_freelist = (int)&unk_200000EC;
3 b% I1 ?& o5 K# ^/ q, [+ a    unk_200000EC = 0x27FC & 0xFFFFFFF8;) G0 s3 L% ]- W& s* }
    unk_200000F0 = 0;; C8 T' ]2 p- p
    _microlib_freelist_initialised = 1;
' Y; n( R' _2 V9 E! I4 v+ R  }
) X9 T4 V0 |8 `8 g4 ~}
( L2 Y9 N1 W8 H2 v​int __fastcall free(int result)8 ~3 u+ w+ Q5 m) j2 r8 h2 D
{3 |& k- F! q4 L  D. b9 S/ ?
  int v1; // r2@23 m% Z2 I; D! p: e8 E1 F
  int i; // r1@2
- }4 F+ @2 F' C5 n& M
) Y$ v: D* a/ v6 |  if ( result )$ p- G* D- Q7 _8 l/ B
  {! m9 |& D/ O) C( g" `* @/ \$ U
    v1 = 0;
/ L  H# m6 O4 R$ D0 s! v    result -= 4;
8 o6 n9 \0 o) I2 i# u6 V    for ( i = _microlib_freelist; i && i <= (unsigned int)result; i = *(_DWORD *)(i + 4) )2 c; T5 E, i  T
      v1 = i;, D0 m( d: Y: {4 R9 A
    if ( v1 )
, m' l, @1 z  e$ H' \& A: ~    {
1 U+ p0 }  [( o      if ( result - v1 == *(_DWORD *)v1 )
& \. i  Q, y2 C2 E+ s      {
, g# K3 l0 G+ s$ u        *(_DWORD *)v1 += *(_DWORD *)result;
$ P$ U5 U) V4 c. X9 c0 k        result = v1;
- e0 f( {9 l8 r: f3 g, ?3 O: p      }
' b3 \7 \0 F; c! w: J      else
0 ^( U) U  c# f# N      {, A% X/ z( I2 W' h! f: P
        *(_DWORD *)(v1 + 4) = result;
( V4 w: `+ z7 T% @3 I4 \0 v; o" G      }9 U+ ~1 s! l5 f. x+ a7 N
    }
5 Z$ ?5 C. s* m3 |* b: y    else
2 T/ y2 g! M5 y  L+ L) Q    {! z- S2 `/ V6 `* c# K* X% K8 W+ J8 N
      _microlib_freelist = result;& a' F" Q5 |" @* w
    }
) f/ f+ o6 l" h1 J$ H    if ( i )
% V. X5 g$ t( U; C1 E- A    {/ @' g% z" ?- e& P1 o3 l- |
      if ( i - result == *(_DWORD *)result )
9 ^5 n7 _' n0 M! Y8 r      {
# `& E, w# M, a9 v% {5 J        *(_DWORD *)result += *(_DWORD *)i;, s! l$ v( `& I" g# V; m
        i = *(_DWORD *)(i + 4);
& O& T& ^' J) @+ G( `! K& {# T: Y  {      }
. y; h( o$ G6 C    }
) l2 ]& O( L- m+ |: n8 ^8 M    *(_DWORD *)(result + 4) = i;
. W# q" P. A, t% a  }- \% O8 C3 Y1 L2 `8 [5 w
  return result;
6 p& K, q6 R$ {5 _- Q7 F! g- V5 {- n}
& f3 h* _! v9 V9 I- w
参考1MDK4.54 hlp下的某个.chm,好吧我落伍了...)
: ~1 o8 U6 Q  `! @calloc(),
6 P1 ?4 \* {/ P2 t8 X  b! L: [" ifree(),9 d7 t4 s8 O* O- u
malloc(),# l2 f2 D4 P2 Z4 R! i, ?0 b+ x
realloc()
% H- `6 D1 z( V- ?The heap functions are thread-safe if the _mutex_* functions are implemented.
4 ^1 a" l9 t- S: \' D/ r" g9 ^# |9 l8 {6 j
A single heap is shared between all threads, and mutexes are used to avoid data corruption when there is concurrent access. Each heap implementation is responsible for doing its own locking. If you supply your own allocator, it must also do its own locking. This enables it to do fine-grained locking if required, rather than protecting the entire heap with a single mutex (coarse-grained locking).( Z( c( i$ `) f% H, @

: J" _! F  A: T( N9 r
参考2:(FROM amobbs)% H' |' m" A5 x6 F- f  Z
5 i: v& |' R& F, X6 U
在ARM上移植ucos (RVDS环境),关于MALLOC的问题bottom↓
3 J; [8 P' e2 X9 v5 p8 a" p看3652|回7|收藏; n" q8 N) F/ j7 J! L/ k) I$ i+ M. D% Q
1楼 chinatf 只看他 3 z3 C- \5 l3 b$ _. ?- Y9 w! U. c
2009-3-31 16:51:19
  B7 k- b5 L1 _- G# C使用RVDS集成开发环境,ARM平台。' f' J( d9 ^( M3 I* v
设置好系统堆栈,使得malloc()函数能够正常使用。
9 `' I# Q5 y: t  _2 n. v
' t- J. F) A0 ]; D4 D7 g( g问题:1 f" d" M! t, @% w7 f( A
====
$ h5 k- G  p% G' l- i我运行uCosII系统,在多个同时运行的任务中调用malloc()函数。
- [" J4 w9 f# Q6 ~$ H1 r由于多个任务可能同时在调用malloc()函数,而malloc()是RVDS提供的库函数,9 p: b4 S# ~& A/ Y
并没有考虑多任务调度的情况,所以多个任务可能同时在调用malloc()函数有可能
4 O* N2 N# S9 F  O' X' o会造成冲突。: h; @' r: V5 j7 i. Q& }& M! M
9 B: W6 j0 t- D$ S. f  n0 F7 }& ?
解决方法:
. m; O0 P2 O4 H; X3 G" Q& G# \( T====/ ?% t7 K: g# X% K3 C' j0 S9 o
在任务中调用malloc()的地方使用互斥量,使得malloc()在某个时候只能被一个任务
8 ~+ L. t& ]- W调用。' I9 B5 q; F4 w) c1 D# m( z9 E
8 Z6 i& ]! c& g1 `' o% U, i
欢迎大家各抒己见!% d1 g1 l5 K; I; Q
2楼 dr2001 只看他 : @% a" V. o& q% L
2009-3-31 17:37:58
; J8 i' Z6 w' j% N, m- {  V* ^malloc用的是C Run Time Library的堆[Heap],和堆栈没关系。不给CRTL初始化堆,再多的堆栈也没什么用。
2 A5 u9 f9 v: j% m
2 s4 k) O9 p2 ?* u9 B! ymalloc可重入与否请参考使用的CRTL的说明,有的也许可重入。不过这类库还是程序加锁比较安全。
2 N2 M* a  n1 j* y/ ~8 i9 ^) h" g3 R  t2 Z4 h1 l$ {
具体使用什么锁看需求吧。MCU环境,单核心,能够引发调度的除了程序主动释放时间片,就是中断,理论上这类操作屏蔽中断的方法效率更高。用mutex,sem,queue都是可以实现的,根据程序结构定了。( q, }/ K" k3 q  a& b1 `
3楼 akin 只看他
( A" I5 l- K: L: Z2 V! E2009-3-31 20:30:17
3 A1 D4 L+ n% ]. F! ^+ p" W+ i我一直担心单片机上用malloc和free会产生碎片,
0 o/ d  X9 L; {6 x6 ?& H6 F以前在RVDS下测试过能用,但有时候又不能,- k8 {2 z$ \9 s  O
所以到目前都是几乎不用这对函数。# m& C5 ?0 j, }
4楼 akin 只看他 : n# M' \9 ]1 i/ X" _2 C& s
2009-3-31 20:32:08
! @2 Y2 @0 F4 u# z太多的不确定性总让人用得不放心,睡不着觉。+ R) y! W7 h( ^4 v
5楼 armrtems 只看他   ]  M  \* s$ g& k
2009-3-31 21:56:19! {/ k, Z% q9 v$ l2 |9 I
RVDS  4.0么? 怎么调试?
- [0 F* v* L* X/ Jmalloc有一个配置选项,可配置为oe模式(保证实时性)和普通模式.4 d6 y9 x, ?: l( j% @5 |. a& q
针对多线程,runlibc有几个函数需要实现,armlink文档里面有说明。实现几个函数,线程切换时切换一个结构体,否则可能会有问题。  |" w0 B( O: Y
runlibc的c库比较稳定,一般不会出问题。
# N( C0 E0 p8 v! ~: n$ L事实上网络上流传的移植包不是完美的,大都没有考虑这个问题,楼主还是比较细心的。: r, a3 R: d- f0 f2 v4 [
6楼 chinatf 只看他
8 [9 @" l+ @" o+ V' B2 C# I- S9 a2009-4-1 09:46:46: u; H$ D7 t# R4 Q
to armrtems6 L  y7 h9 l- D( b) [
我现在用RVDS2.2,我看看这个版本有没有malloc的配置选项。! ]& m( y' X( s* P
7楼 dr2001 只看他 3 \- k+ I! \8 C% r, U, @4 v
2009-4-1 10:03:17
. c. M5 V+ U, j8 ETo 2# akin# |* S$ P: J; M; A4 X9 V: c
如果正确初始化堆,用起来是没有问题的,如果你用了printf之类的库,这些东西比较吃堆空间,堆小了不一定剩下那么多给你用。具体的需要看看CRTL的手册,专门有章节说内存管理的。
( o5 f+ K& U; d* K
6 Y8 T# N" V+ D. l6 k! u4 ~- QMalloc和Free导致的碎片问题确实讨厌,不过这个要看具体的分配策略了,CRTL发展了这么多年,嵌入式环境下应该有基于页的算法了吧。浪费是浪费些,毕竟还有的用。
/ N; v- U, p6 L7 d0 W0 m6 i
+ j( @6 {; }6 E4 ^' n4 I) TTo 4# armrtems$ k4 v0 T9 m- [
RV4 调试只能用ARM ICE;如果要调试,只能用这个的编译器,得到axf,加载到别的支持axf的调试环境来用。RVDS本身还是不要想了,米人除外。-_-!" E, i# s# P8 G: `
8楼 chinatf 只看他   I( e) ^; s, m/ \
2009-4-1 16:18:26; o8 f5 j7 i  y3 _
to 4# armrtems
  m9 n$ G/ z: o1 z你说的malloc的配置选项是RVDS 4.0的新功能吗?
' u% p" T1 k4 w/ P% |up↑( L4 b% z8 }$ y, }5 m  ]" P
阿莫电子论坛(原ourAVR/ourDEV)
8 ?" ^0 O* L% A( j" @  z4 x) a© 2004-2014 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com
( g& W0 `4 l! R6 s( G1 \首页|标准版|触屏版|电脑版
/ ]# r8 R6 p5 X
参考3:# j. r3 e* B, }% i; F
对于可重入、线程安全、异步信号安全几个概念的理解
, t* s' N( {" W7 u2 u- |! y, y5 J
http://blog.chinaunix.net/uid-293474-id-2134181.html+ U! V7 K7 ?" R% \3 s( c8 F/ c
/ Y* T; r; u0 @- j6 {4 ]( m
. [' l: g1 a9 s( a
( _  c5 q7 u4 b0 f5 @
qianfan 回答时间:2015-6-29 10:46:09
Mandelbrot_Set 发表于 2015-6-29 10:17
- k6 r3 j7 Q+ V如果删除自己,( }! J0 q& z' d0 l1 n' @" i" K0 a
taskDelete函数里,在+ x# g/ E6 m! M! F& m* E1 ]
taskSwOn();之后
+ q4 H  {0 C* S
如果是这样呢?% X. n/ J8 S; s. }% Q4 c9 \+ T3 y
6 \1 Y  T( I- M) z( b
  1. /*
    ! B! u/ f% ~- x+ V" N
  2. **delete the task specified by pid from taskList
    - |  p; V6 Z/ Q" a' r
  3. **And free this task's memory .
    7 O* D* ]0 x2 A- O7 `( A7 N. W
  4. */' d! n& l0 q7 C# {! W" Y
  5. int taskDelete(unsigned int pid)" i) q$ b5 P$ F1 ^, A# a
  6. {
    1 W& J0 U' u0 d  F# R
  7.         if( taskList[pid]==NULL ) //No such task " H, P8 `" c3 ^  {9 Z, ^7 C2 X
  8.                 return TASK_ERR_NO_SUCH_TASK;$ S  {& w6 B- b# ~# r
  9.         if( pid == IDLE_PID)1 t7 {; ?/ q0 ?* r
  10.                 return TASK_ERR_PID_ILLEGAL; //cannot delete idle task 7 h; Q. ~. ~; ~7 ]9 q
  11.        
    / N4 v' s8 {, z5 ?
  12.         /*save the task to be deleted*/  N/ ]1 n) |- L! q+ X" B& O5 }
  13.         struct task *task = taskList[pid];) r  D: w4 G3 y3 s. |
  14.        
    # K4 Q* i  p% z" C* s! Z
  15.         if(pid == curPid) //delete self  y2 l" ~4 U1 n7 X, S0 ]
  16.         {6 o/ j5 H% ~$ |2 d
  17.                 /*clean task's pid bit in taskRdyBit and taskList*/. {* e) |9 t/ y4 _6 I$ ^1 R& O! N' ]
  18.                 taskSwOff();
    & o' i" c/ E* {9 {, S* o
  19.                         blockTask(pid);
    $ ^8 b9 H  G! i* n! V  t, k
  20.                         taskListClean(pid);
    ' a0 s9 W& I. u  N# ~
  21.                
    7 H9 A0 `; X3 p9 i! W
  22.                         /*free memory*/$ _  U4 l* Z- ~# y0 ~( }" }# A" O. Z
  23.                         free(task->spBase); //is spBase,not sp!!
    " h, b! D: N; E
  24.                         free(task);
    & P1 p- A6 g( L8 b
  25.                 taskSwOn();
      y! Q$ H" `7 d
  26.                
    1 y7 q) f- c8 V( D- v/ n
  27.                 updateNextTask();0 D# u5 C. ~3 d6 G! S1 O
  28.                 swTask();
    " }  W' r$ t  f- @
  29.         }
    $ K2 O3 |4 @+ e2 A
  30.         else
    5 C* V' V. x2 s
  31.         {4 p) G! B' |1 Z! T% u0 T( R
  32.                 taskSwOff();
    9 F; |* v% I4 K" ^; y7 k+ }
  33.                         blockTask(pid);' p+ |  Z: r) _  \
  34.                         taskListClean(pid);4 p9 F3 ]; ~) \0 }0 ^5 @  c
  35.                 taskSwOn();
    9 `9 ]/ g0 L$ g& D/ l' L$ [! T' C/ k1 r
  36.                
    / v' W6 B- c% a: B& J2 _
  37.                 free(task->spBase);+ K& ?& s6 r6 y( Y* o
  38.                 free(task);& \& F6 @, z% P8 V# k
  39.         }7 U1 K! k" O$ k/ r; J* P
  40.         return 0;* r4 ?/ W8 x) b: R& @% p
  41. }9 Q# g: F5 A1 ]

  42. - u, x$ U. Z4 j2 y2 y( F
  43. int taskDeleteSelf(void)
    1 w  u! x! u/ O& C/ E6 t8 D
  44. {, {6 ?. J7 o. J. S- f+ j) l' s
  45.         return taskDelete(curPid);        , r1 V& x( x$ g2 ?
  46. }
复制代码

0 S; m/ G: J/ P9 D0 w+ T  R( o7 q3 b% H$ y8 |4 ^, P
% g# c, w8 V' Y4 T( ~0 O% M
qianfan 回答时间:2015-6-29 10:02:51
本帖最后由 QianFan 于 2015-6-29 10:05 编辑
4 |5 f2 P% Z4 {. Y6 n' Q
Mandelbrot_Set 发表于 2015-6-29 09:57
& p" M( t( Q2 J! n4 d- S8 ?  y2 M问下taskDelete支持删除当前任务自己id吗?

6 V% v) D' _; x- p0 E2 R& N如果是第一个版本的话,可以传递curPid给taskDelete删除自己。但是第一个版本删除自己之后,并不能实时的进行新的任务调度。在删除之后还占用时间片,直到Systick异常。- M# Y3 r+ ?( {2 }0 _6 w
, [3 g3 p9 l! \
昨晚又更新了一次,在删除自己之后立即进行任务调度,可以支持了删除自己,不过删除自己的函数名是taskDeleteSelf。代码给你看看。还请多多指点啊。% n/ h& W0 B, d
9 a5 g0 U1 V5 K$ q4 K
  1. int taskDeleteSelf(void)5 w6 j2 o8 ^! t, x" J7 Y! U
  2. {% U* A! G% m' N% v( ]3 l0 Q5 z
  3.         int rev = taskDelete(curPid);7 B: W' X( l% ^4 x1 s& L
  4.         if(rev) //delete self has error
    ' z  ?  a, z- o8 [
  5.                 return rev;
    / |+ q  Y% ^: X" W% K
  6.        
    $ D5 W% I8 @" m* P. x
  7.         //delete self and free memory successful
    + D! P4 z$ V4 v7 a
  8.         updateNextTask();5 p! c0 c# J: b' j# D3 `; p8 [& p
  9.         swTask();
    * M1 V, g* c$ o, F
  10.         + a* W6 \1 q, u2 I& D* y3 \. z
  11.         return 0;2 w, X* c. V1 G& N2 D; ]1 Y) M& w
  12. }0 }) S( `$ |9 q- Q, l# O
复制代码

# l, g- ]" s4 p6 ^" q% k" i3 U+ a: d) Y

QSys.rar

下载

854.78 KB, 下载次数: 20

更新版本

Paderboy 回答时间:2015-6-28 16:02:57
多谢分享。。。学习了
moyanming2013 回答时间:2015-6-28 16:17:44
看看。。。
lkl0305 回答时间:2015-6-28 17:46:47
不错,学习学习
JackieLaura 回答时间:2015-6-28 17:56:21
看看作者的作品
jinyi7016 回答时间:2015-6-28 19:56:08
有空也研究研究
u=3562947110,4225194727&amp;fm=21&amp;gp=0.jpg
mark0668 回答时间:2015-6-28 21:31:08
多谢分享。。。学习了..
wtliu 回答时间:2015-6-28 21:35:59
不错,学习了。
slotg 回答时间:2015-6-28 22:34:30
OS系统,感谢分享
wakojosin 回答时间:2015-6-28 22:35:30
感谢楼主分享,关注学习一下。
qscvhu 回答时间:2015-6-29 08:18:54
谢谢分享
jiaswang 回答时间:2015-6-29 08:51:25
感谢分享~!
沐紫 回答时间:2015-6-29 09:04:07
谢谢
黑溱郎 回答时间:2015-6-29 09:07:31
感谢楼主分享,关注学习一下。
stary666 回答时间:2015-6-29 09:20:06
学习,,,,,,,,,,,

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版