Khóa luận Các kỹ thuật gỡ lỗi trong việc phát triển hệ thống nhúng với ngôn ngữ C

Tài liệu Khóa luận Các kỹ thuật gỡ lỗi trong việc phát triển hệ thống nhúng với ngôn ngữ C: ĐẠI HỌC QUỐC GIA HÀ NỘI TRƯỜNG ĐẠI HỌC CÔNG NGHỆ Ngô Thị Nga CÁC KỸ THUẬT GỠ LỖI TRONG VIỆC PHÁT TRIỂN HỆ THỐNG NHÚNG VỚI NGÔN NGỮ C KHÓA LUẬN TỐT NGHIỆP ĐẠI HỌC HỆ CHÍNH QUY Ngành: Công nghệ thông tin HÀ NỘI - 2010 ĐẠI HỌC QUỐC GIA HÀ NỘI TRƯỜNG ĐẠI HỌC CÔNG NGHỆ Ngô Thị Nga CÁC KỸ THUẬT GỠ LỖI TRONG VIỆC PHÁT TRIỂN HỆ THỐNG NHÚNG VỚI NGÔN NGỮ C KHÓA LUẬN TỐT NGHIỆP ĐẠI HỌC HỆ CHÍNH QUY Ngành: Công nghệ thông tin Cán bộ hướng dẫn: TS. Đặng Văn Hưng Cán bộ đồng hướng dẫn: ThS. Vũ Quang Dũng HÀ NỘI - 2010 LỜI CẢM ƠN Em xin chân thành cảm ơn Bộ môn Công nghệ phần mềm, Khoa Công nghệ thông tin, Trường Đại học Công nghệ, Đại học Quốc gia Hà Nội đã tạo điều kiện thuận lợi cho em trong quá trình học tập, rèn luyện và thực hiện đề tài khóa luận tốt nghiệp. Em xin gửi lời cảm ơn chân thành đến tất cả thầy cô trong trường đã giúp đỡ, dìu dắt em từ những ngày đầu tiên nhập trường. Em xin gửi lời cảm ơn sâu sắc nhất đến TS. Đặng Văn Hưng, TS. Trần Thị Minh Châu, T...

pdf65 trang | Chia sẻ: haohao | Lượt xem: 1175 | Lượt tải: 0download
Bạn đang xem trước 20 trang mẫu tài liệu Khóa luận Các kỹ thuật gỡ lỗi trong việc phát triển hệ thống nhúng với ngôn ngữ C, để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
ĐẠI HỌC QUỐC GIA HÀ NỘI TRƯỜNG ĐẠI HỌC CÔNG NGHỆ Ngô Thị Nga CÁC KỸ THUẬT GỠ LỖI TRONG VIỆC PHÁT TRIỂN HỆ THỐNG NHÚNG VỚI NGÔN NGỮ C KHÓA LUẬN TỐT NGHIỆP ĐẠI HỌC HỆ CHÍNH QUY Ngành: Công nghệ thông tin HÀ NỘI - 2010 ĐẠI HỌC QUỐC GIA HÀ NỘI TRƯỜNG ĐẠI HỌC CÔNG NGHỆ Ngô Thị Nga CÁC KỸ THUẬT GỠ LỖI TRONG VIỆC PHÁT TRIỂN HỆ THỐNG NHÚNG VỚI NGÔN NGỮ C KHÓA LUẬN TỐT NGHIỆP ĐẠI HỌC HỆ CHÍNH QUY Ngành: Công nghệ thông tin Cán bộ hướng dẫn: TS. Đặng Văn Hưng Cán bộ đồng hướng dẫn: ThS. Vũ Quang Dũng HÀ NỘI - 2010 LỜI CẢM ƠN Em xin chân thành cảm ơn Bộ môn Công nghệ phần mềm, Khoa Công nghệ thông tin, Trường Đại học Công nghệ, Đại học Quốc gia Hà Nội đã tạo điều kiện thuận lợi cho em trong quá trình học tập, rèn luyện và thực hiện đề tài khóa luận tốt nghiệp. Em xin gửi lời cảm ơn chân thành đến tất cả thầy cô trong trường đã giúp đỡ, dìu dắt em từ những ngày đầu tiên nhập trường. Em xin gửi lời cảm ơn sâu sắc nhất đến TS. Đặng Văn Hưng, TS. Trần Thị Minh Châu, ThS. Vũ Quang Dũng, những thầy cô đã cho em định hướng, tận tình chỉ bảo, hướng dẫn và giúp đỡ em trong quá trình tìm hiểu về hệ thống nhúng, cùng các kiến thức cần thiết khác để em hoàn thành khóa luận. Em xin gửi những lời cảm ơn, những tình cảm thương yêu tới gia đình, và người thân. Những người luôn bên em, động viên em cả về tinh thần và vật chất trong thời gian qua. Trong quá trình thực hiện khóa luận, em cũng đã nhận được nhiều sự chia sẻ, giúp đỡ, động viên của các thành viên lớp Công nghệ phần mềm K51, và của những thành viên trong diễn đàn sinh viên Đại học Công nghệ. Tôi xin gửi tới các bạn sự biết ơn sâu sắc. Đề tài “Các kỹ thuật gỡ lỗi trong việc phát triển hệ thống nhúng với ngôn ngữ C ” là một đề tài khá khó, lại được hoàn thành trong quỹ thời gian hạn hẹp nên khó tránh khỏi những khiếm khuyết. Em mong nhận được những góp ý chân thành từ thầy cô giáo và các bạn để đề tài có thể mở rộng và nghiên cứu kỹ hơn, đưa vào trong thực tiễn ngành công nghệ thông tin hiện nay. Hà Nội, ngày 15 tháng 05 năm 2010 Sinh viên Ngô Thị Nga i TÓM TẮT KHÓA LUẬN Khóa luận tập trung trình bày tổng quan về hệ thống nhúng, định nghĩa, đặc trưng của hệ thống, những khó khăn trong việc tìm hiểu một hệ thống nhúng. Sau đó, khóa luận đưa ra những kỹ thuật gỡ lỗi thường được áp dụng trên hệ thống nhúng, trong đó bao gồm cả các kỹ thuật gỡ lỗi dựa trên các công cụ phần mềm và công cụ phần cứng. Từ đó, khóa luận lựa chọn trình bày công cụ gỡ lỗi µVision của công ty Keil ARM, đây là một công cụ mạnh về gỡ lỗi theo kỹ thuật mô phỏng – một kỹ thuật được các kỹ sư lập trình áp dụng rất nhiều trong thực tế. Để minh họa cho việc áp dụng kỹ thuật gỡ lỗi và sử dụng công cụ gỡ lỗi, khóa luận xây dựng các chương trình phần mềm ứng dụng nhỏ là Đèn led nhấp nháy và Hello World – truyền các chuỗi ký tự ra cổng nối tiếp. Khóa luận áp dụng kỹ thuật và công cụ gỡ lỗi trên hai chương trình đó. ii MỤC LỤC CHƯƠNG 1: MỞ ĐẦU.............................................................................................1 1.1. Đặt vấn đề......................................................................................................1 1.2. Đề tài, đối tượng nghiên cứu và phương pháp nghiên cứu.............................1 1.3. Mục tiêu của khóa luận..................................................................................2 1.4. Cấu trúc của khóa luận...................................................................................2 CHƯƠNG 2: TỔNG QUAN.....................................................................................3 2.1. Hệ thống nhúng..............................................................................................3 2.1.1. Hệ thống nhúng là gì? ............................................................................3 2.1.2. Các thiết bị phần cứng thông thường......................................................3 2.1.3. Đặc trưng của hệ thống nhúng................................................................6 2.1.4. Ví dụ về hệ thống nhúng ........................................................................8 2.2. Sự lựa chọn ngôn ngữ lập trình cho hệ thống nhúng......................................8 CHƯƠNG 3: CÁC KỸ THUẬT GỠ LỖI ..............................................................10 3.1. Gỡ lỗi...........................................................................................................10 3.1.1. Gỡ lỗi trong quá trình phát triển hệ thống nhúng..................................10 3.1.2. Định nghĩa gỡ lỗi ..................................................................................11 3.1.3. Tầm quan trọng của việc gỡ lỗi.............................................................12 3.1.4. Mục đích của quá trình gỡ lỗi ..............................................................12 3.2. Kiểm thử trên máy chủ ................................................................................13 3.2.1. Kỹ thuật cơ bản ....................................................................................13 3.2.2. Gọi các thường trình ngắt .....................................................................15 3.2.3. Gọi thường trình ngắt định thời ............................................................15 3.2.4. Các tệp kịch bản và tệp kết xuất ...........................................................15 3.2.5. Những phản đối, hạn chế và nhược điểm..............................................16 3.3. Bộ mô phỏng ...............................................................................................17 3.4. Sử dụng macro assert ..................................................................................20 3.5. Sử dụng các công cụ trong phòng thí nghiệm ..............................................21 3.5.1. Máy hiện sóng ......................................................................................22 3.5.2. Bộ phân tích logic (Logic Analyzer) ....................................................24 3.5.2.1. Bộ phân tích logic theo chế độ thời gian .......................................26 3.5.2.2. Bộ phân tích logic theo chế độ trạng thái ......................................26 3.5.3. Bộ mô phỏng trong mạch .....................................................................28 CHƯƠNG 4: CÔNG CỤ GỠ LỖI...........................................................................31 4.1. Lý do chọn họ vi xử lý ARM........................................................................31 4.2. Giới thiệu công cụ µVision...........................................................................32 4.3. Các chức năng chính của công cụ µVision ..................................................33 4.3.1. Các chức năng của µVision IDE...........................................................33 4.3.2. Các chức năng của µVision Debugger..................................................35 4.4. Ưu điểm của µVision ...................................................................................37 4.4.1. Ưu điểm của µVision IDE.....................................................................37 4.4.2. Ưu điểm của µVision Simulator...........................................................38 iii 4.5. Một số hạn chế của µVision phiên bản dùng thử .........................................38 4.6. Cài đặt..........................................................................................................39 CHƯƠNG 5: ỨNG DỤNG CÔNG CỤ µVISION VÀO VIỆC GỠ LỖI...............41 5.1. Vi điều khiển LPC2148................................................................................41 5.2. Chương trình “Đèn led nhấp nháy”..............................................................41 5.3. Chương trình Hello world............................................................................43 5.4. Nhận xét.......................................................................................................45 CHƯƠNG 6: KẾT LUẬN.......................................................................................47 TÀI LIỆU THAM KHẢO.........................................................................................49 PHỤ LỤC: CÁC THÔNG SỐ KỸ THUẬT CỦA VI ĐIỀU KHIỂN LPC2148......50 iv DANH MỤC HÌNH ẢNH Hinh 2.1. Hệ thống nhúng thông thường Hình 3.1. Quá trình phát triển phần mềm nhúng Hình 3.2. Hệ thống kiểm thử Hình 3.3. Đồ thị máy hiện sóng Hình 3.4. Máy hiện sóng Hình 3.5. Bộ phân tích logic Hình 3.6. Chế độ thời gian của bộ phân tích logic Hình 3.7. Chế độ trạng thái của bộ phân tích logic Hình 4.1. Mẫu đăng ký sử dụng phần mềm Keil Hình 4.2. Giao diện IDE Hình 4.3. Giao diện của Debugger Hình 5.1. Kết quả chạy chương trình Led Hình 5.2. Kết quả chạy chương trình Hello world DANH MỤC BẢNG BIỂU Bảng 2.1. Họ vi xử lý ARM Bảng 3.1. Hàm NDEBUG Bảng 4.1. Các chức năng của MicroVision IDE Bảng 4.2. Các chức năng của MicroVision Debugger Bảng 5.1. Chương trình Led.c Bảng 5.2. Chương trình Hello.c v DANH SÁCH CÁC THUẬT NGỮ VÀ KHÁI NIỆM Thuật ngữ Khái niệm AGSI Advanced Simulation Interface – Giao diện mô phỏng nâng cao. ARM Advanced RISC Machine – Máy có bộ lệnh RISC mở rộng. AVR Đây là cấu trúc RISC 8 – bit của công ty Atmel. Big - Endian Bộ nhớ lưu các ký tự quan trọng nhất ở các bit địa chỉ thấp nhất. Cross–compiler Biên dịch chéo. Debugger Bộ gỡ lỗi. DWARF Đây là một định dạng tập tin gỡ lỗi được dùng trong nhiều trình biên dịch. ELF Executable and Linkable Format hay Extensible Linking Format – Tệp tin lưu dưới dạng thực thi và liên kết. Ground Điện áp bằng 0, tình trạng nối đất. ICE In – circuit Emulator – Bộ mô phỏng trong mạch. IDE Intergrated Development Environment – Môi trường phát triển tích hợp. ISS Instruction Set Simulator – Bộ mô phỏng tập lệnh. LED Light Emitting Diode – Đèn hai cực quang phát xạ. Linker/ Locator Bộ liên kết/ Định vị. Little - endian Bộ nhớ lưu các ký tự quan trọng nhất ở các bit địa chỉ cao nhất. MIPS Million Intruction Per Second – Số triệu dòng lệnh thực hiện trong một giây, Overlay memory Bộ nhớ nạp chồng. RAM Random Access Memory – Bộ nhớ truy cập ngẫu nhiên. RE Read Enable signal – Tín hiệu cho phép đọc từ ROM. RISC Reduced Instruction Set Computing – Máy tính dùng tập lệnh rút gọn. ROM Read Only Memory – Bộ nhớ chỉ đọc. vi Thuật ngữ Khái niệm RTOS Real Time Operating System – Hệ điều hành thời gian thực. Symbolic Output Format Định dạng kết xuất ký hiệu. VCC Voltage Connected to Collector – Điệp áp kết nối bộ gom – VCC thường đại diện cho điện áp ở mức cao (High). vii CHƯƠNG 1: MỞ ĐẦU 1.1. Đặt vấn đề Ngày nay, chúng ta có thể nhìn thấy các thiết bị nhúng ở khắp mọi nơi xung quanh ta từ những vật dụng đơn giản như chiếc đồng hồ điện tử, lò vi sóng, tủ lạnh, máy điện thoại di dộng, máy in, máy ảnh kỹ thuật số... đến những hệ thống lớn như các hệ thống điều khiển các dây chuyền sản xuất trong công nghiệp, điều khiển các hoạt động trong lò phản ứng hạt nhân... Chúng ta khó mà có thể tìm được một thiết bị điện tử mà bên trong nó không có một vài vi xử lý, vi điều khiển. Đặc biệt là các họ vi xử lý ARM đã được ứng dụng rất nhiều trong các thiết bị nhúng. Các hệ thống nhúng ngày càng phát triển, các phần mềm để điều khiển cho các thiết bị cũng ngày càng đa dạng. Vì vậy, các nhà sản xuất cần đảm bảo cho các thiết bị của mình đến được tay người dùng với độ ổn định, hiệu quả và ít lỗi nhất có thể. Quá trình gỡ lỗi sẽ đảm bảo cho sản phẩm có chất lượng tốt nhất. Hiện nay, có rất nhiều công cụ gỡ lỗi cho hệ thống nhúng, các kỹ sư lập trình cần phải chọn cho mình được một công cụ gỡ lỗi phù hợp với thiết bị của mình để đạt hiệu quả gỡ lỗi cao nhất. 1.2. Đề tài, đối tượng nghiên cứu và phương pháp nghiên cứu Đề tài của khóa luận là “Các kỹ thuật gỡ lỗi trong việc phát triển hệ thống nhúng với ngôn ngữ C”. Khóa luận mong muốn cung cấp cho các kỹ sư lập trình phần mềm nhúng một cái nhìn tổng quát về hệ thống, các kỹ thuật gỡ lỗi, công cụ gỡ lỗi. Đối tượng nghiên cứu chính trong đề tài là vi điều khiển LPC2148 của công ty Philips. Đây là một vi điều khiển được thiết kế dựa trên cấu trúc của vi xử lý ARM đã được sử dụng rộng rãi trong nhiều thiết bị, sản phẩm. Khóa luận tập trung tìm hiểu về lý thuyết hệ thống nhúng, các kỹ thuật gỡ lỗi, sau đó áp dụng các kiến thức đó vào thực hiện việc gỡ lỗi cho phần mềm nhúng. Khóa luận tập trung nghiên cứu kỹ thuật gỡ lỗi bằng phương pháp mô phỏng. Phương pháp này có ưu điểm là phổ biến, có nhiều công cụ, dễ sử dụng, được sự hỗ trợ lớn về mặt kiến thức và chuyên môn từ các nhà sản xuất và cộng đồng người sử dụng, có thể áp dụng phương pháp mô phỏng này khi phần cứng còn đang được phát triển, hay phần cứng không có sẵn. 1 1.3. Mục tiêu của khóa luận Để đạt được các vấn đề đã nêu ra, khoá luận sẽ lần lượt trình bày những kiến thức cần thiết để giải quyết yêu cầu trên. Khóa luận sẽ tập trung vào một số các vấn đề sau: • Tìm hiểu khái quát về hệ thống nhúng, các đặc điểm của hệ thống và việc lựa chọn các ngôn ngữ lập trình cho hệ thống. • Tìm hiểu các kỹ thuật gỡ lỗi cơ bản cho hệ thống nhúng. • Tìm hiểu công cụ gỡ lỗi µVision, các chức năng, ưu nhược điểm của chương trình. • Xây dựng chương trình, ứng dụng công cụ gỡ lỗi vào việc gỡ lỗi cho chương trình để thấy được những ưu nhược điểm của công cụ. 1.4. Cấu trúc của khóa luận Khóa luận được trình bày theo cấu trúc như sau: Chương mở đầu: Giới thiệu về đề tài, mục tiêu của khóa luận và cấu trúc khóa luận. Chương hai: Giới thiệu tổng quan về hệ thống nhúng, định nghĩa hệ thống nhúng, các đặc trưng của hệ thống và việc chọn lựa một ngôn ngữ lập trình phù hợp với hệ thống nhúng. Chương ba: Tiếp cận với các kỹ thuật gỡ lỗi thường dùng trong hệ thống nhúng: kiểm thử trên máy chủ, kiểm thử sử dụng bộ mô phỏng, macro assert và gỡ lỗi dùng các thiết bị phần cứng. Chương bốn: Tiếp cận tìm hiểu công cụ gỡ lỗi µVision của công ty Keil ARM, là một công cụ hỗ trợ việc gỡ lỗi rất hiệu quả cho các vi xử lý thuộc họ ARM, giới thiệu các chức năng, ưu nhược điểm của công cụ. Chương năm: Xây dựng ví dụ minh họa và áp dụng công cụ để gỡ lỗi cho các chương trình “Đèn led nhấp nháy” và “Hello world” bằng kỹ thuật mô phỏng để thực hiện mục tiêu của khóa luận. Chương sáu: Đánh giá kết quả khóa luận đã đạt được và nêu ra hướng phát triển trong tương lai của đề tài. 2 CHƯƠNG 2: TỔNG QUAN Chương 2 giới thiệu tổng quan về: hệ thống nhúng: định nghĩa hệ thống nhúng, đặc trưng của hệ thống, ví dụ về hệ thống. Và sự lựa chọn ngôn ngữ lập trình cho hệ thống nhúng. 2.1. Hệ thống nhúng 2.1.1. Hệ thống nhúng là gì? Thuật ngữ hệ thống nhúng thường được dùng để chỉ bất kỳ hệ thống máy tính nào ẩn chứa bên trong các thiết bị, hệ thống [4]. Bên cạnh đó còn có nhiều định nghĩa khác cho khái niệm hệ thống nhúng. Dưới đây là một khái niệm được đưa ra trong từ điển Các hệ thống nhúng: “Hệ thống nhúng là một sự kết hợp giữa phần cứng và phần mềm của máy tính và có thể có thêm các thiết bị cơ khí hay các bộ phận khác, nó được thiết kế để thực hiện một chức năng cụ thể”. [2] Trong vài trường hợp, hệ thống nhúng có thể chỉ là một phần nhỏ trong một hệ thống lớn như trong các thiết bị điều khiển xe hơi. Bởi những thiết kế của hệ thống nhúng là để phục vụ cho một vài chức năng cụ thể đã được định trước như là bộ phận hẹn giờ trong lò vi sóng, hệ thống điều khiển đèn giao thông,... nên nó khác với các máy tính cá nhân thông thường – hệ thống có thể thực hiện nhiều nhiệm vụ khác nhau do người dùng cài đặt. [1] 2.1.2. Các thiết bị phần cứng thông thường Bất kỳ một hệ thống thông thường nào cũng đều có các thành phần cấu thành nên nó. Một hệ thống nhúng thông thường sẽ gồm có một số thành phần như hình 2.1 sau: Hình 2.1. Hệ thống nhúng thông thường 3 Mỗi hệ thống đều cần có vi xử lý để điều khiển các thông tin và dữ liệu trong hệ thống. Trong các thiết bị gia dụng như lò vi sóng, nồi cơm điện, hay chiếc điện thoại cũng có ít nhất một bộ vi xử lý. Các vi xử lý được chia làm hai loại: bộ vi xử lý chính dùng để điều khiển các thiết bị trung tâm, và các vi xử lý phụ được thêm vào để mở rộng các tập lệnh của vi xử lý chính, quản lý bộ nhớ, các đường truyền, và các thiết bị nhập xuất. Trong các thiết bị nhúng, vi xử lý chính thường là các vi điều khiển, để phù hợp với các phần mềm, các chương trình rất nhỏ ẩn chứa bên trong những thiết bị. Các vi xử lý giống như bộ não của con người, nếu không có nó thì các thiết bị không thể hoạt động được. Chính vì thế, vi xử lý đóng vai trò trung tâm, quan trọng nhất trong thiết bị. Thiết bị nhúng được ứng dụng rộng rãi trong nhiều lĩnh vưc, nó cũng tiêu thụ nhiều nhất số vi xử lý được sản xuất ra hàng năm. Các họ vi xử lý được phát triển và ứng dụng rộng rãi là 8051 của Intel, họ AVR của Atmel, họ ARM của công ty ARM,... trong các họ này thì các thiết bị được xây dựng trên nền tảng thiết kế của ARM là phổ biến nhất. Bảng 2.1 sẽ đưa ra một số vi xử lý của họ ARM và ứng dụng của chúng trong các thiết bị điện tử. 4 Bảng 2.1. Một số họ vi xử lý ARM và ứng dụng của nó [10] Họ Lõi Đặc tính MIPS điển hình/ MHz Ứng dụng ARM7T DMI ARM7TDMI (-S) 3-tầng pipeline 15 MIPS/ 16.8 MHz Game Boy Advance, Nintendo DS, iPod ARM9E ARM946E-S Nintendo DS, Nokia N-Gage, Conexant 802.11 chip ARM966E-S ST Micro STR91xF, gồm cạc Ethernet ARM926EJ- S Jazelle DBX 220 MIPS/ 200 MHz Điện thoại di động: Sony Ericsson (K, W series),Siemens và Benq (đời x65 và đời mới hơn) Cortex Cortex-A8 NEON, Jazelle RCT, Thumb-2 Texas Instruments OMAP3 Cortex-R4 600 DMIPS Broadcom là một hãng sử dụng Cortex-M3 120 DMIPS/ 100MHz Họ vi điều khiển Luminary Micro XScale PXA27x 800 MIPS/ 624 MHz HTC Universal, Zaurus SL-C1000 PXA900 Blackberry 8700 IXP460/IXP 465 Một hệ thống nhúng cần sử dụng bộ nhớ cho hai mục đích: để lưu trữ chương trình và lưu trữ dữ liệu. Không giống như một hệ thống máy tính cá nhân – các chương trình và dữ liệu đuợc lưu trong những phần bộ nhớ giống nhau, hệ thống nhúng dùng các bộ nhớ khác nhau cho các mục đích khác nhau. Bởi vì thông thường một hệ thống nhúng không có ổ đĩa cứng để nạp chương trình, chương trình phải được lưu trong bộ nhớ, thậm chí ngay cả khi tắt nguồn. Bộ nhớ của hệ thống nhúng thường là: bộ nhớ chỉ đọc (ROM), bộ nhớ truy cập ngẫu nhiên (RAM) và có thể là cả bộ nhớ mở rộng với các hệ thống lớn. [4] 5 Các hệ thống nhúng cũng có thể chứa các thiết bị đầu vào và thiết bị đầu ra. Ví dụ như trong các máy điện thoại di động, thiết bị đầu vào là các nút bấm trên bề mặt điện thoại, và thiết bị đầu ra là màn hình điện thoại và loa. Các thiết bị đầu vào của hệ thống nhúng thường ở dưới dạng các thiết bị cảm biến, đầu dò, tín hiệu, hay các nút bấm. Các thiết bị đầu ra của hệ thống thường là màn hình và các tín hiệu. Hệ thống nhúng không giống các máy vi tính thông thường, có một số thành phần của máy vi tính có thể sẽ không có trong hệ thống nhúng. Các thành phần đó là: • Bàn phím: Một số hệ thống có thể có vài nút bấm để người dùng nhập dữ liệu đầu vào, như là máy in, nhưng cũng có những hệ thống không có bàn phím như là máy điện báo. • Chuột: Đối với những máy tính thông thường thì chuột máy tính sẽ làm cho việc sử dụng máy tính được dễ dàng, thuận lợi hơn. Nhưng trong hầu hết các hệ thống nhúng thì chuột đều không xuất hiện. Các tác vụ mà chúng ta thực hiện với hệ thống thường được kích hoạt qua các nút bấm, các cảm biến điện tử. • Màn hình: Nhiều hệ thống sẽ có một màn hình tinh thể lỏng hiển thị vài chức năng đặc trưng, ví dụ như máy giặt thì có một màn hình hiển thị chế độ đang giặt. Hay một số hệ thống chỉ có điốt phát quang để báo hiệu thiết bị đang ở chế độ nào, ví dụ như máy in có đèn nháy để biết rằng máy đang ở chế độ in hay chế độ chờ. • Ổ đĩa cứng: Do thiết kế nhỏ gọn, nên các hệ thống nhúng thường không có ổ đĩa cứng gắn rời bên ngoài mà các chương trình và dữ liệu của hệ thống nhúng thì thường được lưu trữ ở bộ nhớ trong của máy tính (RAM và ROM). • Đĩa quang, loa, tai nghe: hầu hết các hệ thống nhúng không cần tới những thiết bị này. Ngoài ra thì hệ thống nhúng còn có thể có thêm các bộ phận như là: các cổng nối tiếp, các cổng kết nối mạng internet, các phần cứng tương tác với bộ cảm biến,... 2.1.3. Đặc trưng của hệ thống nhúng Mỗi hệ thống nhúng đều có những đặc trưng khác nhau, để thỏa mãn được những yêu cầu khác nhau. Vì các hệ thống nhúng thường nhỏ và chỉ có một số thiết bị cần thiết - nó không giống như các máy vi tính thông thường, nên khi làm việc với các hệ thống nhúng ta gặp rất nhiều khó khăn: 6 • Công suất: Hệ thống cần điều khiển được một lượng lớn dữ liệu trong một khoảng thời gian rất ngắn. • Tính đáp ứng: Hệ thống cần lặp lại các sự kiện một cách nhanh chóng. Ví dụ: việc nhấp nháy của các điôt phát quang là trong một chu kỳ ngắn, lặp lại liên tục. • Khả năng kiểm thử: Kiểm thử cho một hệ thống nhúng có thể là một việc rất khó khăn. • Khả năng gỡ lỗi: Làm thế nào để ta tìm ra các lỗi trong chương trình của hệ thống nhúng với thiết kế đặc trưng là không bàn phím, không màn hình? Làm sao để biết được một phần mềm nào đó đang làm gì trong thiết bị nhúng quả là một việc không dễ dàng gì. Ở đây chúng ta cần đến các thiết bị, các chương trình phần mềm riêng biệt để gỡ lỗi cho nó. • Độ tin cậy: Hệ thống nhúng phải có thể tự điều khiển được trong bất kỳ tình huống nào mà không có sự can thiệp của con người. Với các hệ thống lái xe tự động, hệ thống cần quyết định tất cả những việc cần làm, như chạy ở tốc độ bao nhiêu, đi hướng nào. Hệ thống gần như phải chạy tốt trong mọi trường hợp có thể tính toán trước của nhà sản xuất với độ ổn định cao. • Không gian bộ nhớ: Bộ nhớ của hệ thống nhúng thường bị giới hạn, chúng ta cần phải làm cho các phần mềm và dữ liệu chứa vừa vặn trong không gian nhớ đó. Các thanh ghi địa chỉ thường chỉ là loại 8 bit, hay 16 bit, nên việc cung cấp không gian nhớ là rất hạn chế. Vì vậy một nhiệm vụ khó khăn đặt ra cho các kỹ sư lập trình là phải tối ưu mã làm sao cho với số dòng lệnh ít nhất, chương trình nhỏ nhất mà vẫn có thể thực hiện đuợc các tác vụ yêu cầu. • Cài đặt chương trình: Thông thường ta sẽ cần một công cụ đặc biệt để nạp các chương trình vào trong hệ thống. • Điện năng tiêu thụ: Các hệ thống nhúng thường ở trong các thiết bị nhỏ, nên điện năng tiêu thụ cũng ít. Thông thường mức tiêu thụ điện năng trên các thiết bị này đuợc tính bằng mW/ MIPS (miliwatts/ MIPS, MIPS – số triệu dòng lệnh thực hiện được trong một giây), giá trị này càng nhỏ thì điện năng tiêu thụ càng ít. Mức tiêu thụ điện năng nhỏ cũng làm cho thiết bị sử dụng các pin nhỏ hơn, nhẹ hơn, thiết kế của thiết bị cũng nhỏ gọn hơn. 7 • Tốc độ tính toán: Tốc độ tính toán của một thiết bị thường được đo bằng MIPS. Nếu các thiết bị có chỉ số MIPS càng cao thì làm việc càng hiệu quả, Ngày nay các thiết bị có độ rộng các thanh ghi là từ 8 – 64 bit, với các thiết bị nhúng thì thường dùng các vi xử lý có độ rộng thanh ghi là 8 - 16 bit, các thanh ghi 32 - 64 bit cho phép nạp đuợc nhiều chương trình, dữ liệu vào thiết bị hơn. [1] • Giá thành phát triển: Với các hệ thống nhúng trong các thiết bị hàng ngày, các thiết bị nhỏ, thì giá thành phát triển của một sản phẩm có thể cũng sẽ nhỏ, nhưng khi áp dụng để sản xuất hàng loạt các sản phẩm đó thì công ty vẫn có lãi. Với các thiết bị chuyên biệt, giá thành sản phẩm đến hàng triệu đôla, thì giá thành phát triển của nó cũng tương đối lớn. • Giá thành sản phẩm: Với các thiết bị thông thường, giá thành sản phẩm của nó có thể chỉ nhỏ hơn 10 đôla, điều đó ảnh hưởng rất lớn đến các thiết kế của sản phẩm. 2.1.4. Ví dụ về hệ thống nhúng Với sự phát triển mạnh mẽ của các hệ thống nhúng, ta có thể bắt gặp chúng ở khắp mọi nơi. Ví dụ điển hình của một hế thống nhúng mà ta có thể bắt gặp hàng ngày đó là chiếc điện thoại di động. Thiết kế của chiếc điện thoại di động ngày nay nhỏ gọn, thường có các nút bấm hay có khả năng điều khiển bằng màn hình chạm (touch-screen) dùng để nhập liệu, màn hình để hiển thị các thông tin, bộ nhớ trong từ vài KB đến vài trăm MB, có thể hỗ trợ bộ nhớ mở rộng, và tiêu thụ ít điện năng, các máy điện thoại thường dùng pin sạc. Hầu hết các máy điện thoại di động đều thực hiện được các chức năng thông thường như là nghe, gọi, nhắn tin, tra danh bạ, báo thức, ghi chú, hiển thị ngày tháng, chơi các chương trình điện tử đơn giản. Với những máy điện thoại di động cao cấp, ta còn có thể nghe nhạc, truy cập mạng internet, quay phim, chụp ảnh, đọc sách, và thậm chí có các các hệ điều hành hỗ trợ cho người sử dụng thực hiện các tác vụ yêu cầu. Giá thành một chiếc điện thoại cũng không quá cao, mà độ tin cậy và độ ổn định của điện thoại di động là khá cao. 2.2. Sự lựa chọn ngôn ngữ lập trình cho hệ thống nhúng Đối với một dự án phần mềm nhúng việc chọn ngôn ngữ lập trình cho nó là rất 8 quan trọng. Ngôn ngữ lập trình này phải đáp ứng được cho việc thiết kế các hệ thống với chỉ vài byte, KB đến vài trăm MB bộ nhớ, và hỗ trợ tốt cho nhóm phát triển với số lượng nhà lập trình từ một vài người đến hàng trăm người. Ngôn ngữ này cũng phải được dịch ra các mã máy để nạp vào thiết bị một cách dễ dàng. Hiện nay, ngôn ngữ được sử dụng phổ biến nhất là C. Ngôn ngữ C có rất nhiều ưu điểm hỗ trợ cho việc phát triển các hệ thống nhúng. Nó là một ngôn ngữ dễ học, dễ dùng, khả chuyển và có thể chạy trên hầu hết các hệ điều hành. Các đoạn mã viết bằng ngôn ngữ C cũng nhỏ, gọn, dễ biên dịch và gỡ lỗi hơn. Một trong những tính năng nổi bật để làm cho C trở thành một ngôn ngữ thích hợp cho việc lập trình: C là “ngôn ngữ trung gian”. Nó vừa hỗ trợ cho người lập trình có thể can thiệp sâu vào phần cứng máy tính, cũng vừa là một ngôn ngữ lập trình bậc cao với cấu trúc và các tập lệnh dễ hiểu. Ngoài ngôn ngữ C, chúng ta có thể lập trình cho hệ thống nhúng bằng một số ngôn ngữ như Assembly, Ada, C++, Java,... Nhưng việc lập trình trên các ngôn ngữ này gặp một số khó khăn. Assembly có ưu điểm là can thiệp sâu vào phần cứng, mã lệnh viết ra có thể thực thi trực tiếp, nhược điểm của nó là khó học, khó sử dụng. C++ là một ngôn ngữ lập trình bậc cao, hướng đối tượng nên cũng khó cho người lập trình tác động nhiều đến phần cứng. Ngôn ngữ Java với công nghệ JavaME cũng là một ngôn ngữ mới cho phép người lập trình viết các ứng dụng chạy trên nền các thiết bị phần cứng nhỏ như chip, thẻ thông minh, điện thoại... 9 CHƯƠNG 3: CÁC KỸ THUẬT GỠ LỖI Trong chương này, khóa luận sẽ đưa ra khái niệm về gỡ lỗi và các kỹ thuật gỡ lỗi cho các phần mềm của hệ thống nhúng. Các kỹ sư lập trình có thể áp dụng một hoặc kết hợp một vài phương pháp gỡ lỗi để cho kết quả tốt nhất. 3.1. Gỡ lỗi 3.1.1. Gỡ lỗi trong quá trình phát triển hệ thống nhúng Quá trình phát triển hệ thống nhúng và phần mềm ứng dụng thông thường đều gồm những bước giống nhau. Hình 3.1 là biểu đồ những giai đoạn cơ bản của một quá trình phát triển phần mềm nhúng. Hình 3.1. Quá trình phát triển phần mềm nhúng Quá trình phát triển phần mềm nhúng thường bắt đầu bằng giai đoạn thiết kế, và cài đặt. Sau đó là giai đoạn sinh mã, nạp mã, gỡ lỗi và sửa lỗi, đây là một quá trình lặp đi lặp lại và tiêu tốn thời gian, công sức của các kỹ sư lập trình nhất. Ngoài ra còn một số giai đoạn khác nữa như là kiểm thử, tối ưu mã, tích hợp hay sau khi sản phẩm được đưa tới người tiêu dùng thì chúng ta còn cần phải tiến hành bảo trì cho sản phẩm. Trong giai đoạn thiết kế, các kỹ sư lập trình sử dụng các công cụ, ngôn ngữ đặc tả mô hình hóa các chức năng của hệ thống, để từ đó có thể cài đặt đúng các chức năng 10 mà hệ thống yêu cầu. Giai đoạn cài đặt, các kỹ sư lập trình viết các chương trình của mình bằng các ngôn ngữ lập trình như Assembly, C/C++, Java... Các ngôn ngữ lập trình này thường dễ học, dễ sử dụng, khả chuyển giúp cho các kỹ sư lập trình trong một đội có thể hiểu được chương trình của nhau. Giai đoạn tiếp theo là sinh mã. Các hệ thống nhúng của chúng ta không hiểu các lệnh, các chương trình được viết bằng những ngôn ngữ bậc cao, chúng chỉ hiểu được mã máy - dạng các chuỗi bit 0, 1. Vì vậy sau khi cài đặt, chúng ta cần biên dịch, liên kết, định địa chỉ bộ nhớ cho các tệp tin chương trình thành một tệp tin thực thi dạng mã nhị phân để hệ thống có thể hiểu được, quá trình này gọi là sinh mã. Các máy đích có kiến trúc khác nhau thì chương trình thực thi trong nó sẽ khác nhau, vì vậy các tệp tin thực thi dạng mã nhị phân này thường phải tuân theo một số định dạng nhất định như là hex hay elf… là những định dạng phổ biến mà nhiều hệ thống hiểu được. Giai đoạn nạp mã và gỡ lỗi là giai đoạn mà chúng ta nạp tệp tin thực thi đã được sinh ra ở trên vào trong máy đích, và tìm các lỗi có trong chương trình. Thời gian này là để chúng ta tìm các lỗi khi chương trình chạy trên phần cứng, các lỗi này có thể là những lỗi do không tương thích giữa phần cứng và phần mềm, hay những lỗi thời gian phản ứng chậm hơn so với quy định,... Đây là một giai đoạn quan trọng trong quá trình phát triển phần mềm vì nó giúp đảm bảo chất lượng cho phần mềm. Phần sau của khóa luận sẽ trình bày cụ thể về công việc gỡ lỗi cho hệ thống nhúng. Sau khi tìm ra được lỗi thì các kỹ sư lập trình bắt đầu sửa các lỗi trong chương trình của mình, để đảm bảo cho chương trình của mình chạy tốt. Quá trình sinh mã, nạp mã, gỡ lỗi và sửa lỗi được tiến hành lặp đi lặp lại, để đảm bảo cho sản phẩm khi đi tới người tiêu dùng là ít lỗi nhất, và ổn định nhất có thể. 3.1.2. Định nghĩa gỡ lỗi Không có một hệ thống nào hoàn hảo cả, hầu như các hệ thống đều có lỗi, chỉ khác nhau ở tỷ lệ lỗi nhiều hay ít. Việc kiểm thử và gỡ lỗi giúp chúng ta giảm thiểu được các lỗi, để có thể đưa tới cho khách hàng những sản phẩm ít lỗi hơn. Gỡ lỗi là quá trình loại bỏ các lỗi ra khỏi chương trình, các lỗi từ bản đặc tả tới lỗi trong khi phát triển mã lệnh. Gỡ lỗi là hành động sửa lại các lỗi sau khi viết và bắt đầu kiểm thử hệ thống. Gỡ lỗi thường là phần tốn công sức nhất trong quá trình phát triển hệ thống. [2] 11 3.1.3. Tầm quan trọng của việc gỡ lỗi Việc gỡ lỗi cho phần mềm nói chung và phần mềm nhúng nói riêng là một khâu quan trọng nhằm đảm bảo chất lượng của phần mềm vì những lý do sau: Thứ nhất, việc gỡ lỗi thường gặp khó khăn và tốn thời gian hơn so với các phần mềm ứng dụng thông thường. Bởi đôi khi phần cứng và phần mềm của hệ thống nhúng đang được phát triển song song, nên chưa có phần cứng ổn định để kiểm thử hoặc giá thành của phần cứng cao nên ta cần phải áp dụng nhiều phương pháp gỡ lỗi và kiểm thử không trực tiếp trên phần cứng. Việc gỡ lỗi cũng khó khăn hơn với so với các hệ thống khác vì những đặc trưng cấu tạo của hệ thống là thường không có các thiết bị nhập xuất thông thường như bàn phím, màn hình để có thể theo dõi được. [4] Thứ hai là các lỗi của các phần mềm nhúng rất khó được người dùng chấp nhận, bởi khi một chương trình đã được nạp vào phần cứng, đưa vào dây chuyền sản xuất hàng loạt, và phân phối ra thị trường mà mới phát hiện ra một lỗi nào đó thì sự việc này có thể gây hậu quả nghiêm trọng cho người dùng, ảnh hưởng rất lớn tới uy tín và lợi nhuận của công ty sản xuất. 3.1.4. Mục đích của quá trình gỡ lỗi Mục đích của quá trình gỡ lỗi thông thường là: • Tìm lỗi sớm trong quá trình phát triển: Việc tìm ra lỗi sớm trong quá trình kiểm thử giúp chúng ta tiết kiệm thời gian và tiền bạc. Và nó cũng cho ta ý tưởng về các lỗi dễ mắc phải trong quá trình phát triển phần mềm, để có những cách sửa lỗi hay tránh lỗi. Nhưng: hệ thống đích không phải lúc nào cũng có ngay từ đầu trong quá trình phát triển, hệ thống này có thể đang được phát triển song hành với các phần mềm ứng dụng trên nó. Hoặc hệ thống đích đã có nhưng chưa được ổn định, còn gặp lỗi nên việc gỡ lỗi cho các phần mềm gặp nhiều khó khăn. • Thực thi tất cả các lệnh: Việc chạy tất cả các lệnh, tức là chạy tất cả các trường hợp từ các trường hợp tổng quát đến các trường hợp đơn lẻ, các ngoại lệ, các trường hợp mà ta không mong muốn xảy ra. Nhưng: Thực hiện các tất cả các lệnh trên máy chủ là rất khó khăn, vì những tình huống xảy ra trên thực tế, đôi khi lại khó có thể mô phỏng, thực hiện được trên máy đích. 12 • Phát triển dùng lại, kiểm thử nhắc lại: Khi một lỗi xảy ra rất nhanh chỉ trong vài giây, chúng ta hy vọng rằng nó sẽ xảy ra các lần sau nữa để có thể kiểm soát lỗi, và thực hiện việc gỡ lỗi. Nhưng lỗi này không xảy ra lần nữa, việc tìm ra lỗi và kiểm thử nó trở lên khó khăn hơn. Với các phần mềm được phát triển lặp lại, từ phiên bản 1, phiên bản 2, đến phiên bản 3,... có những lỗi mà chúng ta đã phát hiện, đã sửa được từ phiên bản 1, và không thấy xuất hiện ở phiên bản 2, nhưng đến phiên bản 3 ta lại thấy. Vì vậy, việc kiểm thử nhắc lại trong quá trình phát triển dùng lại là rất quan trọng. Nó đảm bảo chất lượng của sản phẩm khi đưa tới khách hàng. Nhưng: Tương tự với những khó khăn khi thực thi tất cả mã lệnh, thường thì việc thiết kế các ca kiểm thử nhắc lại trên môi trường đích là khó khăn. • Giữ lại “biên bản kiểm tra” các kết quả kiểm thử: Chúng ta thường khó biết được các hệ thống của chúng ta làm việc như thế nào, chúng gửi nhận dữ liệu, tín hiệu ra sao. Các biên bản kiểm tra sẽ cho chúng ta thấy chúng thật sự làm việc như thế nào. Nhưng: Các hệ thống nhúng hầu như không có ổ đĩa cứng để lưu lại dấu vết kiểm tra, cùng các thông tin, nên việc giữ lại các dấu vết kiểm tra là khó khăn. 3.2. Kiểm thử trên máy chủ Đối với các phần mềm nhúng, có nhiều lý do để phát triển phần mềm trên một hệ thống máy chủ và sau đó mới đưa phần mềm vào hệ thống đích để chạy. Các hệ thống chúng ta sản xuất có thể giống như một chiếc máy điện báo, không có màn hình, không có bàn phím, không có ổ đĩa, hay thậm chí không có đèn để chúng ta biết rằng nó đang hoạt động. Vậy giải pháp ở đây là phát triển phần mềm trên một hệ thống máy - nơi có các công cụ để viết lệnh, biên dịch, gỡ lỗi - máy chủ, và sau đó nạp nó vào hệ thống máy đích để nó có thể thực hiện được các chức năng yêu cầu. 3.2.1. Kỹ thuật cơ bản Hình 3.1 mô phỏng cho chúng ta thấy phương pháp cơ bản để kiểm thử phần mềm nhúng trên máy chủ: 13 Hình 3.2. Hệ thống kiểm thử Phần bên trái của hình vẽ tương ứng với hệ thống đích, nó được chia thành ba thành phần: các mã độc lập với phần cứng, các mã phụ thuộc phần cứng và phần cứng. Phần bên phải của hình vẽ tương ứng với hệ thống kiểm thử, hệ thống này gồm hai thành phần chính là: các mã độc lập phần cứng và mã nền kiểm thử (test scaffold code). Nền kiểm thử là thay thế cho các mã phụ thuộc phần cứng và phần cứng, trong đó nó cung cấp bàn phím, màn hình và ổ đĩa để phục vụ cho việc viết mã lệnh, biên dịch, kết nối, gỡ lỗi cho các phần mềm. Mã nền kiểm thử dùng để: – Cung cấp các điểm tiếp nhận giống như các đoạn mã phụ thuộc phần cứng trên hệ thống đích. – Gọi các chức năng tương tự như các mã phụ thuộc phần cứng gọi đến phần mã không phụ thuộc phần cứng. – Đọc các lệnh từ bàn phím hay từ các tệp tin. – Hiển thị thông tin lên màn hình hay ghi ra tệp tin. Kỹ thuật này yêu cầu chúng ta có một thiết kế giao diện rõ ràng giữa phần mã độc lập phần cứng và phần còn lại. Thậm chí nó còn đòi hỏi chia các đoạn mã của phần mềm thành các đoạn mã độc lập phần cứng và các phần còn lại một cách dễ 14 dàng. Và điều này không phải lúc nào cũng thực hiện được. 3.2.2. Gọi các thường trình ngắt Hầu hết các hệ thống nhúng thực hiện các chức năng khi các ngắt (interrupt) xảy ra và thường trình ngắt (interrupt routine) được thực thi. Trong môi trường kiểm thử, để hệ thống thực hiện các lệnh thì mã nền kiểm thử cũng cần thực thi các thường trình ngắt. Các thường trình ngắt chia thành hai loại: một loại dùng để gọi đến phần cứng và một loại dùng để gọi đến phần còn lại của hệ thống. Để kiểm thử thì các thường trình ngắt cần được thiết lập để cho phần mã phụ thuộc phần cứng gọi đến phần mã không phụ thuộc phần cứng. Các mã lệnh viết bằng ngôn ngữ C giúp chúng ta thực hiện việc này một cách dễ dàng.[4] 3.2.3. Gọi thường trình ngắt định thời Trong hầu hết các phần mềm hệ thống nhúng, các thường trình ngắt định thời (timer interrupt routine) thường được gọi một cách tự động sau khi máy chủ đã thực hiện xong một số lệnh. Nếu mã nền kiểm thử bị mất quyền kiểm soát việc gọi các thường trình ngắt định thời thì sẽ gây ra các lỗi gián đoạn. Vì vậy, mã nền kiểm thử nên gọi thường trình ngắt định thời một cách trực tiếp. Điều này sẽ giúp cho chúng ta có thể nhìn thấy các hoạt động của hệ thống từng giây, từng phút, nó có thể sẽ gây ra một số phiền phức, nhưng bù lại chúng ta có thể tránh được các lỗi nghiêm trọng. Nó cũng cho phép chúng ta kiểm thử các đoạn mã mà sẽ chỉ được gọi sau các lệnh khác bằng cách gọi các thường trình ngắt định thời. [4] 3.2.4. Các tệp kịch bản và tệp kết xuất Chúng ta thường phải viết các lệnh để gọi các thường trình ngắt lặp lại liên tục khi thực hiện việc kiểm thử. Nhưng có một cách dễ dàng hơn để làm việc này, đó là viết các tệp kịch bản (script file), nền kiểm thử chỉ cần đọc tệp kịch bản, thực thi các lệnh trong tệp và ghi kết quả thực hiện ra các tệp tin. Các tệp kịch bản này thường được viết ngắn gọn, đơn giản. Khi viết các tệp kịch bản, ta cần lưu ý một số điểm sau [4]: • Các lệnh nên được viết đơn giản với các đoạn mã lệnh ngắn. Một bộ phân tích cú pháp cho các tệp kịch bản được viết khá dễ dàng với ngôn ngữ C. • Các kỹ sư lập trình nên sử dụng các ghi chú, để cho cấu trúc tệp tin được rõ 15 ràng, dễ hiểu, và chúng ta có thể biết rằng tệp kịch bản thực thi những lệnh nào, các phần nào đang được kiểm thử. Việc viết các tệp tin và các ghi chú cũng nên tuân theo các chuẩn chung để tất cả mọi người làm việc trong dự án có thể hiểu và thực hiện nó. Các ghi chú thường được bắt đầu bằng ký hiệu #. • Dữ liệu nhập vào có thể là ở dạng mã ASCII hoặc ở các định dạng khác. Nhiều hệ thống nhúng nhận các dữ liệu dạng nhị phân, hệ thống cần có cách để có thể đọc được các dữ liệu, định dạng và hiển thị được các dữ liệu kiểu nhị phân. Việc đọc các tệp kịch bản và kết xuất thông tin ra các tệp tin làm cho công việc kiểm thử lặp lại được thực hiện dễ dàng hơn. 3.2.5. Những phản đối, hạn chế và nhược điểm Các kỹ sư phần mềm thường phản đối việc kiểm thử các đoạn mã hệ thống nhúng trên máy chủ vì một số lý do sau đây: Thứ nhất, họ cho rằng, các đoạn mã của hệ thống nhúng là “rất phụ thuộc phần cứng”. Đúng là có một số hệ thống nhúng, các mã lệnh của họ hoàn toàn phụ thuộc phần cứng và các hệ thống nhúng thì chắc chắn là sẽ phải có các mã lệnh phụ thuộc phần cứng, nhưng trên thực tế thì các hệ thống nhúng không trực tiếp làm việc với phần cứng, nó tương tác qua các vi xử lý và số lượng các mã lệnh phụ thuộc phần cứng là ít hơn nhiều so với các mã lệnh không phụ thuộc phần cứng. Thứ hai, họ cho rằng việc xây dựng các mã nền kiểm thử là phức tạp hơn nhiều so với giá trị mà nó mang lại. Có hai lý do cho sự phản đối này là: việc tìm các lỗi trong phòng thí nghiệm trên mã nền kiểm thử là tốn thời gian, mà sau đó chỉ tìm ra một vài lỗi và thêm nữa là mã nền kiểm thử đôi khi còn làm việc không được tốt... Các kỹ sư lập trình cho rằng thật tốn thời gian để viết mã nền kiểm thử và các tệp kịch bản. Nhưng hiệu quả rất lớn của việc viết nền kiểm thử, các tệp kịch bản và các tệp kết xuất mang lại cho họ là họ có thể thực hiện việc kiểm thử lặp đi lặp lại, và các thông tin kết xuất được sắp xếp một cách hợp lý, khoa học. Điều này sẽ giúp tiết kiệm thời gian hơn rất nhiều. Thứ ba, để dùng kỹ thuật này, chúng ta cần phải có một phiên bản của hệ điều hành thời gian thực (RTOS - Real Time Operating System) chạy trên hệ thống máy chủ. Lý do này thiếu sức thuyết phục vì các nhà cung cấp RTOS đã cung cấp các phiên bản hệ điều hành của họ có thể chạy trên các hệ điều hành Windows, DOS hay Unix, các kỹ sư lập trình chỉ cần chọn một RTOS phù hợp với hệ điều hành mà máy chủ của 16 họ đang sử dụng để dùng. Thứ tư, kỹ thuật kiểm thử trên máy chủ không thể kiểm thử được một số đặc trưng quan trọng của phần mềm trên máy chủ, bao gồm một số đặc trưng sau: • Phần mềm tương tác với phần cứng: Ví dụ, nếu phần mềm viết dữ liệu vào UART sai địa chỉ, chúng ta sẽ không thể kiểm thử được đặc tính này trên mã nền kiểm thử. • Tính đáp ứng và công suất: Khi các mã lệnh được biên dịch với các bộ biên dịch ngôn ngữ C khác nhau và chạy trên các vi xử lý khác với tốc độ khác nhau và đặc trưng về độ trễ ngắt khác nhau, thì tính đáp ứng và công suất của thiết bị sẽ khác nhau. • Vấn đề chia sẻ dữ liệu: Vấn đề này phát sinh khi một ngắt đột ngột xảy ra, chúng ta không biết điều gì đã xảy ra, các cờ giải quyết tranh chấp có thể chưa được bật lên. Những lỗi như thế này khó mà tìm ra trong khi kiểm thử trên máy chủ. • Vấn đề về tính khả chuyển: Hệ thống máy chủ và máy đích có thể khác nhau. Ví dụ, nếu hệ thống máy chủ là big - endian và hệ thống máy đích là little – endian, có những vấn đề có thể xuất hiện ở máy đích mà không xuất hiện ở máy chủ. Tóm lại, chúng ta không thể kiểm thử mọi trường hợp trên máy chủ. Tuy nhiên, thực hiện kiểm thử trên máy chủ giúp chúng ta kiểm thử được với một lượng lớn mã lệnh lặp lại và việc kiểm thử sớm trong quá trình phát triển phần mềm đã giảm được nhiều lỗi. 3.3. Bộ mô phỏng Mô phỏng là một kỹ thuật đã được sử dụng trong khoa học kỹ thuật, công nghệ, giáo dục và y tế từ lâu. Ngày nay, chúng ta có thể thấy rất nhiều sản phẩm được mô phỏng, như các trò chơi được mô phỏng trên máy tính, các lớp học ảo, các thiết bị thực hành, các phần mềm giả lập để phục vụ cho việc nghiên cứu. Đối với ngành công nghệ thông tin, việc mô phỏng các máy tính, các chương trình trên một máy tính giúp cho việc phát triển phần mềm, phần cứng ngày càng dễ dàng hơn. Bộ mô phỏng (Simulator) hay bộ mô phỏng tập lệnh (ISS) là một phần mềm chạy trên máy chủ và cho phép chúng ta giả lập vi xử lý và bộ nhớ trên máy đích. Ta có thể 17 thấy rất nhiều phần mềm mô phỏng chạy trên nhiều hệ điều hành, cung cấp những tiện ích cho người dùng như là Virtual Box của Oracle, VMWare của công ty VMWare, µVision của Keil, QEMU, Crosswork và Yagarto của công ty Rowley ... Bộ mô phỏng đã khắc phục được một số nhược điểm của kỹ thuật gỡ lỗi trên máy chủ. Sử dụng bộ mô phỏng, chúng ta phải biên dịch và liên kết, tạo ra các tệp tin thực thi chạy được trên các máy đích, sau đó nạp tệp thực thi này vào bộ mô phỏng. Ta cần phải biết chắc rằng bộ mô phỏng có thể hiểu được định dạng kết xuất của bộ liên kết/ định vị (Linker/ Locator). Chúng ta thường phải biên dịch ra các tệp tin có định dạng .hex hay .elf để nạp vào bộ mô phỏng, đây thực chất là các tệp tin dưới dạng mã máy, để máy đích có thể chạy trực tiếp được nó. Bộ mô phỏng cũng cần hiểu được kiến trúc vi xử lý của máy đích và các tập lệnh của nó, cũng như là có thể đọc các lệnh từ bộ nhớ (được mô phỏng) và thay đổi các giá trị trong RAM (được mô phỏng) và các thanh ghi trong vi xử lý làm việc như thế nào. Thông thường, chúng ta nên sử dụng các bộ mô phỏng được xây dựng riêng cho các họ vi xử lý khác nhau, như cho họ vi xử lý của 8051, ARV, ARM... Giao diện người dùng của các bộ mô phỏng cũng gần tương tự như giao diện của các bộ gỡ lỗi, nó cho phép chúng ta biên dịch, chạy chương trình, gỡ lỗi, thiết lập các điểm dừng, xem các trạng thái của bộ nhớ, thanh ghi. Nhiều bộ mô phỏng còn hỗ trợ ngôn ngữ macro, cho phép thiết lập các kịch bản gỡ lỗi để thực thi mã lệnh. Bộ mô phỏng có các ưu điểm sau: • Xác định được sự đáp ứng và công suất: Mặc dù các bộ mô phỏng không chạy cùng tốc độ với hệ thống đích, nhưng hầu hết chúng thống kê thời gian thực thi các lệnh cụ thể. Ví dụ, bộ mô phỏng có thể ghi lại số lệnh vi xử lý đích đã thực hiện hay số vòng của bus máy đích đã quay. Bằng việc tính thời gian hệ thống đích thực hiện một lệnh hay thời gian bus quay được một vòng có thể tính được cụ thể thời gian thực hiện. • Kiểm thử các mã lệnh assembly: Các bộ mô phỏng sử dụng tập lệnh của hệ thống máy đích, các mã lệnh được viết bằng assembly sẽ được thực hiện một cách dễ dàng. Chúng ta thực thi các mã lệnh thông qua trình biên dịch trung gian chéo (cross – assembler), bộ liên kết/ định vị và sau đó tải chương trình vào bộ mô phỏng. Chúng ta có thể kiểm thử các mã lệnh như trên máy đích, các mã khởi động (startup code) và thường trình ngắt. 18 • Giải quyết vấn đề tính khả chuyển: Bởi vì chúng ta dùng cùng một bộ công cụ để phát triển mã lệnh cho bộ mô phỏng và máy đích, nên chúng ta sẽ có ít sự khác biệt khi chuyển các mã lệnh từ bộ mô phỏng sang máy đích hơn là khi chuyển từ máy chủ sang máy đích. • Kiểm thử mã lệnh với các thiết bị bên trong vi xử lý: Hầu hết các bộ mô phỏng sẽ mô phỏng các thiết bị bên trong vi xử lý của hệ thống đích. Nếu phần mềm có làm việc với một bộ định thời (timer) gắn liền bên trong, thì bộ mô phỏng sẽ mô phỏng bộ định thời, và khi đếm hết vòng lặp thì bộ mô phỏng cũng sẽ thực thi một thường trình ngắt, tức là một thường trình ngắt định thời đã được gọi lên. • Các bộ mô phỏng giúp cho các kỹ sư lập trình học tập, làm việc, nghiên cứu ngay cả khi chưa có phần cứng vẫn có thể thực thi, kiểm thử các mã lệnh. Về mặt tài chính, thì việc sử dụng các bộ mô phỏng để làm việc là tiết kiệm và hiệu quả trong rất nhiều trường hợp. Nó mở ra khả năng nghiên cứu tại nhà mà không cần những phòng thí nghiệm hiện đại, các công cụ đắt tiền, dễ hỏng hóc. Tuy nhiên bộ mô phỏng cũng có một số nhược điểm sau: • Lỗi chia sẻ dữ liệu: Lỗi này thường xảy ra khi các ngắt xảy ra ở một thời điểm không định trước. Bộ mô phỏng có thể mô phỏng các ngắt xảy ra trong quá trình kiểm thử, trừ khi chúng ta có nhiều thời gian để xem xét từng ngắt tại các thời điểm khác nhau để biết lỗi thực sự ở ngắt nào, nếu không thì việc mô phỏng và thực thi các ngắt này là liên tục nên sẽ khó bắt được lỗi. • Với các thiết bị phần cứng khác: Bộ mô phỏng sẽ mô phỏng được vi xử lý, RAM, ROM, và các thiết bị gắn bên trong vi xử lý, nhưng với các thiết bị phần cứng mở rộng khác như loa, tai nghe, bộ cảm biến,… thì bộ mô phỏng không thể làm được gì. Bộ mô phỏng có thể làm cho các kỹ thuật kiểm thử với máy chủ ở trên trở lên khó khăn. Với kỹ thuật kiểm thử trên máy chủ, thì tại một thời điểm, chúng ta có thể thực thi nhiều tệp tin và bắt được các tệp tin kết xuất. Còn với kỹ thuật kiểm thử dùng bộ mô phỏng, thì tại thời điểm thực thi mã lệnh và mô phỏng thì chương trình chỉ có thể thực hiện được một nhiệm vụ đó, và việc truy cập vào phần mềm bằng bàn phím, hay chuột là vô ích. Để dùng được những kỹ thuật kiểm thử trên máy chủ thì bộ mô phỏng của ta cần phải đọc các tệp kịch bản vào môi trường mô phỏng và lấy kết quả 19 ra. Ta có thể sử dụng các kỹ thuật trong phần 3.2 để kiểm thử cho các ca kiểm thử thông thường và sau đó dùng bộ mô phỏng để thực hiện các ca kiểm thử khác để mang lại hiệu quả kiểm thử tốt. 3.4. Sử dụng macro assert Macro assert là một công cụ rất hữu ích đối với các kỹ sư lập trình. Macro là một tập các phát biểu của hợp ngữ hay ngôn ngữ bậc cao mà có thể được gọi ra bằng các từ đơn hay các cụm từ trong mã nguồn, macro làm giảm các bước gõ lệnh và tăng tính dễ hiểu bởi ý tưởng thay các cụm từ phổ biến thường dùng bằng một phát biểu đơn [2]. Macro có thể tự động thực hiện thao tác và làm giảm các bước cũng như thời gian hoàn thành công việc. Macro assert là một biểu thức đơn: nếu biểu thức trả lại giá trị true thì hàm assert không làm gì cả; nếu biểu thức trả về giá trị false thì hàm assert làm cho chương trình bị ngừng lại và đưa ra một số thông báo hữu ích. Chúng ta dùng hàm assert cho chương trình kiểm tra những thứ mà ta chắc chắn là phải đúng, hay nói cách khác là kiểm tra các lệnh trong chương trình của chúng ta có đúng không. Việc sử dụng assert một cách hợp lý sẽ làm cho chương trình dừng lại đúng cách, tránh cho chương trình phải dừng lại sau khoàng 100.000 lệnh. Các macro assert giúp tìm kiếm các lỗi một cách sớm nhất có thể để chúng ta có cách giải quyết với chúng. Điều này rất có ích khi chúng ta kiểm thử trên máy chủ. Tuy nhiên, trên máy đích hầu hết các hệ thống nhúng không có một thiết bị hiển thị thích hợp để hiển thị các thông báo của hàm assert. Hơn nữa, trong các chương trình ứng dụng, hàm assert sẽ gọi ra các hàm exit hay abort để dừng chương trình lại, nhưng trong các hệ thống nhúng thì thường không tồn tại các hàm đó. [4] Việc định nghĩa các marco có thể khác nhau giữa các trình biên dịch, nhưng thường chúng được viết trong tệp assert.h và có dạng như sau: Bảng 3.1 Mã lệnh của hàm NDEBUG #ifdef NDEBUG #define assert(bool_expression) //Xác định assert #else 20 #define assert(bool_expression) if(bool_expression) ; else bad_assertion(_FILE_, _LINE_, #bool_expression); #endif Các hàm macro thường được biên dịch không có lệnh như NDEBUG, nó thường là các biểu thức logic trả về cho chương trình giá trị true hay false. Việc định nghĩa các hàm assert một cách chính xác rất quan trọng, vì nó sẽ làm ảnh hưởng đến hệ thống của chúng ta, có thể làm giảm hiệu suất của hệ thống. Hàm bad_assertion sẽ giúp chúng ta phát hiện được các lỗi của chương trình sớm khi biên dịch. Các hàm bad_assertion được viết để thực hiện các công việc sau: • Vô hiệu hóa các ngắt hay các vòng lặp vô hạn, giúp cho chương trình dừng lại đúng cách và ta có thể biết được chương trình của chúng ta đang làm gì. • Bật một số đèn led hay các âm thanh đặc trưng để chúng ta biết được rằng hệ thống đang có vấn đề. • Ghi ra giá trị của các biểu thức vào các vị trí nhớ đặc trưng, mà chúng ta có thể bắt được các kết xuất đó bằng bộ phân tích logic. • Ghi ra vị trí các lệnh mà nó gọi từ các vị trí nhớ đặc trưng. • Thực thi một lệnh không hợp lý hay làm bất kỳ điều gì cần thiết để dừng hệ thống mà không làm tổn hại đến chương trình. 3.5. Sử dụng các công cụ trong phòng thí nghiệm Phần mềm nhúng thường được phát triển trên các phần cứng đặc trưng của nó. Vì vậy mà việc kiểm thử cho các phần mềm nhúng thì bao gồm cả việc kiểm thử dựa trên các phần cứng, và kiểm thử bằng các công cụ trong phòng thí nghiệm là một phần không thể thiếu. Các công cụ kiểm thử trong phòng thí nghiệm: - Máy hiện sóng (Oscilloscope). - Bộ phân tích logic ( Logic analyzer). - Bộ mô phỏng trong mạch (Emulator). 21 Sử dụng các công cụ này, đòi hỏi chúng ta phải có kiến thức về phần cứng máy tính, để có thể hiểu được các thông số mà các thiết bị đưa ra. Máy hiện sóng và bộ phân tích logic có ích trong trường hợp gỡ lỗi cho các tương tác giữa bộ vi xử lý và các chip khác trên mạch, vì chúng có thể hiển thị các tin hiệu giao tiếp giữa bộ vi xử lý và các thiết bị, nhưng không điều khiển được phần mềm, nên chỉ giúp phát hiện lỗi mà không giải quyết được. Bộ mô phỏng trong mạch giúp chúng ta có thể gỡ lỗi được tốt hơn. 3.5.1. Máy hiện sóng Máy hiện sóng (Oscilloscopes) là một thiết bị hiển thị đồ thị điện áp – thời gian. Đồ thị của một máy hiện sóng như sau: Hình 3.3. Đồ thị của một máy hiện sóng [11] Ở đây, thời gian nằm ở trục hoành và được tính bằng nano giây (ns) còn điện áp nằm ở trục tung và được tính bằng vôn (V). Máy hiện sóng là một thiết bị tương tự (analog device), nó không chỉ đo được điện áp đang ở mức cao hay thấp mà còn đo được chính xác điện áp. Máy hiện sóng có một số ưu điểm như sau: • Có thể hiển thị một hoặc hai tín hiệu đồng thời. • Có thể điều chỉnh độ quét theo thời gian hay điện áp trên một dải rộng. • Có thể điều chỉnh trục tung trên màn hình máy hiện sóng để hiển thị tình trạng nối đất hay ở mức thấp. • Có thể điều chỉnh khi máy hiện sóng bắt đầu vẽ thông qua việc dùng một ràng 22 buộc cơ học để chỉ cho máy hiện sóng biết rằng điều kiện để ghi lại tín hiệu là gì. Ví dụ như, ta muốn máy hiện sóng bắt đầu ghi lại tín hiệu sau khi thiết bị khởi động được 5 phút. Máy hiện sóng là một công cụ tuyệt vời đối với các kỹ sư phần cứng, còn các kỹ sư phần mềm dùng nó cho những mục đích sau: • Ta có thể dùng máy hiện sóng như một vôn kế dùng để đo điện áp. Nếu điện áp của một tín hiệu không thay đổi thì hình ảnh hiển thị trên máy hiện sóng sẽ là một đường thẳng kéo dài trên màn hình, và tung độ của điểm xác định điện áp của tín hiệu. • Ta cũng có thể dùng máy hiện sóng để thấy rằng bản mạch đang hoạt động. Nếu đường hiện thị trên màn hình máy hiện sóng thẳng, thì sau đó bộ vi xử lý không thực hiện lệnh nào cả. Tương tự như khi đọc các địa chỉ hay tín hiệu trên RAM, ta có thể xác định được chương trình của mình đang làm gì. • Ta có thể dùng máy hiện sóng để thấy các tín hiệu đang thay đổi như thế nào. Giả sử với các tín hiệu lặp đi lặp lại thì ta sẽ thấy trên màn hình của máy hiện sóng các đường lặp đi lặp lại. • Thường thì chúng ta sẽ tìm ra một lỗi phần cứng khi đo một tín hiệu số đã chuyển từ trạng thái nối đất sang trạng thái vô cùng hay ngược lại trong vài phần nghìn giây, điều đó cho thấy là đã có một lỗi xảy ra, hay một phần cứng trong mạch không hoạt động tốt. Các kỹ sư phần cứng sẽ dựa vào đó để xác định lỗi và sửa lại lỗi đó. Các máy hiện sóng thông thường bắt sóng bằng việc quét các tin hiệu lặp lại, và để đo được điện áp thì các tín hiệu cũng nên được phát lặp đi lặp lại thông qua một ràng buộc cơ học. Hình 3.4. mô tả cấu tạo của một máy hiện sóng. 23 Hình 3.4. Máy hiện sóng [14] ◦ Cấu tạo cơ bản của một máy hiện sóng bao gồm các phần: • Màn hình để hiển thị đồ thị. • Các nút điều chỉnh nguồn, điều chỉnh các ràng buộc cơ học. • Một đầu dò (probe) và một dây nối đất. Các máy hiện sóng kiểu cũ thường không phải là một thiết bị lưu trữ, các đồ thị điện áp – thời gian được vẽ ra trên màn hình, và rất nhanh sau đó sẽ bị thay thế bằng các đồ thị khác. Nhưng các máy hiện sóng hiện đại được thiết kế như một thiết bị lưu trữ, giúp chúng ta lưu các thông tin, đồ thị, để từ đó có thể dễ dàng tìm ra lỗi. Cách sử dụng máy hiện sóng đơn giản là ta chọc đầu dò vào phần thiết bị cần đo điện áp, kẹp dây nối đất vào bản mạch và sau đó đo điện áp của thiết bị. Máy hiện sóng là một thiết bị đo rất nhạy, nên để đo được chính xác điện áp của thiết bị ta luôn luôn phải kiểm tra xem dây nối đất đã được nối đất chưa. 3.5.2. Bộ phân tích logic (Logic Analyzer) Bộ phân tích logic là một công cụ khác dùng để bắt các tín hiệu và vẽ chúng trên màn hình. Về chức năng, nó gần tương tự như máy hiện sóng, nhưng có vài điềm khác 24 biệt sau: • Một bộ phân tích logic có thể dò được nhiều tín hiệu ngay lập tức. Điều đó phụ thuộc vào ta muốn mua thiết bị đo được bao nhiêu tín hiệu, vì muốn đo được bao nhiêu tín hiệu thì ta cần từng đó đầu dò để bắt tín hiệu. • Một bộ phân tích logic chỉ biết hai mức điện áp là: mức cao (VCC) và mức thấp - mức 0 – nối đất (ground). Với một mức điện áp nằm giữa mức cao và mức thấp thì nó sẽ báo không chính xác, không như máy hiện sóng là sẽ hiện ra điện áp chính xác của thiết bị. • Tất cả các bộ phân tích logic đều là những thiết bị lưu trữ. Chúng bắt các tín hiệu đầu tiên và sau đó hiển thị chúng. Các bộ phân tích logic thường phải được đặt các ràng buộc cơ học và sau đó bắt các dữ liệu từ nguồn để giải quyết vấn đề. • Bộ phân tích logic có các ràng buộc cơ học phức tạp hơn máy hiện sóng. Ta có thể thiết lập các ràng buộc như là chỉ bắt tín hiệu khi tín hiệu A ở mức cao, tín hiệu B ở mức thấp và tín hiệu C ở mức cao khi tín hiệu E bắt đầu hoạt động được 10 nano giây. Hình 3.5 mô tả cấu tạo bên ngoài của bộ phân tích logic. Hình 3.5. Bộ phân tích logic [13] 25 Các bộ phân tích logic sẽ làm việc theo hai chế độ: bộ phân tích logic theo chế độ thời gian, và bộ phân tích logic theo chế độ trạng thái. 3.5.2.1. Bộ phân tích logic theo chế độ thời gian Với bộ phân tích logic theo chế độ thời gian, ta sẽ giải quyết được một số việc sau đây: • Ta có thể tìm ra dấu vết nếu một sự kiện nào đó đã xảy ra thông qua những tín hiệu mà bộ phân tích logic đã bắt được. • Ta có thể đo được khoảng thời gian mà phần mềm đáp ứng lại yêu cầu. Ví dụ ta nối đầu dò của bộ phân tích logic vào một nút ngắt tín hiệu chuông của thiết bị theo dõi bể ngầm, khi nào ta nhấn nút ngắt để tắt chuông, thì bộ phân tích logic sẽ cho ta biết thời gian từ khi nhấn nút đến khi hệ thống ngừng chuông. • Ta có thể thấy nếu phần mềm gọi một tín hiệu thích hợp để điều khiển phần cứng. Hình 3.6. Màn hình hiển thị của bộ phân tích logic theo chế độ thời gian [13] Bởi vì các bộ phân tích logic có thể bắt được nhiều tín hiệu đồng thời, nên có thể gắn thêm các dây để chúng bắt các tín hiệu riêng của hệ thống. Cần lưu ý là với mỗi đầu dò để đo một tín hiệu thì đều có dây nối đất, khi dò tín hiệu thì cần phải nối dây nối đất cho các đầu dò để có thể đo tín hiệu một cách chính xác. 3.5.2.2. Bộ phân tích logic theo chế độ trạng thái Trong chế độ thời gian, bộ phân tích logic tự động bắt các tín hiệu mà không liên 26 quan đến bất kỳ sự kiện nào của bản mạch. Còn trong chế độ trạng thái, bộ phân tích logic là sẽ bắt các tín hiệu khi mà một sự kiện xảy ra trong hệ thống. Khi dùng bộ phân tích logic ở chế độ trạng thái sẽ thấy các lệnh mà vi xử lý đã nạp, những dữ liệu đã đọc và ghi từ bộ nhớ và các thiết bị xuất nhập. Để thấy các lệnh mà vi xử lý đã nạp, ta nối đầu dò của bộ phân tích logic tới tất cả các tín hiệu địa chỉ và dữ liệu trong hệ thống và tín hiệu RE/ trên ROM. Nếu ta thiết lập cho bộ phân tích logic bắt tín hiệu khi tín hiệu RE/ được bật lên thì nó sẽ bắt các tín hiệu địa chỉ và dữ liệu của RE/ khi RE/được bật. Hầu hết các bộ phân tích logic có thể thu được nhiều tín hiệu đồng thời như thế. [4] Bộ phân tích logic chế độ trạng thái thường hiển thị dạng dữ liệu văn bản lên màn hình, với mỗi dòng là trạng thái của tất cả tín hiệu khi một sự kiện xảy ra. Hầu hết các bộ phân tích logic cho phép chúng ta định dạng dữ liệu theo nhiều kiểu khác nhau. Ví dụ, ta có thể định dạng cho dữ liệu ra là kiểu bát phân như hình 3.7. Hình 3.7. Màn hình hiển thị của bộ phân tích logic theo chế độ trạng thái [12] Ta thấy rằng các mã bát phân này khó đọc, vì thế bộ phân tích logic có thể hiển thị các lệnh dưới dạng ngôn ngữ assembly, nó sẽ dễ hiểu hơn là dạng mã bát phân hay nhị phân. Nhưng để làm được điều này thì bộ phân tích logic cần hiểu về vi xử lý mà ta đang dùng, và yêu cầu đối với máy đích. Một vài bộ phân tích logic sẽ có ràng buộc để bắt các lệnh từ mã nguồn, cho phép ta thấy một phần của phần mềm đang thực thi. Bộ phân tích logic theo chế độ trạng thái là một công cụ hữu ích cho các kỹ sư 27 phần mềm: • Ta có thể tạo các ràng buộc để nếu vi xử lý nạp các lệnh từ một địa chỉ không được phép, và nếu gây ra lỗi thì ta có thể tìm được lỗi này. • Ta có thể xây dựng các ràng buộc để nếu vi xử lý ghi các giá trị không hợp lệ vào một vị trí cụ thể trên RAM gây ra lỗi thì ta có thể bắt được lỗi. Ví dụ như hệ thống viết giá trị 5 vào giá trị trạng thái của một tập chỉ có 4 trạng thái, thì sẽ gây ra lỗi. • Ta có thể xây dựng các ràng buộc để bộ phân tích logic bắt các sự kiện khi vi xử lý nạp lệnh đầu tiên hay khi các thường trình ngắt xảy ra, và thấy vi xử lý thực thi các thường trình ngắt. • Nếu có một lỗi rất hiếm gặp xảy ra, ta có thể để bộ phân tích logic chạy và kiểm tra kết quả được in trên màn hình để biết dấu vết của lỗi. • Hầu hết các bộ phân tích logic cho phép ta tạo một bộ lọc để giới hạn các kết quả thu được. Thông thường, các ràng buộc trong bộ phân tích logic là một tập các sự kiện mà ta tin rằng ở đó có lỗi và sau đó ghi lại để kiểm tra các trạng thái của hệ thống để tìm ra lỗi. Tuy nhiên, bộ phân tích logic cũng tồn tại một vài nhược điểm: • Mặc dù bộ phân tích logic cho ta thấy vi xử lý đang làm gì, nhưng ta không thể dừng hệ thống bằng cách thiết lập các điểm ngắt để xem xét từng bước của quá trình thực hiện, để có thể xem kết quả trên các thanh ghi, bộ nhớ,... • Ta chỉ biết được trạng thái của bộ nhớ khi vi xử lý đang đọc hay ghi trên nó, và trạng thái của các thanh ghi trong vi xử lý là ẩn. • Nếu chương trình bị ngắt đột ngột thì ta sẽ không biết bất kỳ điều gì xảy ra với hệ thống, từ bộ nhớ, thanh ghi hay vi xử lý, các thông tin không được ghi lại. • Nếu vi xử lý có một bộ nhớ đệm lớn và thực thi các lệnh trong đó, và khi bị tràn bộ nhớ đệm thì ta không thể biết được vi xử lý đang làm gì. Những gì mà bộ phân tích logic ghi lại được chỉ là các lệnh đã được nạp. 3.5.3. Bộ mô phỏng trong mạch Bộ mô phỏng trong mạch (ICE) thường được gọi là bộ mô phỏng (emulator), là 28 một thiết bị phần cứng thay thế cho vi xử lý trong mạch của máy đích: ta có thể tháo vi xử lý trong bản mạch ra và thay bộ mô phỏng vào đó. Bộ mô phỏng sẽ thay thế cho vi xử lý cua máy đích, nó chấp nhận kết nối tất cả các tín hiệu được gửi tới vi xử lý thật và thực hiện như một vi xử lý thật. Bộ mô phỏng cung cấp cho ta khả năng gỡ lỗi tương tự như các phần mềm gỡ lỗi chuẩn. Ta có thể đặt các điểm dừng, và sau đó khi chương trình chạy ta có thể xem trạng thái của các thanh ghi, bộ nhớ, mã nguồn đang được dịch và gỡ lỗi từng bước. Thậm chí nếu chương trình bị ngắt, bộ mô phỏng vẫn có thể cho chúng ta thấy được các thông số của bộ nhớ và thanh ghi. Hầu hết các bộ mô phỏng sẽ bắt các vết tương tự như khi ta bắt các vết với bộ phân tích logic ở chế độ trạng thái, mặc dù chúng không linh hoạt bằng bộ phân tích trong trường hợp này. Nhiều bộ mô phỏng có khả năng gọi các bộ nhớ nạp chồng (overlay memory). Ta sẽ chỉ cho bộ mô phỏng biết những dải địa chỉ của bộ nhớ ROM và bộ nhớ RAM. Khi vi xử lý được mô phỏng đọc và viết vào bất kỳ địa chỉ nào trong một dải đặc biệt, bộ mô phỏng sẽ dùng bộ nhớ bị nạp chồng thay thế cho bộ nhớ của máy đích. Các phần mềm hỗ trợ cho bộ mô phỏng chạy trên máy chủ đọc các tệp kết xuất định vị và tải xuống bộ nhớ nạp chồng của phần mềm. Điều này giúp tải các phiên bản của phần mềm vào hệ thống đích để gỡ lỗi dễ dàng và hiệu quả.[4] Bộ mô phỏng là một công cụ hữu ích, nó có những ưu điểm như một trình gỡ lỗi thông thường và cũng có khả năng của một bộ phân tích logic. Tuy nhiên, về nhiều mặt, bộ phân tích logic có nhiều ưu điểm hơn bộ mô phỏng: • Bộ phân tích logic có bộ lọc vết (trace) tốt hơn và có các ràng buộc cơ học phức tạp hơn. • Bộ phân tích logic có thể chạy được chế độ thời gian. • Bộ phân tích logic có thể làm việc với mọi vi xử lý, còn bộ mô phỏng thì thường chỉ làm việc với một số vi xử lý nhất định. Và giá thành của một bộ mô phỏng không hề rẻ, mà mỗi khi ta làm việc với một vi xử lý mới thì ta có thể sẽ cần một bộ mô phỏng mới. • Với các bộ phân tích logic ta có thể nối một vài hay nhiều kết nối mà ta muốn. Còn với bộ mô phỏng, ta phải kết nối tất cả các tín hiệu để nó có thể chạy được. • Đối với bộ mô phỏng, đôi khi những lỗi cũ không xuất hiện nữa hay lỗi mới lại xuất hiện khi vi xử lý bị thay thế bằng một bộ mô phỏng. 29 Hiện nay, nhiều công ty đã sản xuất các thiết bị lai giữa bộ phân tích logic và bộ mô phỏng để cho ta có được những ưu điểm của cả hai thiết bị. Việc kiểm thử trong các hệ thống nhúng khó khăn đã làm cho các nhà cung cấp đưa ra các sản phẩm sáng tạo hơn. 30 CHƯƠNG 4: CÔNG CỤ GỠ LỖI Như khóa luận đã trình bày ở trên, có rất nhiều kỹ thuật gỡ lỗi cho hệ thống nhúng, mỗi kỹ thuật đều có ưu nhược điểm riêng. Sau đây khóa luận sẽ trình bày về công cụ gỡ lỗi dùng kỹ thuật mô phỏng cho họ vi xử lý ARM là công cụ Keil µVision. 4.1. Lý do chọn họ vi xử lý ARM ARM là một cấu trúc vi xử lý 32 bit kiểu RISC được sử dụng rộng rãi trong các ứng dụng nhúng. Các thiết kế của nó hướng tới việc nâng cao hiệu năng, tiết kiệm điện, giảm giá thành hệ thống và được phát triển thêm bởi các nhà phát triển thứ ba làm cho các sản phẩm dựa trên nền tảng vi xử lý ARM ngày càng phổ biến. Ngày nay, ta có thể thấy các sản phẩm, ứng dụng của vi xử lý ARM ở khắp mọi nơi, từ những thiết bị điện tử công nghệ cao như smartphone, smartbook, netbook đến các thiết bị nhúng như là thiết bị điều khiển ôtô tự động, mạng không dây, máy in, các thiết bị mạng, thẻ từ, hộ chiếu điện tử,... Các vi xử lý ARM có khả năng chạy trên nhiều hệ điều hành như Microsoft Windows (CE/Embedded), Linux, Android/ Chrome, và Symbian. Với hơn 15 tỷ vi xử lý đã được tạo ra và hơn 10 triệu vi xử lý được bán ra mỗi ngày, ARM thực sự là kiến trúc phần cứng của kỷ nguyên số. [15] ARM có một số đặc điểm sau: • Cấu trúc nạp/ lưu trữ. • Tập lệnh trực giao. • Có 16 thanh ghi 32 bit. • Chiều dài mã máy cố định là 32 bit. • Hầu hết các lệnh đều thực hiện trong vòng một chu kỳ đơn. • Hầu hết các lệnh đều cho phép thực thi có điều kiện, điều này làm giảm việc phải viết các lệnh rẽ nhánh. • Có kiểu định địa chỉ theo chỉ số rất mạnh. • Có hệ thống con thực hiện ngắt hai mức ưu tiên đơn giản, nhưng rất nhanh, kèm theo cho phép chuyển từng nhóm thanh ghi. • Hỗ trợ mã lệnh Thumb 16 bit, giúp cho chương trình gọn hơn. 31 Với những đặc điểm về tính năng và sự phổ biến của họ vi xử lý ARM nên khóa luận lựa chọn họ vi xử lý ARM để làm ứng dụng cho phần lý thuyết về các kỹ thuật gỡ lỗi ở chương trước. 4.2. Giới thiệu công cụ µVision µVision là một công cụ kết hợp giữa môi trường phát triển tích hợp (IDE - Integrated Development Environment) và bộ gỡ lỗi (Debugger) được phát triển bởi công ty Keil ARM. Keil ARM là một công ty chuyên phát triển, sản xuất và phân phối các công cụ phát triển phần mềm nhúng cho các họ vi điều khiển 8051, 251, ARM, XC16x/ C16x/ ST10 và các sản phầm phần cứng như các bộ mô phỏng trong mạch (Emulator) và các bo mạch kiểm định (Evaluation Board). Phiên bản mới nhất của công cụ là µVision phiên bản 4.11. Keil cung cấp miễn phí các bản dùng thử cho người dùng. Để tải được các bản dùng thử, người dùng chỉ cần điền vào một bảng thu thập thông tin có dạng như sau: Hình 4.1. Mẫu đăng ký sử dụng bản dùng thử của Keil Keil cũng cung cấp phần mềm có bản quyển cho người dùng có nhu cầu với mức phí khoảng 4000 euro cho một phần mềm. 32 Công cụ µVision cung cấp trình soạn thảo và gỡ lỗi cho các ứng dụng với thiết kế giao diện người dùng đồ họa đẹp và dễ sử dụng. Công cụ cho phép các kỹ sư lập trình viết chương trình ứng dụng, gỡ lỗi và mô phỏng với nhiều loại máy đích khác nhau. Khóa luận tập trung đi vào nghiên cứu công cụ µVision phiên bản dùng thử chạy cho họ vi xử lý ARM là MDK-ARM dùng cho các vi điều khiển ARM7, ARM9, Cortex-M0, Cortex-M1 và Cortex-M3. 4.3. Các chức năng chính của công cụ µVision 4.3.1. Các chức năng của µVision IDE µVision IDE là một nền phát triển phần mềm dựa trên giao diện cửa sổ kết hợp giữa trình soạn thảo, quản lý dự án, và công cụ Make Utility. µVision hỗ trợ tất cả các công cụ của Keil bao gồm C/C++ Compiler, Marco Assembler, Linker, Library Manager, và Object-HEX Converter. Hình 4.2 minh họa giao diện của µVision IDE. Hình 4.2. Giao diện của µVision IDE 33 Bảng 4.1 đưa ra một số tính năng chính mà µVision IDE cung cấp. [8] Bảng 4.1. Các chức năng của µVision IDE [5] STT Tên Mô tả chức năng Đường dẫn 1 Device Database Lựa chọn thiết bị và cấu hình cho công cụ phát triển cụ thể cho vi điều khiển đích. File → Device Database 2 Project Manager Tạo và chỉnh sửa dự án. Project 3 Make Utilities Chuyển thành hợp ngữ, biên dịch, liên kết các ứng dụng nhúng. 4 Edit Có đầy đủ các chức năng của trình soạn thảo mã lệnh. Edit 5 Template Editor Chèn các chuỗi từ phổ biến hay các đoạn mã header. View → Template Window 6 Source Browser Đưa ra các đối tượng của mã lệnh, vị trí và phân tích dữ liệu trong ứng dụng. View → Source Browser Window 7 Function Browser Chuyển giữa các hàm trong chương trình. View → Function Browser Window 8 Function Outlining Điều khiển phạm vi tầm nhìn trong một tập tin mã nguồn. Edit → Outlining 9 Built-in Utilities Các tiện ích có sẵn như là Find in Files và các chức năng cho phép ghi chú hay không ghi chú ở mã nguồn. Edit → Advanced 11 Configuration Wizard Cung cấp trình soạn thảo cho mã khởi động và tập tin cấu hình của vi điều khiển. Edit → Configuration 12 Software Version Control Systems Giao diện để cấu hình Software Version Control Systems và các tiện SVCS → Configure Software Version 34 STT Tên Mô tả chức năng Đường dẫn ích của nhà cung cấp thứ ba. Control System 13 Flash Programming Utilities Tương tự như bộ chuyển đổi Keil ULINK USB-JTAG . Flash 14 Dialogs Điều chỉnh công cụ phát triển. 15 Help Liên kết tới các bảng số liệu kỹ thuật của vi điều khiển và hướng dẫn người sử dụng. Help 4.3.2. Các chức năng của µVision Debugger µVision Debugger được tích hợp cùng trong µVision IDE, chỉ khi chương trình của chúng ta đã được biên dịch đúng thì ta mới có thể gỡ lỗi bằng µVision Debugger. Nhấn vào nút Start/ Stop Debug Session (Ctrl + F5) để bắt đầu gỡ lỗi chương trình trong máy chủ đã chọn, nhấn Run (F5) để chạy chương trình. Hình 4.3 minh họa cho giao diện của µVision Debugger khi chương trình đang chạy. Hình 4.3. Giao diện của µVision Debugger 35 µVision Debugger cung cấp các chức năng như sau [8]: Bảng 4.2: Các chức năng của µVision Debugger [5] STT Tên chức năng Mô tả Đường dẫn 1 Disassembly Tách mã nguồn C/C++ hay hợp ngữ với chương trình thực thi trong các stepping modes khác khau và view modes khác nhau như là hợp ngữ, kí tự hay cả hai. View → Disassembly Window 2 Breakpoint Tùy chọn nhiều điểm dừng bao gồm các điểm dừng truy cập và phức tạp. Debug → Breakpoint 3 Bookmark Đánh dấu để dễ dàng tìm và xác định được điểm mâu thuẫn. Edit → Insert/ Remove Bookmark 4 Review, modify Xem và sửa các giá trị của bộ nhớ, biến, thanh ghi. View → Memory Window, Register Window, 5 Program call tree Liệt kê cây chương trình gọi bao gồm biến stack dưới dạng cây. View → Call Stack Window 6 Peripheral Xem tình trạng của các thiết bị ngoại vi tích hợp trên vi điều khiển. Peripherals 7 Command Chức năng gỡ lỗi bằng dòng lệnh hay kịch bản giống C. View → Command Window 8 Execution Profiling Ghi và hiển thị thời gian thực thi cũng như số chu kỳ cần cho mỗi lệnh. Debug → Execution Profiling 9 Code Coverage Thống kê tỷ lệ các lệnh được thực thi. View → Analysis Windows → Code Coverage 10 Performance Analyzer Thống kê số lần gọi, thời gian gọi hàm. View → Analysis Windows → Performance Analyzer 11 Logic Analyzer Bắt, lưu và hiển thị các tín hiệu. View → Analysis Windows → Logic Analyzer 12 Instruction Trace Hiển thị lịch sử thực thi của các lệnh. View → Trace → Instruction Trace 36 µVision Debugger cung cấp hai chế độ gỡ lỗi là dùng Simulator và Target Mode. Chúng ta có thể lựa chọn chế độ gỡ lỗi bằng cách vào thẻ Project → Option for Target “Target 1” rồi chọn thẻ Debug. Simulator Mode là chế độ gỡ lỗi mô phỏng các tập lệnh và các thiết bị ngoại vi tích hợp trên chip cho máy đích. Chế độ này dùng để kiểm thử, gỡ lỗi khi phần cứng chưa sẵn sàng. Chức năng này của µVision Debugger giúp cho những người không có phần cứng sẵn sàng cũng có thể nghiên cứu và làm việc được, nó giúp cho việc phát triển các hệ thống nhúng không còn quá phụ thuộc vào phần cứng, và là tiền đề thúc đẩy nhanh việc phát triển hệ thống. Target Mode là chế độ gỡ lỗi khi phần mềm làm việc trực tiếp trên phần cứng. Phiên bản µVision 4.10 cho phép việc gỡ lỗi trên các thiết bị phần cứng như là: ULINK ARM Debugger, Signum Systems JTAGjet, J-LINK/ J-TRACE, ULINK Pro ARM Debugger là các bộ công cụ được Keil hay các công ty thứ ba phát triển. 4.4. Ưu điểm của µVision 4.4.1. Ưu điểm của µVision IDE µVision IDE có một số ưu điểm sau:[6] • Device Database của µVision tự động cấu hình các công cụ phát triển cho vi điều khiển đích: Các lỗi trong cài đặt công cụ thực sự được loại bỏ và thời gian cấu hình cho công cụ là ngắn nhất. • µVision IDE cho phép tích hợp thêm công cụ của nhà phát triển thứ ba. Điều này cho phép chúng ta nhanh chóng truy cập tới tất cả các công cụ phát triển từ một môi trường đơn. Tất cả các chi tiết cấu hình đều được lưu trong dự án (project) của µVision. • µVision tích hợp việc quản lý dự án, trình soạn thảo và bộ gỡ lỗi trong một môi trường đơn nhằm tăng tốc cho việc phát triển các ứng dụng. Trong khi soạn thảo, ta có thể cấu hình các chức năng của bộ gỡ lỗi. Trong khi gỡ lỗi, ta cũng có thể sửa mã nguồn. • Đồng nhất bộ gỡ lỗi với giao diện người dùng của bộ mô phỏng. • Chức năng Code Coverage của bộ mô phỏng µVision phân tích, thống kê cho việc thực thi các chương trình, cho phép xem và in ra các báo cáo. 37 • Bộ mô phỏng µVision là một bộ gỡ lỗi duy nhất mô phỏng đầy đủ tất cả các thiết bị ngoại vi trong mạch của các thiết bị ARM như là Atmel, Philips, và thẻ thông minh của Samsung. Ta có thể nghiên cứu sự khác nhau giữa việc cấu hình phần cứng và tối ưu thiết kế phần cứng. • µVision cũng cho phép mô phỏng nâng cao với giao diện mô phỏng nâng cao (AGSI - Advanced Simulation Interface) đối với các hệ thống phức tạp có thể được mô phỏng chính xác bằng việc thêm chính các trình điều khiển thiết bị ngoại vi. 4.4.2. Ưu điểm của µVision Simulator µVision Simulator có một số ưu điểm sau:[7] • Cho phép thiết lập không hạn chế số lượng điểm dừng. • Mô phỏng các thiết bị ngoại vi đồng bộ với chương trình thực thi. • Có khả năng mô phỏng cả những tình huống bị dừng hay ngắt điện đột ngột của phần cứng như là: trạng thái ngắt điện và chạy không tải. • Các chức năng Code Coverage, Trace, Timing Profile, Logic Analyzer cho phép phân tích các vết và thời gian. • Cho phép nhập các tín hiệu vào từ một ngôn ngữ kịch bản và đồng bộ với chương trình. • Mô phỏng chính xác thời gian trong mối tương quan với các thiết bị ngoại vi. 4.5. Một số hạn chế của µVision phiên bản dùng thử Keil hỗ trợ cho những người dùng mới, hay những người dùng có nhu cầu làm việc với các dự án nhỏ phiên bản dùng thử của µVision. Các phiên bản này được tải xuống trực tiếp từ hệ thống máy chủ của công ty. Tuy nhiên, vì đây là phiên bản dùng thử nên nó có một số hạn chế như sau:[9] • Nếu chương trình có dung lượng lớn hơn 32 KB thì dữ liệu sẽ không được biên dịch, hợp ngữ hóa hay liên kết, và vì thế cũng sẽ không được gỡ lỗi. • Bộ biên dịch thường không tạo ra danh sách tách rời của mã máy. Các tùy chọn biên dịch dòng lệnh --S, --asm và --interleave bị vô hiệu hóa. • Bộ hợp dịch và kết nối tạo ra các đối tượng định dạng xuất ký hiệu (Symbolic 38 Output Format) không liên kết với những tiện ích của nhà phát triển thứ ba. Công cụ có bản quyền sẽ tạo ra những tập tin ELF/DWARF chuẩn để người sử dụng có thể dùng được các tiện ích của nhà phát triển thứ ba. • Bộ liên kết không chấp nhận các tệp mô tả sự tải phân tán cho các sơ đồ bộ nhớ phức tạp. Lệnh --scatter thường bị vô hiệu hóa. • Địa chỉ tham chiếu cho mã lệnh và hằng trong bộ nhớ phải là 0x000080000, 0x000100000, 0x000200000, 0x000300000, 0x000400000, 0x010400000, 0xXX000000, hay 0xXX800000 ( với XX là mã thập lục phân từ 00-FF). Địa chỉ tham chiếu 0x0 là nơi bộ liên kết đặt mã khởi động của bộ nhớ Flash trên chip của hầu hết các vi điều khiển cơ bản của vi xử lý ARM. Mặc dù có một số hạn chế như trên, nhưng với đối tượng là sinh viên, những người nghiên cứu và làm việc với các dự án nhỏ thì bản dùng thử này đã cung cấp những tính năng cần thiết và hoàn toàn miễn phí cho họ. 4.6. Cài đặt Trước khi cài đặt phần mềm, ta cần kiểm tra xem hệ thống của ta có thỏa mãn một số yêu cầu sau đây không: • Hệ điều hành của máy chủ là từ Windows 2000 trở lên. • Có chuột hoặc những thiết bị tương tự chuột. • Không gian ổ đĩa cứng phải còn tối thiểu là 300MB. • RAM tối thiểu là 512 MB. • Máy tính dòng Pentium trở lên. Các sản phẩm của Keil có thể tải xuống trực tiếp từ trang chủ của công ty: hoặc dùng các đĩa CD-ROM của công ty. Trên trang chủ của Keil luôn cập nhật những phiên bản mới nhất các sản phẩm của công ty. Công cụ có thể được cài đặt theo một trong hai cách sau đây: • Cài đặt thông qua mạng internet: - Ta điền vào bảng thu thập thông tin của công ty, sau đó tải tập tin mdk410.exe xuống. - Thực hiện việc cài đặt tập tin mdk410.exe như với các phần mềm thông 39 thường. • Cài đặt từ đĩa CD-ROM: - Chèn đĩa CD vào ổ, phần mềm sẽ tự động khởi động việc cài đặt. Nếu không được thì ta có thể chạy tập tin setup.exe. - Chọn Install Products & Updates từ thanh thực đơn của đĩa. - Cài đặt từng bước theo hướng dẫn. Đối với các phần mềm có bản quyền, chúng ta có thể liên hệ trực tiếp với công ty Keil hoặc các công ty đại diện cho Keil tại khu vực chúng ta sống để có thể biết chi tiết giá thành phần mềm. Tại Việt Nam, công ty Vijasemi (trang chủ đặt tại: là đại diện và nhà phân phối độc quyền các sản phẩm phát triển trên nền tảng chíp ARM và các công cụ phát triển của ARM/Keil. Chúng ta có thể liên hệ với công ty để biết thêm thông tin về các sản phẩm, công cụ có bản quyền và để được hỗ trợ kỹ thuật. Việc sử dụng sản phẩm có bản quyền sẽ cung cấp cho chúng ta nhiều tiện ích hơn so với các bản dùng thử của công ty. 40 CHƯƠNG 5: ỨNG DỤNG CÔNG CỤ µVISION VÀO VIỆC GỠ LỖI Ở chương 4, khóa luận đã chỉ ra những ưu điểm của việc dùng công cụ µVision vào việc gỡ lỗi. Chương này, khóa luận sẽ trình bày ứng dụng của công cụ vào việc gỡ lỗi cho một số chương trình dưới đây. 5.1. Vi điều khiển LPC2148 Các chương trình viết trong chương này đều được viết cho vi điều khiển LPC2148 của công ty NXP (trang chủ đặt tại: được phát triển dựa trên nhân của họ vi xử lý ARM và được µVision hỗ trợ gỡ lỗi, mô phỏng. Đối với các kỹ sư lập trình, kỹ sư kiểm thử, gỡ lỗi cho phần mềm nhúng thì họ không chỉ phải hiểu các ngôn ngữ lập trình, hiểu phần mềm, mà còn phải hiểu cả phần cứng của thiết bị mà mình lập trình hay gỡ lỗi. Đây là một khác biệt khá lớn trong công việc lập trình giữa phần mềm nhúng và phần mềm ứng dụng thông thường. LPC2148 cũng như các sản phẩm cùng họ ARM7TDMI-S được ứng dụng trong nhiều lĩnh vực khác nhau. Chi tiết các thông số kỹ thuật của vi điều khiển sẽ được trình bày ở phần phụ lục “Các thông số kỹ thuật của vi điều khiển LPC2148. ” 5.2. Chương trình “Đèn led nhấp nháy” Mỗi kỹ sư lập trình khi bắt đầu một ngôn ngữ lập trình, một công cụ mới thì Hello world luôn là chương trình đầu tiên được viết ra. Chương trình hiển thị dòng chữ “Hello world” trên màn hình như một sự khởi đầu mới, là lời chào thân ái khi chúng ta bắt đầu tiếp cận với một ngôn ngữ lập trình mới. Đối với các kỹ sư lập trình phần mềm nhúng thì chương trình Hello world chính là lập trình cho các đèn led nhấp nháy để báo hiệu rằng hệ thống của ta đang làm việc. Mục đích của chương trình nhấp nháy led dưới đây là lập trình để các đèn led ở các chân cắm 0, 2, 4, 6 trên GPIO Port 0 nhấp nháy: Bảng 5.1: Mã lệnh của chương trình Led.c /* Chuong trinh Led.c ** Muc dich: nhay cac led 0, 2, 4, 6 tren Port0 trong thoi gian 600000 micro giay ** Kiem tra cac led co hoat dong khong? */ #include"lpc214x.h" /* Khai bao prototype ham lam tre thoi gian*/ 41 void delay(unsigned long int); /* Ham main co nhiem vu thuc thi cac chuong trinh chinh*/ int main() { IODIR0 = 0x00000055; // Dat GPIO pin 0, 2, 4, 6 = Output IOSET0 = 0x00000055; // Set GPIO-1[24] Output Pin(OFF LED) while(1) { IOCLR0 = 0x00000055; // Xoa Output GPIO1[24] Pin (ON LED) delay(600000); // Delay IOSET0 = 0x00000055; // Set Output GPIO1[24] Pin (OFF LED) delay(600000); // Delay } } /* Ham tre voi khoang thoi gian cho truoc time*/ void delay(unsigned long time) { while(time > 0) { time--; } } Ý nghĩa của các giá trị, phép gán, hàm: • IODIR0: bật các chân cắm 0, 2, 4, 6 của cổng Port 0, thiết lập trạng thái của các chân cắm là trạng thái xuất (giá trị nhị phân tại các chân cắm là 1 – chân cắm ở trạng thái xuất). • IOSET0: đưa các chân cắm tương ứng bit = 1 trong thanh ghi lên mức cao khi đã thiết lập trạng thái xuất. • IOCLR0: đưa các chân cắm tương ứng bit = 1 trong thanh ghi xuống mức thấp khi đã thiết lập trạng thái xuất. • Hàm delay: hàm làm trễ thời gian giữa 2 lần nhấp nháy led với một khoảng thời gian cho trước. 42 • Giá trị: 0x00000055 là giá trị theo cơ số 16, tương đương với giá trị 00000000000000000000000101010101 các giá trị tại bit 0, 2, 4, 6 là 1. Thực hiện Translate (nhấn Ctrl + F7) để biên dịch chương trình, kiểm tra xem chương trình có lỗi hay không? Sau đó Build (nhấn F7) để chương trình được biên dịch lại, kết nối và tạo ra tập tin thực thi .hex. Nếu chương trình không có lỗi biên dịch – các lỗi ngữ nghĩa (compiler error) thì chương trình mới có thể được gỡ lỗi, mô phỏng. Thực hiện gỡ lỗi cho chương trình bằng Debug (nhấn Ctrl + F5) để bắt đầu quá trình gỡ lỗi và chạy chương trình mô phỏng bằng Run (F5). Thông thường thì chương trình sẽ gọi ra ngay màn hình hiển thị của GPIO để cho chúng ta thấy led đang nhấp nháy, nếu không thấy ta có thể vào thẻ Peripherals - GPIO – Fast GPIO – Port 0 để bật hiển thị GPIO. Sau khi chạy chương trình và gỡ lỗi, ta được kết quả như sau: Hình 5.1. Kết quả thực thi chương trình Led.c Chương trình đã mô phỏng cho sự nhấp nháy của led bằng việc nhấp nháy các chân cắm 0, 2, 4, 6 của thanh ghi GPIO. Chương trình cũng cho thấy tốc độ nhấp nháy của led nhanh hay chậm phụ thuộc vào thời gian làm trễ mà ta đã viết. 5.3. Chương trình Hello world Ở chương trình trên, ta mô phỏng sự hoạt động của các các chân cắm trên cổng để đèn led nhấp nháy. Chương trình tiếp theo là để minh họa cho việc sử dụng cổng nối tiếp UART để ghi ra các chuỗi kí tự. Chương trình thực hiện việc ghi ra cổng nối tiếp UART dòng chữ “Hello world” và lặp lại 5 lần dòng chữ: “This is my embedded programming. ”: 43 Bảng 5.2: Mã lệnh Hello.c /* Chuong trinh Hello.c thuc hien viec in ra man hinh cac dong chu Hello world. * va 5 lan dong chu “This is my embedded programming. ” */ #include #include /* Thu vien LPC214x.h */ /* Ham main thuc hien chuong trinh chinh */ int main () { int count = 5; // Khai bao gia tri cua bien dem count = 5 // Cac khai bao cho cac chan cam, cong PINSEL0 = 0x00050000; // Bat RXD1 và TXD1 U1LCR = 0x83; // Bat DLAB = 1, 8 bit. 1 stop bit U1DLL = 97; // 9600 Baud Rate @ 15MHz VPB Clock U1LCR = 0x03; // DLAB = 0 printf ("Hello World\n"); // In ra “Hello world” // Ham in ra 5 lan dong chu “This is my embedded programming. ” while (count > 0) { printf("This is my embedded programming. \n"); count --; } // Ham lap vo han de dung chuong trinh while (1) {;} } Ý nghĩa của các hàm, giá trị, phép gán: • PINSEL0 có giá trị 0x00050000 tương đương với mã nhị phân có các bit 16 và 18 có giá trị bằng 1. Bit 16 trong PINSEL0 có giá trị bằng 1 tức là mở cổng truyền dữ liệu TXD1 của UART1. Bit 18 trong PINSEL0 có giá trị bằng 1 là mở cổng nhận dữ liệu RXD1 của UART1. • Ở đây U1LCR có giá trị là 0x83 tương đương với mã nhị phân 1000 0011. Trong đó bit 7 bằng 1 là bật DLAB lên, bit 2 bằng 0 là có 1 stop bit, bit 0 và 1 là 11 nên trạng thái là truy cập với độ dài 8 bit ký tự. 44 • U1DLL truy cập vào bộ khóa chia (Divisor Latch Access) của UART1. Giá trị 97 là để tính toán tốc độ baud của thiết bị. • Giá trị của U1LCR là 0x03 là tắt DLAB (bit 7 đại diện cho DLAB chuyển về mức 0). • Vòng lặp while (count > 0) để chương trình in ra 5 lần dòng chữ “This is my embedded programming. ” • Vòng lặp while (1) là vòng lặp vô hạn, để chương trình dừng lại, không tiếp tục thực hiện lại hàm main. Để thực hiện việc in các ký tự ra cổng nối tiếp thì ta còn cần phải viết các hàm phụ để thực hiện việc truyền nhận dữ liệu từ chương trình đến cổng nối tiếp UART1. Sau khi biên dịch và thực hiện chương trình ta được kết quả như sau: Hình 5.2. Kết quả thực thi chương trình Hello world Chương trình của ta lập trình cho việc ghi ra cổng nối tiếp UART1, nhưng trong hình thì cổng xuất ra các ký tự lại là cổng UART1. Điều này được giải thích như sau: trong bộ gỡ lỗi của µVision các cổng nối tiếp UART được đánh số từ UART1, UART2 chứ không đánh số như trong thiết kế của LPC2148 là UART0, UART1. Vì vậy, UART2 tương ứng với UART1 mà ta đã khai báo trong chương trình. 5.4. Nhận xét Chương trình đèn led nhấp nháy và truyền các dữ liệu ra cổng nối tiếp UART là hai chương trình đơn giản được viết bằng KeilC và được biên dịch, chạy, gỡ lỗi và mô phỏng trong µVision. Qua hai chương trình nhỏ này, chúng ta thấy µVision là một công cụ trực quan, 45 giúp cho người lập trình, ngay cả khi không có các thiết bị phần cứng thích hợp vẫn có thể viết các ứng dụng của mình trực tiếp trên µVision IDE và sau đó chạy trên các thiết bị phần cứng đã được mô phỏng và thực hiện các chức năng tương tự như với các vi điều khiển thật sự. Tuy nhiên, µVision chỉ là một công cụ mô phỏng, công cụ sẽ khó tránh khỏi việc có một vài sai khác so với việc chạy trên các vi điều khiển thật, nhưng sai khác này không quá lớn và ta vẫn có thể chấp nhận được. 46 CHƯƠNG 6: KẾT LUẬN Các hệ thống nhúng được ứng dụng rộng rãi trong đời sống của chúng ta, và chúng ngày càng phát triển vượt bậc cả về số lượng lẫn chất lượng. Việc gỡ lỗi cho các hệ thống nhúng ngày càng trở lên quan trọng hơn do số lượng các hệ thống nhiều lên, đòi hỏi của người dùng với sản phẩm cũng cao hơn, sản phẩm cần có được độ ổn định, an toàn và chất lượng tốt. Đáp ứng mục tiêu gỡ lỗi cho các hệ thống nhúng, sau một thời gian nghiên cứu và học hỏi, khóa luận đã đạt được các kết quả sau: • Khóa luận đã mang đến một cái nhìn tổng quát về hệ thống nhúng, trình bày những đặc điểm của một hệ thống nhúng thông thường. Khóa luận cũng đã đưa ra một số thông tin về các ngôn ngữ lập trình để các kỹ sư lập trình có thể lựa chọn cho mình được ngôn ngữ lập trình thích hợp với hệ thống của mình. • Khóa luận cũng đã đưa ra lý thuyết về các kỹ thuật gỡ lỗi cho hệ thống nhúng bằng nhiều phương pháp khác nhau, từ kiểm thử cho máy chủ, đến sử dụng các công cụ phần mềm, hay phần cứng để gỡ lỗi. • Khóa luận giới thiệu công cụ mô phỏng µVision của công ty Keil là một công cụ mô phỏng cho các họ vi xử lý ARM – một họ vi xử lý lớn, được ứng dụng rộng rãi trong các thiết bị điện tử ngày nay. • Phần ứng dụng kiểm thử cũng đã trình bày việc gỡ lỗi cho các chương trình viết cho vi điều khiển LPC2148 phát triển trên nền tảng ARM của công ty Philips để minh họa cho việc sử dụng công cụ µVision vào việc mô phỏng các vi điều khiển. Tuy nhiên do quỹ thời gian nghiên cứu hạn hẹp cũng như điều kiện kĩ thuật bị giới hạn, khóa luận không tránh khỏi các hạn chế sau: • Khóa luận chỉ mới dừng lại ở việc giới thiệu về hệ thống và các kỹ thuật gỡ lỗi cho hệ thống và đưa ra được một công cụ mà theo chủ quan của chúng tôi là một lựa chọn tốt cho các kỹ sư lập trình cho các thiết bị dựa trên nền tảng vi xử lý ARM lập trình và gỡ lỗi cho các phần mềm khi mà phần cứng của thiết bị chưa sẵn sàng hay không có sẵn. • Các ứng dụng kiểm thử trong khóa luận là những chương trình đơn giản và chưa thực sự khai thác được hết những ưu điểm của bộ công cụ µVision. 47 Gỡ lỗi và kiểm thử là một công việc hết sức thú vị, chúng tôi mong rằng sau này mình có thể làm việc nhiều hơn với các hệ thống nhúng, để có thể ứng dụng nhiều hơn những kiến thức đã học hỏi vào thực tế. Việc gỡ lỗi giúp nâng cao chất lượng phần mềm, nhưng các phương pháp, các công cụ chỉ là những thiết bị bổ trợ, cách hiệu quả nhất để giảm thiểu số lỗi trong phần mềm là chính bản thân các kỹ sư lập trình cần viết chương trình sáng sủa, rõ ràng, và kiểm soát các lỗi của họ. Điều này sẽ giúp cho công việc gỡ lỗi đỡ vất vả hơn rất nhiều. 48 TÀI LIỆU THAM KHẢO [1] Micheal Barr, Anthony Massa, Programming Embedded Systems: with C and GNU Development tools, 2nd Edition, O'Reilly Media, October 1, 2006 (2nd Edition). [2] Jack Ganssle, Micheal Barr, Embedded System Dictionary, CMP Books, 2003. [3] Tammy Noergaard, Embedded System Architecture: A Comprehensive Guide for Engineers and Programmers, Newnes, February 24, 2005, page 129. [4] David .E Simon, An Embedded Software Primer, Addison – Wesley Professional, August 15, 1999, chapter 1, 10. [5] Keil ARM, µVision IDE Overview, 2010. [6] Keil ARM, Advantages of the µVision IDE for ARM, 2010. [7] Keil ARM, Advantages of the µVision Simulator for ARM, 2010. [8] Keil ARM, Getting Started Creating Applications with µVision 4, 2010. [9] Keil ARM, Limitions, 2010. [10] Wikipedia, ARM Architechture, 2010. [11] AWRCorp, Example: Downconverter, https://awrcorp.com/download/faq/english/examples/Downconverter.aspx, 2009. [12] Link Instruments, IO-3200 Logic Analyzer Pattern Generator, 2010. [13] Agilent, Logic Analyzer, 2010. [14] Wikipedia, Oscilloscope, 2010. [15] ARM, Processors, 2010. . 49 PHỤ LỤC CÁC THÔNG SỐ KỸ THUẬT CỦA VI ĐIỀU KHIỂN LPC2148 1. Một số đặc điểm chính của vi điều khiển LPC2148 LPC2148 là vi điều khiển 16/32 bit, dựa trên cấu trúc ARM7TDMI-S. Bộ nhớ SRAM trên chip là 8 – 40 kB, bộ nhớ chương trình flash là từ 32 – 512 KB. Có 64 chân cắm, 45 chân GPIO. Tích hợp USB 2.0, hỗ trợ USB RAM tới 2 KB. Có 14 kênh ADC 10 - bit, và 1 kênh DAC 10 – bit. Có 2 bộ timer 32 – bit, 6 ngõ điều xung. Đồng hồ thời gian thực với tần số ngõ vào 32 kHz. Khả năng thiết lập độ ưu tiên, định địa chỉ cho ngắt. Có nhiều giao diện cổng nối tiếp gồm: 2 cổng nối tiếp UART, 2 bus Fast I2C (400 kbit/s), SPI và SSP. Trạng thái tiết kiệm điện: chế độ không tải và ngắt nguồn. Có 9 chân ngắt ngoài. CPU clock đạt tối đa 60 MHz thông qua bộ PLL lập trình được. Xung PLCK hoạt động độc lập. 2. Đặc điểm một số thanh ghi 2.1. Các cổng nhập/ xuất thông thường (GPIO) LPC2148 có 2 cổng là Port0 và Port1: Port0 (GPIO0): PO.0 – PO.23, PO.25, PO.28 – PO.30: là các chân nhập/ xuất thông thường. PO.31 là chân chỉ xuất. Các chân PO.24, PO.26, PO.27 không được xét. Port1 (GPIO1): P1.16 – P1.31 là các chân nhập/ xuất thông thường, các chân còn lại không được xét. Có thể truy cập các cổng theo hai cách: “slow” GPIO và “fast” GPIO. Việc truy 50 cập này được khai báo thông qua thanh ghi SCS (System Control and Status flag register – Thanh ghi cờ điều khiển hệ thống và trạng thái). Bảng 1 : Các giá trị của thanh ghi SCS Bit Ký hiệu Ý nghĩa Giá trị sau khi reset 0 GPIO0M Bit chọn mode port 0 0: slow 1: fast 0 1 GPIO1M Bit chọn mode port 1 0: slow 1: fast 0 31:02 - Không hỗ trợ Không xác định Các thanh ghi chức năng của GPIO: Bảng 2: Bảng giá trị các thanh ghi GPIO ST T Tên thanh ghi Bit Ý nghĩa Truy cập Giá trị sau khi reset 1 IODIR 31:01 Bit 0 tương ứng với P0.0... 0: chân tương ứng là nhập 1: chân tương ứng là xuất Đọc/ Ghi 0x00000000 2 IOSET 31:01 Bit 0: không xảy ra hiệu ứng Bit 1: chân tương ứng được set bằng 1 Đọc/ Ghi 0x00000000 3 IOCLR 31:01 Bit 0: không xảy ra hiệu ứng Bit 1: chân tương ứng được set bằng 0 Chỉ đọc 0x00000000 4 IOPIN 31:01 Trạng thái của port 0 luôn được đọc trong thanh ghi này, việc ghi vào IO0PIN sẽ ảnh hưởng tới toàn bộ port 0 Đọc/ Ghi Không xác định 5 FIODIR 31:01 Bit 0 tương ứng với P0.0... 0: chân tương ứng là nhập 1: chân tương ứng là xuất Đọc/ Ghi 0x00000000 6 FIOMASK 31:01 Quản lý các chân theo tập hợp các bit có giá trị 0 trong FIOMASK. Đọc/ Ghi 0x00000000 7 FIOPIN 31:01 Tương tự IOPIN, nhưng chỉ có tác dụng với các chân được định nghĩa trong FIOMASK. Đọc/ Ghi 0x00000000 8 FIOSET 31:01 Tương tự IOSET, nhưng chỉ có tác Đọc/ Ghi 0x00000000 51 ST T Tên thanh ghi Bit Ý nghĩa Truy cập Giá trị sau khi reset dụng với các chân được định nghĩa trong FIOMASK. 9 FIOCLR 31:01 Tương tự IOCLR, nhưng chỉ có tác dụng với các chân được định nghĩa trong FIOMASK. Đọc/ Ghi 0x00000000 2.2 Khối kết nối giữa các chân (Pin Connect Block) Mục đích chính của khối kết nối giữa các chân là để cấu hình cho các chân của vi điều khiển để thực hiện một mục đích cụ thể. LPC2148 có 3 thanh ghi PINSEL (Pin function Select register) để cấu hình cho các chân cắm là: PINSEL0, PINSEL1, PINSEL2. Bảng 3: Bảng các giá trị bit của thanh ghi PINSEL0 Bit Ký hiệu Giá trị Chức năng Giá trị sau khi reset 1:0 P0.0 00 GPIO Port 0.0 0 01 TXD (UART0) 10 PWM1 11 3:2 P0.1 00 GPIO Port 0.1 0 01 RXD (UART0) 10 PWM3 11 EINT0 5:4 P0.2 00 GPIO Port 0.2 0 01 SCL0 (I2 C0) 10 Capture 0.0 (Timer 0) 11 7:6 P0.3 00 GPIO Port 0.3 0 01 SDA0 (I2 C0) 10 Match 0.0 (Timer 0) 11 EINT1 52 Bit Ký hiệu Giá trị Chức năng Giá trị sau khi reset 9:8 P0.4 00 GPIO Port 0.4 0 01 SCK0 (SPI0) 10 Capture 0.1 (Timer 0) 11 AD0.6 11:10 P0.5 00 GPIO Port 0.5 0 01 MISO0 (SPI0) 10 Match 0.1 (Timer 0) 11 AD0.7 13:12 P0.6 00 GPIO Port 0.6 0 01 MOSI0 (SPI0) 10 Capture 0.2 ( Timer 0) 11 AD1.0 15:14 P0.7 00 GPIO Port 0.7 0 01 SSEL0 (SPIO) 10 PWM2 11 EINT2 17:16 P0.8 00 GPIO Port 0.8 0 01 TXD (UART1) 10 PWM4 11 AD1.1 19:18 P0.9 00 GPIO Port 0.9 0 01 RXD (UART1) 10 PWM6 11 EINT3 21:20 P0.10 00 GPIO Port0.10 0 01 RST (UART1) 10 Capture 1.0 (Timer 1) 11 AD1.2 23:22 P0.11 00 GPIO Port 0.11 0 01 CTS (UART1) 53 Bit Ký hiệu Giá trị Chức năng Giá trị sau khi reset 10 Capture 1.1 (Timer 1) 11 SCL1 (I2C1) 25:24 P0.12 00 GPIO 0.12 0 01 DSR (UART1) 10 Match 1.0 (Timer 1) 11 AD1.3 27:26 P0.13 00 GPIO Port 0.13 0 01 DTR (UART1) 10 Match 1.1 (Timer1) 11 AD1.4 29:28 P0.14 00 GPIO Port 0.14 0 01 DCD (UART1) 10 EINT1 11 SDA1(I2C1) 31:30 P0.15 00 GPIO Port 0.15 0 01 RI (UART1) 10 EINT2 11 AD1.5 Trên đây là bảng các giá trị bit của thanh ghi PINSEL0, với các thanh ghi PINSEL1, và PINSEL2 cũng tương tự, chỉ có một vài khác biệt mà ta không xét tới ở đây. 2.3 Bộ nhận truyền bất đối xứng (UART – Universal Assynchronous Receiver/ Transmitter) LPC2148 hỗ trợ 2 bộ UART là UART0 và UART1. Các thanh ghi này có chức năng: nhận và truyền nối tiếp 16 byte; nhận các điểm ràng buộc FIFO ở byte thứ 1, 4, 8, và 14; tạo ra tốc độ baud với khả tăng tạo baud tự động; cài đặt để điều khiển các luồng. UART có các chân cắm là : • RXDx: nhận dữ liệu trên cổng nối tiếp. 54 • TXDx: truyền dữ liệu trên cổng nối tiếp. Bảng các thanh ghi của UART1: Ở đây ta quan tâm tới hai thanh ghi là U1LCR và U1DLL. • U1LCR (Line control Register – Thanh ghi điều khiển dòng) quyết định dạng ký tự của dữ liệu được truyền hay nhận: Bảng 4: Bảng giá trị bit của U1LCR Bit Kí hiệu Giá trị Ý nghĩa Giá trị sau khi reset 1:0 Lựa chọn độ dài từ 00 01 10 11 Độ dài của ký tự là 5 bit. Độ dài ký tự là 6 bit. Độ dài ký tự là 7 bit. Độ dài ký tự là 8 bit. 0 2 Lựa chọn bit dừng 0 1 1 bit dừng. 2 bit dừng (bằng 1,5 nếu U1LCR[1:0] = 00). 0 3 Có chẵn lẻ 0 1 Không kiểm tra tính chẵn lẻ. Kiểm tra tính chẵn lẻ. 0 5:4 Lựa chọn kiểm tra chăn lẽ 00 01 10 11 Bù lẻ. Số bit 1 trên đường truyền phải là lẻ. Bù chẵn.Số bit 1 trên đường truyển phải chẵn. Thêm 1. Thêm 0. 0 6 Điều khiển dừng 0 1 Không cho phép dừng. Cho phép dừng. 0 7 Bit truy cập tới bộ phân chia DLAB 0 1 Không được phép truy cập tới bộ phân chia. Được phép truy cập. 0 U1DLL là để chứa dữ liệu 8 bit khi mà DLAB của thanh ghi U1LCR được bật lên, cùng với U1DLM nó sẽ quyết định tốc độ baud của UART1. Công thức tính tốc độ baud của UART1 là: UART1baudrate= PCLK 16∗256∗U1DLMU1DLL ∗ MulVal MulValDivAddVal Trong đó: UART1baudrate : Tốc độ baud của UART1. 55 U1DLM, U1DLL đã cho. PCLK (peripheral clock - tốc độ của ngoại vi) đã cho. DIVADDVAL và MULVAL là tỷ số baud đặc trưng của thiết bị, nó thường được cho trước. Thanh ghi UART0 cũng có các chức năng tương tự thanh ghi UART1. 3. Nhận xét Vì điều kiện thời gian không cho phép, nên khóa luận không trình bày hết tất các thông số kỹ thuật của vi điều khiển LPC2148 mà khóa luận chỉ tập trung đưa ra những thông số kỹ thuật cần thiết, liên quan đến phần ứng dụng của khóa luận. Tất cả các thông số kỹ thuật của vi điều khiển LPC2148 có thể được tìm thấy trong trang chủ của nhà sản xuất NXP (Philips). 56

Các file đính kèm theo tài liệu này:

  • pdfLUẬN VĂN-CÁC KỸ THUẬT GỠ LỖI TRONG VIỆC PHÁT TRIỂN HỆ THỐNG NHÚNG VỚI NGÔN NGỮ C.pdf