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

【经验分享】STM32堆栈指针疑问

[复制链接]
STMCU小助手 发布时间:2022-1-29 13:57
1. 下面的代码看的不是很明白,百为stm32开发板光盘\测试程序\CortexM3\Mode_Privilege\project,堆是程序员分配和使用的,栈是编译器指定的,存放函数参数,临时变量。
  1. #include "stm32f10x_lib.h"
    5 S" z+ B' ^) C+ |: {
  2. #define SP_PROCESS_SIZE             0x200  /* Process stack size */6 R: _( ?# y: c) h' Y$ |5 f
  3. #define SP_PROCESS                  0x02   /* Process stack */; k: [" M/ x6 E3 N5 N% p8 f
  4. #define SP_MAIN                     0x00   /* Main stack */
    . O- H8 x; ^7 I6 V/ A6 ^8 B4 Y
  5. #define THREAD_MODE_PRIVILEGED      0x00   /* Thread mode has privileged access */( x8 M) D! N: V0 F  ~3 w- P
  6. #define THREAD_MODE_UNPRIVILEGED    0x01   /* Thread mode has unprivileged access */0 X1 W) u8 Y9 x8 G* R4 I1 o

  7. 9 T8 u5 W1 P& I+ H1 |! q
  8. ErrorStatus HSEStartUpStatus;
    / v4 A  [$ G; x3 S& g0 b8 i- f4 g
  9. vu8 PSPMemAlloc[SP_PROCESS_SIZE];
    ( Q! [, v, ]8 w3 o& l
  10. vu32 Index = 0, PSPValue = 0, CurrentStack = 0, ThreadMode = 0;9 S7 [( L8 G$ B- D7 }, [* \

  11. $ y& o! ~! P& w6 @( n! Z9 ~' h/ r
  12. /* Private function prototypes -----------------------------------------------*/
    2 a3 ?) w; y4 @. y( ?
  13. void RCC_Configuration(void);  A, c) `& x: r
  14. void NVIC_Configuration(void);* ^$ T( ?. ]: d. J' k' e
  15. / K9 N  N0 i2 ?' {" v3 K0 m5 Y9 R

  16. , D0 F0 ]% i' T! l4 Q0 l
  17. int main(void)
    6 R4 m- v6 e3 b2 y- l+ q, H. k/ t: R$ q
  18. {) C6 b0 d4 c& r. ]2 Q$ ?" ~/ G) L2 L+ N, g
  19. #ifdef DEBUG
    & f4 @+ Y$ M/ Z( W! `# O
  20.   debug();
    . n2 y. e! g% U( v
  21. #endif$ y+ W" m. r1 h: z+ |, G2 ?
  22. 6 @) g/ I$ b( O# Q% {. v' X
  23.   //时钟配置
      i- r4 l) L  ]- q) e
  24.   RCC_Configuration();
    7 K: t: M9 z- d! {0 m
  25. * X; q, @) t8 [! T" E. f
  26.   //中断向量表配置/ C- R- J0 b2 |0 e! W
  27.   NVIC_Configuration();
    2 E0 y4 B9 [# K" a2 G9 d5 u
  28. 5 j5 P5 |! D  r, D8 Q
  29.   //STM32有一个主堆栈指针MSP,和线程堆栈指针PSP,把进程堆栈指针指向这个数组的高地址,因为堆栈指针是向下增长的
    ! i& O" H; Y3 d5 `- [0 Q
  30. /* Switch Thread mode Stack from Main to Process -----------------------------*/
    ( ]' s! E# S4 b5 t/ w; m* U9 r3 c; W
  31.   /* Initialize memory reserved for Process Stack */8 }) A$ A: O& N7 |/ E. d
  32.   for(Index = 0; Index < SP_PROCESS_SIZE; Index++)
    * E5 c! M0 I6 @% b
  33.   {
      e; C* h" ]( `7 r- [
  34.     PSPMemAlloc[Index] = 0x00;4 X# N. G( Z6 ?- x: b
  35.   }
    2 H9 D2 ?! ^8 e7 s
  36.   //系统上电,是在线程模式,特权级别下,所以可以修改CONTROL寄存器,这个寄存器选择特权级和用户级,还有系统选哪个堆栈指针
    ! d& k* ~" Y3 [) F$ f5 S  M. G
  37.   /* Set Process stack value */
    ) L" s/ \6 |5 K: r6 r
  38.   __MSR_PSP((u32)PSPMemAlloc + SP_PROCESS_SIZE);
    7 A) K4 _4 n/ h  ?
  39.   //选择线程堆栈作为线程模式的堆栈,有点绕口
      ~; E7 d- |( X& b0 t: I9 u* _/ A, j
  40.   /* Select Process Stack as Thread mode Stack */
    6 p4 K$ y" G" t+ z
  41.   __MSR_CONTROL(SP_PROCESS);
    1 F6 J  n7 C8 \/ l- j
  42. 4 c5 p4 M- I8 q9 l4 @
  43.   /* Get the Thread mode stack used */
    ! O1 v3 b6 }: u$ E+ z% ~; G# q
  44.   if((__MRS_CONTROL() & 0x02) == SP_MAIN)
    ) f3 q$ z' M% j! j8 y8 a
  45.   {
    8 s8 y0 l' F  O1 i6 _7 @0 n
  46.     /* Main stack is used as the current stack */$ z# @0 c. D# W3 k/ T
  47.     CurrentStack = SP_MAIN;7 H* h, ?# ?- m1 G# @3 U, a, B
  48.   }( e' @  I& s* z5 G; J
  49.   else
    . s1 s/ ?8 w/ v9 m& ^3 g
  50.   {
    - D; q/ F9 i1 O% Y
  51.     /* Process stack is used as the current stack */7 M; l0 z0 `/ b' @$ p/ j* m
  52.     CurrentStack = SP_PROCESS;
    8 w$ s  n5 Z  ]3 h  B. \% k

  53. - N. p1 V- m8 g
  54.     /* Get process stack pointer value */
    2 v9 W5 g5 b  |) q; g6 \0 R
  55.     PSPValue = __MRS_PSP();' L9 K3 D# \. N1 L8 J$ d
  56.   }0 J3 D8 F- i- ?* w- v

  57. % T* N2 s1 m4 U' i* [
  58. /* Switch Thread mode from privileged to unprivileged ------------------------*//切换线程模式到非特权
    - A5 C( ]' H; ^0 v
  59.   /* Thread mode has unprivileged access */
    6 S# D+ [3 G0 _
  60.   __MSR_CONTROL(THREAD_MODE_UNPRIVILEGED | SP_PROCESS);0 M8 {! h  r2 Z4 @% f9 C" t7 O
  61.   /* Unprivileged access mainly affect ability to:
    ) X) n# H7 B% t- p( F( P  a- D
  62.       - Use or not use certain instructions such as MSR fields
    9 R# O( U" v' k! r
  63.       - Access System Control Space (SCS) registers such as NVIC and SysTick */
    + j% L' t1 q& e8 A

  64. - u. G( P5 D* `1 T7 w* j- N* |6 I
  65.   /* Check Thread mode privilege status */ //检查当前是特权还是用户级别
    ! }! Q7 \2 D* \. O: P/ z
  66.   if((__MRS_CONTROL() & 0x01) == THREAD_MODE_PRIVILEGED)/ i( R1 I! D, Z) X4 X
  67.   {, d$ `$ m* X/ [: x  C
  68.     /* Thread mode has privileged access  */
    % _. L% {5 f% K( _* |1 }: g0 I
  69.     ThreadMode = THREAD_MODE_PRIVILEGED;2 ^) i" g' y) ~. o. J! b8 j
  70.   }& P! G, @4 a& r; [  {8 X# K" q
  71.   else4 T' g+ E. ~7 z; W! Z4 T
  72.   {2 C* q  N/ U* c" f2 E( H  S5 G
  73.     /* Thread mode has unprivileged access*/
    + L/ O( G; i1 }
  74.     ThreadMode = THREAD_MODE_UNPRIVILEGED; //应该是用户级别
    % ?: q( ?2 y, N
  75.   }
    + f& ^" o' I2 o7 Y) J, X2 R4 g/ N
  76. 2 u( Y) y2 w: U1 c
  77. /* Switch back Thread mode from unprivileged to privileged -------------------*/  //切换到特权模式: F& ~$ o" o- O- v( v* N+ c% n
  78.   /* Try to switch back Thread mode to privileged (Not possible, this can be. `4 d; S: p3 [3 G. S
  79.      done only in Handler mode) */
    9 T3 \3 r4 n, `) ]& P- e) i: I
  80.   __MSR_CONTROL(THREAD_MODE_PRIVILEGED | SP_PROCESS);
    ; ?. U) ^7 i0 I% q8 ?! `' f
  81. 4 B+ p3 m% a# F8 }8 Z6 M
  82.   /* Generate a system call exception, and in the ISR switch back Thread mode4 f$ N! l7 A% K  }
  83.     to privileged */
    % }  y/ g# ]: q9 }4 G$ u
  84.   __SVC(); //产生中断,进入handler模式,特权级别7 T2 f! n  Z- a

  85. ; Y2 b0 a& \  }9 m  r) D
  86.   /* Check Thread mode privilege status */' O7 o% K' _$ b. {* d& L
  87.   if((__MRS_CONTROL() & 0x01) == THREAD_MODE_PRIVILEGED)
    " g1 x5 t4 i  z5 ~  Y6 ^: a
  88.   {
    4 _# {4 F6 l& v! p
  89.     /* Thread mode has privileged access  */
    & ^! p) F% L# A7 V  e9 K
  90.     ThreadMode = THREAD_MODE_PRIVILEGED;  //应该是特权级别: w4 V! a! s* m. m" I% ~8 _$ I
  91.   }- F, Q, T% P- @' k* A* ]
  92.   else
    + u  [" K0 j) }5 K1 ~9 G8 J0 p6 X3 s
  93.   {
    + l* ^# V. V; t& Q% f
  94.     /* Thread mode has unprivileged access*/
    ; v4 O0 z( K* y' [' o& E
  95.     ThreadMode = THREAD_MODE_UNPRIVILEGED;* v+ W' _" r7 J9 y- R; k
  96.   }
    / R$ R/ @, S' D6 B. Q7 I

  97. 2 {2 T6 I% E2 E$ u* V
  98.   while (1)
      K) n' _/ ^; C8 [4 ?8 I7 U& U
  99.   {
    ( T4 n- t" _0 H- a
  100.   }
    5 p' S0 _; E: ^3 n
  101. }
复制代码
- g3 Y: `; y) l- N1 p1 w! F
2. 暂时不明白这个程序什么用途,只是学习的过程中遇到了,拿出来研究一下。
Cortex-M3处理器支持两种处理器的操作模式,还支持两级特权操作。& P$ M/ s$ m) j+ p
两种操作模式分别为:处理者模式(handler mode)和线程模式(thread mode)。引入两个模式的本意,是用于区别普通应用程序的代码和异常服务例程的代码——包括中断服务例程的代码。Cortex-M3的另一个侧面则是特权的分级——特权级和用户级。这可以提供一种存储器访问的保护机制,使得普通的用户程序代码不能意外地,甚至是恶意地执行涉及到要害的操作。处理器支持两种特权级,这也是一个基本的安全模型。
3. 在CM3运行主应用程序时(线程模式),既可以使用特权级,也可以使用用户级;但是异常服务例程必须在特权级下执行。复位后,处理器默认进入线程模式,特权极访问。在特权级下,程序可以访问所有范围的存储器(如果有MPU,还要在MPU规定的禁地之外),并且可以执行所有指令。
在特权级下的程序可以为所欲为,但也可能会把自己给玩进去——切换到用户级。一旦进入用户级,再想回来就得走“法律程序”了——用户级的程序不能简简单单地试图改写CONTROL寄存器就回到特权级,它必须先“申诉”:执行一条系统调用指令(SVC)。这会触发SVC异常,然后由异常服务例程(通常是操作系统的一部分)接管,如果批准了进入,则异常服务例程修改CONTROL寄存器,才能在用户级的线程模式下重新进入特权级。事实上,从用户级到特权级的唯一途径就是异常:如果在程序执行过程中触发了一个异常,处理器总是先切换入特权级,并且在异常服务例程执行完毕退出时
4.如果根据下表和上面解释重新看代码的话,应该很清楚了。
2 n% k& g: _* F
1300009-20171222170030818-1131604041.jpg
, {. z" P- ~* h, g" P  @
5. 在看下CONTROL寄存器介绍

1 P7 n. B) k. X( Z1 {
1300009-20171222170243725-510842683.jpg
) e  C9 w' Y- d2 M5 H" _
6. 如此一来,基本搞明白了。

3 I9 r+ K0 |5 B
赞 收藏 评论0 发布时间:2022-1-29 13:57

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版