先提一个问题吧,什么是UDP?
答:https://zhuanlan.zhihu.com/p/24860273 请先阅读完再继续下文。。。。。。
这几天也没闲着,我手上有1块CC2538的板子。要做UDP无线通讯,至少要2块板子,于是在*宝上又入手了一块CC2538的板子,
最后搞好的样子是这样的:
于是,先将LINUX开发环境的CONTIKI测试,\contiki-ng-release-v4.6\examples\rpl-udp下的udp-client.c和udp-server.c
进行MAKE编译,把udp-server、udp-server的HEX分别下载到俩个板子上进行测试,在LINUX上是完全正常:
上图测试代码,是我改过的,因为在IAR system中UDP出问题了,但在LINUX中一点问题都没有,
哎,真苦b啊,正在查找原因。。...
我在IAR测试中,多处工作点加入大量printf信息,比如RF_ISR(),DMA_ISR等等。发现在IAR平台时
没有进入udma-isr()中断,看来问题就在这里了(IAR 啊 IAR啊,让我爱 也让我恨啊!!),所以
又要对UDMA进行单独测试,使用各种方法测试它!!
提示一下,CONTIKI NG在2020年12月08日发布了最新版本为contiki-ng-release-v4.6
下载地址: https://github.com/contiki-ng/contiki-ng/releases 从头到尾花了20分钟左右就移植好了。官方说是提升性能,修复BUG,必须要更新它!!
时间:2020-12-10
要检查DMA是不是工作正常,我们只能去查看DMA寄存器了。找到MYdemo\user\cc2538-dev下的udma.h、udma.c
以STAT寄存器为例子,依此类推,看udma.h:
1 /*---------------------------------------------------------------------------*/ 2 /** 3 * \name uDMA Register offset declarations寄存器偏移声明 4 * @{ 5 */ 6 #define UDMA_STAT 0x400FF000 /**< DMA status 状态 */ 7 #define UDMA_CFG 0x400FF004 /**< DMA configuration */ 8 9 10 /*---------------------------------------------------------------------------*/ 11 /** 12 * \name UDMA_STAT register bit masks 寄存位掩码 13 * @{ 14 */ 15 #define UDMA_STAT_DMACHANS 0x001F0000 /**< Available uDMA channels minus 1 */ 16 #define UDMA_STAT_STATE 0x000000F0 /**< Control state machine status */ 17 #define UDMA_STAT_MASTEN 0x00000001 /**< Master enable status */
我们再打开cc2538的数据手册:
给出我的测试代码:
1 udma_init(); // 查看数据手册. 2 printf("UDMA_STAT_addr:0x%x\nUDMA_STAT_data:0x%x\n", ®(UDMA_STAT), REG(UDMA_STAT)); 3 printf("UDMA_STAT_STATE:0x%x\n", (REG(UDMA_STAT)&UDMA_STAT_STATE)>>4); 4 printf("UDMA_STAT_DMACHANS:0x%x\n", (REG(UDMA_STAT)&UDMA_STAT_DMACHANS)>>16); 5 printf("UDMA_STAT_MASTEN:0x%x\n", (REG(UDMA_STAT)&UDMA_STAT_MASTEN)>>0);
运行效果:
以前感觉这些好难的,不知为什么。今天随手就写出来了,首先REG()是CONTIKI操作寄存器的宏。
1----> REG()使用的话,就是某个寄存器内的值。可以读出来或写入,能不能写入要去查数据手册。
2----> ®()使用的话,就是取寄存器物理地址,取出来的地址和数据手册的地址要一致!
3----> 寄存位掩码 和移位,现在发现这个真是个好东东,位掩码可以关心必要的bit位,其他的bit位被屏蔽掉。
位移更是个好东东,移动多少位要看数据手册,给个小巧门,比如STATE位段在7 6 5 4,你就右移4位就好了。
再比如DMACHANS位段在20 19 18 17 16(看数据手册),你就右移16位好了,这样取的数据就很精炼了。
即然都说到这里了,也顺便说一下位操作吧,会发现数据都是移出来的,位移是最高效的处理方式:
#define SetBit(byte,bit) byte|=(1<<bit) //BIT置1 #define ResetBit(byte,bit) byte&=~(1<<bit) //BIT置0 #define RevBit(byte,bit) byte^=(1<<bit) //BIT取反 ~位取反 #define GetBit(byte,bit) ((byte)>>(bit)&1) //取当前BIT的值 #define MAX(a,b) ((a)>(b)?(a):(b)) //最大值
如果单一的位操作的话,完全可以用上面的方法。byte就是上面提到的REG()
来个例子加以说明:
代码:
REG(UDMA_CFG)&=~(1<<0); //将bit0位置0 printf("UDMA_STAT_MASTEN:0x%x\n", (REG(UDMA_STAT)&UDMA_STAT_MASTEN)>>0); REG(UDMA_CFG)|=(1<<0); //将bit0位置1 printf("UDMA_STAT_MASTEN:0x%x\n", (REG(UDMA_STAT)&UDMA_STAT_MASTEN)>>0);
执行:
哪么最后一个问题,对于位段我们可以用寄存位掩码加移位,把数据取出来,哪怎么对位段进行写入呢?
看看CC2538的CTLBASE寄存器,这个比较典型 如下:
上面的地址是8bit+8bit+6bit,总共就是22bit. 假设我要把 0X375624写到ADDR里面去,要怎么操作呢?
来吧,看招:
REG(UDMA_CTLBASE) = 0x375624<<8; printf("UDMA_CTLBASE_addr:0x%x\nUDMA_CTLBASE_data:0x%x\n", ®(UDMA_CTLBASE), REG(UDMA_CTLBASE)>>8);
执行效果:
第一个字节是RESERVED,是0,用0X00表示; 第二个字的低2bit位是00,用0xF?; ?号位只能是1100, 1000, 0100, 0000这么说吧.
它就只能是0xFC; 0XF8; 0XF4; 0XF0,这4种值了!要还不明白,我也没办法解释了(用惯STM32集成库的后果,不会寄存器操作!!)
看代码后,你会发现,这数据还真是移出来的!!!。一个字节是0XFF,哪么半字节就是0X0F或0xF0,其实最小处理单位是半字节。
(还记得老古董--->4位单片机吗?? :)
时间:2020-12-11
将IAR下\MYdemo\user\src的platform.c和对应的linux下的platform.c都改成如下:
#include "contiki.h" #include "dev/uart.h" #include "dev/cc2538-rf.h" #include "dev/udma.h" #include "lib/sensors.h" #include "net/netstack.h" #include "net/mac/framer/frame802154.h" #include "net/linkaddr.h" #include "sys/platform.h" #include "soc.h" #include "cpu.h" #include "reg.h" #include "ieee-addr.h" #include <stdint.h> #include <string.h> #include <stdio.h> static void set_rf_params(void) { uint16_t short_addr; uint8_t ext_addr[8]; ieee_addr_cpy_to(ext_addr, 8); short_addr = ext_addr[7]; short_addr |= ext_addr[6] << 8; NETSTACK_RADIO.set_value(RADIO_PARAM_PAN_ID, IEEE802154_PANID); NETSTACK_RADIO.set_value(RADIO_PARAM_16BIT_ADDR, short_addr); NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, IEEE802154_DEFAULT_CHANNEL); NETSTACK_RADIO.set_object(RADIO_PARAM_64BIT_ADDR, ext_addr, 8); } /*---------------------------------------------------------------------------*/ void platform_init_stage_one(void) { soc_init(); } /*---------------------------------------------------------------------------*/ void platform_init_stage_two() { uart_init(0); udma_init(); /* Populate linkaddr_node_addr */ ieee_addr_cpy_to(linkaddr_node_addr.u8, LINKADDR_SIZE); INTERRUPTS_ENABLE(); } /*---------------------------------------------------------------------------*/ void platform_init_stage_three() { set_rf_params(); printf("\nUDMA_STAT_addr:%p---------UDMA_STAT_data:0x%x\n", ®(UDMA_STAT), (unsigned int)REG(UDMA_STAT)); printf("UDMA_CFG_addr:%p----------UDMA_CFG_data:0x%x\n", ®(UDMA_CFG), (unsigned int)REG(UDMA_CFG)); printf("UDMA_CTLBASE_addr:%p------UDMA_CTLBASE_data:0x%x\n", ®(UDMA_CTLBASE), (unsigned int)REG(UDMA_CTLBASE)); printf("UDMA_ALTBASE_addr:%p------UDMA_ALTBASE_data:0x%x\n", ®(UDMA_ALTBASE), (unsigned int)REG(UDMA_ALTBASE)); printf("UDMA_WAITSTAT_addr:%p-----UDMA_WAITSTAT_data:0x%x\n", ®(UDMA_WAITSTAT), (unsigned int)REG(UDMA_WAITSTAT)); printf("UDMA_SWREQ_addr:%p--------UDMA_SWREQ_data:0x%x\n", ®(UDMA_SWREQ), (unsigned int)REG(UDMA_SWREQ)); printf("UDMA_USEBURSTSET_addr:%p--UDMA_USEBURSTSET_data:0x%x\n", ®(UDMA_USEBURSTSET), (unsigned int)REG(UDMA_USEBURSTSET)); printf("UDMA_USEBURSTCLR_addr:%p--UDMA_USEBURSTCLR_data:0x%x\n", ®(UDMA_USEBURSTCLR), (unsigned int)REG(UDMA_USEBURSTCLR)); printf("UDMA_REQMASKSET_addr:%p---UDMA_REQMASKSET_data:0x%x\n", ®(UDMA_REQMASKSET), (unsigned int)REG(UDMA_REQMASKSET)); printf("UDMA_REQMASKCLR_addr:%p---UDMA_REQMASKCLR_data:0x%x\n", ®(UDMA_REQMASKCLR), (unsigned int)REG(UDMA_REQMASKCLR)); printf("UDMA_ENASET_addr:%p-------UDMA_ENASET_data:0x%x\n", ®(UDMA_ENASET), (unsigned int)REG(UDMA_ENASET)); printf("UDMA_ENACLR_addr:%p-------UDMA_ENACLR_data:0x%x\n", ®(UDMA_ENACLR), (unsigned int)REG(UDMA_ENACLR)); printf("UDMA_ALTSET_addr:%p-------UDMA_ALTSET_data:0x%x\n", ®(UDMA_ALTSET), (unsigned int)REG(UDMA_ALTSET)); printf("UDMA_ALTCLR_addr:%p-------UDMA_ALTCLR_data:0x%x\n", ®(UDMA_ALTCLR), (unsigned int)REG(UDMA_ALTCLR)); printf("UDMA_PRIOSET_addr:%p------UDMA_PRIOSET_data:0x%x\n", ®(UDMA_PRIOSET), (unsigned int)REG(UDMA_PRIOSET)); printf("UDMA_PRIOCLR_addr:%p------UDMA_PRIOCLR_data:0x%x\n", ®(UDMA_PRIOCLR), (unsigned int)REG(UDMA_PRIOCLR)); printf("UDMA_ERRCLR_addr:%p-------UDMA_ERRCLR_data:0x%x\n", ®(UDMA_ERRCLR), (unsigned int)REG(UDMA_ERRCLR)); printf("UDMA_CHASGN_addr:%p-------UDMA_CHASGN_data:0x%x\n", ®(UDMA_CHASGN), (unsigned int)REG(UDMA_CHASGN)); printf("UDMA_CHIS_addr:%p---------UDMA_CHIS_data:0x%x\n", ®(UDMA_CHIS), (unsigned int)REG(UDMA_CHIS)); printf("UDMA_CHMAP0_addr:%p-------UDMA_CHMAP0_data:0x%x\n", ®(UDMA_CHMAP0), (unsigned int)REG(UDMA_CHMAP0)); printf("UDMA_CHMAP1_addr:%p-------UDMA_CHMAP1_data:0x%x\n", ®(UDMA_CHMAP1), (unsigned int)REG(UDMA_CHMAP1)); printf("UDMA_CHMAP2_addr:%p-------UDMA_CHMAP2_data:0x%x\n", ®(UDMA_CHMAP2), (unsigned int)REG(UDMA_CHMAP2)); printf("UDMA_CHMAP3_addr:%p-------UDMA_CHMAP3_data:0x%x\n", ®(UDMA_CHMAP3), (unsigned int)REG(UDMA_CHMAP3)); } /*---------------------------------------------------------------------------*/ void platform_idle() { }
将IAR和LINUX的contiki-main.c都改成这样:
#include "contiki.h" #include "contiki-net.h" #include "sys/node-id.h" #include "sys/platform.h" #include "sys/energest.h" #include "sys/stack-check.h" #include "dev/watchdog.h" #include "net/queuebuf.h" #include "net/app-layer/coap/coap-engine.h" #include "net/app-layer/snmp/snmp.h" #include "services/rpl-border-router/rpl-border-router.h" #include "services/orchestra/orchestra.h" #include "services/shell/serial-shell.h" #include "services/simple-energest/simple-energest.h" #include "services/tsch-cs/tsch-cs.h" #include <stdio.h> #include <stdint.h> /*---------------------------------------------------------------------------*/ /* Log configuration */ #include "sys/log.h" #define LOG_MODULE "Main" #define LOG_LEVEL LOG_LEVEL_MAIN /*---------------------------------------------------------------------------*/ /*---------------------------------主MAIN入口--------------------------------*/ int main(void) { platform_init_stage_one(); rtimer_init(); process_init(); process_start(&etimer_process, NULL); ctimer_init(); platform_init_stage_two(); netstack_init(); node_id_init(); #if NETSTACK_CONF_WITH_IPV6 { uip_ds6_addr_t *lladdr; memcpy(&uip_lladdr.addr, &linkaddr_node_addr, sizeof(uip_lladdr.addr)); process_start(&tcpip_process, NULL); lladdr = uip_ds6_get_link_local(-1); LOG_INFO_6ADDR(lladdr != NULL ? &lladdr->ipaddr : NULL); } #endif /*NETSTACK_CONF_WITH_IPV6 */ platform_init_stage_three(); autostart_start(autostart_processes); /*---------------------------------主循环体----------------------------------*/ while(1){ do{ } while(process_run() > 0); }//while(1) return 0; }//main()
这个在Iinux测试中,UDP功能正常的,IAR不正常的。
我把它们printf信息放在一起 ,看一下它们的区别:
// linux server: fe80::212:4b00:5aa:8aa0 UDMA_STAT_addr:#0x400ff000---------UDMA_STAT_data:0x1f0001 UDMA_CFG_addr:#0x400ff004----------UDMA_CFG_data:0x0 UDMA_CTLBASE_addr:#0x400ff008------UDMA_CTLBASE_data:0x20000000 UDMA_ALTBASE_addr:#0x400ff00c------UDMA_ALTBASE_data:0x20000200 UDMA_WAITSTAT_addr:#0x400ff010-----UDMA_WAITSTAT_data:0xfffffc0 UDMA_SWREQ_addr:#0x400ff014--------UDMA_SWREQ_data:0x0 UDMA_USEBURSTSET_addr:#0x400ff018--UDMA_USEBURSTSET_data:0x0 UDMA_USEBURSTCLR_addr:#0x400ff01c--UDMA_USEBURSTCLR_data:0x0 UDMA_REQMASKSET_addr:#0x400ff020---UDMA_REQMASKSET_data:0xc UDMA_REQMASKCLR_addr:#0x400ff024---UDMA_REQMASKCLR_data:0xc UDMA_ENASET_addr:#0x400ff028-------UDMA_ENASET_data:0x0 UDMA_ENACLR_addr:#0x400ff02c-------UDMA_ENACLR_data:0x0 UDMA_ALTSET_addr:#0x400ff030-------UDMA_ALTSET_data:0x0 UDMA_ALTCLR_addr:#0x400ff034-------UDMA_ALTCLR_data:0x0 UDMA_PRIOSET_addr:#0x400ff038------UDMA_PRIOSET_data:0x0 UDMA_PRIOCLR_addr:#0x400ff03c------UDMA_PRIOCLR_data:0x0 UDMA_ERRCLR_addr:#0x400ff04c-------UDMA_ERRCLR_data:0x0 UDMA_CHASGN_addr:#0x400ff500-------UDMA_CHASGN_data:0x0 UDMA_CHIS_addr:#0x400ff504---------UDMA_CHIS_data:0x0 UDMA_CHMAP0_addr:#0x400ff510-------UDMA_CHMAP0_data:0x0 UDMA_CHMAP1_addr:#0x400ff514-------UDMA_CHMAP1_data:0x0 UDMA_CHMAP2_addr:#0x400ff518-------UDMA_CHMAP2_data:0x0 UDMA_CHMAP3_addr:#0x400ff51c-------UDMA_CHMAP3_data:0x0 The UDP-server. wudma_isr() // IAR server: fe80::212:4b00:5aa:8aa0 UDMA_STAT_addr:#0x400ff000---------UDMA_STAT_data:0x1f0001 UDMA_CFG_addr:#0x400ff004----------UDMA_CFG_data:0x0 UDMA_CTLBASE_addr:#0x400ff008------UDMA_CTLBASE_data:0x20006000 UDMA_ALTBASE_addr:#0x400ff00c------UDMA_ALTBASE_data:0x20006200 UDMA_WAITSTAT_addr:#0x400ff010-----UDMA_WAITSTAT_data:0xfffffc0 UDMA_SWREQ_addr:#0x400ff014--------UDMA_SWREQ_data:0x0 UDMA_USEBURSTSET_addr:#0x400ff018--UDMA_USEBURSTSET_data:0x0 UDMA_USEBURSTCLR_addr:#0x400ff01c--UDMA_USEBURSTCLR_data:0x0 UDMA_REQMASKSET_addr:#0x400ff020---UDMA_REQMASKSET_data:0xc UDMA_REQMASKCLR_addr:#0x400ff024---UDMA_REQMASKCLR_data:0xc UDMA_ENASET_addr:#0x400ff028-------UDMA_ENASET_data:0x0 UDMA_ENACLR_addr:#0x400ff02c-------UDMA_ENACLR_data:0x0 UDMA_ALTSET_addr:#0x400ff030-------UDMA_ALTSET_data:0x0 UDMA_ALTCLR_addr:#0x400ff034-------UDMA_ALTCLR_data:0x0 UDMA_PRIOSET_addr:#0x400ff038------UDMA_PRIOSET_data:0x0 UDMA_PRIOCLR_addr:#0x400ff03c------UDMA_PRIOCLR_data:0x0 UDMA_ERRCLR_addr:#0x400ff04c-------UDMA_ERRCLR_data:0x0 UDMA_CHASGN_addr:#0x400ff500-------UDMA_CHASGN_data:0x0 UDMA_CHIS_addr:#0x400ff504---------UDMA_CHIS_data:0x0 UDMA_CHMAP0_addr:#0x400ff510-------UDMA_CHMAP0_data:0x0 UDMA_CHMAP1_addr:#0x400ff514-------UDMA_CHMAP1_data:0x0 UDMA_CHMAP2_addr:#0x400ff518-------UDMA_CHMAP2_data:0x0 UDMA_CHMAP3_addr:#0x400ff51c-------UDMA_CHMAP3_data:0x0 The UDP-server.
哈哈哈哈,仔细对照一下,发现它俩的值不一样。
UDMA_CTLBASE_addr:#0x400ff008
UDMA_ALTBASE_addr:#0x400ff00c
时间:2020-12-12
在udma.c的udma_init():
void udma_init() { memset((void *)&channel_config, 0, sizeof(channel_config)); REG(UDMA_CFG) = UDMA_CFG_MASTEN; REG(UDMA_CTLBASE) = (uint32_t)(&channel_config);//NVIC_EnableIRQ(UDMA_SW_IRQn); //NVIC_EnableIRQ(UDMA_ERR_IRQn); }
这个channel_config是一个结构体数组,原型如下:
static volatile struct channel_ctrl channel_config[UDMA_CONF_MAX_CHANNEL + 1] __attribute__ ((section(".udma_channel_control_table")));
__attribute__直接关联\arch\cpu\cc2538的startup-gcc.c文件:
/*---------------------------------------------------------------------------*/ /* Allocate stack space */ static uint64_t stack[256] __attribute__ ((section(".stack"))); /*---------------------------------------------------------------------------*/ __attribute__((__section__(".vectors")))
我也是无语了,在IAR中,我都不用原来GCC的启动文件了,使用自己改写的IAR文件。搞来搞去还是回到startup-GCC文件这里来,
startup-iar.c还没想好怎么写,先这样吧!!
时间:2020-12-13
把platform.c的udma_init()注译掉,直接操作寄存器:发现Linux平台下make,HEX烧进芯片里面去,都是正常的:
void platform_init_stage_two() { uart_init(0); //udma_init(); 下在完成一样的功能,在LINUX通过 REG(UDMA_CFG) = UDMA_CFG_MASTEN; REG(UDMA_CTLBASE) = 0x20000000;//直接操作寄存器, REG(UDMA_ALTBASE) = 0x20000200; NVIC_EnableIRQ(UDMA_SW_IRQn); NVIC_EnableIRQ(UDMA_ERR_IRQn); printf("\n------------------------func:%s()\tline:%d\n", __FUNCTION__, __LINE__); //函数名+加行号,找到代码出处 printf("UDMA_CTLBASE_addr:%p------UDMA_CTLBASE_data:0x%x\n", ®(UDMA_CTLBASE), (unsigned int)REG(UDMA_CTLBASE)); printf("UDMA_ALTBASE_addr:%p------UDMA_ALTBASE_data:0x%x\n", ®(UDMA_ALTBASE), (unsigned int)REG(UDMA_ALTBASE)); /* Populate linkaddr_node_addr */ ieee_addr_cpy_to(linkaddr_node_addr.u8, LINKADDR_SIZE); INTERRUPTS_ENABLE(); }
运行效果:
但是在IAR就有问题了!仿真时,cc2538-rf.c停在while(udma_channel_get_mode(CC2538_RF_CONF_RX_DMA_CHAN))这里,
有个ERR_ISR异常,无语了:
这个udma_channel_get_mode()原型,位于udma.c里面:
/*---------------------------------------------------------------------------*/ //////////////////////////LINUX是这个值呀/////////#define TTES 0x20000038 uint8_t udma_channel_get_mode(uint8_t channel) { if(channel > UDMA_CONF_MAX_CHANNEL) { return 0; } ///////////////////////////printf("channel_config_data:%x\n", (unsigned int)channel_config[channel].ctrl_word & 0x7); ///////////////////////////printf("channel_config_addr:%p\n", &channel_config[channel].ctrl_word); /////////IAR//UDP没有通过/////printf("channel_config_data:%x\n", (unsigned int)channel_config[channel].ctrl_word & 0x7); ///////////////////////////printf("tt_addr:%p\n", ®(TTES)); ///////////////////////////printf("tt_data:%x\n", (unsigned int)REG(TTES)); // while(1);/////////////// 地址不对 return (channel_config[channel].ctrl_word & 0x07); }
LINUX和IAR打印出来的值跟本不一样,虽然知道问题点,但不知道如果解决它!这个系统是深度定制芯片的吧?一定要用GCC?一定要用STARTUP-GCC?
难道真要转到LINUX平台下去玩吗??
比如在IAR OK的 printf("UDMA_ALTBASE_addr:%p------UDMA_ALTBASE_data:0x%x\n", ®(UDMA_ALTBASE), REG(UDMA_ALTBASE));
在LINUX就不行了,加入强制作转换才行, printf("UDMA_ALTBASE_addr:%p------UDMA_ALTBASE_data:0x%x\n", ®(UDMA_ALTBASE), (unsigned int)REG(UDMA_ALTBASE));
太多 太多这些小区别了!!!难受。。。。。。。。。
时间:2020-12-16
只要不放弃,想方设法,问题终于会解决的。所以CONTIKI NG在IAR上的应用进度,我们还得继续下去。
从上次的打印息中,有一个cc2538_rf_err_isr()的错误中断,看来RF外设工作有问题了,所以DMA一直
等待RF传输完成,而RF一直在报错中断里面,永远完成不了,进入while(1)了。
因此,还要把RF无线发射器的外设,它相关寄存器也要全面的核对一遍!!(就像DMA一样 哈哈)
说不定会有天大的惊喜呢!!先认准RF相关文件目录条,
CONTIKI代码上的:
数据手册上的
我们只能求助官方数据的手册了,多回读一下【进阶学习CONTIKI NG之网络协议导读1】和
【进阶学习CONTIKI NG之网络协议导读2】,因这些基础升华是不断强化的过程。要不然连CoAP
是啥都不清楚。。。。。
时间:2020-12-20
做人做事,如果很明白前因后果,就要当机立断,不可犹豫不决。
CONTIKI NG是LINIUX平台的,同样的C源码,在WINDOWS平台确实存在差异,
关于集成RF这部份(核心部份),估计要碰及低层部份,如此一来就没有必要了,
还不如直接在LINUX下玩,就好比你用XP系统作业,难道要去编写XP的核心底层吗?
即使花大量精力去了解,其实也做不出什么实质性的、市场认可的产品出来!
因此决定,将WINDOW的IAR平台CONTIKI删除所有关于RF的无线网络的功能
;当要使用到无线节点互联时,将转到LINUX下去研究CONTIKI。OS下的services、
storage全部功能要在IAR中保留,别把CONTIKI搞成四不像!!
( 在IAR中,如果UDP通了,就等于COAP通了,也相当于LWM2M也通了。只能说
个人能力有限,可能操作系统的应用,多数是团队合作完成的吧 )