0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

使用MM32F3270基于Azure RTOS动态内存管理的应用

灵动MM32MCU 来源:灵动MM32MCU 2022-12-23 11:01 次阅读

简 介

Azure RTOS ThreadX 是 Microsoft 提供的高级工业级实时操作系统 (RTOS)。它是专门为深度嵌入式实时 IoT 应用程序设计的。Azure RTOS ThreadX 提供高级计划、通信、同步、计时器、内存管理和中断管理功能。此外,Azure RTOS ThreadX 具有许多高级功能,包括 picokernel 体系结构、preemption-threshold 计划、event-chaining、执行分析、性能指标和系统事件跟踪。Azure RTOS ThreadX 非常易于使用,适用于要求极其苛刻的嵌入式应用程序。Azure RTOS ThreadX 在各种产品(包括消费者设备、医疗电子设备和工业控制设备)上的部署次数已达数十亿次。

在前文描述移植基本内核的基础上,该应用手册描述了MM32F3270系列MCU结合Azure RTOS ThreadX内存池的使用,引导用户理解Azure RTOS ThreadX动态内存管理功能。

表 1 适用系列型号

系列 芯片型号 开发板
MM32F3270 MM32F3273G9P EVB-F3270

1移植应用的准备

1.1 硬件开发板的准备

该移植过程中应用的开发板为MM32的EVB-F3270,板载MM32F3273G9P。

f6ae7fdc-81fb-11ed-8abf-dac502259ad0.png

EVB-F3270 (MM32F3273G9P) 的简要参数

Arm Cortex-M3 内核

板载 MM32F3273G9P(LQFP144)

USB Host / Device、SPI、I2C

4 x Key、4 x LED

I2S Speaker

TF-Card

Ethernet PHY

1.2 软件的准备

库函数和例程(Lib Samples)

该移植过程中应用的 Firmware 分别为 MM32F3270 库函数和例程。

f6d63676-81fb-11ed-8abf-dac502259ad0.png    

Azure RTOS ThreadX(源码)

ThreadX 的源代码已经开放,我们可以从 ThreadX 公共源代码存储库获取 Azure RTOS ThreadX,网址为:

https://github.com/azure-rtos/threadx/

Azure RTOS 何时需要许可证?

Microsoft 将 Azure RTOS 源代码发布到 GitHub。安装和使用该软件进行内部开发、测试和评估无需许可证。分发或销售组件和设备需要许可证,除非使用 Azure RTOS 许可的硬件。

ThreadX 安装

可以通过将 GitHub 存储库克隆到本地计算机来安装 ThreadX。下面是用于在 PC 上创建 ThreadX 存储库的克隆的典型语法。

shell复制

git clone https://github.com/azure-rtos/threadx

或者,也可以使用 GitHub 主页上的“下载”按钮来下载存储库的副本。

下载后的仓库代码目录列表如下:

f6e7f082-81fb-11ed-8abf-dac502259ad0.png    

Azure RTOS ThreadX(源码)支持的开发环境

ThreadX 内核提供好了各种主流硬件平台和软件平台的移植文件,以Cortex_M3为例,可以支持以下六种开发环境:

f6f5f16e-81fb-11ed-8abf-dac502259ad0.png

本次移植过程使用Azure RTOS原有的sample_threadx.c文件为例,稍作修改,演示动态内存管理功能。

2ThreadX 动态内存管理的应用

该章节介绍动态内存管理相关知识,演示程序可在MM32F3273G9P的EVB-F3270上运行。此示例在文件 main_malloc_demo.c 中实现,旨在说明如何在嵌入式多线程环境中使用动态内存管理功能。

2.1 动态内存管理

2.1.1 内存块池

在实时应用程序中,采用快速且确定的方式分配内存始终是一项挑战。考虑到这一点,ThreadX 提供了创建和管理多个固定大小的内存块池的功能。

由于内存块池由固定大小的块组成,因此永远不会出现任何碎片问题。当然,碎片会导致出现本质上不确定的行为。此外,分配和释放固定大小内存块所需的时间与简单的链接列表操作所需的时间相当。另外,还可以在可用列表的开头完成内存块分配和取消分配。这可以提供最快的链接列表处理速度,并且有助于将实际的内存块保存在缓存中。

缺乏灵活性是固定大小内存池的主要缺点。池的块大小必须足够大,才能处理其用户最坏情况下的内存需求。当然,如果对同一个池发出了许多大小不同的内存请求,则可能会浪费内存。一种可能的解决方案是创建多个不同的内存块池,这些池包含不同大小的内存块。

每个内存块池都是一个公用资源。ThreadX 对如何使用池没有任何限制。

2.1.1 创建内存块池

内存块池由应用程序线程在初始化期间或运行时创建。应用程序中内存块池的数量没有限制。

2.1.3 内存块大小

如前所述,内存块池包含许多固定大小的块。块大小(以字节为单位)在创建池时指定。

ThreadX 为池中的每个内存块增加了少量开销(C 指针的大小)。此外,ThreadX 可能需要填充块大小,从而确保每个内存块的开头能够正确对齐。

2.1.4 池容量

池中的内存块数是在创建过程中提供的内存区域的块大小和总字节数的函数。池容量的计算方法是将块大小(包括填充和指针开销字节)除以提供的内存区域的总字节数。

2.1.5 池的内存区域

如前所述,块池的内存区域在创建时指定。与 ThreadX 中的其他内存区域一样,该区域可以位于目标地址空间的任何位置。

这是一项重要的功能,因为它提供了相当大的灵活性。例如,假设某个通信产品有一个用于 I/O 的高速内存区域。将此内存区域设置为 ThreadX 内存块池,即可轻松对其进行管理。

2.1.6 线程挂起

在等待空池中的内存块时,应用程序线程可能会挂起。当块返回到池时,将为挂起的线程提供此块,并恢复线程。

如果同一内存块池中挂起多个线程,这些线程将按挂起的顺序 (FIFO) 恢复。

不过,如果应用程序在取消线程挂起的块释放调用之前调用 tx_block_pool_prioritize,还可以恢复优先级。块池设置优先级服务将优先级最高的线程置于挂起列表的前面,让所有其他挂起的线程采用相同的 FIFO 顺序。

2.1.7 运行时块池性能信息

ThreadX 提供可选的运行时块池性能信息。如果 ThreadX 库和应用程序是在定义 TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO 的情况下生成的,ThreadX 会累积以下信息。

整个系统的总数:

已分配的块数

已释放的块数

分配挂起数

分配超时数

每个块池的总数:

已分配的块数

已释放的块数

分配挂起数

分配超时数

此信息在运行时通过 tx_block_pool_performance_info_get和 tx_block_pool_performance_system_info_get服务提供。块池性能信息在确定应用程序是否正常运行时非常有用。此信息对于优化应用程序也很有用。例如,“分配挂起数”相对较高可能表明块池太小。

2.1.8 内存块池控制块 TX_BLOCK_POOL

每个内存块池的特征都可在其控制块中找到。该控制块包含诸如可用的内存块数和内存池块大小等信息。此结构在 tx_api.h文件中定义。

池控制块也可以位于内存中的任意位置,但最常见的是通过在任何函数的作用域外部定义该控件块来使其成为全局结构。

2.1.9 覆盖内存块

务必确保已分配内存块的用户不会在其边界之外写入。如果发生这种情况,则会损坏其相邻的内存区域(通常是后续区域)。结果不可预测,且对于应用程序来说通常很严重。

2.1.10 内存字节池

内存字节池由应用程序线程在初始化期间或运行时创建。应用程序中内存字节池的数量没有限制。

2.1.12 池容量

内存字节池中可分配的字节数略小于创建期间指定的字节数。这是因为可用内存区域的管理带来了一些开销。池中的每个可用内存块都需要相当于两个 C 指针的开销。此外,创建的池包含两个块:一个较大的可用块和在内存区域末端永久分配的一个较小的块。这个分配块用于提高分配算法的性能。这样就无需在合并期间持续检查池区域末端。

在运行时,池中的开销通常会增加。如果分配奇数字节数,系统会加以填充,以确保正确对齐下一个内存块。此外,随着池变得更加零碎,开销也会增加。

2.1.13 池的内存区域

内存字节池的内存区域在创建过程中指定。与 ThreadX 中的其他内存区域一样,该区域可以位于目标地址空间的任何位置。这是一项重要的功能,因为它提供了相当大的灵活性。例如,如果目标硬件有高速内存区域和低速内存区域,用户可以通过在每个区域中创建池来管理这两个区域的内存分配。

2.1.14 线程挂起

在等待池中的内存字节时,应用程序线程可能会挂起。当有足够的连续内存可用时,将为已挂起的线程提供其请求的内存,并且恢复线程。

如果同一内存字节池中挂起多个线程,则按这些线程挂起的顺序 (FIFO) 为其提供内存(恢复)。

不过,如果应用程序在信号灯发出取消线程挂起的字节释放调用之前调用 tx_byte_pool_prioritize,还可以恢复优先级。字节池设置优先级服务将最高优先级的线程置于挂起列表的前面,让所有其他挂起的线程采用相同的 FIFO 顺序。

2.1.15 运行时字节池性能信息

ThreadX 提供可选的运行时字节池性能信息。如果 ThreadX 库和应用程序是在定义 TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO 的情况下生成的,ThreadX 会累积以下信息。

整个系统的总数:

分配数

版本

搜索的片段数

合并的片段数

创建的片段数

分配挂起数

分配超时数

每个字节池的总数:

分配数

版本

搜索的片段数

合并的片段数

创建的片段数

分配挂起数

分配超时数

此信息在运行时通过 tx_byte_pool_performance_info_get和 tx_byte_pool_performance_system_info_get 服务提供。字节池性能信息在确定应用程序是否正常运行时非常有用。此信息对于优化应用程序也很有用。例如,“分配挂起数”相对较高可能表明字节池太小。

2.1.16 内存字节池控制块 TX_BYTE_POOL

每个内存字节池的特征都可在其控制块中找到。该控制块包含诸如池中可用的字节数等有用的信息。此结构在 tx_api.h 文件中定义。

池控制块也可以位于内存中的任意位置,但最常见的是通过在任何函数的作用域外部定义该控件块来使其成为全局结构。

2.1.17 非确定性行为

尽管内存字节池提供了最灵活的内存分配,但这些池也受一些非确定性行为的影响。例如,内存字节池可能有 2,000 字节的可用内存,但可能无法满足 1,000 字节的分配请求。这是因为无法保证有多少可用字节是连续的。即使存在 1,000 字节可用块,也不能保证找到此块需要多长时间。完全有可能需要搜索整个内存池来查找这个 1,000 字节块。

由于内存字节池的不确定性行为,通常应避免在需要确定性实时行为的区域中使用内存字节服务。许多应用程序在初始化或运行时配置期间预先分配其所需的内存。

2.1.18 覆盖内存块

务必确保已分配内存的用户不会在其边界之外写入。如果发生这种情况,则会损坏其相邻的内存区域(通常是后续区域)。结果不可预测,且对于程序执行来说通常是灾难性的。

2.2 Azure ThreadX 动态内存管理的相关函数

tx_block_allocate分配固定大小的内存块

UINTtx_block_allocate(
TX_BLOCK_POOL*pool_ptr,
VOID**block_ptr,
ULONGwait_option);

说明

此服务从指定的内存池中分配固定大小的内存块。内存块的实际大小是在创建内存池的过程中确定的参数。

pool_ptr:指向之前创建的内存块池的指针。

block_ptr:指向目标块指针的指针。成功分配时,已分配内存块的地址就位于此参数所指向的位置。

wait_option:定义此服务在没有可用的内存块时的行为方式。等待选项的定义如下:

TX_NO_WAIT (0x00000000)

如果选择 TX_NO_WAIT,则无论此服务是否成功,都会导致立即从此服务返回 。如果从非线程(例如初始化、计时器或 ISR)调用服务,则这是唯一有效的选项。

TX_WAIT_FOREVER (0xFFFFFFF)

选择 TX_WAIT_FOREVER 会导致发出调用的线程无限期挂起,直到内存块可用为止 。

超时值(0x00000001 至 0xFFFFFFFE)

如果选择一个数值(1 到 0xFFFFFFFE),则会指定在等待内存块时发出调用的线程保持挂起的最大计时器时钟周期数。

返回值

TX_SUCCESS (0x00) 成功分配内存块。

TX_DELETED (0x01) 线程挂起时删除了内存块池。

TX_NO_MEMORY (0x10) 服务无法在指定的等待时间内分配内存块。

TX_WAIT_ABORTED (0x1A) 挂起状态由其他线程、计时器或 ISR 中止。

TX_POOL_ERROR:(0x02) 内存块池指针无效。

TX_WAIT_ERROR:(0x04) 从非线程调用时指定了除 TX_NO_WAIT 以外的等待选项。

TX_PTR_ERROR:(0x03) 指向目标指针的指针无效。

示例

TX_BLOCK_POOLmy_pool;
unsignedchar*memory_ptr;

UINTstatus;

/*Allocateamemoryblockfrommy_pool.Assumethatthepoolhas
alreadybeencreatedwithacalltotx_block_pool_create.*/

status=tx_block_allocate(&my_pool,(VOID**)&memory_ptr,
TX_NO_WAIT);

/*IfstatusequalsTX_SUCCESS,memory_ptrcontainstheaddressof
theallocatedblockofmemory.*/

另请参阅

tx_block_pool_create

tx_block_pool_delete

tx_block_pool_info_get

tx_block_pool_performance_info_get

tx_block_pool_performance_system_info_get

tx_block_pool_prioritize

tx_block_release

tx_byte_allocate

tx_byte_pool_create

tx_byte_pool_delete

tx_byte_pool_info_get

tx_byte_pool_performance_info_get

tx_byte_pool_performance_system_info_get

tx_byte_pool_prioritize

tx_byte_release

2.3 动态内存管理的应用演示

2.3.1 工程目录的建立

打开目标工程文件夹“MM32F3270Project”:

f7045812-81fb-11ed-8abf-dac502259ad0.png

移除原有样例.c 文件sample_threadx.c:

f7187b4e-81fb-11ed-8abf-dac502259ad0.png

参考sample_threadx.c建立main_malloc_demo.c文件,并添加hardware目录中的led.c、key.c到工程项目中。

f72d8b9c-81fb-11ed-8abf-dac502259ad0.png

注意:

需要在delay.c中配置USE_SYSTICK_DELAY 为 0。

#define USE_SYSTICK_DELAY 0

3ThreadX 的内存管理应用

创建如下几个任务:

LED1闪烁指示当前系统运行。

按键(K1、K2、K3、K4)按下,对应的事件标志置位:

获取事件标志,执行处理程序:

K1按下,从指定的内存块池中申请固定大小的内存块

K2按下,将以前分配的内存块释放回其关联的内存池

K3按下,从指定的内存字节池中分配指定的字节数

K4按下,将以前分配的内存字节数释放回其关联的内存池

打印内存池信息

3.1 代码实现

下载调试默认会运行到main()函数,如下为全部实现的代码。

Demo演示代码

/*Thisisasmalldemoofthehigh-performanceThreadXkernel.Itincludesexamplesofsix
threadsofdifferentpriorities,usingamessagequeue,semaphore,andaneventflagsgroup.*/

#include"tx_api.h"
#include"delay.h"
#include"led.h"
#include"key.h"
#include"uart.h"

#defineDEMO_STACK_SIZE1024

#defineTHREAD0_PRIORITY1
#defineTHREAD0_PREEMPTION_THRESHOLD1
#defineTHREAD1_PRIORITY2
#defineTHREAD1_PREEMPTION_THRESHOLD2

#defineTHREAD5_PRIORITY4
#defineTHREAD5_PREEMPTION_THRESHOLD4
//#defineTHREAD5_PREEMPTION_THRESHOLD_NEW0


#defineBIT_0((ULONG)0x0000001)
#defineBIT_1((ULONG)0x0000002)
#defineBIT_2((ULONG)0x0000004)
#defineBIT_3((ULONG)0x0000008)
#defineBIT_ALL(BIT_0|BIT_1|BIT_2|BIT_3)

/*DefinetheThreadXobjectcontrolblocks...*/
TX_THREADthread_0;
TX_THREADthread_1;

TX_THREADthread_5;

TX_EVENT_FLAGS_GROUPEventGroup;

TX_BLOCK_POOLMyBlock;
TX_BYTE_POOLMyByte;

/*Definethecountersusedinthedemoapplication...*/
ULONGthread_0_counter;
ULONGthread_1_counter;

ULONGthread_5_counter;

/*Definethethreadstacks.*/
UCHARthread_0_stack[DEMO_STACK_SIZE];
UCHARthread_1_stack[DEMO_STACK_SIZE];

UCHARthread_5_stack[DEMO_STACK_SIZE];

/*Definethreadprototypes.*/

voidthread_0_entry(ULONGthread_input);
voidthread_1_entry(ULONGthread_input);

voidthread_5_entry(ULONGthread_input);


volatileunsignedintbootloop;


uint32_tMyBlockBuf[1024];
uint32_tMyByteBuf[1024];



voidSystem_Init(void);
voidAppThreadCreate(void);
voidAppModuleCreate(void);


/*Definemainentrypoint.*/

intmain()
{
System_Init();

/*EntertheThreadXkernel.*/
tx_kernel_enter();
}


/*Definewhattheinitialsystemlookslike.*/

voidtx_application_define(void*first_unused_memory)
{
AppThreadCreate();
AppModuleCreate();

}

voidSystem_Init(void)
{
DELAY_Init();//cannotusesystick
LED_Init();
KEY_Init();
CONSOLE_Init(115200);
printf("!!!Start!!!
");

}

voidAppThreadCreate(void)
{
/*Createthread0.*/
tx_thread_create(
&thread_0,
"thread0",
thread_0_entry,
0,
thread_0_stack,
DEMO_STACK_SIZE,
THREAD0_PRIORITY,
THREAD0_PREEMPTION_THRESHOLD,
TX_NO_TIME_SLICE,
TX_AUTO_START);

/*Createthread1.*/
tx_thread_create(
&thread_1,
"thread1",
thread_1_entry,
0,
thread_1_stack,
DEMO_STACK_SIZE,
THREAD1_PRIORITY,
THREAD1_PREEMPTION_THRESHOLD,
TX_NO_TIME_SLICE,
TX_AUTO_START);


/*Createthread5.*/
tx_thread_create(
&thread_5,
"thread5",
thread_5_entry,
5,
thread_5_stack,
DEMO_STACK_SIZE,
THREAD5_PRIORITY,
THREAD5_PREEMPTION_THRESHOLD,
TX_NO_TIME_SLICE,
TX_AUTO_START);

}

voidAppModuleCreate(void)
{
/*Createsamemoryblockforapplyingforafixed-sizememoryunit*/
tx_block_pool_create(&MyBlock,
"MyBlock",
4,/*Thesizeofthememoryunit*/
(VOID*)MyBlockBuf,/*Memoryblockaddress,ensure4-bytealignment*/
sizeof(MyBlockBuf));/*Memoryblocksize,inbytes*/
/*Createamemorypool*/
tx_byte_pool_create(&MyByte,
"MyByte",
(VOID*)MyByteBuf,/*Memorypooladdress,ensure4-bytealignment*/
sizeof(MyByteBuf));/*Memorypoolsize*/
/*Createaneventflaggroup*/
tx_event_flags_create(&EventGroup,"EventGroupName");
}


/*Definethetestthreads.*/
voidthread_0_entry(ULONGthread_input)
{
/*ThisthreadsimplycontrolsLEDflashingtoindicatethatthesystemisrunning*/
while(1)
{
/*Incrementthethreadcounter.*/
thread_0_counter++;

LED1_TOGGLE();

/*Sleepfor300ticks.*/
tx_thread_sleep(300);

}
}

voidthread_1_entry(ULONGthread_input)
{
UCHAR*BlockPtr;
UCHAR*BytePtr;
ULONGavailable;

ULONGactual_events;
UINTstatus;

while(1)
{
/*Incrementthethreadcounter.*/
thread_1_counter++;
status=tx_event_flags_get(&EventGroup,
BIT_ALL,
TX_OR_CLEAR,
&actual_events,
TX_WAIT_FOREVER);
if(status==TX_SUCCESS)
{
switch(actual_events)
{
caseBIT_0:
/*Applyformemoryblocksof4byteseachtime*/
status=tx_block_allocate(&MyBlock,
(VOID**)&BlockPtr,
TX_NO_WAIT);
if(status==TX_SUCCESS)
{
printf("Succeededinapplyingforamemoryblock.
");
tx_block_pool_info_get(&MyBlock,
TX_NULL,
&available,
TX_NULL,
TX_NULL,
TX_NULL,
TX_NULL);
printf("NumberofblocksavailableinMyBlock=%d
",(int)available);
}
break;
caseBIT_1:
status=tx_block_release(BlockPtr);
if(status==TX_SUCCESS)
{
printf("Thememoryblockwasreleasedsuccessfully.
");
tx_block_pool_info_get(&MyBlock,
TX_NULL,
&available,
TX_NULL,
TX_NULL,
TX_NULL,
TX_NULL);
printf("NumberofblocksavailableinMyBlock=%d
",(int)available);
}
break;
caseBIT_2:
/*Applyforamemorybytepool,specifying100bytes*/
status=tx_byte_allocate(&MyByte,
(VOID**)&BytePtr,
100,
TX_NO_WAIT);
if(status==TX_SUCCESS)
{
printf("Succeededinapplyingforthememorybytepool.
");
tx_byte_pool_info_get(&MyByte,
TX_NULL,
&available,
TX_NULL,
TX_NULL,
TX_NULL,
TX_NULL);
printf("TheavailableMyBytesize=%dbytes.
",(int)available);
}
break;
caseBIT_3:
status=tx_byte_release(BytePtr);
if(status==TX_SUCCESS)
{
printf("Thememorybytepoolwasreleasedsuccessfully.
");
tx_byte_pool_info_get(&MyByte,
TX_NULL,
&available,
TX_NULL,
TX_NULL,
TX_NULL,
TX_NULL);
printf("TheavailableMyBytesize=%dbytes.
",(int)available);
}
break;
default:
break;
}

}
}
}


voidthread_5_entry(ULONGthread_input)
{
UCHARt=0;
/*Thisthreadsimplyscanbuttonispressedtosendthesemaphore.*/
while(1)
{
/*Incrementthethreadcounter.*/
thread_5_counter++;
t=KEY_Scan(0);
if(KEY1_PRES==t)
{
//LED1_TOGGLE();
tx_event_flags_set(&EventGroup,BIT_0,TX_OR);
}
elseif(KEY2_PRES==t)
{
//LED2_TOGGLE();
tx_event_flags_set(&EventGroup,BIT_1,TX_OR);
}
elseif(KEY3_PRES==t)
{
//LED3_TOGGLE();
tx_event_flags_set(&EventGroup,BIT_2,TX_OR);
}
elseif(KEY4_PRES==t)
{
//LED4_TOGGLE();
tx_event_flags_set(&EventGroup,BIT_3,TX_OR);
}
else
{
tx_thread_sleep(10);
}
}
}

3.2 下载与调试

运行程序,板载LED1闪烁。观察串口调试助手,依次按下K1、K2、K3、K4键,串口打印信息:

f74afcc2-81fb-11ed-8abf-dac502259ad0.png

创建事件标志组初始化为零,用于任务同步。任务5执行按键扫描,当按键按下时通过tx_event_flags_set设置事件标志。任务1通过tx_event_flags_get用于检索事件标志,执行对应的处理程序,其中K1进行内存块申请,K2进行内存块释放,K3用于内存字节申请,K4用于内存字节释放,观测串口打印信息,Demo演示成功。

按下K3从MyByte内存池中申请分配了100个字节,还有3980字节可用,而按下K4释放后变成了4088字节可用,前后差值为108个字节,为什么多了8个字节?感兴趣的同学可以思考一下,找找答案!

4小结

Azure RTOS ThreadX提供内存池能够以快速且确定的方式分配内存,结合MM32F3270的强大性能,可以实现Azure RTOS广泛的应用场景。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • threadx
    +关注

    关注

    0

    文章

    14

    浏览量

    13693
  • RTOS
    +关注

    关注

    20

    文章

    776

    浏览量

    118796
  • 动态内存管理

    关注

    0

    文章

    5

    浏览量

    6596
  • Azure
    +关注

    关注

    1

    文章

    109

    浏览量

    12689

原文标题:灵动微课堂 (第241讲)|使用MM32F3270基于Azure RTOS动态内存管理的应用

文章出处:【微信号:MindMotion-MMCU,微信公众号:灵动MM32MCU】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    使用MM32F3270基于Azure RTOS定时器组的应用

    高级计划、通信、同步、计时器、内存管理和中断管理功能。此外,Azure RTOS ThreadX 具有许多高级功能,包括 picokerne
    的头像 发表于 12-29 17:26 1254次阅读

    MM32F3270系列32位MCU的特点有哪些

    、家电、电源管理、打印机和扫描仪、通信转换模块等应用领域范围。MM32F3270系列支持工业级(-40℃至85℃)和扩展工业级(-40℃~105℃)工作温度。内置多种省电工作模式保证低功耗应用的要求
    发表于 11-03 07:20

    基于灵动微MM32F3270微控制器的无线计量仪表的设计资料分享

    和分析。基于灵动微MM32F3270微控制器的无线计量仪表参考方案,具有以下特点:-通过高速SPI可以与各个模块之间通信;-通过485通讯接口进行多个设备互联,以及远程传输-通过UART与4G&GPS通讯进行远程定位与远程抄送基站监控/电力物联网仪表MM32 MCU型号:
    发表于 11-29 06:34

    使用MM32F3270基于Azure RTOS定时器组的应用

    各种产品(包括消费者设备、医疗电子设备和工业控制设备)上的部署次数已达数十亿次。在前文描述移植基本内核的基础上,该应用手册描述了MM32F3270系列MCU结合Azure RTOS ThreadX
    发表于 02-07 14:18

    灵动微电子MM32F3270系列MCU的特点介绍

    、家电、电源管理、打印机和扫描仪、通信转换模块等应用领域范围。MM32F3270系列支持工业级(-40℃~85℃)和扩展工业级(-40℃~105℃)工作温度。内置多种省电工作模式保证低功耗应用的要求。
    发表于 03-22 16:57 1945次阅读

    【国产MCU移植】MM32F3270 EVBoard

    【国产MCU移植】MM32F3270 EVBoard
    发表于 12-03 17:21 5次下载
    【国产MCU移植】<b class='flag-5'>MM32F3270</b> EVBoard

    基于MM32F3270 以太网 Client使用

    接下来给大家介绍基于TCP包的通讯。内容分为基于MM32F3270以太网Client的使用与基于MM32F3270以太网Server的使用。
    发表于 02-08 15:10 0次下载
    基于<b class='flag-5'>MM32F3270</b> 以太网 Client使用

    使用MM32F3270基于Azure RTOS信号量的应用

    高级计划、通信、同步、计时器、内存管理和中断管理功能。此外,Azure RTOS ThreadX 具有许多高级功能,包括 picokerne
    的头像 发表于 12-16 09:23 622次阅读

    MM32F3270 产品手册(中文版)

    MM32F3270 产品手册(中文版)
    发表于 02-23 18:40 0次下载
    <b class='flag-5'>MM32F3270</b> 产品手册(中文版)

    MM32F3270 勘误表(中文版)

    MM32F3270 勘误表(中文版)
    发表于 02-23 18:42 0次下载
    <b class='flag-5'>MM32F3270</b> 勘误表(中文版)

    使用MM32F3270基于Azure RTOS事件标志组的应用

    使用MM32F3270基于Azure RTOS事件标志组的应用
    的头像 发表于 10-27 11:31 283次阅读
    使用<b class='flag-5'>MM32F3270</b>基于<b class='flag-5'>Azure</b> <b class='flag-5'>RTOS</b>事件标志组的应用

    使用MM32F3270基于Azure RTOS (ThreadX) 的移植

    使用MM32F3270基于Azure RTOS (ThreadX) 的移植
    的头像 发表于 10-27 10:15 476次阅读
    使用<b class='flag-5'>MM32F3270</b>基于<b class='flag-5'>Azure</b> <b class='flag-5'>RTOS</b> (ThreadX) 的移植

    基于MM32F3270 I2S使用

    基于MM32F3270 I2S使用
    的头像 发表于 09-27 15:50 502次阅读
    基于<b class='flag-5'>MM32F3270</b> I2S使用

    基于MM32F3270以太网Client使用

    基于MM32F3270以太网Client使用
    的头像 发表于 09-27 15:44 439次阅读
    基于<b class='flag-5'>MM32F3270</b>以太网Client使用

    基于MM32F3270以太网UDP使用

    基于MM32F3270以太网 UDP使用
    的头像 发表于 09-27 15:42 283次阅读
    基于<b class='flag-5'>MM32F3270</b>以太网UDP使用