Thực hành Contiki OS - Lập trình Contiki NG cơ bản (tiếp theo)

19 Tháng Tư 2021

Contiki-NG sử dụng ngôn ngữ lập trình C để phát triển các ứng dụng cho các motes WSN. Trong loạt bài này, bạn sẽ học ngôn ngữ cơ bản này để tạo các chương trình Contiki-NG. Các đoạn code mẫu sẽ được cung cấp để tăng tốc độ học tập của bạn. Trong bài viết trước chúng ta đã tìm hiểu về các khái niệm cơ bản, bài này chúng ta sẽ tiếp tục phần còn lại

Thực hành Contiki OS - Lập trình Contiki NG cơ bản (tiếp theo)

Review Protothreads

Protothreads là các luồng lightweight được thiết kế cho các hệ thống hạn chế bộ nhớ (dung lượng bộ nhớ thấp), chẳng hạn như các hệ thống nhúng dạng mini hoặc các mote WSN. Bạn có thể xem mã nguồn về protothreads cho Contiki-NG tại thư mục <contiki_root>/os/sys/pt.h

#ifndef PT_H_
#define PT_H_

#include "sys/lc.h"

struct pt {
  lc_t lc;
};

#define PT_WAITING 0
#define PT_YIELDED 1
#define PT_EXITED  2
#define PT_ENDED   3

#define PT_INIT(pt)   LC_INIT((pt)->lc)

#define PT_THREAD(name_args) char name_args

#define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; if (PT_YIELD_FLAG) {;} LC_RESUME((pt)->lc)

#define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; 
                   PT_INIT(pt); return PT_ENDED; }

#define PT_WAIT_UNTIL(pt, condition)	        
  do {						
    LC_SET((pt)->lc);				
    if(!(condition)) {			
      return PT_WAITING;			
    }						
  } while(0)

#define PT_WAIT_WHILE(pt, cond)  PT_WAIT_UNTIL((pt), !(cond))

#define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread))

#define PT_SPAWN(pt, child, thread)		
  do {						
    PT_INIT((child));				
    PT_WAIT_THREAD((pt), (thread));		
  } while(0)

#define PT_RESTART(pt)				
  do {						
    PT_INIT(pt);				
    return PT_WAITING;			
  } while(0)

#define PT_EXIT(pt)				
  do {						
    PT_INIT(pt);				
    return PT_EXITED;			
  } while(0)

#define PT_SCHEDULE(f) ((f) < PT_EXITED)

#define PT_YIELD(pt)				
  do {						
    PT_YIELD_FLAG = 0;				
    LC_SET((pt)->lc);				
    if(PT_YIELD_FLAG == 0) {		
      return PT_YIELDED;			
    }						
  } while(0)

#define PT_YIELD_UNTIL(pt, cond)		
  do {						
    PT_YIELD_FLAG = 0;				
    LC_SET((pt)->lc);				
    if((PT_YIELD_FLAG == 0) || !(cond)) {	
      return PT_YIELDED;			
    }					
  } while(0)

#endif /* PT_H_ */

Sau đây là danh sách các mô tả chức năng dựa trên pt.h

  • PT_INIT(pt): hàm được sử dụng để khởi tạo một protothread
  • PT_THREAD (name_args) là một macro được sử dụng để khai báo một luồng protothread
  • PT_BEGIN (pt) được sử dụng để khai báo điểm bắt đầu của một protothread.
  • PT_END (pt) được sử dụng để kết thúc một protothread
  • PT_WAIT_UNTIL (pt, điều kiện) được sử dụng để chặn luồng protothread cho đến khi điều kiện truyền vào là true.
  • PT_WAIT_WHILE (pt, cond) được sử dụng để chặn và chờ trong khi điều kiện là đúng
  • PT_WAIT_THREAD (pt, luồng) được sử dụng để lên lịch cho một luồng con. Protothread hiện tại sẽ chặn cho đến khi protothread con hoàn thành
  • PT_SPAWN (pt, con, luồng) được sử dụng để sinh ra một protothread con và đợi cho đến khi nó thoát ra.
  • PT_RESTART (pt) sẽ chặn và làm cho luồng protothread đang chạy khởi động lại quá trình thực thi của nó tại vị trí của lệnh gọi PT_BEGIN ().
  • PT_EXIT (pt) được sử dụng để thoát khỏi một protothread.
  • PT_SCHEDULE (f) được sử dụng để lên lịch cho một protothread. Giá trị trả về của hàm là khác 0 nếu luồng protothread đang chạy hoặc bằng 0 nếu protothread đã thoát
  • PT_YIELD (pt) lấy lại kết quả từ protothread hiện tại
  • PT_YIELD_UNTIL (pt, cond) mang lại kết quả từ protothread cho đến khi một điều kiện xảy ra

Extending the Contiki-NG Library

Contiki-NG OS bao gồm một số thư viện và ứng dụng mà bạn có thể mở rộng tùy theo trường hợp của mình. Để mở rộng các chức năng của Hệ điều hành Contiki-NG, bạn có thể làm theo cùng một phương pháp được sử dụng trong khi xây dựng các chương trình C

Bạn thêm các thư viện bổ sung bằng cách thêm file header C và đoạn code liên quan. Chương trình Contiki-NG của chúng ta sẽ sử dụng các thư viện đó. Đối với bản "múa lửa" này, chúng ta tạo tệp header có tên mycounter.h với code sau:

#ifndef MYCOUNTER_H
#define MYCOUNTER_H
int next_counter(int current);
#endif

Trong file header C này mình định nghĩa một hàm next_counter (). Hàm này sẽ được triển khai vào tệp mycounter.c. Chúng tôi tăng bộ đếm với giá trị tối đa là 99. Bạn có thể viết code hoàn chỉnh như sau:

#include "mycounter.h"
int next_counter(int current)
{
 if(current>99)
 current = 1;
 else
 current++;
 return current;
}

Để truy cập thư viện mở rộng chúng ta sẽ thực hiện include file header đã định. Sau đó, chúng ta gọi các hàm thư viện từ code đã thực hiện.

#include "mycounter.h"
...
static int counter = 0;
counter = next_counter(counter);
printf("Counter: %d\n", counter);

Trong bài hướng dẫn về mô phỏng mình sẽ hướng dẫn kỹ hơn về chỗ này

Contiki-NG Coding Conventions

Hãy tưởng tượng bạn đang phát triển một chương trình với một nhóm gồm hơn ba nhà phát triển. Mỗi nhà phát triển có một phong cách và phương pháp lập trình. Khi các chương trình được hợp nhất, nó có thể gây ra vấn đề vì các đoạn code không nhất quán trong cách viết. Vấn đề này có thể được giải quyết nếu code được viết theo cùng một kiểu.

Quy ước viết mã Contiki là các quy tắc cho một phong cách viết. Chúng bao gồm các hướng dẫn về cách viết các chương trình Contiki-NG. Bạn có thể đọc các quy ước mã hóa đầy đủ cho Contiki tại đây

Tổng kết

Chúng ta đã khám phá ngôn ngữ lập trình cơ bản Contiki-NG. Đây là ngôn ngữ cốt lõi dựa trên ngôn ngữ lập trình C sẽ giúp bạn phát triển ứng dụng Contiki-NG. Trong chương tiếp theo, chúng ta sẽ tìm hiểu cách làm việc về các vấn đề concurency trong các chương trình Contiki-NG để giải quyết nhiều công việc. Chúc bạn đọc vui vẻ

Bình luận