查看: 1703|回复: 0

TI NDK应用开发过程中的一点经验及改进

[复制链接]

该用户从未签到

发表于 2020-11-22 19:57:15 | 显示全部楼层 |阅读模式
分享到:

最近在TI的处理器上做软件开发,项目需要网络通讯功能,而在TI的处理器上做网络编程只能使用TI自家的NDK,除非是非常专业的选手,否则用户几乎没有其他选择。
     本文假设设计者熟悉TI的集成开发环境Code Composer Studio v6,因此一些基本的工程、项目、软件包的配置说明将被略过,若有需要了解请移步TI官网查询。
       本人项目中使用的处理器是TI C6457 DSP,软件包有NDK v2.24.03.35,SYS/BIOS v6.42.02.29。其中NDK需要SYS/BIOS的支持,因此SYS/BIOS是必选项。

一.NDK的配置
1.系统配置
        NDK使用SYS/BIOS的Clock模块对NDK内部的工作进行计时驱动,这一模块的实例在NDK中被设计为动态创建得到,虽然NDK自带一套不依赖于系统动态内存管理功能的内存管理单元,并且有自己的堆内存,但Clock的实例却不能在其中创建,只能在系统的全局对中创建。因此SYS/BIOS中的内存堆必须分配足够的大小,且必须将SYS/BIOS的动态内存分配功能使能,否则编译工具将无法产生正确的Clock动态创建代码,而程序也无法正常启动NDK服务。

2.模块配置
     按项目需求,需要使用芯片的网络接口设备,因此NDK配置选择了EMAC模块;又因为主要使用UDP协议通信,所以添加了IP模块;其他的TELNET、HTTP、FTP等上层服务一概不选。

3.底层驱动配置
        底层驱动分别需要EMAC驱动和NIMU Ethernet驱动,另外CSL库是必须的,它们都可以在针对C64PLUS芯片的MCSDK中找到。这个软件包集合可以安装CSL、PDK、MCSDK三个包,CSL包不必说了,PDK中可以找到EMAC驱动,NIMU Ethernet驱动在MCSDK包中,后两个最好用CCS打开工程自己编译一下,然后需要手动将它们(包括CSL包)的lib文件及include路径添加到自己的工程中。其他的配置略过。

二.基于NDK的部分UDP编程经验
1.基于NDK的socket编程代码必须在Task中执行,原因有:
(1).NDK的启动、初始化以及后台守护任务都在Task中执行;
(2).socket编程需要文件描述符的支持,SYS/BIOS实现了一个简化版的文件描述符,但必须在Task中打开(用fdOpenSession)和关闭(用fdCloseSession)。

2.使用socket编程的用户Task不可一直占用CPU的执行时间,必须以合适的时间间隔自动阻塞,原因有:
(1).SYS/BIOS的Tasks并不是以分片时间自动调度执行,而是按优先级自动重入执行,对相同优先级的Tasks仅在当前执行的Task通过结束任务或者阻塞来主动放弃执行时间后,等待执行的Task才有机会获得执行时间。
(2).NDK的守护任务在完成初始化后即会自动降低Task优先级至最低的IDLE Task级,若用户Task执行在高于IDLE的优先级,且一直不通过阻塞来主动放弃执行时间的话,则NDK的数据报队列状态将一直得不到更新,从而导致用户Task的socket函数无法正常接收和发送数据报。

3.setsockopt应谨慎改变NDK的自定义属性SOL_BLOCKING,否则socket API recv和recvfrom无法正常接收数据报,原因目前未明。
4.recv、recvfrom、send、sendto函数的查询模式实现
这些函数虽然自带阻塞功能,但在一些需要使用查询的应用中并不合适,而多Task的方案又较为复杂,增加了程序设计的难度。实际上可以为它们的flag参数传递MSG_DONTWAIT来防止函数进入阻塞状态,此时这些函数将返回工作失败状态,用fdError()查询可得错误状态码为EWOULDBLOCK。另外在查询模式下,需要编程者手动调整Task的执行时间,或者按后面的方法对NDK进行一点小的改进。

5.在连接以Windows作为操作系统的PC机的网络接口时sendto函数有时会返回错误状态
这是因为Windows系统服务在网络接口连接后会断断续续的发送一些报文,这些报文会暂时占据NDK的数据报队列,导致查询模式下的sendto函数失败,此时fdError()会返回ENOBUFS状态。这种情况下,将Task阻塞一小段时间,再sendto就会成功了。

三.适应执行时间紧张应用场景的NDK小改进
正如上文所说,在查询模式下需要编程者手动调整Task的执行时间,以预留足够的时间给NDK守护任务用于刷新数据报队列,这在应用执行时间比较紧张的情况下将带来额外的调试任务和难度。
为解决这个问题,可考虑将NDK的守护任务执行函数在用户主Task中按合适的时间频度调用,但这可能引入更多的Task间的互斥同步编程,且可能与守护任务的执行上下文产生冲突,因此有必要采用更安全的做法。
我的做法是:在调用socket通信函数(recv、recvfrom、send、sendto等)发现NDK资源不足时,临时提高一次NDK守护任务的优先级,在守护任务执行完一次刷新任务后,又将自身的优先级降回IDLE。这需要对NDK的源代码做一点小更改,并重新编译。
涉及的NDK源码更改为:

  1. /* (NDK安装目录)/packages/ti/ndk/netctrl/netctrl.c中的NetScheduler函数前添加自定义的API函数 */
  2. static int netStartTaskPri = 0;
  3. static HANDLE hTaskNetService = 0;
  4. void NC_tmpRaiseNetServicePri(void)
  5. {
  6.     if (hTaskNetService) {
  7.         TaskSetPri( hTaskNetService, netStartTaskPri );
  8.     }
  9. }

  10. /* 更改NetScheduler函数的实现代码 */
  11. static void NetScheduler( uint const SerilCnt, uint const EherCnt)
  12. {
  13.     register int fEvents;

  14.     /* Set the Scheduler priority */
  15.     register HANDLE hTaskSelf = hTaskNetService = TaskSelf();/* 获取和保存守护Task的句柄 */
  16.     netStartTaskPri = TaskSetPri( hTaskSelf, SchedulerPriority );/* 设置守护Task优先级为SchedulerPriority(默认为IDLE级),并保存原来的优先级 */
  17.     /*
  18.      * 说明:NetScheduler所在的Task在执行NetScheduler之前执行的是NDK的初始化任务,默认情况下该Task的
  19.      * 优先级高于用户Task的优先级,直到初始化任务完毕后,在NetScheduler函数中才将自身优先级降为IDLE。
  20.      * 因此上面的代码中将原来的优先级和Task句柄一并保存,在自定义的API函数NC_tmpRaiseNetServicePri中
  21.      * 即可恢复守护Task的优先级,从而使守护Task从用户Task中重入并得以执行。
  22.      */

  23.     /* Enter scheduling loop */
  24.     while( !NetHaltFlag )
  25.     {
  26.         .../* 原循环代码省略 */
  27.         /* 检查守护Task的优先级,并根据需要重设优先级至SchedulerPriority */
  28.         if (TaskGetPri( hTaskSelf ) != SchedulerPriority) {
  29.             TaskSetPri( hTaskSelf, SchedulerPriority );
  30.         }
  31.     }
  32. }
  33. /* (NDK安装目录)/packages/ti/ndk/inc/netctrl/netctrl.h中添加自定义API函数的声明 */
  34. _extern void NC_tmpRaiseNetServicePri(void);
复制代码
用法示例:
SOCKET s;
struct sock_addr_in from;
int fromLen;
...
int ret = recvfrom(s, recvBuff, recvBytes, MSG_DONTWAIT, (struct sock_addr*)&from, &fromLen);
if (ret == INVALID_SOCKET) {
    ret = fdError();
    if (ret == EWOULDBLOCK || ret == ENOBUFS) {
        NC_tmpRaiseNetServicePri();
    }
}
...


回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /5 下一条



手机版|小黑屋|与非网

GMT+8, 2024-12-24 08:50 , Processed in 0.113179 second(s), 15 queries , MemCache On.

ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

苏公网安备 32059002001037号

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.