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

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

亲爱的支持,

目前我正在在自定义嵌入式项目中实现GTL接口(OVER 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 \ folder)。

我面临的挑战是内存分配。到目前为止,我们一直避免在我们的嵌入式代码中使用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字节的参数(我们有32kb的总共可用,因此每个350个字节的350个字节的350个字节的数据包,其中350字节的单独读缓冲区为350字节和a写入350字节的缓冲区(对于异步读取/写入)不是很真实)。

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

亲切的问候,
阿扬

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

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

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

亲切的问候,
阿扬

MT_dialog
离线
最后看到:5个月2个星期前
工作人员
加入:2015-06-08 11: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就足够了。

ablimen.
离线
最后看到:4年8月前
加入:2015-02-10 17:44
@mt_dialog谢谢你的

@mt_dialog感谢您的回复,我最终使用动态内存分配以获得明显的原因。然而,它具有静态内存分配的有意义的实验。

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

也许你可以帮助我解决一个新问题;SDK中的所有数据结构都在正确的边界上明确对齐吗?或者它假设数据结构将包装在DA14580中以及主机代码(为了使用SDK)?我注意到尺寸频繁地用于确定不同消息参数的大小,我只是想知道是否考虑了潜在的隐式填充。

谢谢,
阿扬

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

如果您不太确定对齐,则可以打印出地址。

ablimen.
离线
最后看到: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;

///保存LLS警报级别以在ATT DB中设置
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
我没有注意到这件事

我之前没有注意到这件事,但它似乎发生了错误。也许填充字节总是在最后一个成员后添加?

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

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

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

即使是艰难的我相信这是这种情况,迄今为止如何使用SDK,我真的很感谢对话本身的回应。

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

请注意,使用此方法(使用当前的主机平台)绝对没问题,因为我们的主机也使用32位ARM Cortex-M0 +处理器。DA14580和主处理器都配置了很少的字节字节顺序。换句话说,sizeof()将在两个平台上返回相同的结果,并且结构构件在两个平台上都会完全相同(编译器添加相同的隐式填充)。

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

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

期待您的回复对话框。
亲切的问候,
阿扬

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

嗨abremen,

将对齐留给编译器来决定,原因是因为Windows和Arm具有相同的exidianess(小endian)和大小。在不同的体系结构的情况下,编译器将失败,您必须刚才声明结构。

由于MT_dialog

ablimen.
离线
最后看到:4年8月前
加入:2015-02-10 17:44
嗨mt_dialog,

嗨mt_dialog,

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

亲切的问候,
阿扬

主题锁定