您现在的位置是:首页 >其他 >[AI写代码]单片机内存管理网站首页其他
[AI写代码]单片机内存管理
简介[AI写代码]单片机内存管理
单片机stm32f429 HAL 写一个内存管理代码,可动态管理内部内存,也可以管理外部扩展的内存,管理时可能需要选择内存,这个程序会用在ucosiii的任务中
/* mem_manager.h */
#ifndef __MEM_MANAGER_H
#define __MEM_MANAGER_H
#include "stm32f4xx_hal.h"
/* 内存池类型定义 */
typedef enum {
MEM_INTERNAL = 0, // 内部SRAM
MEM_EXTERNAL = 1 // 外部SRAM
} MEM_POOL_TYPE;
/* 内存块状态 */
typedef struct {
uint8_t used; // 使用标志
uint32_t size; // 块大小
} MEM_BLOCK;
/* 内存池配置结构体 */
typedef struct {
uint8_t *memStart; // 内存起始地址
uint32_t totalSize; // 总大小
uint32_t blockSize; // 最小分配单元
uint32_t maxBlocks; // 最大块数
MEM_POOL_TYPE type; // 内存类型
} MEM_POOL_CONFIG;
/* 内存池控制块 */
typedef struct {
MEM_POOL_CONFIG config;
MEM_BLOCK *blocks;
uint8_t *memBase;
uint32_t freeSize;
uint32_t usedBlocks;
} MEM_POOL_CTRL;
/* 函数声明 */
HAL_StatusTypeDef MEM_Init(void);
void* MEM_Alloc(MEM_POOL_TYPE type, uint32_t size);
HAL_StatusTypeDef MEM_Free(void* ptr);
uint32_t MEM_GetFreeSize(MEM_POOL_TYPE type);
void MEM_GetStatus(MEM_POOL_TYPE type, uint32_t *total, uint32_t *used, uint32_t *free);
#endif
/* mem_manager.c */
#include "mem_manager.h"
#include "os.h"
/* 内存池配置 */
#define INTERNAL_MEM_START ((uint8_t*)0x20000000) // 内部SRAM起始地址
#define INTERNAL_MEM_SIZE (128*1024) // 内部SRAM大小
#define EXTERNAL_MEM_START ((uint8_t*)0x68000000) // 外部SRAM起始地址
#define EXTERNAL_MEM_SIZE (1024*1024) // 外部SRAM大小
#define MIN_BLOCK_SIZE 32 // 最小分配单元
/* 内存池控制块定义 */
static MEM_POOL_CTRL internalPool;
static MEM_POOL_CTRL externalPool;
static OS_MUTEX memMutex;
/* 初始化内存池 */
static HAL_StatusTypeDef InitMemPool(MEM_POOL_CTRL *pool, MEM_POOL_CONFIG *config)
{
pool->config = *config;
pool->memBase = config->memStart;
pool->freeSize = config->totalSize;
pool->usedBlocks = 0;
// 分配块管理数组
pool->blocks = (MEM_BLOCK*)config->memStart;
config->memStart += (config->maxBlocks * sizeof(MEM_BLOCK));
config->totalSize -= (config->maxBlocks * sizeof(MEM_BLOCK));
// 初始化所有块
for(uint32_t i = 0; i < config->maxBlocks; i++) {
pool->blocks[i].used = 0;
pool->blocks[i].size = 0;
}
return HAL_OK;
}
/* 内存管理初始化 */
HAL_StatusTypeDef MEM_Init(void)
{
OS_ERR err;
// 创建互斥量
OSMutexCreate(&memMutex, "Memory Mutex", &err);
if(err != OS_ERR_NONE) {
return HAL_ERROR;
}
// 配置内部内存池
MEM_POOL_CONFIG internalConfig = {
.memStart = INTERNAL_MEM_START,
.totalSize = INTERNAL_MEM_SIZE,
.blockSize = MIN_BLOCK_SIZE,
.maxBlocks = INTERNAL_MEM_SIZE / MIN_BLOCK_SIZE,
.type = MEM_INTERNAL
};
// 配置外部内存池
MEM_POOL_CONFIG externalConfig = {
.memStart = EXTERNAL_MEM_START,
.totalSize = EXTERNAL_MEM_SIZE,
.blockSize = MIN_BLOCK_SIZE,
.maxBlocks = EXTERNAL_MEM_SIZE / MIN_BLOCK_SIZE,
.type = MEM_EXTERNAL
};
// 初始化两个内存池
if(InitMemPool(&internalPool, &internalConfig) != HAL_OK) {
return HAL_ERROR;
}
if(InitMemPool(&externalPool, &externalConfig) != HAL_OK) {
return HAL_ERROR;
}
return HAL_OK;
}
/* 内存分配 */
void* MEM_Alloc(MEM_POOL_TYPE type, uint32_t size)
{
OS_ERR err;
MEM_POOL_CTRL *pool;
void *ptr = NULL;
// 选择内存池
pool = (type == MEM_INTERNAL) ? &internalPool : &externalPool;
// 对齐大小到块大小
size = (size + pool->config.blockSize - 1) & ~(pool->config.blockSize - 1);
// 获取互斥量
OSMutexPend(&memMutex, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
if(err != OS_ERR_NONE) {
return NULL;
}
// 查找可用块
for(uint32_t i = 0; i < pool->config.maxBlocks; i++) {
if(!pool->blocks[i].used && pool->blocks[i].size >= size) {
pool->blocks[i].used = 1;
pool->blocks[i].size = size;
pool->usedBlocks++;
pool->freeSize -= size;
// 计算返回指针
ptr = (void*)(pool->memBase + (i * pool->config.blockSize));
break;
}
}
// 释放互斥量
OSMutexPost(&memMutex, OS_OPT_POST_NONE, &err);
return ptr;
}
/* 内存释放 */
HAL_StatusTypeDef MEM_Free(void* ptr)
{
OS_ERR err;
MEM_POOL_CTRL *pool;
uint32_t blockIndex;
// 检查指针是否在内部内存范围内
if(ptr >= (void*)INTERNAL_MEM_START &&
ptr < (void*)(INTERNAL_MEM_START + INTERNAL_MEM_SIZE)) {
pool = &internalPool;
}
// 检查指针是否在外部内存范围内
else if(ptr >= (void*)EXTERNAL_MEM_START &&
ptr < (void*)(EXTERNAL_MEM_START + EXTERNAL_MEM_SIZE)) {
pool = &externalPool;
}
else {
return HAL_ERROR;
}
// 计算块索引
blockIndex = ((uint8_t*)ptr - pool->memBase) / pool->config.blockSize;
// 获取互斥量
OSMutexPend(&memMutex, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
if(err != OS_ERR_NONE) {
return HAL_ERROR;
}
// 释放块
if(pool->blocks[blockIndex].used) {
pool->freeSize += pool->blocks[blockIndex].size;
pool->blocks[blockIndex].used = 0;
pool->blocks[blockIndex].size = 0;
pool->usedBlocks--;
}
// 释放互斥量
OSMutexPost(&memMutex, OS_OPT_POST_NONE, &err);
return HAL_OK;
}
/* 获取剩余内存大小 */
uint32_t MEM_GetFreeSize(MEM_POOL_TYPE type)
{
return (type == MEM_INTERNAL) ? internalPool.freeSize : externalPool.freeSize;
}
/* 获取内存使用状态 */
void MEM_GetStatus(MEM_POOL_TYPE type, uint32_t *total, uint32_t *used, uint32_t *free)
{
MEM_POOL_CTRL *pool = (type == MEM_INTERNAL) ? &internalPool : &externalPool;
if(total) *total = pool->config.totalSize;
if(used) *used = pool->config.totalSize - pool->freeSize;
if(free) *free = pool->freeSize;
}
需要注意的事项:
- 需要根据实际的STM32F429配置修改内存起始地址和大小
- 最小分配单元(MIN_BLOCK_SIZE)可以根据需求调整
- 确保在使用外部SRAM之前已经正确初始化了外部SRAM
// 初始化内存管理
MEM_Init();
// 在内部内存中分配100字节
void* ptr1 = MEM_Alloc(MEM_INTERNAL, 100);
// 在外部内存中分配200字节
void* ptr2 = MEM_Alloc(MEM_EXTERNAL, 200);
// 释放内存
MEM_Free(ptr1);
MEM_Free(ptr2);
// 获取内存使用情况
uint32_t total, used, free;
MEM_GetStatus(MEM_INTERNAL, &total, &used, &free);
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。