亲爱的支持,
目前,我正在一个自定义嵌入式项目中实现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 /免费在我们的嵌入式代码中使用,只需防止引入灾难性的副作用,例如内存泄漏(也可能与我们的RTO结合引入新的挑战)。在上述项目的BLE_MSG中,我看到MALLOC和免费使用例如BLEMSGALLOC和BLEFREEMSG,同样用于UART.C中的Sendtomain。此外,UARTPROC(UART.C)中的接收缓冲区的大小为1000个字节,MAX_PACKET_LENGTH为350字节(UART.H)。在UARTSEND(UART.C)中分配了另外500个字节。
从我所理解的来源和通过综合进程应用程序的UM-B-017 GTL接口阅读.pdf和UM-B-010_DA14580_581_583 Proximity Application_v1.3.pdf,GTL接口不能被分类为停止 -等待协议。换句话说,DA14580可以在任何给定时刻将DA14580发送到外部处理器的多个事件分组/消息。另一方面,外部处理器可以在应用程序所需时发送命令包/消息。
我完全理解使用动态内存分配的原因,它对可变数量的包和变量PAR_LEN字段值是有意义的。然而,我想知道静态内存分配是否是一个可行的选择(并且可以通过查看内存需求来实现)。在本例中,我想知道PAR_LEN的最大值是什么(消息可以包含的参数的最大字节数),以及DA14580可能发送的包/消息的数量。如果可行,我可以创建一个循环缓冲区(X)的数据包数量,每个MAX_PAR_LEN字节的参数(我们有32 kb的内存可用,例如三包与一个单独的每个350字节的读350字节的缓冲区和写350字节的缓冲区(异步读/写)不太现实)。
我很想听到你的想法。如果可能,我宁愿不使用malloc /免费。
亲切的问候,
arjan.
编辑02-11-2015
我添加了有关外部性和数据结构填充的信息,也许其他论坛用户也可能会发现这种有用。
很乐意听到别人在嵌入式系统中如何在具有有限的嵌入式系统中实现这一点和/或Malloc /免费被认为是不良的做法。
亲切的问候,
arjan.
嗨,ablimen,
我们从来没有想过要做这样的事情,尽管它是可以做到的。潜在的最大数据包,可以交换是完全依赖于当前应用程序,我想,你可以动态地计算在当前实现中有多少被分配和发送数据包,都使用某种计数器,你要能够判断应该预先分配的内存大小。
谢谢mt_dialog.
您可以使用动态内存分配,并且您可以选择由静态缓冲区实现的,而不是原点。更重要的是,您可以添加一个调试功能,如PrintF到Project DA14580_SDK_3.0.4.0 \ host_Apps \ Windows \ Proximity \ Monitor,看看发送和接收多少数据包。就我而言,32KB的RAM完全充分,也许5KB就足够了。
@MT_dialog谢谢你的回复,因为显而易见的原因,我最终使用了动态内存分配。然而,静态内存分配的实验是有意义的。
@summer20100514感谢您的回复。请注意,我提到的32kB RAM用于整个系统,而不仅仅是BLE相关的部分。所以5kB仍然是一个相当大的块;-)。
也许你能帮我出个新问题;SDK中的所有数据结构是否在正确的边界上显式对齐?或者假设数据结构将被打包在DA14580和主机代码中(为了使用SDK)?我注意到sizeof经常用于确定不同消息参数的大小,我只是想知道是否考虑了潜在的隐式填充。
谢谢,
arjan.
如果不太确定对齐方式,可以打印地址。
@ Summer20100514也许我应该澄清我的问题。
让我们拍摄struct 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的情况下,解除对单个成员的引用不会有真正的问题,因为填充仅仅是在最后一个成员之后添加的。然而,如果你举下面的例子,个人成员可能不会在你期望他们在的地方(取决于发送者和接收者是否对包装结构采取不同的规则)。
长话短说,我很想从对话本身学习哪些设计选择是用达SDK制作的。是否在字段之间发送或没有填充字节的数据包参数?
我之前没有注意到这件事,但似乎没有什么不对劲的。也许填充字节总是添加在最后一个成员之后?
由于我尚未遇到任何明确地指定数据的文档,因为在结构成员之间包含数据结构以及数据结构是否存在,我的猜测是直到现在,SDK仅用于/打算(32位)平台,带有少量内存架构的没有结构(例如,我在SDK代码中找到了任何__Attribute __(packed))。
只要两个系统都使用sizeof(struct)来设置GTL包参数长度,并将传入和输出参数字节数组转换为这些结构类型,一切都将正常工作(因为两个平台都期望相同的结构成员填充/成员对齐)。
尽管我认为这是迄今为止使用SDK的情况,但我真的希望Dialog能够对此做出回应。
- 是否假设结构未打包(编译器添加的隐式填充)是正确的?
- 没有添加显式填充,以确保成员正确对齐,结构大小是其最大成员大小的倍数?(即,这是留给编译器)
请注意,我完全可以使用这种方法(使用我们当前的主机平台),因为我们的主机也使用32位ARM Cortex-M0+处理器。DA14580和主机处理器都配置了小端字节顺序。换句话说,sizeof()将在两个平台上返回相同的结果,并且struct成员将在两个平台上完全对齐(通过编译器添加相同的隐式填充)。
我在跨平台解决方案中使用了这些类型的面向字节的面向的基于包装的协议(具有不同的内存架构)。也许对于SDK的未来未来添加可以是添加额外的抽象级别,通过指定字段之间存在没有填充字节,并使用写/读取模块以以endianness独立方式写入/读取多字节数据类型。这样你就可以删除它的平台依赖性方面。
我是SDK的忠实粉丝(特别是5.0.3,爱它!),我只是喜欢尽可能地清理的东西:-)。
期待你的回复。
亲切的问候,
arjan.
嗨,ablimen,
对齐由编译器决定,原因是windows和ARM具有相同的端序(小端序)和大小。如果是不同的体系结构,编译器将会失败,你将不得不显式地声明结构。
谢谢mt_dialog.
嗨MT_dialog,
谢谢你的确认。现在可以关闭此主题。
亲切的问候,
arjan.