想来想去,还是得先写一个程序,找下感觉,增强一下自信心,那就国际惯例Hello World吧。
先到这个网址下一个Instant Contiki 2.7。之所以没用3.0的,是因为有些问题,我源码是下的3.0的。
http://sourceforge.net/projects/contiki/files/Instant%20Contiki/
下完后装个VMWear,载入Instant Contiki 2.7虚拟机,就可以在Ubuntu上用contiki了。
打开终端,默认是用user用户名登录,密码也是user。ls一下,看见有contiki目录就对了。接下来在user根目录下建一个demo目录用来存放自己的工程,然后在demo目录下建一个helloworld目录,然后进去。
建一个hello-world.c文件,输入如下代码:
1 #include "contiki.h"
2 #include <stdio.h>
3 PROCESS(HW, "HWP");
4 AUTOSTART_PROCESSES(&HW);
5 PROCESS_THREAD(HW, ev, data)
6 {
7 PROCESS_BEGIN();
8 printf("Hello world!\n"); //此处放自己的代码
9 PROCESS_END();
10 }
接下来回到user根目录,然后进入contiki目录,敲pwd命令,记下当前路径,等下要用。重新进入helloworld目录,新建一个Makefile文件,输入如下代码:
CONTIKI_PROJECT = hello-world
all: $(CONTIKI_PROJECT)
/* Contiki源文件根目录,使用前面记下的路径 */
CONTIKI = /home/user/contiki
include $(CONTIKI)/Makefile.include
准备工作完成,敲入命令make,编译、生成可执行文件。此处相当坑爹,代码写错几处,编译不过,要删除生成的文件再编译,折磨死我了。先将就着,以后要换个工具写代码。生成完后,如图所示,生成很多文件。
看到绿色文件没?执行它,结果如图所示:
出现Hello World!后程序不会自动退出,这跟在Linux下写C程序可是不一样的。按Ctrl+C退出程序。
好,举杯庆祝迈出了关键一步。下面的大段分析就以此展开。
hello-world.c的代码真正属于自己的代码只有printf语句,其他都是固定格式。也就是说将来写程序是在PROCESS_BEGIN();和PROCESS_END();之间写自己的代码。main()方法呢?main方法是有,不在这里,不用我们自己写,习惯就好。
好,先分析第一句代码
PROCESS(HW, "HWP");
先看看PROCESS源码,就在前一篇process结构体上面:
1 #if PROCESS_CONF_NO_PROCESS_NAMES
2 #define PROCESS(name, strname) \
3 PROCESS_THREAD(name, ev, data); \
4 struct process name = { NULL, \
5 process_thread_##name }
6 #else
7 #define PROCESS(name, strname) \
8 PROCESS_THREAD(name, ev, data); \
9 struct process name = { NULL, strname, \
10 process_thread_##name }
和之前一样,只考虑有名字的情况,代入实参PROCESS变为:
PROCESS(HW, "HWP");
再代入下面公式,变为:
PROCESS_THREAD(HW, ev, data); \
struct process HW= { NULL, "HWP", process_thread_HW }
接下来看看PROCESS_THREAD的声明,
1 /**
2 * Define the body of a process.
3 *定义process主体
4 * This macro is used to define the body (protothread) of a
5 * process. The process is called whenever an event occurs in the
6 * system, A process always start with the PROCESS_BEGIN() macro and
7 * end with the PROCESS_END() macro.
8 *此宏用于定义一个process的主体,当某事件发生时,process被调用。process总是从PROCESS_BEGIN()宏开始,并结束于
9 *PROCESS_END() 宏
10 */
11 #define PROCESS_THREAD(name, ev, data) \
12 static PT_THREAD(process_thread_##name(struct pt *process_pt, \
13 process_event_t ev, \
14 process_data_t data))
越来越复杂了,继续代入吧 PROCESS_THREAD(HW, ev, data); 变为:
static PT_THREAD(process_thread_HW(struct pt *process_pt,
process_event_t ev,
process_data_t data))
还没完,还得跟踪PT_THREAD,在Pt.h头文件中,先看看定义:
#define PT_THREAD(name_args) char name_args
这个……这个上一篇日志中刚接触过,用于把一个东西变成函数指针,先代入看看:
static char process_thread_HW(struct pt *process_pt, process_event_t ev, process_data_t data)
这回没变成函数指针,而是一个方法,看来PT_THREAD这个宏定义专门用来生成函数,它有注释,看看怎么说:
* Declaration of a protothread.
*声明一个线程原型
* This macro is used to declare a protothread. All protothreads must
* be declared with this macro.
*此宏用于声明线程原型,所有的线程原型必须通过此宏声明
* \param name_args The name and arguments of the C function
*参数name_args:C函数的名称和参数
* implementing the pr