内存保护单元(Memory Protection Unit)

对于ARM Corte-M3/4F,freeRTOS提供两个版本,一个是不带内存保护的标准版本,一个是带内存保护的freeRTOS-MPU版本。

使用内存保护单元可以从多个潜在的错误中,未被发现的编程错误和硬件故障中保护应用。在任务执行无效的操作时,freeRTOS-MPU可以保护RTOS内核和数据。同样,在任务导致的非预期修改和任务堆栈溢出时,可以保护系统外设。

LPC17xx的版本里包含了如何使用内存保护单元的章节,示例工程在源代码的路径FreeRTOS/Demo/CORTEX_MPU_Simulator_Keil_GCC下。

FreeRTOS-MPU的特点

  • 兼容ARM Corte-M3/4F
  • 可以运行在特权模式或用户模式下。用户模式只能访问任务自己的栈空间和最多三个用户可定义的存储器区域。用户定义的存储区域与任务关联,如果需要,在运行时可重新配置
  • 用户定义存储区域可以独立配置,比如有些区域是只读的,有些区域是不可执行的
  • 用户模式下的任务无共享数据,但是用户模式下的任务可以通过队列和信号量机制相互之间传递数据,任务之间可以共享用户自定义存储区域,但是,这不推荐
  • 特权模式下的任务可以将自身向用户模式转变,但是逆向的转换是不支持的
  • freeRTOS的API定位于Flash的开始区域,仅仅只能有处理器在特权模式下访问(调用API会短暂的切换到特权模式)
  • RTOS的内核在特权模式下维护位于RAM开始区域的数据(所有的非栈数据都是freeRTOS源文件的私有数据)
  • 系统外设的访问只能在处理器处于特权模式下,标准外设(UART等)可以被任何代码访问,但是能使用用户自定义存储区域显式的保护起来

创建限制(受保护)任务

使用标准的任务创建API—xTaskCreat(),无法使用内存保护单元。创建的任务可以运行在特权模式和用户模式下,在特权模式下,拥有全部内存空间的访问权限,在用户模式下只能访问自己的栈空间。不管在什么模式下,内存保护单元都不会自动捕捉栈溢出,即使使用了标准的freeRTOS栈溢出检测机制。

如果任务想使用内存保护单元,那么下列条件需要提供:

  • 任务堆栈的地址
  • 用户自定义内存区域的起始地址、大小、访问参数需要

因此,创建任务时需要的参数数量将变得多起来,为了使得使用内存保护单元(MPU)的任务创建简单些,freeRTOS提供xTaskCreatRestricted()API函数。这允许将所有的参数定义在一个结构体中,而这个结构体作为一个单独的参数传递给xTaskCreatRestricted()

使用xTaskCreatRestricted()创建的任务同样可以运行在特权模式和用户模式下,但是此时,用户模式下,任务可以访问用户自定义内存区域。特权模式下的任务可以调用portSWITCH_TO_USER_MODE()将自身切换到用户模式下,用户模式下无法向特权模式转换。

为任务分配的内存区域可以使用vTaskAllocateMPURegions()更改。

更进一步的信息,可以参阅源代码路径FreeRTOS/Demo/CORTEX_MPU_Simulator_Keil_GCC下的示例及相关API参考指南。