由于要使用网络,NDK就是个很不错的选择,但自己也是刚开始对NDK的学习。帖子不免有些基础。
程序首先是使用PlatformInit函数对系统时钟,调试串口,初始化。
- Void PlatformInit()
- {
- // 平台初始化
- platform_init_flags Flags;
- platform_init_config Config;
- memset((void *)&Flags, 0, sizeof(platform_init_flags));
- memset((void *)&Config, 0, sizeof(platform_init_config));
- Flags.pll = 0; // 锁相环
- Flags.ddr = 0; // ddr3
- Flags.tcsl = 0; // 时间戳计数器
- Flags.phy = 1; // 以太网
- Flags.ecc = 0; // DDR3 ECC
- Config.pllm = 0;
- // 调试串口初始化
- platform_uart_init(PLATFORM_UART0);
- platform_uart_set_baudrate(PLATFORM_UART0, 115200);
- // 调试信息同时输出到串口和 CCS Console
- platform_write_configure(PLATFORM_WRITE_ALL);
- int status;
- status = platform_init(&Flags, &Config);
- IF(status != Platform_EOK)
- {
- platform_write("Platform faiLED to initialize. Error code %d \n", status);
- platform_write("We will fall in an infinite loop... \n");
- while(1)
- {
- platform_led(0, PLATFORM_LED_ON, PLATFORM_USER_LED_CLASS);
- platform_delay(1000);
- platform_led(0, PLATFORM_LED_OFF, PLATFORM_USER_LED_CLASS);
- platform_delay(1000);
- }
- }
- }
在网卡驱动支持函数中,有一些是对中断的配置,但有一些函数看上去没有意义。
如下:
- void Osal_emacBeginMemAccess(void *addr, uint32_t size)
- {
- (void)addr;
- (void)size;
- return;
- }
这个函数没有返回值,函数体中也没有什么有用的语句,不知道这个函数的意义是什么 ,但是没有这些函数是会有错误的,可以在库中这些函数在其他的工程中是有实际意义的,只是在这个工程中没有用,所以就写了个类似的空函数。不知道这么理解对不对,初次学习NDK。
void CacheInit()缓存配置中使用了Cache_Size结构体,而这个结构体最终的原型是如下结构体。就是对L1、L2缓存的配置。
新建Task函数Void TaskInit()中递增建了一个task,名字为NDKTask。
使用Task_Params_init()函数创建这个配置参数结构,这个函数的声明原型为Void Task_Params_init(Task_Params *params);
对于Task_Params结构体:
- typedef struct Task_Params {
- // Instance config-params structure
- IInstance_Params *instance;
- // Common per-instance configs
- UInt affinity;
- // The core which this task is to run on. Default is Task_AFFINITY_NONE
- UArg arg0;
- // Task function argument. Default is 0
- UArg arg1;
- // Task function argument. Default is 0
- Ptr env;
- // Environment data struct
- Int priority;
- // Task priority (0 to Task.numPriorities-1, or -1). Default is 1
- Ptr stack;
- // Task stack pointer. Default = null
- IHeap_Handle stackHeap;
- // Mem heap used for dynamically created task stack
- SizeT stackSize;
- // Task stack size in MAUs
- Bool vitalTaskFlag;
- // Exit system immediately when the last task with this flag set to TRUE has terminated
- } Task_Params;
分配的stack的大小是512*1024
使用Task_create()函数创建这个任务。
- Task_Handle NDKTaskHandle;
- Task_Params TaskParams;
- Task_Params_init(&TaskParams);
- TaskParams.stackSize = 512 * 1024;
- NDKTaskHandle = Task_create(NDKTask, &TaskParams, NULL);
- if(NDKTaskHandle == NULL)
- {
- platform_write("NDK Task create failed!\r\n");
- }
NDKTask线程无疑是程序的主要部分。
在NDKTask中,首先是初始化操作系统环境,必须在使用 NDK 之前最先调用,这里使用的是NC_SystemOpen()函数,该函数为所有网络应用程序建立堆栈和内存环境,它初始化堆栈的内存管理和操作系统。它还配置了网络事件调度程序的任务优先级和操作模式。
这个函数有两个参数,一个是NDK优先级,一个是操作模式。
优先级有两个定义一个是高一个是低:NC_PRIORITY_LOW 与 NC_PRIORITY_HIGH
操作模式也有两个定义,是个是轮询一个是中断:NC_OPMODE_POLLING 与NC_OPMODE_INTERRUPT
面这里选择的是高优先级与中断方式。
- Int rc;
- rc = NC_SystemOpen(NC_PRIORITY_HIGH, NC_OPMODE_INTERRUPT);
- if(rc)
- {
- platform_write("NC_SystemOpen Failed (%d)\n", rc);
- for(;;);
- }
CfgNew()函数会创建一个配置句柄,这个句柄的类型是HANDLE,HANDLE 实际上只是一个空指针,它的定义如下:
typedef void * HANDLE;
而CfgNew()函数返回值赋给了这个句柄,使用方法如下程序:
- HANDLE hCfg;
- hCfg = CfgNew();
- if(!hCfg)
- {
- platform_write("Unable to create configuration\n");
- goto Exit;
- }
利用该句柄使用CfgAddEntry()函数可以添加DHCP、DNS、HTTP等服务和配置SOCKET缓冲区大小与ARP超时参数。
- CfgAddEntry(hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_HOSTNAME, 0, strlen(HostName), (UINT8 *)HostName, 0);
如下是CfgAddEntry()函数的几个参数的含义:
由于接下来的几篇都是NDK的讲解与使用方法的说明,在NDK的最后一篇将把所有的源码与二进制文件上传。