Tải bản đầy đủ (.doc) (29 trang)

Làm quen với hệ điều hành contiki trên KIT MSP430G2553

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (628.03 KB, 29 trang )

TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI

VIỆN ĐIỆN TỬ - VIỄN THÔNG

ĐỒ ÁN I

THIẾT KẾ PHẦM MỀM
Đề tài:

LÀM QUEN VỚI HỆ ĐIỀU HÀNH CONTIKI
TRÊN KIT MSP430G2553

Giảng viên hướng dẫn:

THS. NGUYỄN NAM PHONG

Hà Nội, 6-2015


MỤC LỤC
MỤC LỤC.................................................................................................................................................................2
Mở Đầu......................................................................................................................................................................3
Phần 1. Giới thiệu về hệ điều hành Contiki và kit lunchpad MSP430............................................................3
1.1 Hệ điều hành Contiki................................................................................................................................3
1.1.1 Tổng quan và lịch sử phát triển.........................................................................................................3
1.1.2 Đặc điểm của hệ điều hành Contiki..................................................................................................4
1.2 Kit MSP430G2553....................................................................................................................................4
1.2.1 Tổng quan.........................................................................................................................................4
1.2.2 Cấu trúc.............................................................................................................................................6
1.2.3 Kết nối UART...................................................................................................................................7
1.3 Cài đặt và nạp code lên Kit......................................................................................................................8


1.3.1 Cài đặt Contiki..................................................................................................................................8
1.3.2Cài đặt eclip.......................................................................................................................................9
1.3.3 Cài contiki launchpad và các trình biên dịch....................................................................................9
Phần 2. Tổ chức và hệ thống Contiki.................................................................................................................11
2.1 Process Contiki.......................................................................................................................................11
2.1.1 The Structure of a Process..............................................................................................................11
2.1.1.1 The Process Control Block......................................................................................................12
2.1.1.2 The Process Thread.................................................................................................................12
2.1.2 Protothreads....................................................................................................................................13
2.1.3 Protothreads in Processes................................................................................................................13
2.1.4 Events..............................................................................................................................................14
2.1.4.1 Asynchronous Events..............................................................................................................15
2.1.4.2 Synchronous Events................................................................................................................15
2.1.4.3 Polling.....................................................................................................................................15
2.1.5 The Process Scheduler....................................................................................................................15
2.1.5.1 Starting Processes....................................................................................................................16
2.1.5.2 Exiting and Killing Processes.................................................................................................16
2.1.5.3 Autostarting Processes............................................................................................................16
2.2.1 The Contiki Timer Modules............................................................................................................16
2.2.2 The Clock Module..........................................................................................................................17
2.2.3 The Timer Library...........................................................................................................................17
2.3.1 Serial Communication.....................................................................................................................18
2.1.2 LEDs...............................................................................................................................................19
Phần 3. Giải thích code mẫu và bài tập..............................................................................................................21
3.1.1 Blink example.................................................................................................................................21
3.1.2 Button example...............................................................................................................................23
3.2.1 Sử dụng các cấu trúc tuần tự, lặp, rẽ nhánh....................................................................................24
3.2.2 Điều khiển leds bằng tập lệnh thông qua uart.................................................................................26

2



Mở Đầu
Đối với ngành Điện tử truyền thông nói chung và Điện tử nói riêng thì việc
lập trình cho vi xử lý là vô cùng quan trọng. Các phong cách lập trình cũ sẽ bị hạn
chế nhiều bởi tính song song của chương trình. Do đó, đồ án sẽ nghiên cứu một
cách lập trình mới cho vi xử lý sử dụng hệ điều hành contiki. Để đơn giản và thuận
lợi cho quá trình làm việc cũng như sự liền mạch cho các đồ án sau này, chúng ta sử
dụng mạch mô phỏng là kit MSP430G2533 của TI.
Do thời gian thực hiện và kiến thức còn hạn chế nên còn nhiều sai sót trong
quá trình thực hiện đề tài, rất mong được sự bổ sung đóng góp của các thầy cô và
các bạn.
Chúng em xin chân trọng cảm ơn thầy Nguyễn Nam Phong và anh Nguyễn
Văn Giang đã nhiệt tình hướng dẫn chúng em suốt quá trình học tập.

Phần 1. Giới thiệu về hệ điều hành Contiki và kit
lunchpad MSP430
1.1 Hệ điều hành Contiki
1.1.1 Tổng quan và lịch sử phát triển
Hệ điều hành contiki là hệ điều hành mã nguồn mở, được nghiên cứu, thiết
kế và phát triển bởi một nhóm các nhà phát triển từ viện khoa học máy tính Thụy
Điển, người đứng đầu là Adam Dunkels. Nhóm phát triển Contiki gồm nhiều thành
viên đến từ SICS, CISCO, cùng nhiều tổ chức và các trường đại học khác trên thế
giới. Hệ điều hành Contiki được thiết kế cho các vi điều khiển có bộ nhớ nhỏ, với
thông số 2KB RAM và 40KB ROM. Nhờ đó, Contiki được sử dụng cho các hệ
thống nhúng và các ứng dụng trong mạng cảm biến không dây. Contiki bắt đầu
được nghiên cứu từ năm 2001 và phát hành phiên bản đầu tiên Contiki 1.0 năm
2003. Phiên bản hiện nay của Contiki là 2.4, với nhiều thay đổi, bổ sung và phát
triển vượt bậc. Trong thực tế, Contiki đã được ứng dụng trong nhiều dự án như
giám sát đường hầm xe lửa, theo dõi nước trong biển Baltic. Nhiều cơ chế, ý tưởng


3


trong Contiki đã được ứng dụng rộng rãi trong công nghiệp. Điển hình như mô hình
uIP được phát hành năm 2001 đã được sử dụng trong hệ thống ứng dụng của
hàng trăm công ty trong các lĩnh vực hàng hải, thông tin vệ tinh, khai thác dầu mỏ,
…;
Mô hình Protothreads được công bố lần đầu tiên năm 2005, đến nay đã được
sử dụng trong nhiều ứng dụng như bộ giải mã kỹ thuật số và thiết bị cảm biến rung
không dây.
1.1.2 Đặc điểm của hệ điều hành Contiki
Contiki OS được lập trình bằng ngôn ngữ C, hoạt động dựa trên cơ chế
event – driven và có những đặc điểm phù hợp với các hệ thống nhúng và mạng cảm
biến không dây:
• Contiki được chia thành nhiều modul hoạt động độc lập. Nhờ đó các ứng
dụng có thể sử dụng các modul một cách lih động và chỉ load những modul
cần thiết.
• Cơ chế hoạt động điều khiển sự kiện làm giảm năng lượng tiêu hao và hạn
chế dung lượng bộ nhớ cần sử dụng.
• Có thể sử dụng IP trong mạng cảm biến thông qua uIP stack được xây dựng
dựa trên nền TCP/IP
• Có những modul cho phép ước lượng và quản lý năng lượng một cách hiệu
quả.
• Các giao thức tương tác giữa các lớp và các node trong mạng dễ dàng hơn.
• Sử dụng RIME stack phục vụ các giao thức dành cho mạng năng lượng thấp
một cách hiệu quả.
Bên cạnh đó, Contiki còn cung cấp những công cụ hỗ trợ mô phỏng với
giao diện đơn giản, dễ sử dụng và hỗ trợ tốt những thiết bị trong thực tế, phục vụ
những mục đích nghiên cứu, mô phỏng và triển khia những giao thức mới.


1.2 Kit MSP430G2553
1.2.1 Tổng quan
Các dòng vi điều khiển msp430 này do hãng TI ( Texas Instruments) sản
xuất, ngoài ra thì TI còn sản xuất và cung cấp nhiều linh kiện điện tử và các module
4


khác, để tìm hiểu thì các bạn có thể tham khảo ở địa chỉ : www.ti.com để biết rõ
hơn. Vi điều khiển( Micro controller unit – MCU ) là đơn vị xử lý nhỏ, nó được tích
hợp toàn bộ các bộ nhớ như ROM , RAM , các port truy xuất , giao tiếp ngoại vi
trực tiếp trên 1 con chip hết sức nhỏ gọn. Được thiết kế dựa trên cấu trúc VONNEUMAN , đặc điểm của cấu trúc này là chỉ có duy nhất 1 bus giữa CPU và bộ nhớ
(data và chương trình) , do đó mà chúng phải có độ rộng bit tương tự nhau.
MSP430 có một số phiênbản như: MSP430x1xx, MSP430x2xx, MSP430x3xx,
MSP430x4xx, MSP430x5xx. Dưới đây là những đặc điểm tổng quát của họ vi điều
khiển MSP430:
+ Cấu trúc sử dụng nguồn thấp giúp kéo dài tuổi thọ của Pin
• Duy trì 0.1µA dòng nuôi RAM.
• Chỉ 0.8µA real-time clock.
• 250 µA/ MIPS.
+ Bộ tương tự hiệu suất cao cho các phép đo chính xác
• 12 bit hoặc 10 bit ADC-200 kskp, cảm biến nhiệt độ, Vref.
• 12 bit DAC.
+Bộ giám sát điện áp nguồn.
16 bit RISC CPU cho phép được nhiều ứng dụng, thể hiện một phần ở kích
thước Code lập trình.
-

Thanh ghi lớn nên loại trừ được trường hợp tắt nghẽn tập tin khi đang làm
việc.


-

Thiết kế nhỏ gọn làm giảm lượng tiêu thụ điện và giảm giá thành.

-

Tối ưu hóa cho những chương trình ngôn ngữ bậc cao như C, C++

-

Có 7 chế độ định địa chỉ.

-

Khả năng ngắt theo véc tơ lớn.

+ Trong lập trình cho bộ nhớ Flash cho phép thay đổi Code một cách linh hoạt,
phạm vi rộng, bộ nhớ Flash còn có thể lưu lại như nhật ký của dữ liệu.

5


1.2.2 Cấu trúc

Hình 1.1 Hình minh họa kit LaunchPad Rev.1.1 (bản ổn định hiện tại là Rev.1.5)
Một kit LaunchPad gồm hai thành phần, với GND được phủ chung:
- Nửa trên: Là phần mạch nạp theo chuẩn spy-bi-wire Jtag (2 dây), kết hợp
với chuyển đổi giao tiếp UART với máy tính. Trên cùng là đầu USBmini để nối với
máy tính, phía dưới là hàng Header để nối ra đối tượng cần giao tiếp, bao gồm các

chân:
TXD, RXD: phục vụ giao tiếp UART với máy tính.
RST, TEST: phục vụ nạp và debug (sửa lỗi) theo chuẩn spy-bi-wire Jtag.
VCC: cấp nguồn 3V3 cho đối tượng (thường là nửa dưới LaunchPad).

Hình1.2 Các chân cơ bản

6


- Nửa dưới: là một mạch phát triển MSP430 đơn giản, bao gồm:
Socket cắm MSP430 (thường gắn sẵn chip MSP430G2553), Pad hàn thạch
anh, Nút nhấn Reset chip.
Nút nhấn gắn vào P1.3, hai Led hiển thị có jumper để gắn vào P1.0 và P1.6.
Hai hàng header để kết nối hai hàng chân của chip ra ngoài, một hàng header
nguồn GND-GND-VCC để lấy nguồn 3V3 trên LaunchPad.
1.2.3 Kết nối UART
UART (Universal Asynchronous Receive/Transmit) – Truyền nhận dữ liệu
không đồng bộ . Đây là một trong những giao thức truyền thong phổ biến trong các
dòng vi điều khiển .
Kết nối phần cứng cơ bản :

Hình 1.3 Cấu trúc khung truyền/nhận

Hình 1.4 Khung truyền nhận dữ liệu
7


Để sử dụng được ở chế độ này, ta phải thay đổi chân cắm jump như hình sau:


Hình 1.5 Tinh chỉnh jump ở chế độ UART

1.3 Cài đặt và nạp code lên Kit
1.3.1 Cài đặt Contiki
• Step 1: Install Ubuntu
- Nên cài bản Ubuntu mới nhất là Ubuntu 14.04 64bit
- Link hướng dẫn: />- Lưu ý: Làm đúng theo các bước. Nếu làm sai có thể dẫn tới tình trạng Ubuntu cài
đè lên Windows.

8


• Step 2: Install GIT:
GIT là phần mềm quản lý mã nguồn Mở Terminal lên: Ctrl+Alt+T sudo apt-get
update sudo install git
• Step 3: Install CONTIKI từ Git Clone git clone
/>
1.3.2 Cài đặt eclip
• Step 1: Install Java 8 on Ubuntu
sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java8-installer
• Step 2: Download Eclipse Lunar
/>file=/technology/epp/downloads/release/luna/SR1a/eclipse-cpp-luna-SR1a-linuxgtk.tar.gz
• Step 3: Giải nén và sử dụng
- Khởi động Eclipse
- Để Import Contiki vào Eclipse: Chọn Project/Import... Chọn Browse và chọn thư
mục contiki. Nhấn Finish

1.3.3 Cài contiki launchpad và các trình biên dịch

• Step 1: Install Build Dependencies
sudo apt-get install subversion gcc-4.4 texinfo patch \ libncurses5-dev zlibc zlib1gdev libx11-dev libusb-dev \ libreadline6-dev
• Step 2: Install Compiler MSPDebug

9


tar xvfz mspdebug-0.9.tar.gz
cd mspdebug-0.9
make
sudo make install
• Step 3: Install MSP-GCC sudo apt-get install gcc-msp430
• Step 4: Download Contiki for Launchpad
git clone git://github.com/msloth/contiki-launchpad.git
• Step 5: Make a example
cd contiki-launchpad/example/blink
make clean
make
make blink.upload

10


Phần 2. Tổ chức và hệ thống Contiki
2.1 Process Contiki
Code trong Contiki được chia làm một trong hai loại:
• Cooperative code: Đoạn code này sẽ chạy tuần tự, code trước hoàn thành thì
nó mới thực hiện.
• Preemptive code: Đoạn mã này được dùng để ngắt hoặc khi sử dụng realtime timers.


Hình 2.1 Các loại code processes
Tất cả các chương trình trong contiki được gọi là processes. Mỗi processes
thường được bắt đầu khi khởi động hệ thống, một modul được nạp vào thống. Và
nó sẽ chạy khi một sự kiện nào đó xảy ra, chẳng hạn như timer xả, một điều kiện từ
bên ngoài,…
2.1.1 The Structure of a Process
Contiki process bao gồm 2 phần: Process control block và Process thread.
Process control block được lưu trữ trong RAM, chứa các thông tin tức thời như: tên,
trạng thái, con trỏ. Process Thread là đoạn mã và được lưu trữ trong ROM.

11


2.1.1.1 The Process Control Block
Process Control Block chứa thông tin về mỗi process, chẳng hạn như trạng
thái, con trỏ, và tên mô tả. Khối này chỉ được sử dụng bởi kernel và không bao giờ
được truy cập trực tiếp bằng process.
Cấu trúc bên trong của Process Control Block:
struct process {
struct process *next;
const char *name;
int (* thread)(struct pt *,
process_event_t,
process_data_t);
struct pt pt;
unsigned char state, needspoll;
};

Trong trường đầu tiên, next, trỏ tới Process Control Block kế tiếp trong danh sách
các process được khởi tạo. Trường name trỏ tới tên mô tả process. Trường thread, là

một con trỏ, trỏ đến process thread. Trường pt giữ trạng thái của protothread trong
process thread. Trường state và needspoll là cờ giúp giữ trạng thái của process. Các
cờ needspoll được thiết lập bởi hàm process_poll() khi process được hỏi.
Quá trình phức tạp trên được sử dụng trực tiếp thông qua lệnh:
PROCESS(name, "strname");
Example PROCESS(hello_world_process, "Hello world process");

2.1.1.2 The Process Thread
Process Thread là code của process.
Cấu trúc của như sau:
PROCESS_THREAD(name, ev, data)
{
PROCESS_BEGIN();
// code
PROCESS_END();
}
Example
PROCESS_THREAD(hello_world_process, ev, data)
{
PROCESS_BEGIN();
printf("Hello, world\n");
PROCESS_END();
}

12


2.1.2 Protothreads
Protothreads là một cấu trúc code cho phép hệ thống chạy các hoạt động
khác khi đợi một điều gì đó xảy ra. Protothreads ở đây khai thác trực tiếp trong hệ

điều hành contiki, ngoài ra nó được sử dụng tốt trong các lĩnh vực khác.
Protothread cho phép sử dụng các hàm có trong C giống như trong threads
mà không bị tràn bộ nhớ. Nó giảm dung lượng bộ nhớ và là điều rất quan trọng
trong các hệ thống có bộ nhớ khiêm tốn sử dụng Contiki.
Protothread là 1 hàm C. Hàm này bắt đầu và kết thúc bởi 2 lệnh

PT_BEGIN()

và PT_END().
Bản chất khi thực hiện chương trình trong protothread:
struct pt { lc_t lc };
#define PT_WAITING 0
#define PT_EXITED 1
#define PT_ENDED
2
#define PT_INIT(pt)
#define PT_BEGIN(pt)
#define PT_END(pt)

LC_INIT(pt->lc)
LC_RESUME(pt->lc)
LC_END(pt->lc);
\
return PT_ENDED
#define PT_WAIT_UNTIL(pt, c) LC_SET(pt->lc);
\
if(!(c))
\
return PT_WAITING
#define PT_EXIT(pt)

return PT_EXITED

Local continuationsimplementedwith the C switchstatement:
typedef
#define
#define
#define
#define

unsigned short lc_t;
LC_INIT(c)
c = 0
LC_RESUME(c) switch(c) { case 0:
LC_SET(c)
c = __LINE__; case __LINE__:
LC_END(c)
}

2.1.3 Protothreads in Processes
Trong Contiki, protothread được sử dụng dưới những câu lệnh riêng, có phần
khác biệt so với nguyên bản ở trên.
Các hàm trong Contiki processes:

PROCESS_BEGIN(); // Khai báo bắt đầu process' protothread.
PROCESS_END(); // Khai báo kết thức process' protothread.
PROCESS_EXIT(); // Thoát ra khỏi the process.
PROCESS_WAIT_EVENT(); // Đợi 1 event nào đó.
PROCESS_WAIT_EVENT_UNTIL(c); // Đợi 1 event nào đó nhưng có điều kiện
PROCESS_YIELD(); // Giống PROCESS_WAIT_EVENT().Khác ở chỗ nó đảm bảo sẽ chạy ít
nhất 1 lần, process không kết thúc trong 1 vòng lặp vô hạn chiếm CPU

PROCESS_WAIT_UNTIL(c); // Chờ 1 điều kiện, có thể không thuc hiện
PROCESS_PAUSE(c); // Tạm dừng process đang thực hiện

13


2.1.4 Events
Trong Contiki, mỗi process khi chạy sẽ nhận 1 event. Có 2 loại event:
asynchronous events(sự kiện đồng bộ) and synchronous events(sự kiện không đồng
bộ).

Hình 2.2 Mô tả sự kiện không đồng bộ
Khi một sự kiện không động bộ được gửi, sự kiện đó được đặt vào kernel's event
queue(hàng đợi sự kiện) và chuyển tiếp đến một process vào thời gian sau đó.

Hình 2.3. Mô tả sự kiện đồng bộ
Khi một sự kiện đồng bộ được gửi, sự kiện đó ngay lập tức được chuyển cho
process.

14


2.1.4.1 Asynchronous Events
Asynchronous events được chuyển tiếp đến process sau khi được gửi đi.
Giữa khoảng thời gian gửi đi và được chuyển tiếp, nó nằm ở hàng đợi sự kiện trong
Contiki kernel.
Process nhận event có thể là một process cụ thể, hoặc tất cả các process đang
chạy. Nếu là 1 process cụ thể, kernel sẽ gọi nó lên đển cung cấp sự kiện. Nếu là
nhiều process, kernel sẽ tuần tự cung cấp các sự kiện giống nhau cho tất cả các
processs, cái này đến cái khác.

Asynchronous events được gửi đi bằng hàm process_post(). Đầu tiên hàm
kiểm tra kích cỡ của hàng đợi lệnh. Nếu còn trống sẽ đưa vào, nếu hết chỗ sẽ báo
lỗi.

2.1.4.2 Synchronous Events
Khác với Asynchronous events, synchronous events được gửi trực tiếp đến
một process cụ thể. Do đó, process này được gọi trực tiếp và sẽ không được nhận
event tiếp theo cho đến khi xử lý xong event này.
2.1.4.3 Polling
Một yêu cầu poll được thực hiện bằng hàm

process_poll().

Khi thực hiện

yêu cầu này, process sẽ được ưu tiên thực hiện nhanh nhất có thể.
Polling là cách để process chạy từ một ngắt. Hàm process_poll() chỉ được sử
dụng trong thân của một protothread, nó an toàn để dùng ở preemptive mode.
2.1.5 The Process Scheduler
Mục tiêu của process scheduler là để gọi process lên chạy khi được phép.
Quá trình này được thực hiện bằng cách gọi hàm thực hiện Process Thread. Process
scheduler được gọi là để đáp ứng với một sự kiện được gửi tới nó, hoặc một yêu cầu
poll.
Trong quá trình gọi, một con trỏ chưa xác định sẽ được duyệt. Con trỏ được
cung cấp bởi lệnh gọi có thể lấy giá trị NULL ứng với việc không có dữ liệu được
duyệt. Khi dùng poll, mặc định không có dữ liệu được duyệt.

15



2.1.5.1 Starting Processes
Hàm process_start(). Mục tiêu của hàm là thiết lập cấu trúc điều khiển
process, thêm process vào danh sách thực thi của kernel, và gọi code cài đặt process
lên. Khi hàm process_start() được gọi, process sẽ bắt đầu.
Đầu tiên, hàm sẽ kiểm tra xem process đã được bắt đầu chưa, nếu chạy rồi
thì hoàn thành. Nếu process chưa được bắt đầu, process sẽ được đặt vào danh sách
khởi động, trạng thái của process được thiết lập

PROCESS_STATE_RUNNING



protothread được cài đặt bằng PT_INIT().
Cuối cùng, process gửi một synchronous event, PROCESS_EVENT_INIT. Đồng
thời con trỏ sẽ đi tới process cần khởi động kèm theo dữ liệu. Tuy nhiên, thông
thường dữ liệu được gửi kèm theo là NULL. Process cần khởi động sẽ được kernel gọi
lên để nhận synchronous event.
2.1.5.2 Exiting and Killing Processes
Thoát ra khỏi process có hai cách:


Tự thoát ra: khi chương trình tìm đến dòng PROCESS_END().



Thoát ra bởi 1 chương trình khác PROCESS_EXIT()

Khi một chương trình được thoát, kernel sẽ gửi thông báo thoát của process cần
thoát cho tất cả các process khác đang sử dụng nó
2.1.5.3 Autostarting Processes

Contiki cung cấp một cơ chế giúp tự động bắt đầu một process chỉ định trước
khi hệ thống khởi động.
2.2 Timer
2.2.1 The Contiki Timer Modules
Contiki có một mô-đun clock và nhiều mô-đun timer: timer, stimer, ctimer,
etimer, and rtimer. Các mô-đun khác nhau thực hiện các công việc khác nhau.
Mô-đun clock cung cấp các hàm để điều khiển thời gian của hệ thống cũng
như chặn CPU trong một khoảng thời gian ngắn.

16


Timer và stimer cung cấp cấu trúc đơn giản nhất về thời gian và được sử
dụng kiểm tra một khoảng thời gian đã qua. Các ứng dụng cần timer nếu nó đã kết
thúc. Sự khác biệt giữa chúng là đơn vị thời gian: timer sử dụng clock hệ thống,
stimer sử dụng giây. Không giống với các timer khác, timer và stimer có thể sử
dụng an toàn từ ngắt.
Thư viện etimer cung cấp event timers và sử dụng để lên lịch chạy cho các
process contiki sau một khoảng thời gian.
2.2.2 The Clock Module
Clock module cung cấp hàm để điều khiển thời gian của hệ thống.
The API for the Contiki clock module gồm những hàm sau:
Hàm clock_time() trả về thời gian hiện tại trong clock. Số clock mỗi giây phụ thuộc
vào nền tảng phần cứng và xác định bởi hằng số CLOCK_SECOND.
Clock module có 2 hàm chặn CPU: clock_delay(), và clock_wait()
Hàm clock_init() được gọi trong suốt quá trình hệ thống cài clock module
The Clock Module API:
clock_time_t clock_time(); // Get the system time.
unsigned long clock_seconds(); // Get the system time in seconds.
void clock_delay(unsigned int delay); // Delay the CPU.

void clock_wait(int delay); // Delay the CPU for a number of clock ticks.
void clock_init(void); // Initialize the clock module.
CLOCK_SECOND; // The number of ticks per second.

2.2.3 The Timer Library
Thư viện Contiki timer cung cấp các hàm để tinh chỉnh, khởi động lại timer,
và kiểm tra timer kết thúc chưa. Một ứng dụng phải được kiểm tra timers đã kết
thúc chưa bằng tay, nó không được làm tự động. Các thư viện timer sử dụng
clock_time() để có được thời gian hiện tại của hệ thống.
Một timer được khái báo bằng struc timer và truy cập thông qua địa chỉ con
trỏ.
The TimerLibraryAPI:
void timer_set(struct timer *t, clock_time_t interval); // Khởi tạo timer
void timer_reset(struct timer *t); // khởi động lại timer đã expired
void timer_restart(struct timer *t); // khoi động lại timer hiện tại
int timer_expired(struct timer *t); // kiểm tra timer expired

17


clock_time_t timer_remaining(struct timer *t); // trả về giá trị còn lại tính
đến khi timer expired.

The EtimerLibraryAPI:
void etimer_set(struct etimer *t, clock_time_t interval); // Start the timer.
void etimer_reset(struct etimer *t); // Restart the timer from the previous
expiration time.
void etimer_restart(struct etimer *t); // Restart the timer from current time.
void etimer_stop(struct etimer *t); // Stop the timer.
int etimer_expired(struct etimer *t); // Check if the timer has expired.

int etimer_pending(); // Check if there are any non-expired event timers.
clock_time_t etimer_next_expiration_time(); // Get the next event timer
expiration time.
void etimer_request_poll(); // Inform the etimer library that the system clock
has

2.3 Input and output
Các loại thiết bị I/O có sẵn để người lập trình phụ thuộc nhiều vào nền tảng
phần cứng sử dụng. Contiki cung cấp 2 giao diện cơ bản: serial I/O và LEDs. Serial
output được hỗ trợ bởi API của C để print, trong khi đó serial input phụ thuộc vào
cơ chế riêng của Contiki. LEDs API, cung cấp các lệnh để sử dụng thuộc tính của
LEDs.
2.3.1 Serial Communication
The serial I/O API
int printf(const char *format, ...); // in ra một chuỗi *format.
int putchar(int c); // in một kí tự đơn.

Printing
Sử dụng printf() giống như trong C
Receiving
Contiki có giao tiếp cơ bản được xác định trong core/dev/serial-line.h
Hàm serial_line_init() phải được gọi lên trước khi gọi serial_line_process để
serial_line_process được thêm vào process_list.

18


Hình 2.4. Quá trình nhận dữ liệu qua uart
Một ngắt sẽ được phát ra khi có một kí tự được đọc từ serial port. Quá trình
điều khiển ngắt gọi serial_line_input_byte, nó chiếm bộ nhớ đệm cho đến khi dòng

kí tự mới được nhận. Sau khi nhận được xâu kí tự hoàn chỉnh, chúng ta sẽ phát một
event cho tất cả các process.
Serial_line_input_byte() là hàm callback, nó nhận bytes đầu vào. Hàm này
ghi vào bộ nhớ đệm cho đến khi một dòng ngắt được nhận, sau đó nó gọi hàm
serial_line_process. Kích thước của bộ nhớ đệm cho serial lines có thể điều chính
thông qua tham số SERIAL_LINE_CONF_BUFSIZE, và mặc định là 80bytes. Nếu dòng
lớn hơn được nhận, (chỉ có SERIAL_LINE_CONF_BUFSIZE-1) bytes và 1 nil byte sẽ
được

cho

qua

để

vào

serial_line_process.

serial_line_process truy ền

mộ

serial_line_event_message() t ới t ất c ả các process trong h ệ th ống.

Serial line driver có 2 hàm để điều khiển đầu vào: IGNORE_CHAR(c) có
chức năng như một bộ lọc đơn giản, nó trả về giá trị đúng nếu đó là kí tự c. Còn
không sẽ chuyển mã ascii của kí tự mới đến bộ nhớ đệm và gọi seral_line_process
lên.
2.1.2 LEDs

LEDs đơn giản nhưng là công cụ quan trọng để giao ti ếp với ng ười dùng
hoặc debug chương trình. LEDs API được thể hiện dưới đây
The LEDsAPI
void leds_init(void); // Khởi tạo sử dụng LEDs.
unsigned char leds_get(void); // Lấy trạng thái leds.

19


void leds_on(unsigned char ledv); // bật LEDs.
void leds_off(unsigned char ledv); // tắt LEDs.
void leds_toggle(unsigned char ledv); // đổi trạng thái LEDs.
void leds_invert(unsigned char ledv); // đổi trạng thái LEDs.

Các led đượ c l ấy b ằng hàm leds_get(). Hàm này tr ả v ề LED vector ki ểu unsigned
char, trong đó 1 bit đại di ện cho màu c ủa LED.
LEDidentifiersfor use in LEDvectors.
#define LEDS_GREEN

1

#define LEDS_YELLOW

2

#define LEDS_RED

4

#define LEDS_ALL


7

20


Phần 3. Giải thích code mẫu và bài tập
3.1 Code mẫu
3.1.1 Blink example
1. #include <stdio.h>
2. #include "contiki.h" // thu vien contiki
3. #include "dev/leds.h" // thu vien leds
4. /* ----------------Khoi tao process control block---------------- */
5. PROCESS(red_process, "Red light process");
6. PROCESS(blink_process, "Blink");
7. AUTOSTART_PROCESSES(&blink_process);
8. /*----------------------------------------------------------------*/
9. /* This process is started from the other process and blinks an LED fast.
10. */
11. static struct etimer etr;
12. PROCESS_THREAD(red_process, ev, data)
13. {
14. PROCESS_POLLHANDLER();
15. PROCESS_EXITHANDLER();
16. PROCESS_BEGIN();
17. while(1) {
18. leds_toggle(LEDS_RED);
19. etimer_set(&etr, CLOCK_SECOND/8);
20. PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&etr));
21. }

22. PROCESS_END();
23. }
24. /*----------------------------------------------------------------*/
25. /* this process starts another process and then periodically blinks an
LED */
26. static struct etimer et;
27. PROCESS_THREAD(blink_process, ev, data)
28. {
29. PROCESS_BEGIN();
30. etimer_set(&et, CLOCK_SECOND);
31. PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
32. process_start(&red_process, NULL);
33. while(1) {
34. /* unnecessary, messy but wanted sth else than what the red process
a. is doing so instead of just toggling, turn on when even seconds
and
b. turn off on uneven seconds.
35. */
36. if(clock_seconds() & 1) {
37. leds_on(LEDS_GREEN);
38. } else {

21


39. leds_off(LEDS_GREEN);
40. }
41. etimer_set(&et, CLOCK_SECOND);
42. PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
43. }

44. PROCESS_END();
45. }
46. /*---------------------------------------------------------------------*/

Mở đầu một chương trình, 3 dòng đầu tiên, chúng ta khai báo các thư viện sử
dụng.
Ở dòng 5, 6, ta khởi tạo các process control block. Mỗi process có biến tên process
và phần mô tả. Ở trong ví dụ này, tên là red_process và mô tả là Red light process.
Sau khi khởi tạo, biến tên process có thể dược sử dụng cho các hàm khác.
Ở dòng 7, ta bắt gặp cấu trúc

AUTOSTART_PROCESSES(),

nó sẽ lên danh sách các

chương trình được phép tự động khởi chạy khi hệ thống được bật hoặc ngay sau khi
code được nạp, trong ví dụ này là blink_process.
Dòng 12 khai báo process thread, nó bao gồm biến tên(đã được khởi tạo ở dòng 5),
ngoài ra tên cảu event là biến ev, và data.
Dòng 16 và 22 là thành phần cơ bản của process thread, cặp hàm
PROCESS_BEGIN() và PROCESS_END(). Ở giữa cặp hàm này là chương trình
chính.
Dòng 17 bắt đầu một vòng lặp vô hạn, tuy nhiên trên thực tế, Contiki không chạy
vòng lặp vô hạn, mà nó sẽ dừng để đợi event. Trong vòng lặp chúng ta gặp các hàm
đảo trạng thái led, leds_toggle() và set etimer, etimer_set(). Khi gặp lệnh lật trạng
thái, led đỏ đang tắt sẽ sáng. Nó sáng đến bao giờ? Vấn đề này được giải quyết bằng
việc kiểm soát thống qua quá trình chặn CPU bằng biến etimer đã được khai báo ở
dòng 11. etr được set với giá trị CLOCK_SECOND/8, sau đó là lệnh đợi có điều
kiện PROCESS_WAIT_EVENT_UNTIL(). Chỉ cần hết thời gian được set,
etimer_expired(&etr)=1,


điều kiện đúng, chương trình sẽ quay về đầu vòng lặp, và

led đang sáng sẽ tắt. Quá trình này lặp lại liên tục làm led đỏ nháy với chu kì 1/8s.
Từ dòng 26 đến 45 tương tự là chương trình nháy led xanh.
Trong dòng 30 đến 32, chúng ta sẽ đợi 1s rồi gọi chương trình nháy led đỏ lên.
Ở dòng 36 đến 40 là 1 cơ chế nháy khác, ở đây ta kiểm tra clock_seconds(), số giây
hàm đếm được là lẻ sẽ sáng led xanh, còn chẵn sẽ tắt.

22


Thực hiện chương trình: Ban đầu chương trình sẽ tự chạy vào blink_process. Đến
dòng 32 thì led đỏ được gọi và nó nháy với chu kì 1/8s. Led xanh được nháy với
chu kì 1s.
3.1.2 Button example
1.
2.
3.
4.

#include
#include
#include
#include

<stdio.h>
"contiki.h"
"dev/leds.h"
"dev/button.h"


5. /* --------------------------------------------------------------- */
6. PROCESS(button_process, "Button process");
7. PROCESS(blink_process, "Blink process");
8. AUTOSTART_PROCESSES(&blink_process, &button_process);
9. /*----------------------------------------------------------------*/
10. static struct etimer etr;
11. PROCESS_THREAD(button_process, ev, data)
12. {
13. PROCESS_POLLHANDLER();
14. PROCESS_EXITHANDLER();
15. PROCESS_BEGIN();
16. static uint8_t btnpresses = 0;
17. while(1) {
18. PROCESS_WAIT_EVENT_UNTIL(ev == button_event);
19. leds_toggle(LEDS_RED);
20. btnpresses++;
21. if(btnpresses == 5) {
22. process_exit(&blink_process);
23. }
24. }
25. PROCESS_END();
26. }
27. /*-----------------------------------------------------------------*/
28. /* this process periodically blinks an LED */
29. static struct etimer et;
30. PROCESS_THREAD(blink_process, ev, data)
31. {
32. PROCESS_BEGIN();
33. while(1) {

34. leds_toggle(LEDS_GREEN);
35. etimer_set(&et, CLOCK_SECOND/8);
36. PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
37. }
38. PROCESS_END();
39. }
40. /*------------------------------------------------------------------*/

Chương trình minh hoạ cho việc điều khiển phím bấm, khi bấm thì led đỏ sáng
tắt theo các lần bấm, đến lần thứ 5 thì thoát blink_process nếu phím được bấm lại.

23


Process blink này đã được phân tích ở ví dụ phía trên, ở đây ta chỉ xem xét đến
process button.
Dòng 18, cho ta thấy mỗi lần nút được bấm, điều kiện đúng, chương trình chuyển
đến dòng 19, led đỏ sẽ được lật trạng thái.
Dòng 16, biến btnpresses được khai báo với giá trị mặc định bằng 0, đây là sẽ biến
lưu trữ số lần bấm phím, bởi ở dòng 20 ta thấy mỗi lần bấm phím btnpresses sẽ
được tăng lên 1 đơn vị.
Trong vòng lặp, chương trình đợi đến khi phím được bấm mới bắt đầu thực hiện.
Đầu tiên led đỏ sẽ được lật sáng thái(đang tắt sẽ sáng lên). Nếu bấm đến lần thứ 5
thì sẽ thoát chương trình nháy led xanh.

3.2 Bài tập
3.2.1 Sử dụng các cấu trúc tuần tự, lặp, rẽ nhánh
Cấu trúc tuần tự đã đươc thể hiện trong các ví dụ ở phần trên, thậm chí trong
button example ta cũng đã bắt gặp cấu trúc lặp. Tuy nhiên để hiểu rõ hơn về lặp ta
thực hiện bài toán sau:

Ban đầu 2 led đều tắt, khi nhấn nút thì 2 đèn nháy với chu kì khác nhau, bấm
thêm 5 lần nữa đèn đỏ tắt, bấm tiếp thêm 5 lần nữa đèn xanh tắt.
1.
2.
3.
4.
5.
6.

/*Code minh hoa re nhanh thong qua nut bam*/
#include <stdio.h>
#include "contiki.h"
#include "dev/leds.h"
#include "dev/button.h"
//khai bao ca thu vien

7. PROCESS(button_process, "Button process");
8. PROCESS(red_process, "Red light process");
9. PROCESS(green_process, "Green process");
10. AUTOSTART_PROCESSES(&button_process);
11. // khoi tao cac process va chon process bat dau
12. static struct etimer etr;
13. PROCESS_THREAD(button_process, ev, data)
14. {
15. PROCESS_POLLHANDLER();
16. PROCESS_EXITHANDLER();
17. PROCESS_BEGIN();
18. static uint8_t btnpresses = 0; // khoi tao bien dem so lan bam
19. while(1) {
20. PROCESS_WAIT_EVENT_UNTIL(ev == button_event);

21. btnpresses++; // moi khi nut dc bam btnpresses tang them 1
22. // neu bam nut lan thu nhât thi se khoi dong 2 chuong trinh nhay led
23. if(btnpresses == 1) {

24


24. process_start(&red_process, NULL);
25. process_start(&green_process, NULL);
26. }
27. // nut dc bam them 5 lan thi thoat ra va tat led do
28. if(btnpresses == 6) {
29. process_exit(&red_process);
30. leds_off(LEDS_RED);
31. }
//nut duoc bam them 5 lan nua thi thoat ra va tat led xanh
32. if(btnpresses == 11) {
33. process_exit(&green_process);
34. leds_off(LEDS_GREEN);
35. }
36. }
37. PROCESS_END();
38. }
39. /********Process nhay led do =*********/
40. static struct etimer etr;
41. PROCESS_THREAD(red_process, ev, data) /
42. {
43. PROCESS_BEGIN();
44. while(1) {
45. leds_toggle(LEDS_RED);

46. etimer_set(&etr, CLOCK_SECOND/2);
47. PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&etr));
48. }
49. PROCESS_END();
50. }
51. /*-----------Process nhay led xanh-----------*/
52. static struct etimer et;
53. PROCESS_THREAD(green_process, ev, data)
54. {
55. PROCESS_BEGIN();
56. while(1) {
57. leds_toggle(LEDS_GREEN);
58. etimer_set(&et, CLOCK_SECOND/4);
59. PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
60. }
61. PROCESS_END();
62. }

Để minh hoạ cho cấu trúc lặp, ta xét bài toán sau:
Khi code được nạp vào, led đỏ sáng trong 3s rồi đến led xanh sáng trong 1s. Quá
trình này được lặp đi lặp lại.
1.
2.
3.
4.
5.
6.
7.

/*

*Chuong trinh chay led do sang trong 3s sau do led xanh sang trong 1 s
*Qua trinh nay duoc lap lai tuan hoan
*/
#include <stdio.h>
#include "contiki.h"
#include "dev/leds.h"

8. /* ------------------------------------------------------- */
9. PROCESS(red_process, "Red light process");
10. PROCESS(green_process, "Green light process");
11. AUTOSTART_PROCESSES(&green_process);
12. /*------------------------------------------------*/

25


×