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的板子上调度成功,测试代码如下:实现了一个灯周期性的闪烁,其它三个灯根据输入的数字点亮:
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按键做反应。