在 PIC 中使用 malloc

电器工程 图片 记忆
2022-01-15 13:01:43

如何在 PIC 中使用malloc()和功能?free()我检查了stdlib.h标题,没有提到它们。我正在使用 MCC18。

有人不得不使用它们吗?

我需要它们,因为我正在将一个库从 Windows XP 移植到 PIC。移植指南说

使操作系统的特定功能适应我的 PIC 功能

但我不知道如何“翻译” malloc()andfree()函数。

4个回答

malloc()在微控制器中通常被认为是“坏事”。但是,如果您绝对需要它,那么您将需要找到第三方版本。

如果幸运的话,您移植的代码可能不依赖于重用内存块。如果是这种情况,您可以编写一个简单的分配器,它将指针返回到 RAM 缓冲区,然后将指针前进请求的块大小。

在将 PC 库移植到微控制器之前,我已经成功地使用过这种方法。

下面,您将使用 设置分配器my_malloc_init()并使用 分配内存my_malloc()my_free()是否可以满足依赖但实际上不会做任何事情。当然,最终你会用完空间。

为了使这项工作发挥作用,您需要测量代码的最坏情况下的内存需求(如果可能,请在 PC 上执行此操作),然后进行HEAP_SIZE相应设置。在进入需要动态内存的库部分之前,调用my_malloc_init(). 在重新使用之前,确保没有任何东西仍然指向heap

uint8_t heap[HEAP_SIZE];
uint8_t *heap_ptr;

void my_malloc_init(void)
{
    heap_ptr = heap;
}

void *my_malloc(size_t len)
{
    uint8_t *p = heap_ptr;
    heap_ptr += len;
    if (heap_ptr >= heap + HEAP_SIZE)
        return NULL;
    else
        return p;
}

void my_free(void)
{
    // do nothing
}

(注意:在现实世界中,您可能需要考虑指针对齐,即向上舍入heap_ptr2 或 4 个字节)

另一种选择是使用比malloc()通常提供的更简单的分配结构,例如FreeList,尽管这可能不允许您分配可变大小的块。

这很难回答您的问题,但是动态内存分配通常不适合小型 RAM 环境并且在没有操作系统的情况下(例如在微控制器世界中)......您在嵌入式环境中可用的堆空间通常是以数百字节为单位...

实现 malloc 和 free 本质上是维护“空闲段”结构的链表,正如您可以想象的那样,与通常可用的内存量相比,与空闲段相关的元数据并不是微不足道的......这就是“开销" 管理动态内存池会消耗大量可用资源。

我不知道 C18 标准库是否支持mallocand free,但Microchip 应用笔记 AN914展示了如何实现自己的。

在任何情况下,Thomas 和其他发帖者都建议,在 PIC 上使用具有非常小的 RAM 空间的动态内存是充满危险的。由于缺乏完整的操作系统为您提供的更高级的虚拟内存管理器,您可能会迅速耗尽连续空间,从而导致分配失败和崩溃。更糟糕的是,它可能不是确定性的,调试起来可能会很痛苦。

如果您正在做的事情是在运行时真正动态确定的(对于大多数嵌入式事物来说很少见),并且您只需要在几个非常特殊的场合分配空间,我可以看到malloc并且free可以接受。

在许多应用程序中,需要分配内存,但不需要释放任何东西,同时保留在它之后分配的东西。在这样的系统上,只需使用链接器使用所有可用 RAM 定义一个数组,设置一个指向该数组开头的指针,然后使用一个简单易用的 malloc 函数:

字符 *next_alloc;
无效 *malloc(int 大小)
{
    字符 *this_alloc;
    this_alloc = next_alloc;
    if ((END_OF_ALLOC_SPACE - this_alloc) < 大小)
      返回-1;
    next_alloc += 大小;
    返回 this_alloc;
}
无效免费(无效*ptr)
{
    如果(指针)
        next_alloc = (char*)ptr;
}

很好也很简单,对于任意数量的分配,总开销只有两个字节。在块上调用 free() 将释放该块及其之后的所有内容。

稍微复杂的分配模式可以通过使用两个指针来处理——一个从内存底部向上分配内容,一个从内存顶部向下分配。如果堆中的数据是同质的并且知道所有外部引用在哪里,也可以使用压缩垃圾收集器。