硬汉嵌入式论坛

 找回密码
 立即注册
查看: 3499|回复: 3
收起左侧

[RL-RTX] 【RTX操作系统教程】第9章  任务运行在特权级或非特权级模式

[复制链接]

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
发表于 2015-12-25 15:17:17 | 显示全部楼层 |阅读模式
第9章      任务运行在特权级或非特权级模式


    本章教程为大家讲解RTX运行模式的一个重要知识点,特权级模式和非特权级模式,有些资料或者书籍将非特权级模式称为用户模式。
    本章教程配套的例子含Cortex-M3内核的STM32F103和Cortex-M4内核的STM32F407。
9.1    RTX任务特权级知识点说明
9.2    RTX任务特权等级深入认识
9.3    实验例程说明
9.4     总结

9.1  RTX任务特权级知识点说明

    对于初学者只需记住本小节的知识点即可,如果要深入的了解还是需要花些时间去研究下Cortex-M3或者M4权威指南。
    对于使用Cortex-M3或者M4内核的芯片来说,RTX操作系统可以让任务运行在特权级或者非特权级模式,这两种模式是M3或者M4内核本身所具有的特性。
    在特权级模式下,用户可以访问和配置系统控制寄存器,比如NVIC中断控制器。然而,如果是在非特权级模式下,系统控制寄存器是不允许访问的,一旦访问将导致硬件异常。
u  Unprivileged
    非特权级,起到保护用户任务的作用,防止用户可以在任意任务中访问和修改系统寄存器,操作不当会造成系统崩溃。
u  Privileged
    特权级,这种模式下用户可以在任意任务中对系统控制寄存器的访问和修改。
    有了这点基础的认识之后,还有以下四个疑问有待解决。

9.1.1      非特权级模式下那些寄存器不可访问

    对于Cortex-M3或者M4内核来说,所有的核心外设寄存器都是只能在特权级下才可以访问,那些又是核心外设寄存器呢,对于STM32来说需要大家看编程手册,如下这些核心外设所有的寄存器都需要在特权级下才可以访问:
9.1.png

    核心外设主要是MPU,NVIC,SCB和STK四个单元。一些初学者要问了,你又是如何知道这些内核外设的寄存器要在特权级下才可以访问?答案就在这里,我们可以任意打开一个寄存器:
9.2.png
9.3.png

关于MPU,NVIC,SCB和STK四个单元的其它寄存器是否需要在特权级下才可以访问,大家可以按照我上面说的方法进行查看。
    除了核心外设寄存器以外,M3/M4内核的特殊功能寄存器也是不能在非特权级下访问的,特殊功能寄存器主要包括以下寄存器:
u  程序状态寄存器组(PSRs或曰xPSR)
u  中断屏蔽寄存器组(PRIMASK, FAULTMASK,以及BASEPRI)
u  控制寄存器(CONTROL)
    对于参考手册上面所说的SPI,USART,USB等所有外设寄存器都是可以在非特权级下进行访问的。

9.1.2      非特权级模式下核心外设寄存器如何初始化

    如果用户将RTX操作系统的任务设置在非特权级模式下运行,那么核心外设寄存器应该放在哪里进行初始化呢,主要有以下两种方法:
u 使用SVC(Supervisor Call)软中断,这个在第19章有详细讲解。
u 在初始化和开启RTX多任务前做核心外设的初始化。

9.1.3     Cortex-M3或者M4内核如何切换两种模式

    Cortex-M3/M4中的特殊功能寄存器包括:
u  程序状态寄存器组(PSRs或曰xPSR)
u  中断屏蔽寄存器组(PRIMASK, FAULTMASK,以及BASEPRI)
u  控制寄存器(CONTROL)
    其中控制寄存器CONTROL是用来设置特权级和非特权级切换的,CONTROL寄存器定义如下:


功能

CONTROL[1]

堆栈指针选择
0=选择主堆栈指针MSP(复位后的缺省值)
1=选择进程堆栈指针PSP
在线程模式,可以使用PSP。在handler模式下,
只允许使用MSP,所以此时不得往该位写1。

CONTROL[0]

0=特权级的线程模式
1=用户级的线程模式
Handler模式永远都是特权级的。

CONTROL[0]
    仅当在特权级下操作时才允许写该位。一旦进入了用户级,唯一返回特权级的途径,就是触发一个软中断,再由服务例程改写该位。
CONTROL寄存器也是通过MRS和MSR指令来操作的:
      MRS   R0,    CONTROL
      MSR   CONTROL, R0

9.1.4     RTX任务特权等级的设置方法

    RTX任务特权等级的设置方法比较简单,查看RTX系统的配置向导,如下图9.1所示:
9.5.png
图9.1 RTX配置向导

u Run in privileged mode
    此参数就是用来设置特权级和非特权级的,选上单选框表示使能任务工作在特权级模式,取消单选框表示任务工作在非特权级模式。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2015-12-25 15:21:13 | 显示全部楼层
9.2    RTX任务特权等级深入认识


    本小节的知识点对于初学者来说比较难理解,需要积累了一定的经验后才能更好的理解,不过还是建议读一读。
    深入了解Cortex-M3/M4内核的特权等级就不得不说说两种操作模式,Cortex-M3/M4支持两种操作模式,两种操作模式分别是:
u  Handlermode,中断模式,简单的说就是指的异常服务程序是处在中断模式。
u  Threadmode,线程模式,简单的说就是异常服务程序以外的程序都是处在线程模式。
    Cortex-M3/M4内核实现这两种操作的目的就是区分普通应用程序的代码和异常服务程序。下面是两种操作模式和两种特权等级的关系:
9.6.png

l 中断和异常的区别
    在 ARM 编程领域中,凡是打断程序顺序执行的事件,都被称为异常(exception)。除了外部中断外,
当有指令执行了“非法操作”, 或者访问被禁的内存区间,因各种错误产生的 fault, 以及不可屏
蔽中断发生时,都会打断程序的执行,这些情况统称为异常。在不严格的上下文中,异常与中断也可
以混用。另外,程序代码也可以主动请求进入异常状态的(常用于系统调用)。

    当处理器处在线程状态下时,既可以使用特权级,也可以使用用户级;另一方面,handler模式总是特权级的。
在系统复位后,处理器进入线程模式+特权级。
     在特权级下的代码可以通过置位CONTROL[0]来进入用户级。而不管是任何原因产生了任何异常,处理器都将
以特权级来运行其服务例程,异常返回后,系统将回到产生异常时所处的级别。用户级下的代码不能再试图修改
CONTROL[0]来回到特权级。它必须通过一个异常handler,由那个异常handler来修改CONTROL[0],才能在
返回到线程模式后拿到特权级。下图是特权级线程模式和用户级线程模式的切换图:
9.7.png


一些简单的应用程序是不需要用户级线程模式的,如下图所示:
9.8.png


    把代码按特权级和用户级分开对待,有利于使CM3/CM4的架构更加安全和健壮。例如,当某个用户程序代码出问题时,不会让它成为害群之马,因为用户级的代码是禁止写特殊功能寄存器和NVIC中断寄存器的。另外,如果还配有MPU,保护力度就更大,甚至可以阻止用户代码访问不属于它的内存区域。
    为了避免系统堆栈因应用程序的错误使用而毁坏,我们可以给应用程序专门配一个堆栈,不让它共享操作系统内核的堆栈。在这个管理制度下,运行在线程模式的用户代码使用PSP,而异常服务例程则使用MSP。这两个堆栈指针的切换是智能全自动的,就在异常服务的始末由硬件处理。
    如前所述,特权等级和堆栈指针的选择均由CONTROL负责。当CONTROL[0]=0时,在异常处理的始末,只发生了处理器模式的转换,如下图所示。
    9.9.png

但若CONTROL[0]=1(线程模式+用户级),则在中断响应的始末,处理器模式和特权等极都要发生变化,如下图所示。
9.10.png

    CONTROL[0]只有在特权级下才能访问。用户级的程序如想进入特权级,通常都是使用一条“系统服务呼叫指令(SVC)”来触发“SVC异常”,该异常的服务例程可以视具体情况而修改CONTROL[0]
           关于操作模式和特权级就跟大家说这么多,后面讲解RTX任务切换时再详述(此章节在后期RTX教程升级版本时再配套)
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2015-12-25 15:27:08 | 显示全部楼层
9.3   实验例程说明

9.3.1     STM32F103开发板实验

配套例子:
    V4-404_RTX实验_任务运行在用户模式(非特权级)
实验目的:
    1. 学习RTX的任务运行在用户模式的设置方法
实验内容:
    1. K1按键按下,串口打印。
    2. K2键按下,设置NVIC分组,从而导致系统进入到硬件异常HardFault_Handler。
    3. 各个任务实现的功能如下:
      AppTaskUserIF任务   :按键消息处理。
      AppTaskLED任务     :LED闪烁。
      AppTaskMsgPro任务 :消息处理,这里用作LED闪烁。
      AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
RTX配置:
    RTX配置向导详情如下:
9.11.png

u  Task Configuration
l Number of concurrent running tasks
    允许创建4个任务,实际创建了如下四个任务
                     AppTaskUserIF任务   :按键消息处理。
                    AppTaskLED任务     :LED闪烁。
                    AppTaskMsgPro任务 :消息处理,这里是用作LED闪烁。
                    AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
l Number of tasks with user-provided stack
    创建的4个任务都是采用自定义堆栈方式。
l Run in privileged mode
    设置RTX任务运行在非特权级,即用户模式。
RTX任务调试信息:
9.12.png

程序设计:
u  任务栈大小分配:
    staticuint64_t AppTaskUserIFStk[512/8];   /* 任务栈 */
    staticuint64_t AppTaskLEDStk[256/8];      /* 任务栈 */
    staticuint64_t AppTaskMsgProStk[512/8];  /* 任务栈 */
    staticuint64_t AppTaskStartStk[512/8];     /* 任务栈 */
      将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。
u  系统栈大小分配:
9.13.png

u  RTX初始化:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: main
  4. *    功能说明: 标准c程序入口。
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. int main (void)
  10. {   
  11.      /* 初始化外设 */
  12.      bsp_Init();
  13.    
  14.      /* 创建启动任务 */
  15.      os_sys_init_user (AppTaskStart,             /* 任务函数 */
  16.                        4,                        /* 任务优先级 */
  17.                        &AppTaskStartStk,         /* 任务栈 */
  18.                        sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */
  19.      while(1);
  20. }
复制代码
u  RTX任务创建:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskCreate
  4. *    功能说明: 创建应用任务
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void AppTaskCreate (void)
  10. {
  11.      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */
  12.                                            1,                         /* 任务优先级 */
  13.                                            &AppTaskUserIFStk,         /* 任务栈 */
  14.                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */
  15.    
  16.      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */
  17.                                         2,                       /* 任务优先级 */
  18.                                         &AppTaskLEDStk,          /* 任务栈 */
  19.                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */
  20.    
  21.      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */
  22.                                            3,                         /* 任务优先级 */
  23.                                            &AppTaskMsgProStk,         /* 任务栈 */
  24.                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */
  25. }
复制代码
u  四个RTX任务的实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskUserIF
  4. *    功能说明: 按键消息处理     
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  8. *********************************************************************************************************
  9. */
  10. __task void AppTaskUserIF(void)
  11. {
  12.      uint8_t ucKeyCode;
  13.     while(1)
  14.     {
  15.          ucKeyCode = bsp_GetKey();
  16.         
  17.          if (ucKeyCode != KEY_NONE)
  18.          {
  19.               switch (ucKeyCode)
  20.               {
  21.                    /* K1键按下,打印调试说明 */
  22.                    case KEY_DOWN_K1:
  23.                        printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\\r\\n");
  24.                        break;  
  25.                    /* K2键按下,非特权级模式下设置NVIC分组,从而导致系统进入到硬件异常HardFault_Handler */
  26.                    case KEY_DOWN_K2:
  27.                        printf("K2键按下,非特权级模式下设置NVIC分组,从而导致系统进入到硬件异常
  28. HardFault_Handler\\r\\n");
  29.                        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
  30.                        break;
  31.                    /* 其他的键值不处理 */
  32.                    default:                    
  33.                        break;
  34.               }
  35.          }
  36.         
  37.          os_dly_wait(20);
  38.      }
  39. }
  40. /*
  41. *********************************************************************************************************
  42. *    函 数 名: AppTaskLED
  43. *    功能说明: LED闪烁。
  44. *    形    参: 无
  45. *    返 回 值: 无
  46. *   优 先 级: 2
  47. *********************************************************************************************************
  48. */
  49. __task void AppTaskLED(void)
  50. {
  51.      const uint16_t usFrequency = 200; /* 延迟周期 */
  52.    
  53.      /* 设置延迟周期 */
  54.      os_itv_set(usFrequency);
  55.    
  56.     while(1)
  57.     {
  58.          bsp_LedToggle(2);
  59.          bsp_LedToggle(3);
  60.          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/
  61.          os_itv_wait();
  62.     }
  63. }
  64. /*
  65. *********************************************************************************************************
  66. *    函 数 名: AppTaskMsgPro
  67. *    功能说明: 消息处理,这里用作LED闪烁
  68. *    形    参: 无
  69. *    返 回 值: 无
  70. *   优 先 级: 3
  71. *********************************************************************************************************
  72. */
  73. __task void AppTaskMsgPro(void)
  74. {
  75.      const uint16_t usFrequency = 500; /* 延迟周期 */
  76.    
  77.      /* 设置延迟周期 */
  78.      os_itv_set(usFrequency);
  79.    
  80.      while(1)
  81.      {
  82.          bsp_LedToggle(1);
  83.          bsp_LedToggle(4);
  84.          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/
  85.          os_itv_wait();
  86.      }   
  87. }
  88. /*
  89. *********************************************************************************************************
  90. *    函 数 名: AppTaskStart
  91. *    功能说明: 启动任务,也就是最高优先级任务。这里实现按键扫描。
  92. *    形    参: 无
  93. *    返 回 值: 无
  94. *   优 先 级: 4
  95. *********************************************************************************************************
  96. */
  97. __task void AppTaskStart(void)
  98. {
  99.      /* 创建任务 */
  100.      AppTaskCreate();
  101.    
  102.     while(1)
  103.     {
  104.          /* 按键扫描 */
  105.          bsp_KeyScan();
  106.         os_dly_wait(10);
  107.     }
  108. }
复制代码

9.3.2     STM32F407开发板实验

配套例子:
    V5-404_RTX实验_任务运行在用户模式(非特权级)
实验目的:
    1. 学习RTX的任务运行在用户模式的设置方法
实验内容:
    1. K1按键按下,串口打印。
    2. K2键按下,设置NVIC分组,从而导致系统进入到硬件异常HardFault_Handler。
    3. 各个任务实现的功能如下:
      AppTaskUserIF任务  :按键消息处理。
      AppTaskLED任务     :LED闪烁。
      AppTaskMsgPro任务 :消息处理,这里用作LED闪烁。
      AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
RTX配置:
    RTX配置向导详情如下:
9.14.png

u  Task Configuration
l Number of concurrent running tasks
    允许创建4个任务,实际创建了如下四个任务
                    AppTaskUserIF任务   :按键消息处理。
                    AppTaskLED任务     :LED闪烁。
                    AppTaskMsgPro任务 :消息处理,这里是用作LED闪烁。
                    AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
l Number of tasks with user-provided stack
    创建的4个任务都是采用自定义堆栈方式。
l Run in privileged mode
    设置RTX任务运行在非特权级,即用户模式。
RTX任务调试信息:
9.15.png

程序设计:
u  任务栈大小分配:
    staticuint64_t AppTaskUserIFStk[512/8];   /* 任务栈 */
    staticuint64_t AppTaskLEDStk[256/8];      /* 任务栈 */
    staticuint64_t AppTaskMsgProStk[512/8];  /* 任务栈 */
    staticuint64_t AppTaskStartStk[512/8];     /* 任务栈 */
      将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。
u  系统栈大小分配:
9.16.png

u  RTX初始化:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: main
  4. *    功能说明: 标准c程序入口。
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. int main (void)
  10. {   
  11.      /* 初始化外设 */
  12.      bsp_Init();
  13.    
  14.      /* 创建启动任务 */
  15.      os_sys_init_user (AppTaskStart,             /* 任务函数 */
  16.                        4,                        /* 任务优先级 */
  17.                        &AppTaskStartStk,         /* 任务栈 */
  18.                        sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */
  19.      while(1);
  20. }
复制代码
u  RTX任务创建:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskCreate
  4. *    功能说明: 创建应用任务
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void AppTaskCreate (void)
  10. {
  11.      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */
  12.                                            1,                         /* 任务优先级 */
  13.                                            &AppTaskUserIFStk,         /* 任务栈 */
  14.                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */
  15.    
  16.      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */
  17.                                         2,                       /* 任务优先级 */
  18.                                         &AppTaskLEDStk,          /* 任务栈 */
  19.                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */
  20.    
  21.      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */
  22.                                            3,                         /* 任务优先级 */
  23.                                            &AppTaskMsgProStk,         /* 任务栈 */
  24.                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */
  25. }
复制代码
u  四个RTX任务的实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskUserIF
  4. *    功能说明: 按键消息处理     
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  8. *********************************************************************************************************
  9. */
  10. __task void AppTaskUserIF(void)
  11. {
  12.      uint8_t ucKeyCode;
  13.     while(1)
  14.     {
  15.          ucKeyCode = bsp_GetKey();
  16.         
  17.          if (ucKeyCode != KEY_NONE)
  18.          {
  19.               switch (ucKeyCode)
  20.               {
  21.                    /* K1键按下,打印调试说明 */
  22.                    case KEY_DOWN_K1:
  23.                        printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\\r\\n");
  24.                        break;  
  25.                    /* K2键按下,非特权级模式下设置NVIC分组,从而导致系统进入到硬件异常HardFault_Handler */
  26.                    case KEY_DOWN_K2:
  27.                        printf("K2键按下,非特权级模式下设置NVIC分组,从而导致系统进入到硬件异常
  28. HardFault_Handler\\r\\n");
  29.                        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
  30.                        break;
  31.                    /* 其他的键值不处理 */
  32.                    default:                    
  33.                        break;
  34.               }
  35.          }
  36.         
  37.          os_dly_wait(20);
  38.      }
  39. }
  40. /*
  41. *********************************************************************************************************
  42. *    函 数 名: AppTaskLED
  43. *    功能说明: LED闪烁。
  44. *    形    参: 无
  45. *    返 回 值: 无
  46. *   优 先 级: 2
  47. *********************************************************************************************************
  48. */
  49. __task void AppTaskLED(void)
  50. {
  51.      const uint16_t usFrequency = 200; /* 延迟周期 */
  52.    
  53.      /* 设置延迟周期 */
  54.      os_itv_set(usFrequency);
  55.    
  56.     while(1)
  57.     {
  58.          bsp_LedToggle(2);
  59.          bsp_LedToggle(3);
  60.          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/
  61.           os_itv_wait();
  62.     }
  63. }
  64. /*
  65. *********************************************************************************************************
  66. *    函 数 名: AppTaskMsgPro
  67. *    功能说明: 消息处理,这里用作LED闪烁
  68. *    形    参: 无
  69. *    返 回 值: 无
  70. *   优 先 级: 3
  71. *********************************************************************************************************
  72. */
  73. __task void AppTaskMsgPro(void)
  74. {
  75.      const uint16_t usFrequency = 500; /* 延迟周期 */
  76.    
  77.      /* 设置延迟周期 */
  78.      os_itv_set(usFrequency);
  79.    
  80.      while(1)
  81.      {
  82.          bsp_LedToggle(1);
  83.          bsp_LedToggle(4);
  84.          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/
  85.          os_itv_wait();
  86.      }   
  87. }
  88. /*
  89. *********************************************************************************************************
  90. *    函 数 名: AppTaskStart
  91. *    功能说明: 启动任务,也就是最高优先级任务。这里实现按键扫描。
  92. *    形    参: 无
  93. *    返 回 值: 无
  94. *   优 先 级: 4
  95. *********************************************************************************************************
  96. */
  97. __task void AppTaskStart(void)
  98. {
  99.      /* 创建任务 */
  100.      AppTaskCreate();
  101.    
  102.     while(1)
  103.     {
  104.          /* 按键扫描 */
  105.          bsp_KeyScan();
  106.         os_dly_wait(10);
  107.     }
  108. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2015-12-25 15:27:50 | 显示全部楼层
9.4  总结

    对于初学者来说,容易在特权级和非特权级的地方出错。如果以前没有这方面基础的话,理解的时候还稍困难些,不急,慢慢来,完全的理解也需要一个循序渐进的过程。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-12 18:34 , Processed in 0.178339 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表