GTL消息和(动态)内存分配

11个员额/ 0个新员额
最后发表
abremen
离线
最后看到:4年8个月前
加入:2015-02-10 17:44
GTL消息和(动态)内存分配

亲爱的支持,

目前,我正在一个自定义嵌入式项目中实现GTL接口(通过UART)。我的第一个目标是让prox_reporter_ext项目与我们的外部处理器(DA1458x_SDK\5.0.2.1\projects\target_apps\ble_examples文件夹)一起工作。我使用了host_proxr_sdk项目作为参考(DA1458x_SDK\5.0.2.1\projects\host_apps\windows\proximity\reporter\文件夹)。

我面临的挑战是内存分配。到目前为止,我们一直避免在我们的嵌入式代码中使用malloc/free,这只是为了防止引入灾难性的副作用,比如内存泄漏(它还可能与我们的RTOS结合带来新的挑战)。在上述项目的ble_msg中,我看到malloc和free是通过BleMsgAlloc和BleFreeMsg使用的,uart.c中的SendToMain也是如此。此外,UARTProc (uart.c)中的接收缓冲区大小为1000字节,MAX_PACKET_LENGTH为350字节(uart.h)。在UARTSend (uart.c)中分配另外500个字节。

根据我的理解,从综合过程应用。pdf和UM-B-017 GTL接口的来源和读取UM-B-010_DA14580_581_583邻近应用_v1.3.pdf, GTL接口不能被分类为停止和等待协议。换句话说,DA14580可以在任何给定时刻向外部处理器发送多个事件包/消息。另一方面,外部处理器可以在应用程序需要时发送命令包/消息。

我完全理解使用动态内存分配的原因,它对可变数量的包和变量PAR_LEN字段值是有意义的。然而,我想知道静态内存分配是否是一个可行的选择(并且可以通过查看内存需求来实现)。在本例中,我想知道PAR_LEN的最大值是什么(消息可以包含的参数的最大字节数),以及DA14580可能发送的包/消息的数量。如果可行,我可以创建一个循环缓冲区(X)的数据包数量,每个MAX_PAR_LEN字节的参数(我们有32 kb的内存可用,例如三包与一个单独的每个350字节的读350字节的缓冲区和写350字节的缓冲区(异步读/写)不太现实)。

我很想听听你对此的看法。如果可能的话,我宁愿不使用malloc / free。

亲切的问候,
阿扬

编辑02-11-2015
我已经在下面添加了关于字节顺序和数据结构填充的信息,也许其他论坛用户也会觉得这很有用。

设备:
abremen
离线
最后看到:4年8个月前
加入:2015-02-10 17:44
想听听别人怎么说吗

我很想知道其他人是如何在内存有限的嵌入式系统中实现这一点的,或者在malloc/free被认为是不好的实践的地方。

亲切的问候,
阿扬

MT_dialog
离线
最后看到:5个月,3个星期前
工作人员
加入:2015-06-08 34
嗨abremen,

嗨abremen,

我们从来没有想过要做这样的事情,尽管它是可以做到的。潜在的最大数据包,可以交换是完全依赖于当前应用程序,我想,你可以动态地计算在当前实现中有多少被分配和发送数据包,都使用某种计数器,你要能够判断应该预先分配的内存大小。

由于MT_dialog

summer20100514
离线
最后看到:4年8个月前
大师
加入:2014-12-30 05:01
你可以使用动态内存

您可以使用动态内存分配,并且可以选择一个由静态缓冲区实现的内存分配,而不是原来的内存分配。更重要的是,您可以添加一个调试函数,如printf到项目DA14580_SDK_3.0.4.0\host_apps\windows\proximity\monitor,以查看发送和接收了多少数据包。就我而言,32kB的RAM就足够了,也许5kB就足够了。

abremen
离线
最后看到:4年8个月前
加入:2015-02-10 17:44
@MT_dialog谢谢你

@MT_dialog谢谢你的回复,因为显而易见的原因,我最终使用了动态内存分配。然而,静态内存分配的实验是有意义的。

@summer20100514感谢您的回复。请注意,我提到的32kB RAM用于整个系统,而不仅仅是BLE相关的部分。所以5kB仍然是一个相当大的块;-)。

也许你能帮我出个新问题;SDK中的所有数据结构是否在正确的边界上显式对齐?或者假设数据结构将被打包在DA14580和主机代码中(为了使用SDK)?我注意到sizeof经常用于确定不同消息参数的大小,我只是想知道是否考虑了潜在的隐式填充。

谢谢,
阿扬

summer20100514
离线
最后看到:4年8个月前
大师
加入:2014-12-30 05:01
你可以把地址打印出来

如果不太确定对齐方式,可以打印地址。

abremen
离线
最后看到:4年8个月前
加入:2015-02-10 17:44
@summer20100514也许我

@summer20100514也许我应该澄清我的问题。

让我们以结构体proxr_enable_req为例:


/ / sdk \ ble_stack \ profiles \ prox \ proxr \ proxr_task.h

/// @ref PROXR_ENABLE_REQ消息的参数
struct proxr_enable_req

/ / /连接句柄
uint16_t conhdl;
/ / /安全级别
uint8_t sec_lvl;

///在ATT DB中保存LLS警报级别
uint8_t lls_alert_lvl;
/// TX功率
int8_t txp_lvl;
};

在创建PROXR_ENABLE_REQ GTL包时,使用sizeof(struct PROXR_ENABLE_REQ)来确定参数长度。在这种情况下,结构体的编译值,以及包参数长度的值是6;在成员txp_lvl之后添加一个额外的填充字节。换句话说;最后一个成员用所需的字节数填充,以便结构的总大小是任何结构成员的最大对齐倍数。

当将传入字节数组强制转换为消息的相应参数结构类型时,我们需要确保发送方和接收方都考虑到或没有考虑到这种隐式填充。在使用proxr_enable_req的情况下,解除对单个成员的引用不会有真正的问题,因为填充仅仅是在最后一个成员之后添加的。然而,如果你举下面的例子,个人成员可能不会在你期望他们在的地方(取决于发送者和接收者是否对包装结构采取不同的规则)。

下面是一个包含各种类型成员的结构,编译前总共为8个字节:


struct MixedData

char Data1;
短Data2;
int Data3;
char Data4;
};

编译后,数据结构将被填充字节补充,以确保其每个成员的正确对齐:


struct MixedData /*在32位x86机器编译后*/

char Data1;/* 1字节*/
char Padding1 [1];/* 1字节为以下'short'对齐在2字节边界
假设结构开始的地址是一个偶数*/
短Data2;/* 2字节*/
int Data3;/* 4字节-最大的结构成员*/
char Data4;/* 1字节*/
char Padding2 [3];/* 3字节使结构的总大小为12字节*/
};

https://en.wikipedia.org/wiki/Data_structure_alignment

长话短说,我很想从Dialog中了解到DA SDK的设计选择。数据包参数是否在字段之间发送带有或没有填充字节?

summer20100514
离线
最后看到:4年8个月前
大师
加入:2014-12-30 05:01
我没有注意到这件事

我之前没有注意到这件事,但似乎没有什么不对劲的。也许填充字节总是添加在最后一个成员之后?

abremen
离线
最后看到:4年8个月前
加入:2015-02-10 17:44
因为我还没来

由于我还没有遇到任何文档显式地指定数据字节序,以及数据结构是否被打包,或者结构成员之间是否存在填充字节,我的猜测是,到目前为止,SDK只用于/打算(32位)平台与一个小的端内存体系结构没有结构被打包(例如,我确实发现任何__attribute__(打包)在SDK代码)。

只要两个系统都使用sizeof(struct)来设置GTL包参数长度,并将传入和输出参数字节数组转换为这些结构类型,一切都将正常工作(因为两个平台都期望相同的结构成员填充/成员对齐)。

尽管我认为这是迄今为止使用SDK的情况,但我真的希望Dialog能够对此做出回应。

-假设结构体没有被打包(由编译器隐式添加的填充)是正确的吗?
-没有显式填充添加,以确保成员对齐正确和结构体大小是其最大成员的倍数?(也就是说,这是留给编译器的)

请注意,我完全可以使用这种方法(使用我们当前的主机平台),因为我们的主机也使用32位ARM Cortex-M0+处理器。DA14580和主机处理器都配置了小端字节顺序。换句话说,sizeof()将在两个平台上返回相同的结果,并且struct成员将在两个平台上完全对齐(通过编译器添加相同的隐式填充)。

我在跨平台解决方案(具有不同的内存架构)中使用了大量面向字节、打包的基于协议。对于SDK来说,未来一个好的补充可能是增加一个额外的抽象级别,指定字段之间不存在填充字节,并使用写/读模块以独立于字节的方式写/读多字节数据类型。通过这种方式,您可以完全删除与平台相关的部分。

我是SDK的超级粉丝(特别是5.0.3,我爱它!),我只是想把事情弄清楚尽可能多:-)。

期待你的回复。
亲切的问候,
阿扬

MT_dialog
离线
最后看到:5个月,3个星期前
工作人员
加入:2015-06-08 34
嗨abremen,

嗨abremen,

对齐由编译器决定,原因是windows和ARM具有相同的端序(小端序)和大小。如果是不同的体系结构,编译器将会失败,你将不得不显式地声明结构。

由于MT_dialog

abremen
离线
最后看到:4年8个月前
加入:2015-02-10 17:44
嗨MT_dialog,

嗨MT_dialog,

谢谢你的确认。这个主题现在可以结束了。

亲切的问候,
阿扬

主题锁定