Lưu đồ thuật toán

Một phần của tài liệu Giám sát và điều khiển thiết bị qua mạng ETHERNET trên nền FPGA luận văn tốt nghiệp đại học (Trang 73)

73

Begin

Bắt đầu vào nhân Kenel

Cho phép cache hoạt động

Gọi main_thread

Hình 3.2: Lưu đồ thuật toán hệ thống.

Hình 3.3: Lưu đồ thực hiện thủ tục main_thread.

74 Main_thread Gọi network_thread Xử lý console_thread Kết thúc thủ tục

Khỏi tạo LwIP

Khởi động file hệ thống(MFS) Gọi web_application _thread Network_thread

Khởi tạo địa chỉ mac và IP

Hình 3.4: Lưu đồ thực hiện thủ tục Network_thread.

Hình 3.5: Lưu đồ thực hiện phương thức conlose_thread.

75 Web_application _thread Gọi platform_init_gpios Tạo TCP socket Gán tới cổng 80 Lắng nghe kết nối Đồng ý cho phép kết nối N Nếu bằng clear Y Thực hiện lệnh xóa Get_line Console_threa d N Nếu bằng ls Y Thực hiện lệnh liệt kê

a) b)

Hình 3.6:a) Lưu đồ thực hiện thủ tục Web_application_thread.

b)Lưu đồ thực hiện hàm process_http_reques.

76

Process_http_reques

Đọc yêu cầu

Gọi hàm xử lý yêu cầu Generate_response Đóng kết nối Kết thúc hàm Generate_response Trả lại giá trị hàm do_http_get Trả lại giá trị hàm do_http_post Trả lại giá trị hàm do_404 Kiểu yêu cầu

là HTTP_POST?

N Kiểu yêu cầu

là HTTP_GET?

Y

N

Hình 3.7: Lưu đồ thực hiện hàm Generate_response. 3.3 Giao diện điều khiển web server

3.3.1 Giới thiệu về ngôn ngữ JavaScript

Để tạo ra một trang web bạn có thể dùng HTML hoặc Microsoft FrontPage. Tuy nhiên, chỉ mới ở mức biểu diễn thông tin chứ chưa phải một trang web có khả năng đáp ứng các sự kiện từ phía người dùng. Hãng Netscape đã đưa ra ngôn ngữ script có tên là LiveScript để thực hiện chức năng này. Sau đó ngôn ngữ này được đổi tên thành JavaScript để tận dụng tính đại chúng của ngôn ngữ lập trình Java. Mặc dù có những điểm tương đồng giữa Java và JavaScript, nhưng chúng vẫn là hai ngôn ngữ riêng biệt.

JavaScript là ngôn ngữ dước dạng script có thể gán với các file HTML. Nó không được biên dịch mà được trình duyệt diễn dịch. Không giống Java phải chuyển thành các mã dễ biên dịch, trình duyệt đọc JavaScript

dưới dạng mã nguồn. Chính vì vậy bạn có thể dễ dàng học JavaScript qua ví dụ bởi bạn có thể thấy cách sử dụng JavaScript trên các trang web. (adsbygoogle = window.adsbygoogle || []).push({});

JavaScript là ngôn ngữ dựa trên đối tượng, có nghĩa là bao gồm nhiều kiểu đối tượng, ví dụ đối tượng Math với tất cả các chức năng toán học. Tuy nhiên, JavaScript không phải là ngôn ngữ hướng đối tượng như C++ hay Java do không hỗ trợ các lớp hay tính thừa kế.

JavaScript có thể đáp ứng các sự kiện như tải hay loại bỏ các form. Khả năng này cho phép JavaScript trở thành một ngôn ngữ Script động.

Giống với HTML và Java, JavaScript được thiết kết độc lập với hệ điều hành. Nó có thể chạy trên bất kỳ hệ điều hành nào có truyền duyệt hỗ trợ JavaScript. Ngoài ra JavaScript giống Java ở khía cạnh an ninh: JavaScript không thể đọc và viết vào file của người dùng. Các trình duyệt web như Nescape Navigator 2.0 trở đi có thể hiển thị những câu lệnh JavaScript được nhúng vào trang HTML. Khi trình duyệt yêu cầu một trang, server sẽ gửi đầy đủ nội dung của trang đó, bao gồm cả HTML và các câu lệnh JavaScript qua mạng tới client. Client sẽ đọc đọc trang đó từ đến cuối, hiển thị các kết quả của HTML và xử lý các câu lệnh JavaScript khi nào chúng xuất hiện.

Các câu lệnh JavaScript được nhúng trong một trang HTML có thể trả lời cho các sự kiện của người sử dụng như kích chuột, nhấp vào một form và điều hướng trang. Ví dụ bạn có thể kiểm tra các giá trị thông tin mà người sử dụng đưa vào mà không cần biết đến bất cứ một quá trình truyền trên mạng nào. Trang HTML với JavaScript được nhúng sẽ kiểm tra các giá trị được đưa vào và sẽ thông báo với người sử dụng khi giá trị đưa vào là không hợp lệ.

3.3.2 Thiết kế giao diện điều khiển hệ thống

Hình 3.8: Giao diện điều khiển và giám sát thiết bị.

Mã nguồn tại phụ lục 2. Chức năng

- Điều khiển 8 led sáng tắt

- Giám sát 4 chuyển mạch trên board.

3.4. Mô phỏng và kết quả

Để kiểm tra sự thông của mạng ta kết nối board với máy tính thông qua cổng ethernet. Trên máy trạm, mở ứng dụng Web browser(Internet Explorer, Firefox, Google chrome) và gõ địa chỉ IP của Web server thiết kế trên FPGA là 192.168.1.10 .

Hình 3.10: Hình test 2 Led tắt và trạng thái chuyển mạch là 1101. Một số bước thực hiện trong chương trình:

- Để load web server xuống board thì ta sẽ dịch web server này thành định dạng file .MFS và được lưu tại bộ nhớ DDRAM.

Trong bộ công cụ ISE có hỗ trợ biên dịch các file sang định dạng

.MFS.Để biên dịch ta thực hiện theo các bước sau:

+ Thứ nhất ta khởi động EDK Sell bằng cách vào Start Xilinx ISE Design Suite 10.1  EDK  Accessories  Launch EDK Shell

+ Tiếp theo ta gõ lệnh như sau:

- Nạp chương trình:+ Đầu tiên ta vào menu của phần mềm Xilinx Platform Studio ta vào Device Configuration  Download Bitstream. Bước này để nạp file .bit.

+ Để nạp các file tiếp theo ta thưc hiện như sau: ta vào Debug XMD Debug Options sau đó chọn kiểu cáp JTAG hay USB và click OK. + Ta chạy Debug  Launch XMD mở ra một hộp thoại command và chúng ta có thể giao tiếp với FPGA.

+ Ta gõ lệnh: dow –data image.mfs 0x87000000 để đưa web server vào bộ nhớ DDRAM tại vị trị đã được cài đặt sẵn trong software.

+ Ta gõi lệnh: dow lwip/executable.elf để đưa bitfile vào bộ nhớ DDRAM.

+ Ngoài ra ta có thể liệt kế các file hệ thống bằng lệnh ls và xóa các dòng lệnh bằng lệnh clear.

Kết luận chương

Trong chương này em đã trình bày sơ đồ khối của hệ thống điều khiển và giám sát thiết bị, các lưu đồ chính thực hiện chương trình. Đồng thời em cũng trình bày khái quát về ngôn ngữ JavaScript dùng để thiết kế web server và kiểm tra kiểm tra kết quả.

KẾT LUẬN

Ethernet là một chuẩn công nghiệp và hiện đang được sử dụng rộng rãi trên thế giới.Với nhưng tính năng vượt trội hơn các chuẩn giao tiếp khác như truyền được đi xa và không bị giới hạn bởi băng thông Ethernet sẽ còn được ứng dụng rộng rãi trong tương lai.

FPGA là một vi mạch lập trình có thể cấu hình lại được tức là nó có thể cấu hình thành lại thành một vi điều khiển thông thường và thực hiện các chức năng như các vi điều khiển đó hoặc nó có thể cấu hình lại để thực hiện các chức năng của một vi điều khiển DSP. Chính vì điều đó mà FPGA có đã và đang được sử dụng phổ biến trên thế giới và tại Việt Nam chúng ta.

Chính vì vậy nên em đã lưu chọn đề tài: “Giám sát và điều khiển thiết bị

qua mạng Ethernet trên nền FPGA” là cần thiết và có ý nghĩa thực tiễn.

Qua thời thực hiện đề tài em đã thực hiện thành công giám sát các Switch và điều khiển các Led trên board mạch Spartan-3E XC3S500E qua mạng LAN thông qua một Switch. Nhưng do thời gian thực hiện đề tài cũng như thời tiếp cận với công nghệ FPGA còn hạn chế nên em vẫn chưa điều khiển được các thiết bị ngoài thực tế như các thiết bị điện 220V,giám sát nhiệt độ, điện áp…, và cũng chưa điều khiển và giám sát được nhiều thiết bị. Ngoài ra em vẫn chưa điều khiển thiết bị qua mạng internet được, để khắc phục điều này ta cần một modem ADSL cấu hình Port Forwarding và đăng ký một tài khoản Open DNS để cập nhật IP của modem kết nối tới board cần điều khiển, lúc đó ta sẽ kết nối với board thông qua domain name thay vì IP. (adsbygoogle = window.adsbygoogle || []).push({});

Chính vì khả năng của FPGA nên đề tài của em có thể phát triển hơn nữa để điều khiển một nhà thông minh, hoặc hệ thống thu thập dữ liệu trong quân sự…

Cuối cùng, dù đã cố gắng rất nhiều, nhưng em vẫn không tránh khỏi những sai sót, trong việc xây dựng hệ thống, trong việc trình bày đồ án. Nhưng em vẫn luôn ý thức được rằng, những sai sót ấy cũng là một cơ hội cho em rèn luyện kỹnăng của mình : kỹ năng sửa chữa những sai sót và khiếm khuyết, để thực hiện những đề tài, dự án về sau một cách hoàn chỉnh hơn. Đó tất cả là nhờ sự theo dõi, hướng dẫn, phản biện tận tình và nghiêm túc của các thầy, cô trong hội đồng bảo vệ.

TÀI LIỆU THAM KHẢO

[1] Jan Axelson,Embedded ethernet and internet complete Designing and

Programming Small Devices for Networking,2003.

[2] Xilinx, UG081, Microblaze Processor Reference Guide,2009. [3] Xilinx, UG230, Spartan-3E Starter KitBoard User Guide, 2009.

[4] Stephen MacMahon, Nan Zang, Anirudha Sarangi,LightWeight IP(LwIP)

Application Examples,2011

[5] http://www.es.ele.tue.nl/mamps/web_server/

[6] http://mp-fpga.blogspot.com/

[7] http://www.xilinx.com/

PHỤ LỤC

Chương trình http_response.c

#include <string.h> #include "mfs_config.h" #include "lwip/inet.h" #include "lwip/sockets.h" #include "webserver.h" #include "platform_gpio.h" #include "platform_fs.h" char *notfound_header = "<html> \ <head> \ <title>404</title> \ <style type=\"text/css\"> \

div#request {background: #eeeeee} \ </style> \

</head> \ <body> \

<h1>404 Page Not Found</h1> \ <div id=\"request\">";

char *notfound_footer = "</div> \

</body> \ </html>";

int do_404(int sd, char *req, int rlen) {

int len, hlen;

int BUFSIZE = 1024; char buf[BUFSIZE];

hlen = generate_http_header(buf, "html", len); if (lwip_write(sd, buf, hlen) != hlen) {

xil_printf("error writing http header to socket\n\r"); xil_printf("http header = %s\n\r", buf);

return -1; }

lwip_write(sd, notfound_header, strlen(notfound_header)); lwip_write(sd, req, rlen);

lwip_write(sd, notfound_footer, strlen(notfound_footer)); return 0;

}

int do_http_post(int sd, char *req, int rlen) { int BUFSIZE = 1024; char buf[BUFSIZE]; int len = 0, n; char *p; if (is_cmd_led(req)) { n = toggle_leds(); len = generate_http_header(buf, "txt", 1); p = buf + len; *p++ = n?'1':'0'; *p = 0; len++;

xil_printf("http POST: ledstatus: %x\n\r", n); } else if (is_cmd_switch(req)) { (adsbygoogle = window.adsbygoogle || []).push({});

xil_printf("http POST: switch state: %x\n\r", s);

len = generate_http_header(buf, "txt", n_switches); p = buf + len; for (n = 0; n < n_switches; n++) { *p++ = '0' + (s & 0x1); s >>= 1; } *p = 0; len += n_switches; } else {

xil_printf("http POST: unsupported command\n\r"); }

if (lwip_write(sd, buf, len) != len) {

xil_printf("error writing http POST response to socket\n\r"); xil_printf("http header = %s\n\r", buf);

return -1; }

return 0; }

int do_http_get(int sd, char *req, int rlen) {

int BUFSIZE = 1024;

char filename[MAX_FILENAME]; char buf[BUFSIZE];

int fsize, hlen, n; int fd;

if (mfs_exists_file(filename) == 0) {

xil_printf("requested file %s not found, returning 404\n\r", filename); do_404(sd, req, rlen);

return -1; }

xil_printf("http GET: %s\n\r", filename); fext = get_file_extension(filename);

fd = mfs_file_open(filename, MFS_MODE_READ); fsize = mfs_file_lseek(fd, 0, MFS_SEEK_END); hlen = generate_http_header(buf, fext, fsize); if (lwip_write(sd, buf, hlen) != hlen) {

xil_printf("error writing http header to socket\n\r"); xil_printf("http header = %s\n\r", buf);

return -1; }

while (fsize) { int w;

n = mfs_file_read(fd, buf, BUFSIZE); if ((w = lwip_write(sd, buf, n)) != n) {

xil_printf("error writing file (%s) to socket, remaining unwritten bytes = %d\n\r",

filename, fsize - n);

xil_printf("attempted to lwip_write %d bytes, actual bytes written = %d\n\r", n, w);

break; }

fsize -= n; }

return 0; }

enum http_req_type { HTTP_GET, HTTP_POST, HTTP_UNKNOWN }; enum http_req_type decode_http_request(char *req, int l)

{

char *get_str = "GET"; char *post_str = "POST";

if (!strncmp(req, get_str, strlen(get_str))) return HTTP_GET; (adsbygoogle = window.adsbygoogle || []).push({});

if (!strncmp(req, post_str, strlen(post_str))) return HTTP_POST;

return HTTP_UNKNOWN; }

/* generate and write out an appropriate response for the http request */ int generate_response(int sd, char *http_req, int http_req_len)

{

enum http_req_type request_type = decode_http_request(http_req, http_req_len); switch(request_type) {

case HTTP_GET:

return do_http_get(sd, http_req, http_req_len); case HTTP_POST:

return do_http_post(sd, http_req, http_req_len); default:

return do_404(sd, http_req, http_req_len); }

Chương trình main.c #include <stdio.h> #include "xmk.h" #include "xenv_standalone.h" #include "xparameters.h" #include "lwip/sockets.h" #include "lwip/sys.h" #include "netif/xadapter.h" #include "utils.h" #ifdef XPAR_ETHERNET_MAC_BASEADDR

#define EMAC_BASEADDR XPAR_ETHERNET_MAC_BASEADDR

#else #error #endif

struct netif server_netif; void print_web_app_header(); void web_application_thread(void *); void print_ip(char *msg, struct ip_addr *ip);

void print_ip_settings(struct ip_addr *ip, struct ip_addr *mask, struct ip_addr *gw); int main_thread();

void network_thread(void *p); void console_thread (void *p); int main()

{ /* enable caches */

/*Bat dau voi kenel va khong tra ve gia tri*/ xilkernel_main();

return 0; }

void print_ip(char *msg, struct ip_addr *ip) {

print(msg);

xil_printf("%d.%d.%d.%d\n\r", ip4_addr1(ip), ip4_addr2(ip), ip4_addr3(ip), ip4_addr4(ip));

}

void print_ip_settings(struct ip_addr *ip, struct ip_addr *mask, struct ip_addr *gw) {

print_ip("Board IP: ", ip); print_ip("Netmask : ", mask); print_ip("Gateway : ", gw); }

void network_thread(void *p) {

struct netif *netif;

struct ip_addr ipaddr, netmask, gw;

/* the mac address of the board. this should be unique per board */

unsigned char mac_ethernet_address[] = { 0x00, 0x0a, 0x35, 0x00, 0x01, 0x02 }; netif = &server_netif;

/* initliaze IP addresses to be used */ IP4_ADDR(&ipaddr, 192, 168, 1, 10); IP4_ADDR(&netmask, 255, 255, 255, 0); (adsbygoogle = window.adsbygoogle || []).push({});

/* print application headers */ print_web_app_header();

/* print out IP settings of the board */ print("\n\r\n\r");

print_ip_settings(&ipaddr, &netmask, &gw);

if (!xemac_add(netif, &ipaddr, &netmask, &gw, mac_ethernet_address, EMAC_BASEADDR)) {

xil_printf("Error adding N/W interface\n\r"); return;

}

netif_set_default(netif);

/* specify that the network if is up */ netif_set_up(netif);

/* start packet receive thread - required for lwIP operation */

sys_thread_new((void(*)(void*))xemacif_input_thread, netif, DEFAULT_THREAD_PRIO);

/* Khoi tao lop file he thong cho web servers */ platform_init_fs();

/*bat dau thread web server */

sys_thread_new(web_application_thread, 0, DEFAULT_THREAD_PRIO);

return; }

void console_thread (void *p) {

while (1) { get_line (line); xil_printf ("%s\n\r", line); if (strcmp (line, "ls") == 0) { mfs_ls (); } if (strcmp (line, "clear") == 0) { clear_console (); } } return; } int main_thread() {

/* Khoi tao Lwip truoc khi goi phuong thuc sys_thread_new */ lwip_init();

/*Bat ky thread nao su dung lwIP nen duoc tao ra bang cach su dung phuong thuc sys_thread_new*/

sys_thread_new (network_thread, NULL, DEFAULT_THREAD_PRIO); sys_thread_new (console_thread, NULL, DEFAULT_THREAD_PRIO); return 0;

}

#include "mfs_config.h" int platform_init_fs() {

/* initialize the memory file system (MFS) image pre-loaded into memory */

mfs_init_fs(MFS_NUMBYTES, (char *)(MFS_BASE_ADDRESS+4), MFS_INIT_TYPE); /* check if we can access index.html */

if (mfs_exists_file("index.html") == 0) {

xil_printf("%s: ERROR: unable to locate index.html in MFS\n\r", __FUNCTION__); xil_printf("Please check if Memory File System has been loaded, \

and it has index.html file in root directory\n\r"); return -1;

}

xil_printf("Memory File System initialized\n\r"); return 0;

}

Chương trinh platform_gpio.c #include "platform_gpio.h" #include "xparameters.h" (adsbygoogle = window.adsbygoogle || []).push({});

#if defined(XPAR_LEDS_8BIT_BASEADDR)

#define LED_BASE XPAR_LEDS_8BIT_BASEADDR #endif

#if defined(XPAR_DIP_SWITCHES_4BIT_BASEADDR)

#define DIP_BASE XPAR_DIP_SWITCHES_4BIT_BASEADDR #endif

{

/* set led gpio data direction to output */ *(volatile unsigned int*)(LED_BASE + 4) = 0; /* set dip switch gpio data direction to in */ *(volatile unsigned int*)(DIP_BASE + 4) = ~0; /* initialize leds to OFF */

*(volatile int *)(LED_BASE) = 0; }

int

toggle_leds() {

static int state = 0; state = ~state;

*(volatile int *)(LED_BASE) = state; return state;

}

unsigned int get_switch_state() {

return *(volatile unsigned int *)(DIP_BASE); }

Chương trinh utils.c #include <stdio.h>

#include "utils.h" #define ROW 50 #define COL 50

void get_line (char *line) {

int count = 0; char c;

memset (line, '\0', SIZE); while (1) { c = getchar (); if (count == (SIZE - 2) || c == 13) { return; } if (c >= 32) // visible character { line [count] = c; count++; } } } void clear_console () { int i,j; for (j = 0; j < ROW; j++) {

{ xil_printf (" "); } xil_printf ("\n\r"); } }

Chương trinh web_utils.c #include <string.h> #include <stdio.h> #include "mfs_config.h" #include "webserver.h" #include "platform_gpio.h" Int is_cmd_led(char *buf) {

/* skip past 'POST /' */ buf += 6;

/* then check for cmd/ledxhr */

return (!strncmp(buf, "cmd", 3) && !strncmp(buf + 4, "ledxhr", 6)); }

int

is_cmd_switch(char *buf) {

/* skip past 'POST /' */ buf += 6;

} void

extract_file_name(char *filename, char *req, int rlen, int maxlen) {

char *fstart, *fend; (adsbygoogle = window.adsbygoogle || []).push({});

/* first locate the file name in the request */

/* requests are of the form GET /path/to/filename HTTP... */ req += strlen("GET ");

if (*req == '/') req++;

fstart = req; /* start marker */

while (*req != ' ') /* file name finally ends in a space */ req++;

fend = req-1; /* end marker */ if (fend < fstart) {

strcpy(filename, "index.html"); return;

}

/* make sure filename is of reasonable size */ if (fend - fstart > maxlen) {

*fend = 0;

strcpy(filename, "404.html");

printf("Request filename is too long, length = %d, file = %s (truncated), max = %d\n\r",

(fend - fstart), fstart, maxlen); return;

}

filename[fend-fstart+1] = 0;

/* if last character is a '/', append index.html */ if (*fend == '/')

strcat(filename, "index.html"); }

char *get_file_extension(char *fname) {

char *fext = fname + strlen(fname) - 1; while (fext > fname) {

if (*fext == '.') return fext + 1; fext--; } return NULL; }

int generate_http_header(char *buf, char *fext, int fsize) {

char lbuf[40];

strcpy(buf, "HTTP/1.0 200 OK\r\nContent-Type: "); if (fext == NULL)

strcat(buf, "text/html"); /* for unknown types */ else if (!strncmp(fext, "htm", 3))

strcat(buf, "text/html"); /* html */ else if (!strncmp(fext, "jpg", 3))

strcat(buf, "image/jpeg"); else if (!strncmp(fext, "gif", 3))

strcat(buf, "text/javascript"); else if (!strncmp(fext, "pdf", 2)) strcat(buf, "application/pdf"); else if (!strncmp(fext, "css", 2)) strcat(buf, "text/css"); else

strcat(buf, "text/plain"); /* for unknown types */ strcat(buf, "\r\n");

sprintf(lbuf, "Content-length: %d", fsize); strcat(buf, lbuf);

strcat(buf, "\r\n"); (adsbygoogle = window.adsbygoogle || []).push({});

strcat(buf, "Connection: close\r\n"); strcat(buf, "\r\n"); return strlen(buf); } Chương trình webserver.c #include <stdio.h> #include <string.h> #include "xmk.h"

#include "lwip/sockets.h" #include "lwipopts.h" #include "webserver.h" #include "platform_gpio.h"

/* thread spawned for each connection */ void

process_http_request(int sd) {

int read_len;

int RECV_BUF_SIZE = 600; unsigned char recv_buf[RECV_BUF_SIZE]; /* read in the request */

if ((read_len = read(sd, recv_buf, RECV_BUF_SIZE)) < 0) return;

/* respond to request */

generate_response(sd, recv_buf, read_len); /* close connection */ close(sd); } /* http server */ int web_application_thread() {

int sock, new_sd;

struct sockaddr_in address, remote; int size;

/* create a TCP socket */

if ((sock = lwip_socket(AF_INET, SOCK_STREAM, 0)) < 0) return;

/* bind to port 80 at any interface */ address.sin_family = AF_INET; address.sin_port = htons(80);

address.sin_addr.s_addr = INADDR_ANY;

if (lwip_bind(sock, (struct sockaddr *)&address, sizeof (address)) < 0) return;

/* listen for incoming connections */ lwip_listen(sock, 5);

size = sizeof(remote); while (1) {

new_sd = lwip_accept(sock, (struct sockaddr *)&remote, &size); process_http_request(new_sd);

} }

void print_web_app_header() {

xil_printf("\n\r\n\r---DO AN TOT NGHIEP DAI HOC ---\n\r"); xil_printf("Open up your favorite browser and type: \n\r");

xil_printf("http://192.168.1.10\n\r"); }

Phụ lục 2:

Một phần của tài liệu Giám sát và điều khiển thiết bị qua mạng ETHERNET trên nền FPGA luận văn tốt nghiệp đại học (Trang 73)