您现在的位置是:首页 >其他 >[AI写代码]单片机内存管理网站首页其他

[AI写代码]单片机内存管理

zd845101500 2025-03-21 12:01:03
简介[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;
}

需要注意的事项:

  1. 需要根据实际的STM32F429配置修改内存起始地址和大小
  2. 最小分配单元(MIN_BLOCK_SIZE)可以根据需求调整
  3. 确保在使用外部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);

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。