亲爱的支持,
目前我正在一个定制的嵌入式项目中实现GTL接口(通过UART)。我的第一个目标是让prox\u reporter\u ext项目与我们的外部处理器(DA1458x\u SDK\5.0.2.1\projects\target\u apps\ble\u examples文件夹)结合使用。我使用了host\u proxr\u sdk项目作为参考(DA1458x\u sdk\5.0.2.1\projects\host\u apps\windows\proximity\reporter\folder)。
The challenge I'm facing is with memory allocation. Up until now we have avoided using malloc/free in our embedded code, simply to prevent introducing disastrous side effects such as memory leaks (also it might introduce new challenges in combination with our RTOS). In ble_msg of the aforementioned project I see that malloc and free are used via for example BleMsgAlloc and BleFreeMsg, the same goes for SendToMain in uart.c. Furthermore the receive buffer in UARTProc (uart.c) is 1000 bytes in size, with MAX_PACKET_LENGTH being 350 bytes (uart.h). Another 500 bytes are allocated in UARTSend (uart.c).
From what I understand from going through the sources and reading through UM-B-017 GTL interface in Integrated Process Application.pdf and UM-B-010_DA14580_581_583 Proximity application_v1.3.pdf, the GTL interface cannot be classified as a stop-and-wait protocol. In other words, multiple event packets / messages can be sent by the DA14580 to the external processor at any given moment. On the other hand the external processor can send a command packet / message whenever required by the application.
我完全理解使用动态内存分配的原因,它对于可变数量的包和可变的PARLIEN字段值是有意义的。然而,我想知道静态内存分配是否是一个可行的选择(并且从内存需求来看是可以实现的)。在这种情况下,我想知道PARYLIN的最大值是(消息可以包含的参数的最大字节数)和DA14580可能发送多少包/消息。如果可行的话,我可以创建一个X数个包的循环缓冲器,每个都具有最大的字节参数(我们总共有32 KB的RAM),例如,每个3字节的每个350字节具有350字节的单独读缓冲器和350字节的写缓冲器(对于异步读/写)是不太现实的。
I would love to hear your thoughts on this. If at all possible, I would rather not use malloc / free.
谨致问候,
arjan.
编辑02-11-2015
I have added information regarding endianness and data structure padding below, perhaps other forum users might find this useful as well.
Would love to hear how others implemented this in embedded systems with limited memory and/or where malloc/free was considered bad practice.
谨致问候,
arjan.
嗨,ablimen,
我们从来没有考虑过要做这样的事,但这是可以做到的。可以交换的潜在数据包的最大数量完全取决于当前的应用程序,我假设您可以在当前的实现中使用某种计数器动态计算分配和发送的数据包的数量,并由此判断应该预分配的内存大小。
Thanks MT_dialog
You can use dynamic memory allocation, and you can choose one implemented by static buffers instead of the origin one. What's more, you can add one debug function such as printf to the project DA14580_SDK_3.0.4.0\host_apps\windows\proximity\monitor to see how many packets are send and received. As far as I am concerned, 32kB of RAM is fully sufficient, maybe 5kB is enough.
@谢谢你的回复,我最后使用了动态内存分配,原因很明显。不过,尝试静态内存分配是有意义的。
@summer20100514感谢您的回复。请注意,我提到的32kB的RAM是针对整个系统的,而不仅仅是与BLE相关的部分。所以5kB仍然是相当大的一块;-)。
也许你能帮我解决一个新问题;SDK中的所有数据结构是否在正确的边界上显式对齐?或者假设数据结构将打包在DA14580和主机代码中(以便使用SDK)?我注意到sizeof经常用于确定不同消息参数的大小,我只是想知道是否考虑了潜在的隐式填充。
谢谢,
arjan.
如果你对路线不太确定,你可以把地址打印出来。
@ Summer20100514也许我应该澄清我的问题。
让我们拍摄struct proxr_enable_req:
// sdk\ble_stack\profiles\prox\proxr\proxr_task.h
/// Parameters of the @ref PROXR_ENABLE_REQ message
结构程序启用请求
{
/// Connection Handle
uint16_t conhdl;
/// 安全级别
uint8_t sec_lvl;
///已保存LLS警报级别以在ATT DB中设置
uint8_t lls_alert_lvl;
///TX功率电平
INT8_T TXP_LVL;
};
When creating a PROXR_ENABLE_REQ GTL packet, sizeof(struct proxr_enable_req) is used to determine the parameter length. In this case the compiled value of the struct, and thus the value for the packet parameter length, is 6; An additional byte of padding is added just after member txp_lvl. In other words; The last member is padded with the number of bytes required so that the total size of the structure is a multiple of the largest alignment of any structure member.
当将传入字节数组强制转换为消息的相应参数struct type时,我们需要确保发送方和接收方都考虑或不考虑这种隐式填充。在proxr\u enable\u req的情况下,取消对单个成员的引用不会有真正的问题,因为填充仅添加在最后一个成员之后。但是,如果您以下面的示例为例,单个成员可能不是您期望的位置(取决于发送方和接收方是否对打包结构采用不同的规则)。
Long story short, I'm curious to learn from Dialog itself which design choice was made with the DA SDK. Are packet parameters sent with or without pad bytes in between fields?
我以前没注意到这件事,但好像没出什么事。也许填充字节总是添加在最后一个成员之后?
由于我尚未遇到任何明确地指定数据的文档,因为在结构成员之间包含数据结构以及数据结构是否存在,我的猜测是直到现在,SDK仅用于/打算(32位)平台,带有少量内存架构的没有结构(例如,我在SDK代码中找到了任何__Attribute __(packed))。
只要两个系统都使用sizeof(struct)来设置GTL包参数长度,并将传入和传出参数字节数组强制转换为这些结构类型,一切都会正常工作(因为两个平台都期望相同的结构成员填充/成员对齐)。
即使是艰难的,我相信这是如何使用SDK到目前为止的情况下,我真的很感谢对话框本身就此事作出回应。
- 是否假设结构未打包(编译器添加的隐式填充)是正确的?
- There is no explicit padding added to make sure that members align properly and struct sizes are a multiple of the size of its largest member? (i.e. this is left to the compiler)
请注意,我完全同意这种方法(使用我们当前的主机平台),因为我们的主机也使用32位ARM Cortex-M0+处理器。DA14580和主机处理器都配置了小端字节顺序。换句话说,sizeof()将在两个平台上返回相同的结果,并且结构成员在两个平台上的对齐方式将完全相同(编译器添加了相同的隐式填充)。
I have worked quite a lot with these type of byte-oriented, packed based protocols in cross-platform solutions (with different memory architectures). Perhaps a good future addition for the SDK could be to add an extra level of abstraction, by specifying that no pad bytes exist in between fields and using a write/read module for writing/reading multi-byte data types in an endianness independent manner. This way you remove the platform-dependent aspect of it all.
I'm a big fan of the SDK (especially 5.0.3, love it!), I just like to get things cleared up as much as possible :-).
期待您的回应对话。
谨致问候,
arjan.
嗨,ablimen,
对齐方式由编译器决定,原因是windows和ARM具有相同的endian(小endian)和大小。在不同架构的情况下,编译器将失败,您必须明确地声明结构。
Thanks MT_dialog
嗨,MT\u dialog,
Thanks for the confirmation. This topic may now be closed.
谨致问候,
arjan.