Phát triển phần mềm cho HTN

Một phần của tài liệu Bài giảng Xây dựng các hệ thống nhúng: Phần 2 (Trang 109 - 115)

4.2 CÀI ĐẶT VÀ THỬ NGHIỆM HTN

4.2.4 Phát triển phần mềm cho HTN

Có nhiều cách để viết mã (coding) cho HTN, mà sự lựa chọn phụ thuộc và tính phức tạp của phần mềm nhúng, và chi phí. Ví dụ như coding cho phần cứng đã được xây dựng (mua bo mạch có sẳn) thì dễ dàng hơn là cho một thiết kế độc lập, tự làm. Ngày nay cũng có thể là theo cách sử dụng nhiều phần mềm mở (bao gồm mã nguồn dạng C, thư viện đi cùng và công cụ phát triển), tải xuống, gỡ rối (debugging code), sửa đổi cho phù hợp, biên dịch … và nạp vào HTN. Còn phát triển kiểu truyền thống lại tiếp cận theo hướng CPU đã chọn và phần mềm mô phỏng (emulator).

Bộ mô phỏng có thể dùng để gỡ rối phần cứng trên bo của sản phẩm thử nghiệm (prototype hardware) trước khi giao cho giúp kỉ sư phần mềm triển khai phần mềm nhúng đích. Bộ mô phỏng được cài trên một hệ khác, gọi là hệ phát triển (development system), ví dụ trên PC. Một số bo mạch thương mại thường có kèm theo mã gỡ rối, là tiện ích giúp kỉ sư phần mềm chạy thử phần mềm viết ra. Sau đây đề cập tới một số vấn đề có thể phải đối mặt khi muốn sử dụng các phần mềm có sẳn cho HTN đích được thiết kế.

ü Compiling code

Khi sử dụng các ngôn ngữ bậc cao để lập trình, ta không quan tâm tới các bước quá trình dịch để tạo ra mã thực thi. Việc biên dịch cần chương trình dịch thích hợp, cần tới cả thư viện chạy liên kết (run-time libraries) và cả trình liên kết để hợp nhất các module thành tệp thực thi cuối cùng. Vấn đề ở đây là sự hợp nhất với hệ thống dùng để phát triển (hệ phát triển-development system) phần mềm cho HTN, mà hệ này có thể mô phỏng được HTN đích tương lai. Phương pháp phát triển như vậy, gọi là biên dịch chéo (cross-compilation+emulation), taị đó phần mềm cho một hệ đích khác được phát triển toàn bộ trên một hệ hoàn toàn khác. Ví dụ dùng PC trên đó có cài phần mềm phát triển hướng cho loại HTN đích, mà thông thường các hãng bán CPU có thể cung cấp.

Hầu hết các trình dịch, cho C, hay PASCAL, …, đều chỉ phát sinh ra một tập các tiện ích, các lệnh từ các thành phần xây dựng bên trong (built-in routines) liên kết với thư viện của ngôn

248

ngữ để cuối cùng tạo ra các hàm chức năng. Quá trình dẫn tới kết quả trải qua vài bước nhất định, được mô tả như sau:

Hình 4.14 Quá trình biên dịch thành mã maý tạo ra HĐH

Pre-processor: tiền xử lí, thường gọi là biên dịch, xử lí mã nguồn, với chức năng kiểm tra cú pháp, khai báo biến, hằng, bắt lỗi cú pháp, phối hợp các tệp include, define vào code nguồn.

Compiler: dịch từ ngôn ngữ lập trình ra ngôn ngữ hợp ngữ - assembler source listing (*. list tệp kết quả từ mã nguồn *.asm). Quá trình này đồng thời thực hiện tối ưu code để sau này chương trình chạy nhanh hơn, sử dụng bộ nhớ hợp lí hơn.

Assembler: dịch từ hợp ngữ ra mã đích (của CPU đích) nhị phân (tệp kết quả: *.obj hay *.o) Linker/Loader: các tệp *.obj chưa thể chạy được, mà cần có linker/loader để kết hợp các mã hàm gọi, từ thư viện, liên kết nhiều module, liên kết các hàm có sẳn trong thư viện, tạo ra tệp thực thi phù hợp cho từng loại Hệ điều hành đích, gọi là tệp có định dạng kiểu ELF (Executable and

249

Linkable Format) ví dụ HĐH Microsoft: *.com hay *.exe, HĐH Linux có kiểu FatELF khả thi với thuộc tính r-x r-x r-x.

Mô hình của tệp elf như sau:

Hình 4.15 Định dạng một tệp thực thi ELF

Trong đó khối ELF header cho biết không gian địa chỉ sử dụng của CPU là 32 hay 64 bit. Khi kết hợp với Program header table tạo chung thành khối PSP (Program Segment Prefix) trong môi trường HĐH Microsoft, cho đặc tả về trạng thái hoạt động của một chương trình khi chạy.

Các khối khác .text (hay .code) chứa code thực thi, .data chứa dữ liệu (gồm các biến, các hằng, bảng …), .rodata (hay .stack) là vùng ngăn xếp.

ü Thư viện các hàm chức năng chạy khi kích hoạt (Run-time libraries)

Vấn đề đầu tiên cho việc thiết kế HTN là có thư viện các chức năng mà chương trình dịch sử dụng để kích hoạt một số các thực thi khi hệ chạy ứng dụng. Việc thực hiện lời gọi thư viện (system call) bằng API (Application Programming Interface), tác động tới sự liên lạc giữa ứng dụng và phần mềm hệ thống đang chạy (runtime system), trong đó liên quan nhiều tới cơ chế vào ra (input/output) và quản lí bộ nhớ của máy tính. Nói đơn giản run- time library chính là một phần của cách xử lí hay sự phản ứng của máy tính, tức là một phần code của phần mềm hệ thống. Như vậy thư viện cho ta hầu như tất cả các chức năng mà qua ngôn ngữ lập trình ta có để sử dụng. Tất nhiên thư viện bao gồm nhiều kiểu chức năng, phụ thuộc vào phần cứng của HTN. Điều này thì không có sẳn khi thiết kế HTN (cả phần cứng và phần mềm ), cho nên phải biến đổi để làm cho các chức năng đó chạy được trên HTN đích. Các trình điều khiển thiết bị là một ví dụ.

250

ü Sự phụ thuộc vào bộ xử lí (Processor dependent)

Sử dụng các thư viện từ ngôn ngữ lập trình bậc cao thông thường sẽ có đòi hỏi chạy các hàm toán học, các xử lí xâu kí tự … mà các xử lí đó hoàn toàn sử dụng CPU, không có liên lạc với thiết bị, vì vậy thư viện các chức năng này không cần có sửa đổi. Tuy nhiên với các phép tính dấu phẩy động thì khác, bởi cần vi mạch chuyên về các phép tính này. Các vi mạch như vậy thường là tùy chọn với loại CPU, ví như CPU Intel 80386 trước đây có 80387 là bộ số học dấu phẩy động. Nói vậy để thấy khi chọn CPU cho HTN cũng phải lưu ý cần hay không cần bộ số học loại này. Điều này sẽ phụ thuộc vào ứng dụng trên HTN.

ü Phụ thuộc vào các thao tác vào/ra dữ liệu (I/O dependent)

Nếu chương trình không có các thao tác vào/ra dữ liệu, thì phần mềm có thể dùng trên các hệ đích mà hầu như không có các trục trặc. Tuy nhiên nếu có vào/ra, thì phải có định nghĩa phần cứng để phần mềm truy nhập. Nói vaajty tức phải viết lại trình điều khiển thiết bị cho hệ đích.

ü Gọi hệ thống (System calls)

Các thủ tục gọi chức năng cũng cần sửa đổi để phù hợp với hệ đích, sao cho phù hợp với cơ chế xử lí các semaphore, cách phân phát bộ nhớ, cách xử lí tác vụ, các lệnh điều khiển.

ü Thoát ra từ chu trình, thủ tục (Exit routines):viết đoạn code thoát

Các phần mềm tải về sử dụng, sau khi dịch thành tệp thực thi không dễ dàng nạp và chạy trong bộ nhớ. Đó là vì còn có các tệp chứa các module khác, như các tệp kèm theo (modulr header) mà hệ điều hành trên HTN sẽ sử dụng để nạp tệp thực thi vào đúng địa chỉ, khởi động chính xác các thanh ghi của CPU, ngăn xếp chạy trình …Tất cả các việc này cần sửa đổi và chạy mô phỏng trước khi chạy trên HTN đích. Các thủ tục (start-up routine, end routine) thì thường viết mã (nằm) trong các module. Kết thúc thực thi các chu trình thường dùng lệnh exit(). Code của lệnh này sẽ thực hiện thu hồi bộ nhớ trả lại cho HĐH, cho nên cũng cần phải viết lại, có điều mã này lại thường nằm trong thư viện động.

ü Tạo thư viện

Làm thế nào tạo ra các tệp thư viện phù hợp với CPU đích trên HTN thiết kế thay thế các tệp thư viện từ mã nguồn tải về ? Có hai giải pháp: thứ nhất là thay thiết kế trong phần cứng sao cho phần cứng phù hợp với code trong thư viện. Có thể đơn giản là thay đổi ánh xạ địa chỉ cho các hàm thư viện hay cổng (port) sao cho các địa chỉ hướng vào là trùng với các địa chỉ trong code của thư viện. nếu có dùng cơ chế I/O, thì địa chỉ mà I/O sử dụng phải giống như đã định nghĩa trong thư viện sao cho phần mềm truy cập đúng. Cách thứ hai là phải sửa code thư viện sao cho hợp với phần cứng của thiết kế. Điều này có nghĩa sẽ thay đổi cách phân bố sử dụng bộ nhớ, cổng I/O và cụ thể là sẽ sử cả TĐKTB (device driver) nếu có thiết bị mới khác biệt mà HTN sử dụng, đôi khi cả cho CPU khác biệt. cách này phụ thuộc nhiều vào thư viện đi kèm, có thể là trong dạng hợp ngữ, hay C và dễ dàng để biến đổi và liên kết thành thư viện mới. Thường các code này bao gồm:

251

đầu vào, cho phép truyền dữ liệu vào thủ tục xử lí và đầu ra chuyển sang thủ tục khác. Trường hợp phức tạp là khi thư viện ở dạng đã dịch thành nhị phân (*.obj) .

Tạo thư viện (Creating a library): Cần có kinh nhiệm lập trình khi viết các mã dạng như TĐKTB (thường gọi là lập trình hệ thống). Viết code cho TĐKTB tạo thư viện chạy thường không có hạn chế nào cho HĐH, cũng như để thay thế các chức năng I/O. Kỉ thuật này sử dụng để viết code cho một thiết bị ảo (theo cách phân loại ở chương TĐKTB) hổ trợ các ngôn ngữ cấp cao truy nhập vào phần cứng cấp thấp mà không cần chèn đoạn code hợp ngữ đặc biệt. Khi chuyển sang hệ đích khác, thiết bị ảo thay đổi, chỉ cần biện dịch lại và liên kết (link) vào mã cho hệ đích mới.

Nhiều nhà cung cấp bo mạch thường cung cấp thông tin về cấu trúc phần cứng, và chương trình gỡ rối (debuger) với các lệnh I/O đi kèm, giúp tham khảo phần cứng bằng cách chạy debug. Việc này rất bổ ích để viết lại thư viện cho hệ đích.

Khi đã viết xong thư viện, công việc tiếp theo là đưa vào chương trình ứng dụng. Việc này thông qua tiện ích liên kết (linker): Chương trình và các thủ tục dạng hợp ngữ được dịch, hợp vào thành các module OBJ và sau đó được liên kết lại bởi linker để tạo ra mã thực thi cuối cùng. Thư viện mới được tích hợp bởi các kỉ thuật: liên kết thêm thư viện (gồm thư viện chuẩn và thư viện mới), hay liên kết bằng thay thư viện mới, bỏ thu viện trùng như không còn sử dụng ở hệ đích.

ü Vấn đề với hệ điều hành

Trong nhiều trường hợp, HĐH là không có sẳn cho bo mạch HTN đã thiết kế, mêm cần phải “tạo”

HĐH theo yêu cầu. Có một số giải pháp sau đây:

- Nếu mua bo mạch HTN, có thể mua luôn phần mềm hệ thống đã được cấu hình cho bo đó.

Trên thị trường có nhiều bo mạch HTN phổ biến và đi kèm là danh sách các HĐH, phần mềm đã được chuyển tải vào bo. Trong trường hợp này chi phí cho dự án HTN sẽ giảm đi vì rằng các phần cứng và phần mềm đã được thử nghiệm.

- Tạo ra nhân HĐH mới cho cấu hình (HW) mới: Khi không thể dùng các HĐH chuẩn trên thị trường và cần nhiều thay đổi cho hợp với cấu hình thiết kế, thì cần tạo mới HĐH (rebuilding the operating system or kernel). Thông thường từ mã nguồn, chọn các module (đã có thay đổi code), và biệ dịch, liên kết lại để tạo ra nhân với phiên bản HĐH mới. Một trong các HĐH dễ thực hiện sẳn có là HĐH Linux, ví dụ với RED HAT 9.0 cài trên máy đầy đủ với mã HĐH, sau đó dùng tiện ích make xconfig đi kèm chọn các module phù hợp, biện dịch lại nhân, tạo và chạy với phiên bản mới, trước khi nạp cho HTN thiết kế. (Xem http://redhat.activeventure.com/9/customizationguide/s1-custom-kernel-

modularized.html).

(Building a Custom Kernel from Linux RED HAT source code)

The instructions in this section apply to building a custom modularized kernel. To build a monolithic kernel instead, see Section A.3 Building a

252

Monolithic Kernel for an explanation of the different aspects of building and installing a monolithic kernel.

Note

This example uses 2.4.20-2.47.1 as the kernel version (the kernel version might differ). To determine the kernel version, type the command uname -r and replace 2.4.20-2.47.1 with the kernel version that is returned.

To build a custom kernel for the x86 architecture (perform all these steps as root):

1. Open a shell prompt and change to the directory /usr/src/linux-2.4/. All commands from this point forward must be executed from this directory.

2. It is important that kernel build starts with the source tree in a known condition. Therefore, it is recommended that the command make mrproper is issued first to remove any configuration files along with the remains of any previous builds that may be scattered around the source tree. If an existing configuration file already exists as the file /usr/src/linux-2.4/.config, back it up to a different directory before running this command and copy it back afterward.

3. It is recommended that the configuration of the default Red Hat Linux kernel be used as a starting point. To do this, copy the configuration file for the system's architecture from the /usr/src/linux-2.4/configs/ directory to /usr/src/linux-2.4/.config. If the system has more than four gigabytes of memory, copy the file that contains the keyword bigmem.

4. Next, customize the settings. If the X Window System is available, the recommended method is to use the command make xconfig to run the Linux Kernel Configuration.

Note

To use the graphical tool started with the

# make xconfig

command, the tk package, which provides the wish command, must be installed. For more information on installing RPM packages, refer to Part V Package Management.

253

5. As shown in windows, select a category to configure by clicking on it. Within each category are components. Select y (yes), m (module), or n (no) beside the component to compile it into the kernel, compile it as a kernel module, or not compile it. To learn more about the component, click the Help button beside it.

6. Click Main Menu to return to the categories list.

7. After finishing the configuration, click the Save and Exit button in the main menu window to create the configuration file /usr/src/linux-2.4/.config and exit the Linux Kernel Configuration program.

8. Even if no changes were made to any of the settings, running the make xconfig command (or one of the other methods for kernel configuration) is required before continuing.

Một phần của tài liệu Bài giảng Xây dựng các hệ thống nhúng: Phần 2 (Trang 109 - 115)

Tải bản đầy đủ (PDF)

(196 trang)