Conkiti的调度内核很简单:使用轻量级的proto-threads进程模型,可以在事件驱动内核上提供一种线性的、类似于线程的编程风格。
因此Conkiti的上下文保存不会使用到汇编而完全用C语言完成,proto-threads属于抢占式OS模型,需要进程主动释放CPU,进程的上下文通过当前文件的行号保存。因此上下文切换可以通过C完成。
1.调度内核涉及的文件:
conkiti/core/sys/
arg.c ctimer.c etimer.h pt-sem.h subprocess.h
arg.h ctimer.h lc-addrlabels.h pt.h timer.c
autostart.c dsc.h lc-switch.h process.c rtimer.c timer.h
autostart.h energest.c lc.h process.h rtimer.h
cc.h energest.h loader.h procinit.c stimer.c
clock.h etimer.c log.h procinit.h stimer.h
conkiti/core/lib/
crc16.c ifft.c makefile me_tabs.h ringbuf.c
crc16.h ifft.h me.c nouse ringbuf.h
gcr.c list.c me.h petsciiconv.c strncasecmp.c
gcr.h list.h me_tabs.c petsciiconv.h
2.移植需要实现的函数:
void clock_init(void) 初始化时钟
安装clock tick中断到lpc11u14的cortex-m0内核定时器中断内
目前系统设置的是一个tick 1ms
clock tick中断为sec计时而设置,每1000个tick对sec做++处理
clock_time_t clock_time(void) 获取当前时钟tick数
直接返回lpc11u14系统tick数Lpc11u_System_GetTick()
unsigned long clock_seconds(void) 获取当期时钟秒计数
返回clock tick 中断内sec值
void clock_delay(unsigned int t) delay函数
这个函数会在contiki的dev下面用,目前移植调度内核,因此该函数暂时为空
3.调度内核配置
/* CC configuration*/
#define CC_CONF_REGISTER_ARGS 1 //允许寄存器变量
#define CC_CONF_FUNCTION_POINTER_ARGS 1 //允许函数指针
#define CC_CONF_FASTCALL __attribute__((fastcall)) //支持fastcall,fastcall是在传递参数时通过寄存器完成,而不使用压栈
//#define CC_CONF_CONST_FUNCTION_BUG
//#define CC_CONF_UNSIGNED_CHAR_BUGS
//#define CC_CONF_DOUBLE_HASH
#define CC_CONF_INLINE __attribute__((inline)) //支持inline函数
//#define CC_CONF_ASSIGN_AGGREGATE
//#define CC_CONF_NO_VA_ARGS 0
#define CC_BYTE_ALIGNED __attribute__ ((packed, aligned(1))) //支持结构体字节对齐
/* Process configuration*/
#define AUTOSTART_ENABLE 1 //开启process自动启动机制
#define PROCESS_CONF_NO_PROCESS_NAMES 0 //保存process name
按照如上配置和实现,已经在ds lpc11u14的板子上调度成功,测试代码如下:实现了一个灯周期性的闪烁,其它三个灯根据输入的数字点亮:
1
#include
"
driver/gpio.h
"
2
#include
"
driver/uart.h
"
3
4
#include
"
lpc11u_system.h
"
5
6
#include
"
contiki.h
"
7
8
9
static
process_event_t
event_data_ready;
10
static
u8
u8Data
=
0
;
11
12
13
PROCESS(Led_Flash,
"
Led-flash
"
);
14
PROCESS(Uart_PRC1,
"
Uart-Proc1
"
);
15
PROCESS(Uart_PRC2,
"
Uart-Proc2
"
);
16
17
AUTOSTART_PROCESSES(
&
Led_Flash,
&
Uart_PRC1,
&
Uart_PRC2);
18
19
int
main()
20
{
21
u8
u8Data;
22
23
u32
u32Time;
24
u8
u8i
=
0
;
25
26
Lpc11u_System_Init();
27
GPIO_Init();
28
Uart_Init();
29
Shell_Init();
30
31
SPI_Flash_Init();
32
33
u32Time
=
Lpc11u_System_GetTick();
34
35
printf(
"
Frank
Test:
Hello
world!\r\n
"
);
36
37
while
(u8i
<
10)
38
{
39
if
(Uart_Read(
0
,
&
u8Data,
1
,
0
)
=
=
1
)
40
{
41
printf(
"
Get
char
%c\r\n
"
,
u8Data);
42
}
43
44
if
(Lpc11u_SysTem_DiffTick(u32Time)
>
=
1000
)
45
{
46
u32Time
=
Lpc11u_System_GetTick();
47
48
if
(u8i%
4
=
=
0
)
49
{
50
GPIO_SetLevel(
0
,
0
);
51
GPIO_SetLevel(
1
,
1
);
52
GPIO_SetLevel(
2
,
1
);
53
GPIO_SetLevel(
3
,
1
);
54
}
55
else
if
(u8i%
4
=
=
1
)
56
{
57
GPIO_SetLevel(
0
,
1
);
58
GPIO_SetLevel(
1
,
0
);
59
GPIO_SetLevel(
2
,
1
);
60
GPIO_SetLevel(
3
,
1
);
61
}
62
else
if
(u8i%
4
=
=
2
)
63
{
64
GPIO_SetLevel(
0
,
1
);
65
GPIO_SetLevel(
1
,
1
);
66
GPIO_SetLevel(
2
,
0
);
67
GPIO_SetLevel(
3
,
1
);
68
}
else
if
(u8i%
4
=
=
3
)
69
{
70
GPIO_SetLevel(
0
,
1
);
71
GPIO_SetLevel(
1
,
1
);
72
GPIO_SetLevel(
2
,
1
);
73
GPIO_SetLevel(
3
,
0
);
74
}
75
u8i
+
+
;
76
}
77
}
78
79
80
printf(
"
Test
OK,
Start
contiki....\r\n
"
);
81
clock_init();
82
process_init();
83
ctimer_init();
84
85
process_start(
&
etimer_process,
NULL
);
86
autostart_start(autostart_processes);
87
88
while
(
1
)
89
{
90
etimer_request_poll();
91
do
92
{
93
}
while
(process_run()
>
0
);
94
}
95
return
0
;
96
}
97
98
99
PROCESS_THREAD(Led_Flash,
ev,
data)
100
{
101
static
u8
u8i
=
0
;
102
static
u8
*
pu8Data;
103
104
PROCESS_BEGIN();
105
106
printf(
"
%s
process
start!\r\n
"
,
PROCESS_NAME_STRING(
&
Led_Flash));
107
108
while
(
1
)
109
{
110
PROCESS_WAIT_EVENT_UNTIL(ev
=
=
event_data_ready);
111
pu8Data
=
data;
112
113
if
(
*
pu8Data
=
=
8
)
114
{
115
GPIO_SetLevel(
0
,
(u8i
+
+
)
&
0x01
);
116
}
117
else
118
{
119
//
printf("%s->
Get
event
data
%u\r\n",
PROCESS_NAME_STRING(&Led_Flash),
*pu8Data);
120
GPIO_SetLevel(
3
,
(
*
pu8Data
&
0x1
));
121
GPIO_SetLevel(
2
,
(
*
pu8Data
>
>
1)
&
0x1
);
122
GPIO_SetLevel(
1
,
(
*
pu8Data
>
>
2)
&
0x1
);
123
}
124
}
125
126
PROCESS_END();
127
}
128
129
PROCESS_THREAD(Uart_PRC1,
ev,
data)
130
{
131
PROCESS_BEGIN();
132
133
static
struct
etimer
timer;
134
etimer_set(
&
timer,
1000
);
//
etimer
who
seting
,whe
used
135
printf(
"
%s
process
start!\r\n
"
,
PROCESS_NAME_STRING(
&
Uart_PRC1));
136
137
event_data_ready
=
process_alloc_event();
138
139
while
(
1
)
140
{
141
PROCESS_WAIT_EVENT_UNTIL(ev
=
=
PROCESS_EVENT_TIMER);
142
//
printf("%s->
Time
Get\r\n",
PROCESS_NAME_STRING(&Uart_PRC1));
143
u8Data
=
8
;
144
process_post(
&
Led_Flash,
event_data_ready,
&
u8Data);
145
etimer_reset(
&
timer);
146
}
147
148
PROCESS_END();
149
}
150
151
PROCESS_THREAD(Uart_PRC2,
ev,
data)
152
{
153
PROCESS_BEGIN();
154
static
struct
etimer
timer;
155
static
u8
u8Read;
156
etimer_set(
&
timer,
20
);
//
etimer
who
seting
,whe
used
157
printf(
"
%s
process
start!\r\n
"
,
PROCESS_NAME_STRING(
&
Uart_PRC2));
158
159
while
(
1
)
160
{
161
PROCESS_WAIT_EVENT_UNTIL(ev
=
=
PROCESS_EVENT_TIMER);
162
if
(
1
=
=
Uart_Read(
0
,
&
u8Read,
1
,
0
))
163
{
164
//
printf("%s
Get
Uart
Data
%c\r\n",
PROCESS_NAME_STRING(&Uart_PRC2),
u8Read);
165
u8Data
=
u8Read
-
0x30
;
166
if
(u8Data
>
=
0
&
&
u8Data
<
=
7
)
167
{
168
//
printf("%s
Send
Uart
Data
%u
to
Led_Flash\r\n",
PROCESS_NAME_STRING(&Uart_PRC2),
u8Data);
169
process_post(
&
Led_Flash,
event_data_ready,
&
u8Data);
170
}
171
else
172
{
173
//
printf("%s
No
Send
Uart
Data\r\n",
PROCESS_NAME_STRING(&Uart_PRC2));
174
}
175
}
176
etimer_reset(
&
timer);
177
}
178
179
PROCESS_END();
180
}
181
182
以上
Led_Flash process接收event,根据event信息决定点亮那些LED
Uart_PRC1 process每1s发一次event到Led_Flash process, 改变LED 0的状态
Uart_PRC2 process每20 ms读一次串口,根据串口接收到的数据改变LED1~3的状态,只对0~7按键做反应。