这个代码我们便是经常定义的一个16字节的buffer。这个buffer是占了空间的,这个空间由我们程序编译时的编译器去进行分配。其在程序的运行过程中buffer的大小及位置是不能进行更改的,这便是“静态”。
根据上面的描述,与之对应的“动态内存”相关的特性我们就可以触类旁通,程序运行过程中的buffer的大小及位置能进行更改的,这便是“动态”。
在C语言中,我们一般会使用 malloc()和 free()动态的分配内存和释放内存。但是我们的MCU是没有MMU(Memory Management Unit)即内存管理单元的,无法实现对内存进行动态映射(这里的知识点较多,大家可以自行百度一下)。一般有以下两个问题:
1. 由于分配算法的复杂度和堆空间的使用情况,分配的时间无法确定;
2. 在大量的申请、释放的过程中,容易因为内存对齐问题而产生碎片化内存;
换句简单的话来说,在MCU上“使用malloc()和 free()来实现动态的分配内存和释放内存”这个做法是存在一定风险的,并不建议日常使用。因为这个缺陷,MCU在使用动态内存分配时的一般解决方法便是自己实现内存管理。
但是,我们使用到的Azure RTOS便有相应的动态内存管理(有现成的内存管理,会用就好),我们便不必自己实现内存管理咯。
4 Azure RTOS的动态内存管理
Azure RTOS的内存管理的相关函数有如下几个:- //分配固定大小的内存块
- UINT tx_block_allocate(
- TX_BLOCK_POOL *pool_ptr,
- VOID **block_ptr,
- ULONG wait_option);
- //创建固定大小内存块的池
- UINT tx_block_pool_create(
- TX_BLOCK_POOL pool_ptr,
- CHAR name_ptr,
- ULONG block_size,
- VOID pool_start,
- ULONG pool_size);
- //删除内存块池
- UINT tx_block_pool_delete(TX_BLOCK_POOL *pool_ptr);
- //检索有关块池的信息
- UINT tx_block_pool_info_get(
- TX_BLOCK_POOL *pool_ptr,
- CHAR **name,
- ULONG *available,
- ULONG *total_blocks,
- TX_THREAD **first_suspended,
- ULONG *suspended_count,
- TX_BLOCK_POOL **next_pool);
- //获取块池性能信息
- UINT tx_block_pool_performance_info_get(
- TX_BLOCK_POOL *pool_ptr,
- ULONG *allocates,
- ULONG *releases,
- ULONG *suspensions,
- ULONG *timeouts));
- //获取块池系统性能信息
- UINT tx_block_pool_performance_system_info_get(
- ULONG *allocates,
- ULONG *releases,
- ULONG *suspensions,
- ULONG *timeouts);
- //设置块池挂起列表的优先级
- UINT tx_block_pool_prioritize(TX_BLOCK_POOL *pool_ptr);
- //释放固定大小的内存块
- UINT tx_block_release(VOID *block_ptr);
涉及了动态内存必备的申请、释放,以及相关内存的信息获取,这部分的信息我们均可从Azure RTOS的手册中看到:[第 4 章 - Azure RTOS ThreadX 服务的说明 | Microsoft Learn](https://learn.microsoft.com/zh-cn/azure/rtos/threadx/chapter4)
5 APM32F4的Azure RTOS 动态内存示例
我们将上次所制作的Examples/ThreadX_Template复制一份出来并改名为ThreadX_Memory_Management,将工程名字也改好。我们将在上次已经做好的示例代码中完成动态内存操作的示例了。
我们将在两个线程内分别完成内存块(Block)的申请与释放操作;内存池(Pool)的申请、释放与信息获取操作。
1. 首先我们需要对内存块及内存池区域进行创建,使用tx_block_pool_create函数:
第一步我们先定义一下内存块及内存池的基本信息:- TX_BLOCK_POOL tx1_block;
- TX_BYTE_POOL tx2_pool;
- uint32_t tx1_block_buffer[1024];
- uint32_t tx2_pool_buffer[1024];
然后线程1完成内存块区域创建:- /* Create a memory block for a fixed size memory unit request */
- tx_block_pool_create(&tx1_block,
- "tx1_block",
- 4, /* Memory unit size */
- (VOID *)tx1_block_buffer, /* The address of a memory block that needs to be 4-byte aligned */
- sizeof(tx1_block_buffer)); /* The size of the memory block is in bytes */
接着在线程2完成内存池区域创建:- /* Creating a memory pool */
- tx_byte_pool_create(&tx2_pool,
- "tx2_pool",
- (VOID *)tx2_pool_buffer, /* Memory pool address, which needs to be 4-byte aligned */
- sizeof(tx2_pool_buffer)); /* The size of the memory pool is in bytes */
2. 第二步,线程1内完成内存块的申请与释放,并打印信息。- /* Apply for memory blocks of 4 bytes each time */
- status = tx_block_allocate(&tx1_block,
- (VOID **)&tx1_block_ptr,
- TX_NO_WAIT);
- if (status == TX_SUCCESS)
- {
- printf("The tx1_block memory block request was successful \r\n");
- }
- status = tx_block_release(tx1_block_ptr);
- if (status == TX_SUCCESS)
- {
- printf("The tx1_block memory block was released successfully \r\n");
- }
3. 最后在线程2内完成内存池的申请、释放及信息查看,并打印相关信息。- status = tx_byte_allocate(&tx2_pool,
- (VOID **)&tx2_pool_ptr,
- 77,
- TX_NO_WAIT);
- if (status == TX_SUCCESS)
- {
- printf("The tx2_pool memory pool application was successful \r\n");
- tx_byte_pool_info_get(&tx2_pool,
- TX_NULL,
- &available,
- TX_NULL,
- TX_NULL,
- TX_NULL,
- TX_NULL);
- printf(" Residual memory pool size : %d bytes \r\n", (int)available);
- }
- status = tx_byte_release(tx2_pool_ptr);
- if (status == TX_SUCCESS)
- {
- printf("The txx2_pool memory pool was released successfully \r\n");
- tx_byte_pool_info_get(&tx2_pool,
- TX_NULL,
- &available,
- TX_NULL,
- TX_NULL,
- TX_NULL,
- TX_NULL);
- printf(" Residual memory pool size : %d bytes \r\n", (int)available);
- }
6 编译与下载
最后我们编译工程,编译结果如下。
然后我们下载程序进板子后,LED2和LED3闪烁,若连接串口可以查看到如下信息:
本次APM32F4基于Azure RTOS动态内存管理的应用过程便到此结束,具体代码请参考:
APM32F4xx_SDK_ThreadX_v0.2.zip
(3.59 MB, 下载次数: 4)
。