STM32F103ZET6的中断管理

1、STM32的中断

  STM32的中断管理是属于内核部分的,所以中断管理的寄存器也是属于内核组,不属于芯片外设,在查看相关资料的时候,需要查看相对应的内核手册。

  STM32F103ZET6是Cortex-M3内核的IC。Cortex-M3内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级的可编程中断设置。但是STM32并没有完全使用Cortex-M3内核的全部中断,只是用了其中的一部分。

  在STM32中,有时候中断也称为异常、系统异常,把它们统一理解为中断就可以了。

2、中断编号

  STM32不同类型的芯片IC所具有的中断个数是不一样的,在HAL库中,可以通过查找IRQn_Type这个结构体来查看该IC所具有的中断。IRQn_Tyepe对该芯片的中断进行了编号。STM32F103ZET6的IRQn_Type结构体定义在stm32f103xe.h头文件中,如下:

typedef enum
{
   /******  Cortex-M3 Processor Exceptions Numbers ***************************************************/
    NonMaskableInt_IRQn         = -14,    /*!< 2 Non Maskable Interrupt                             */
    HardFault_IRQn              = -13,    /*!< 3 Cortex-M3 Hard Fault Interrupt                     */
    MemoryManagement_IRQn       = -12,    /*!< 4 Cortex-M3 Memory Management Interrupt              */
    BusFault_IRQn               = -11,    /*!< 5 Cortex-M3 Bus Fault Interrupt                      */
    UsageFault_IRQn             = -10,    /*!< 6 Cortex-M3 Usage Fault Interrupt                    */
    SVCall_IRQn                 = -5,     /*!< 11 Cortex-M3 SV Call Interrupt                       */
    DebugMonitor_IRQn           = -4,     /*!< 12 Cortex-M3 Debug Monitor Interrupt                 */
    PendSV_IRQn                 = -2,     /*!< 14 Cortex-M3 Pend SV Interrupt                       */
    SysTick_IRQn                = -1,     /*!< 15 Cortex-M3 System Tick Interrupt                   */

  /******  STM32 specific Interrupt Numbers *********************************************************/
    WWDG_IRQn                   = 0,      /*!< Window WatchDog Interrupt                            */
    PVD_IRQn                    = 1,      /*!< PVD through EXTI Line detection Interrupt            */
    TAMPER_IRQn                 = 2,      /*!< Tamper Interrupt                                     */
    RTC_IRQn                    = 3,      /*!< RTC global Interrupt                                 */
    FLASH_IRQn                  = 4,      /*!< FLASH global Interrupt                               */
    RCC_IRQn                    = 5,      /*!< RCC global Interrupt                                 */
    EXTI0_IRQn                  = 6,      /*!< EXTI Line0 Interrupt                                 */
    EXTI1_IRQn                  = 7,      /*!< EXTI Line1 Interrupt                                 */
    EXTI2_IRQn                  = 8,      /*!< EXTI Line2 Interrupt                                 */
    EXTI3_IRQn                  = 9,      /*!< EXTI Line3 Interrupt                                 */
    EXTI4_IRQn                  = 10,     /*!< EXTI Line4 Interrupt                                 */
    DMA1_Channel1_IRQn          = 11,     /*!< DMA1 Channel 1 global Interrupt                      */
    DMA1_Channel2_IRQn          = 12,     /*!< DMA1 Channel 2 global Interrupt                      */
    DMA1_Channel3_IRQn          = 13,     /*!< DMA1 Channel 3 global Interrupt                      */
    DMA1_Channel4_IRQn          = 14,     /*!< DMA1 Channel 4 global Interrupt                      */
    DMA1_Channel5_IRQn          = 15,     /*!< DMA1 Channel 5 global Interrupt                      */
    DMA1_Channel6_IRQn          = 16,     /*!< DMA1 Channel 6 global Interrupt                      */
    DMA1_Channel7_IRQn          = 17,     /*!< DMA1 Channel 7 global Interrupt                      */
    ADC1_2_IRQn                 = 18,     /*!< ADC1 and ADC2 global Interrupt                       */
    USB_HP_CAN1_TX_IRQn         = 19,     /*!< USB Device High Priority or CAN1 TX Interrupts       */
    USB_LP_CAN1_RX0_IRQn        = 20,     /*!< USB Device Low Priority or CAN1 RX0 Interrupts       */
    CAN1_RX1_IRQn               = 21,     /*!< CAN1 RX1 Interrupt                                   */
    CAN1_SCE_IRQn               = 22,     /*!< CAN1 SCE Interrupt                                   */
    EXTI9_5_IRQn                = 23,     /*!< External Line[9:5] Interrupts                        */
    TIM1_BRK_IRQn               = 24,     /*!< TIM1 Break Interrupt                                 */
    TIM1_UP_IRQn                = 25,     /*!< TIM1 Update Interrupt                                */
    TIM1_TRG_COM_IRQn           = 26,     /*!< TIM1 Trigger and Commutation Interrupt               */
    TIM1_CC_IRQn                = 27,     /*!< TIM1 Capture Compare Interrupt                       */
    TIM2_IRQn                   = 28,     /*!< TIM2 global Interrupt                                */
    TIM3_IRQn                   = 29,     /*!< TIM3 global Interrupt                                */
    TIM4_IRQn                   = 30,     /*!< TIM4 global Interrupt                                */
    I2C1_EV_IRQn                = 31,     /*!< I2C1 Event Interrupt                                 */
    I2C1_ER_IRQn                = 32,     /*!< I2C1 Error Interrupt                                 */
    I2C2_EV_IRQn                = 33,     /*!< I2C2 Event Interrupt                                 */
    I2C2_ER_IRQn                = 34,     /*!< I2C2 Error Interrupt                                 */
    SPI1_IRQn                   = 35,     /*!< SPI1 global Interrupt                                */
    SPI2_IRQn                   = 36,     /*!< SPI2 global Interrupt                                */
    USART1_IRQn                 = 37,     /*!< USART1 global Interrupt                              */
    USART2_IRQn                 = 38,     /*!< USART2 global Interrupt                              */
    USART3_IRQn                 = 39,     /*!< USART3 global Interrupt                              */
    EXTI15_10_IRQn              = 40,     /*!< External Line[15:10] Interrupts                      */
    RTC_Alarm_IRQn              = 41,     /*!< RTC Alarm through EXTI Line Interrupt                */
    USBWakeUp_IRQn              = 42,     /*!< USB Device WakeUp from suspend through EXTI Line Interrupt */
    TIM8_BRK_IRQn               = 43,     /*!< TIM8 Break Interrupt                                 */
    TIM8_UP_IRQn                = 44,     /*!< TIM8 Update Interrupt                                */
    TIM8_TRG_COM_IRQn           = 45,     /*!< TIM8 Trigger and Commutation Interrupt               */
    TIM8_CC_IRQn                = 46,     /*!< TIM8 Capture Compare Interrupt                       */
    ADC3_IRQn                   = 47,     /*!< ADC3 global Interrupt                                */
    FSMC_IRQn                   = 48,     /*!< FSMC global Interrupt                                */
    SDIO_IRQn                   = 49,     /*!< SDIO global Interrupt                                */
    TIM5_IRQn                   = 50,     /*!< TIM5 global Interrupt                                */
    SPI3_IRQn                   = 51,     /*!< SPI3 global Interrupt                                */
    UART4_IRQn                  = 52,     /*!< UART4 global Interrupt                               */
    UART5_IRQn                  = 53,     /*!< UART5 global Interrupt                               */
    TIM6_IRQn                   = 54,     /*!< TIM6 global Interrupt                                */
    TIM7_IRQn                   = 55,     /*!< TIM7 global Interrupt                                */
    DMA2_Channel1_IRQn          = 56,     /*!< DMA2 Channel 1 global Interrupt                      */
    DMA2_Channel2_IRQn          = 57,     /*!< DMA2 Channel 2 global Interrupt                      */
    DMA2_Channel3_IRQn          = 58,     /*!< DMA2 Channel 3 global Interrupt                      */
    DMA2_Channel4_5_IRQn        = 59,     /*!< DMA2 Channel 4 and Channel 5 global Interrupt        */
} IRQn_Type;

3、NVIC  

  NVIC的简称是嵌套中断向量控制器,它控制着整个芯片中断相关的功能。NVIC是Cortex-M3内核里面的一个外设,它们共同完成对中断的响应。但是ST在设计芯片的时候对Cortex-M3内核里面的NVIC进行了裁剪,把不需要的部分去掉,所以说STM32的NVIC是Cortex-M3的NVIC的一个子集。

  在HAL库中,NVIC的结构体代码如下:

typedef struct
{
    __IOM uint32_t ISER[8U];               /*!< Offset: 0x000 (R/W)  Interrupt Set Enable Register */
     uint32_t RESERVED0[24U];
    __IOM uint32_t ICER[8U];               /*!< Offset: 0x080 (R/W)  Interrupt Clear Enable Register */
     uint32_t RSERVED1[24U];
    __IOM uint32_t ISPR[8U];               /*!< Offset: 0x100 (R/W)  Interrupt Set Pending Register */
     uint32_t RESERVED2[24U];
    __IOM uint32_t ICPR[8U];               /*!< Offset: 0x180 (R/W)  Interrupt Clear Pending Register */
     uint32_t RESERVED3[24U];
    __IOM uint32_t IABR[8U];               /*!< Offset: 0x200 (R/W)  Interrupt Active bit Register */
     uint32_t RESERVED4[56U];
    __IOM uint8_t  IP[240U];               /*!< Offset: 0x300 (R/W)  Interrupt Priority Register (8Bit wide) */
     uint32_t RESERVED5[644U];
    __OM  uint32_t STIR;                   /*!< Offset: 0xE00 ( /W)  Software Trigger Interrupt Register */
}  NVIC_Type;

  NVIC_Type结构体在core_cm3.h文件中定义 。

  NVIC_Type结构体中的RSERVED都是保留位,即给每个寄存器都预留了很多位,方便以后可以扩展功能。

  ISER[8]中断使能寄存器组:

  Cortxe-M3内核支持256个中断,ISER寄存器的每一个bit位控制一个中断使能,ISER是32位寄存器,8个32位的寄存器组成了256个中断控制位。

  但需要注意的是STM32F103的可屏蔽中断只有60个,所以用不到8个ISER寄存器,只用到了ISER[0]和ISER[1]这两个寄存器,ISER[0]和ISER[1]可以组成成64个中断使能位。

  ISER[0]的bit0~bit31分别对应中断0~31;ISER[1]的bit0~bit31分别对应中断32~59。

  当需要使能某个外设中断时,就必须找到ISER寄存器的对应位,并将其置1,具体是置位哪一个位,可以根据结构体IRQn_Type来查询。比如说WWDG_IRQn在IRQn_Type中的值为0,那么在ISER寄存器中的中断使能位就是ISER[0]中的bit0位。

  假设某外设中的在IRQn_Type的中断编号为IRQn,则可以根据如下操作置位该外设的中断使能位:

  ISER[ IRQn >> 5 ] = (1<<(IRQn & 31))

  IRQn & 31相当于只取低5位的值,因为只有对ISER寄存器写1才能使能中断,但是写0是不会有任何效果的,所以这里直接用等于号而不需要用”|”号。

  ICER[8]中断失能寄存器组:

  ICER寄存器的作用刚好与ISER寄存器的作用相反,ICER寄存器是用来清除某个中断的使能的。ICER寄存器的使用跟ISER是一样的,只是功能相反。

  因为NIVC的寄存器都是写1有效,而写0是无效的,不能通过给ISER寄存器写0来清除中断使能位,所以增加了ICER寄存器与ISER寄存器对应。

  ICER寄存器的使用方式可以参考ISER。

  ISPR[8]中断挂起寄存器组:

  每个位的中断与ISER是一样的,只是功能不同。ISPR寄存器如果置1是将一个正在进行的中断挂起,转而执行同级别或更高级别的中断。同ISER一样,写0无效。

  ICPR[8]中断解除挂起寄存器组:

  ICPR寄存器与ISPR寄存器功能刚好相反,通过置位ICPR寄存器来解除ISPR寄存器挂起的中断。同ISER一样,写0无效。

一般很少用到ISPR寄存器和ICPR寄存器。

  IABR[8]中断激活标志位寄存器组:

  IABR寄存器是一个状态寄存器,它是一个只读寄存器。通过读取IABR寄存器的值,可以知道当前执行的中断是哪一个。IABR寄存器的对应位在中断执行完之后又硬件自动清零。IABR寄存器的中断位与ISER是一样的。

  IP[240]中断优先级控制寄存器组:

  IP寄存器与STM32的中断分组密切相关。IP寄存器组由240个8bit的寄存器组成,每个可屏蔽中断占用8bit,总共可以表示240个可屏蔽中断,但是STM32F103只用到了IP[59]~IP[0]这60个。

  IP寄存器的8个bit并没有全部使用,只用了高4位,也就是bit4~bit7位。Bit4~bit7位又分为抢占优先级和响应先级,抢占优先级在前,响应先级在后。而对于抢占优先级和响应优先级各占几位,则需要根据SCB的AIRCR寄存器中的中断分组设置有决定。

4、中断分组

  STM32将中断分为5个组,组0~组4。STM32中断的分组设置是由SCB的AIRCR寄存器的bit8~bit10为来设置的。而抢占优先级和响应优先级则需要根据分组来决定,如下:

    • 中断分组0:AIRCR[10:8] = 111,那么对于IP寄存器的bit7~bit4的占位情况为:0位抢占优先级和4位响应优先级。
    • 中断分组1:AIRCR[10:8] = 110,那么对于IP寄存器的bit7~bit4的占位情况为:1位抢占优先级和3位响应优先级。
    • 中断分组2:AIRCR[10:8] = 101,那么对于IP寄存器的bit7~bit4的占位情况为:2位抢占优先级和2位响应优先级。
    • 中断分组3:AIRCR[10:8] = 100,那么对于IP寄存器的bit7~bit4的占位情况为:3位抢占优先级和1位响应优先级。
    • 中断分组4:AIRCR[10:8] = 011,那么对于IP寄存器的bit7~bit4的占位情况为:4位抢占优先级和0位响应优先级。

  举个例子来说,如果中断分组设置为3,即AIRCR[10:8] = 100,那么STM32的所有可屏蔽中断,每个中断的IP寄存器的bit7~bit5位是抢占优先级,bit4位是响应优先级,每个可屏蔽中断,可以设置为0~7的抢占优先级,0~1的响应优先级。

  需要注意的是SCB的AIRCR寄存具有写保护,需要对SCB的AIRCR寄存的高16位写入0x05FA这个密钥才能修改AIIRCR寄存器。

  抢占优先级和响应优先级的区别:

  抢占优先级别高于响应优先级,而数值越小所代表的优先级就越高。

  如果两个中断的抢占优先级和响应优先级都是一样的,则哪个中断先发生就先执行。

  如果抢占优先级高不一样,那么抢占优先级高的中断可以打断正在进行的抢占优先级比较低的中断。

  如果抢占优先级和响应优先级都相同的话,就根据中断编号来决定谁先执行,中断编号越小,优先级越高。

  如果中断的抢占优先级相同,响应优先级不同的中断是不可以相互打断的。

  举例说明如下:设定中断分组为2,将RTC的中断的抢占优先级设为2,响应优先级设为1。EXTI0的中断的抢占优先级设为3,响应优先级设为0。EXTI1的抢占优先级设为2,响应优先级设为0。因为数值越小所代表的优先级就越高,那么这3个中断的优先级顺序为:EXTI1中断 > RTC中断 >EXTI0中断。EXTI1和RTC中断都可以打断EXTI0中断;而EXTI1和RTC中断却不能相互打断。

5、中断编程

  首先使能某个外设中断,这个具体由每个外设的相关中断使能控制位控制。比如串口由发送完成中断,接收完成中断,这两个中断都是由串口控制寄存器的相关中断使能位控制。

  然后设置中断的分组和中断优先级,关于中断分组,一般只设置一次就好了,设置过后就不再更改,重复设置为同一个组号也可以。

  使能中断,这里使能的是ISER寄存器的中断使能位。

  在HAL库函数中,对NVIC的操作封装在stm32f1xx_hal_cortex.c文件中,其函数的声明如下:

void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup);
void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority);
void HAL_NVIC_EnableIRQ(IRQn_Type IRQn);
void HAL_NVIC_DisableIRQ(IRQn_Type IRQn);
void HAL_NVIC_SystemReset(void);

  HAL_NVIC_SetPriorityGrouping函数是设置中断分组:

  HAL_NVIC_SetPriority函数是设置中断的优先级。IRQn是对应的中断编号;PreemptPriority是设置抢占优先级;SubPriority是设置响应优先级。

  HAL_NVIC_EnableIRQ函数是使能中断,操作的是ISER寄存器。

  HAL_NVIC_DisableIRQ函数是失能中断,操作的是ICER寄存器。

  void HAL_NVIC_SystemReset函数是软件复位操作。

6、中断服务函数

  在STM32的启动文件当中,为每个中断都写了一个中断服务函数,只是启动文件中的终端服务函数都是空的,为的只是初始化中断向量表。实际的中断服务函数都需要重新编写。

  在HAL库中系统异常和中断服务函数一般写在stm32f10x_it.c文件中,当然也可以写在其它文件,但是必须保证不能出现两个文件具有同一个中断服务函数,否者会报错。

  还需要注意的就是中断服务函数的函数名必须跟启动文件里面预先设置的函数名一样,如果不一样,当触发中断时,系统在中断向量表中找不到中断服务函数的入口,就会直接跳转到启动文件里预先写好的空函数,并且在里面循环,造成死机。

7、中断屏蔽功能

  PRIMASK与FAULTMASK特殊功能寄存器

  PRIMASK用于禁止除了NMI和硬fault之外的所有异常和中断。也就是说PRIMASK能禁止中断,可以当做关总中断来使用,但是不能关闭NMI和硬fault的中断。PRIMASK的使用方式如下:

  关闭中断:

  MOV R0,    #1

  MSR PRIMASK, R0

  将1的值写入PRIMASK中,这样就关闭除了NMI和硬fault之外的中断。

  也可以通过CPS指令快速完成关闭中断:

  CPSID i

  开中断:

  MOV R0,    #1

  MSR PRIMASK, R0

  将PRIMASK的值清0,开启中断。

  也可以通过CPS指令快速完成关闭中断:

    CPSIE i

  而FAULTMSK寄存器能直接把当前优先级改为-1,这样一来,连硬fault中断都被屏蔽了,但是FAULTMSK寄存器不能屏蔽NMI中断,而且FAULTMASK会在异常退出时自动清0,FAULTMASK的使用方式如下:

  关闭中断:

  MOV R0,     #1

  MSR FAULTMASK,  R0

  将1的值写入FAULTMASK中,这样就关闭除了NMI之外的中断。

  开中断

  MOV R0, #1

  MSR FAULTMASK, R0

  将FAULTMASK的值清0,开启中断。

  BASEPRI寄存器

  使用BASEPRI寄存器能根据优先级屏蔽部分中断。中断的优先级设置的数值越小,那么优先级就越高,如果将BASEPRI的值设为0x40,优先级设置由于是高4位有效,也就相当于BASEPRI的值设为2,那么低于或等于优先级2的中断教会被屏蔽,即优先级0和优先级1的中断可响应;优先级2、优先级3以及以上的优先级中断将被屏蔽。

  编程如下:

  MOV R0,   #0x40

  MSR BASEPRI,R0

  如果要取消BASEPRI对中断的屏蔽,则如下:

  MOV R0,   #0

  MSR BASEPRI,R0

  系统中表达优先级的位数,也同样影响BASEPRI中有意义的位数。如果系统中只使用3个位来表达优先级,则BASEPRI有意义的值仅为0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0以及0xE0。

原文地址:https://www.cnblogs.com/h1019384803/p/10993140.html

时间: 2024-11-10 09:51:56

STM32F103ZET6的中断管理的相关文章

STM32中断管理函数

CM3 内核支持256 个中断,其中包含了16 个内核中断和240 个外部中断,并且具有256 级的可编程中断设置.但STM32 并没有使用CM3 内核的全部东西,而是只用了它的一部分. STM32 有76 个中断,包括16 个内核中断和60 个可屏蔽中断,具有16 级可编程的中断优先级. 而我们常用的就是这60 个可屏蔽中断,所以我们就只针对这60 个可屏蔽中断进行介绍. 在 MDK 内,与NVIC 相关的寄存器,MDK 为其定义了如下的结构体: typedef struct { vu32 I

stm32 NVIC中断管理实现[直接操作寄存器]

本文转自:http://www.ichanging.org/stm32_NVIC.html cortex-m3支持256个中端,其中包含了16个内核中断,240个外部中断.stm32只有84个中断,包括16个内核中断和68个可屏蔽中断.stm32f103上只有60个中断,f107上才有68个中断. 中断是stm32很基础的一个功能,学会使用中断,才可以更好的使用其他的外设.理解stm32的中断,必须要先从stm32的中断优先级分组是怎么回事.要理解优先级分组,就要先理解什么是先占优先级,和次占优

我理解的windows中断管理

只谈外部中断的windows内核管理,异常和trap不在此文的讨论之列. 1. windows中断总貌 在windows中,物理上的中断源被抽象为KINTERRUPT结构.一个中断源在windows中对应一个KINTERRUPT数组,数组的长度为CPU的个数,如果是单核系统,那么这个数组长度为1.先分析KINTERRUPT结果. windows存储了IDT(Interrupt Descriptor Table),这张表是一个数组结构,数组的下标是Vector号(此Vector不是PIC/APIC

Linux中断管理 (3)workqueue工作队列

目录: <Linux中断管理> <Linux中断管理 (1)Linux中断管理机制> <Linux中断管理 (2)软中断和tasklet> <Linux中断管理 (3)workqueue工作队列> 关键词: 工作队列的原理是把work(需要推迟执行的函数)交由一个内核线程来执行,它总是在进程上下文中执行. 工作队列的优点是利用进程上下文来执行中断下半部操作,因此工作队列允许重新调度和睡眠,是异步执行的进程上下文,它还能解决软中断和tasklet执行时间过长导

linux 中断管理(一)

一.中断作用 Linux 内核需要对连接到计算机上的所有硬件设备进行管理.如果要管理这些设备,首先得和它们互相通信才行. 一般有两种方案可实现这种功能: 轮询(polling) 让内核定期对设备的状态进行查询,然后做出相应的处理: 中断(interrupt) 让硬件在需要的时候向内核发出信号(变内核主动为硬件主动). 使用轮询的方式会占用CPU比较多的时间,效率极低.例如:要读取一个按键有没有被按下时,一个进程需要不断地查询按键有没有被按下.这样这个任务就占用CPU大量得时间,使得CPU做了大量

linux 中断管理(四)

前言: 前面介绍了linux异常处理体系结构.linux中断管理一.linux中断管理二.linux中断管理三.接下来写一篇使用中断的例子.在2440这块开发板里面有四个按键,将四个按键注册为中断方式,然后在应用层上面将四个按键的值读取出来,并且打印出来. 一.中断注册和释放函数 1.中断注册函数 int request_irq(unsigned int irq, irq_handler_t handler,unsigned long irqflags, const char devname,

C语言学习-中断管理总结 2020-3-1

1.异常与中断的概念: 异常:CPU处理器内部运行状态出现紧急状况,需要CPU去处理.例如:硬件错误,指令出错等异常,属于同步异常. 中断:CPU处理器外部运行状态出现紧急状况,需要CPU去处理.例如:外设请求中断以及外部事件输入导致的中断,属于异步异常. 异常与中断的区别:导致异常的事件来源不同,一个是内部事件,一个是外部事件:另一方面,同步异常产生后,处理器必须立马响应,而异步异常产生后,处理器可以选择延缓处理或者不处理. 中断:中断其实就是CPU的常规执行流程被事件打断,迫使CPU进入紧急

μC/OS-Ⅲ系统的中断管理

一.典型的μC/OS-Ⅲ中断服务程序解析 μC/OS-Ⅲ系统中典型有内核参与中断服务程序示例如下: MyISR:                                                                 (1) Disable all interrupts;                                (2) Save the CPU registers;                             (3) OSIntNesti

RTT之内存管理及异常中断

内存管理分静态内存管理和动态内存管理(根据大小又分2种) 静态内存管理:创建.删除.初始化.解绑.申请和释放.初始化内存池是属于静态内存管理,与创建内存池不同的是,此处内存池对象所使用的内存空间是由用户指定的一个缓冲区空间,用户把缓冲区的指针传递给内存池对象控制块,其余的初始化工作与创建内存池相同. 动态内存:在堆heap上分配. 小堆内存管理模块主要针对系统资源比较少(小于2M内存空间的系统):内存池中有不同的内存块,申请时先查找找到符合要求的(拆分),释放时如果紧邻的空闲则合并成一个. 而S