ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

RT-Thread 堆区大小设置

2022-06-30 15:32:45  阅读:160  来源: 互联网

标签:RT rt RW Thread 堆区 __ void define


一、利用栈区的空间作为堆区

看过我之前的笔记的小伙伴都知道,以前我是通过申请栈区的空间使用的,感兴趣的小伙伴可以看我之前的笔记,RT-Thread移植到stm32

在board.c文件文件中的代码如下所示:

#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
#define RT_HEAP_SIZE 1024
static uint32_t rt_heap[RT_HEAP_SIZE];     // heap default size: 4K(1024 * 4)
RT_WEAK void *rt_heap_begin_get(void)
{
    return rt_heap;
}

RT_WEAK void *rt_heap_end_get(void)
{
    return rt_heap + RT_HEAP_SIZE;
}
#endif

从上面的代码中可以看出,申请了一个栈空间rt_heap数组,大小为4K。但是这样在使用RT-Thread堆内存的时候就不太友好了。缺点如下:

  • 堆内存大小是固定的,使得RT-Thread系统没有最大化的利用STM32的内存空间。

  • 在RT-Thread的堆内存中使用了相应的内存算法,容易造成内存碎片化。,所以应将栈剩余的空间全部用于堆内存使用,有关算法可以看RT-Thread内存管理

  • 发生堆栈溢出的时候,不利于问题的查找。

所以我们使用的时候,应该获取堆区与栈区的内存分界地址,以便于给RT-Thread的堆内存使用。

二、STM32内存知识

在获取堆内存与栈内存之前,我们需要简单的理解STM32的内存知识,如果想了解更详细的内容,可以看我之前的笔记,STM32内存知识

  • code:代码存储区,存放函数体的二进制代码
  • Ro-data:只读数据存储区,存放字常量数据类型(如const类型)程序结束后有系统自动释放
  • RW-data:初始化可读写变量的大小,程序结束后由系统自动释放。
  • ZI-data:没有初始化的可读写变量大小,程序结束后由系统自动释放。
  • heap:堆区,一般由程序员分配释放,若程序员不释放,程序结束时可能由OS释放。
  • stack:栈区,由编译器自动分配释放,存放函数的参数值,局部变量的值等。
  • RO Size:包含Code及RO Data,表示只读数据占用Flash空间的大小。
  • RW Size:包含RW Data及ZI Data,表示运行时占用的RAM的大小。
  • ROM Size包含Code,RO Data及RW Data,表示烧写程序所占用的Flash的大小。
  1. STM32程序运行的流程。如下图所示:

  2. 栈向下生长,内存地址由高至低;堆向上,内存地址由低至高,堆栈之间没有固定的界限,如下图所示:

从上面两点可以看出来,RAM是包含堆区和栈区,而堆区与栈区没有明确的界限,所以内存中没有使用的栈空间都可以申请为堆内存。我们只需要找出栈空间接结束地址,也是ZI段和结束地址即可。

三、获取栈空间的结束地址

因为不同编译器的内存标识不一样,所以需要注意一下不同环境下的获取方式。

  1. MDK环境下,栈结束地址的获取,如下所示:

    extern unsigned char Image$$ER_IROM1$$Limit;       // 获取RW段在FLASH中的加载地址
    extern unsigned char Image$$RW_IRAM1$$Base;        // 获取RW段在RAM中的运行地址    
    extern unsigned char Image$$RW_IRAM1$$RW$$Limit;   // 获取RW段在RAM中的结束地址
    extern unsigned char Image$$RW_IRAM1$$ZI$$Limit;   // 获取ZI段在RAM中的结束地址
    

    所以在MDK中只需要使用Image$$RW_IRAM1$$ZI$$Limit链接便可获得栈空间的结束地址,如下所示:

    extern int Image$$RW_IRAM1$$ZI$$Limit;
    #define HEAP_BEGIN      ((void *)&Image$$RW_IRAM1$$ZI$$Limit)
    
    
  2. IAR环境下,栈结束地址的获取,如下所示:

    #pragma section="CSTACK"
    #define HEAP_BEGIN      (__segment_end("CSTACK"))
    
  3. GCC环境下,栈结束地址的获取,如下所示:

    extern int __bss_end;
    #define HEAP_BEGIN      ((void *)&__bss_end)
    

四、RT-Thread程序更改

只需要在 board.h 文件中定义相关宏即可,然后修改 board.c 文件中rt_system_heap_init函数 的内存获取地址。

board.h 文件

/*
 * Change Logs:
 * Date           Author      
 * 2022-06-29     jiaozhu 
 */
 
#ifndef __BOARD_H__
#define __BOARD_H__

#include "stm32f10x.h"
#include "drv_gpio.h"
#include "drv_usart.h"

#ifdef __cplusplus
extern "C"
{
#endif	
	
/*-------------------------- ROM/RAM CONFIG BEGIN --------------------------*/

#define ROM_START              ((uint32_t)0x08000000)
#define ROM_SIZE               (64 * 1024)
#define ROM_END                ((uint32_t)(ROM_START + ROM_SIZE))

#define RAM_START              (0x20000000)
#define RAM_SIZE               (20 * 1024)
#define RAM_END                (RAM_START + RAM_SIZE)	
	
#define STM32_SRAM1_END                RAM_END	
	
/*--------------------------     GET HEAP SIZE    --------------------------*/
#if defined(__CC_ARM) || defined(__CLANG_ARM)
extern int Image$$RW_IRAM1$$ZI$$Limit;
#define HEAP_BEGIN      ((void *)&Image$$RW_IRAM1$$ZI$$Limit)
#elif __ICCARM__
#pragma section="CSTACK"
#define HEAP_BEGIN      (__segment_end("CSTACK"))
#else
extern int __bss_end;
#define HEAP_BEGIN      ((void *)&__bss_end)
#endif

#define HEAP_END                       STM32_SRAM1_END
	
#ifdef __cplusplus
}
#endif

#endif /* __BOARD_H__ */	

board.C 文件

/*
 * Copyright (c) 2006-2019, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2017-07-24     Tanek        the first version
 * 2018-11-12     Ernest Chen  modify copyright
 */
 
#include <rtthread.h>
#include <board.h>

#define _SCB_BASE       (0xE000E010UL)
#define _SYSTICK_CTRL   (*(rt_uint32_t *)(_SCB_BASE + 0x0))
#define _SYSTICK_LOAD   (*(rt_uint32_t *)(_SCB_BASE + 0x4))
#define _SYSTICK_VAL    (*(rt_uint32_t *)(_SCB_BASE + 0x8))
#define _SYSTICK_CALIB  (*(rt_uint32_t *)(_SCB_BASE + 0xC))
#define _SYSTICK_PRI    (*(rt_uint8_t  *)(0xE000ED23UL))

// Updates the variable SystemCoreClock and must be called 
// whenever the core clock is changed during program execution.
extern void SystemCoreClockUpdate(void);

// Holds the system core clock, which is the system clock 
// frequency supplied to the SysTick timer and the processor 
// core clock.
extern uint32_t SystemCoreClock;

void STM32F10x_peripheral_init(void)
{		
	// Initialize serial port
	USART1_Config();
	// Initialize LED
	LED_GPIO_Config();	
}

static uint32_t _SysTick_Config(rt_uint32_t ticks)
{
    if ((ticks - 1) > 0xFFFFFF)
    {
        return 1;
    }
    
    _SYSTICK_LOAD = ticks - 1; 
    _SYSTICK_PRI = 0xFF;
    _SYSTICK_VAL  = 0;
    _SYSTICK_CTRL = 0x07;
    
    return 0;
}

/**
 * This function will initial your board.
 */
void rt_hw_board_init()
{
	
	STM32F10x_peripheral_init();
	
    /* System Clock Update */
    SystemCoreClockUpdate();
    
    /* System Tick Configuration */
    _SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);

#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
    rt_system_heap_init((void *) HEAP_BEGIN, (void *) HEAP_END);
#endif
	
    /* Set the shell console output device */
#if defined(RT_USING_DEVICE) && defined(RT_USING_CONSOLE)
    rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif	
	
	/* Board underlying hardware initialization */
#ifdef RT_USING_COMPONENTS_INIT
    rt_components_board_init();
#endif
	
}

void SysTick_Handler(void)
{
    /* enter interrupt */
    rt_interrupt_enter();

    rt_tick_increase();

    /* leave interrupt */
    rt_interrupt_leave();
}

五、堆区和栈区的空间使用查看

  1. 栈空间的使用情况查看

    因为栈空间的管理直接是由编译管理的,所以编译完成后直接可以看到编译器查看(这里以MDK环境为例),如下图所示:

    从图中可知,栈空间的使用等于208+3448(字节)。

  2. 堆空间的使用情况查看

    在RT-Thread 有相应内存管理算法,也提供了堆内存是查看方式,所以只需要在 FinSH 中使用 free 指令查看即可,如下图所示,对于 FinSH 不了解的小伙伴,可以查看STM32 移植 RT-Thread 标准版的 FinSH 组件

参考文献

STM32链接脚本详解:https://blog.csdn.net/qq_27575841/article/details/104373417

标签:RT,rt,RW,Thread,堆区,__,void,define
来源: https://www.cnblogs.com/jzcn/p/16427067.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有