Người lập trình ứng dụng thường thực hiện công việc trên cùng một loại máy tính mà ứng dụng chạy. Ví dụ, viết chương trình chạy trên Window thì thường thực hiện công việc lập trình trên máy chạy Window. Việc sửa chữa, dịch, liên kết và gỡ lỗi chương trình đều trên cùng một máy. Điều này thay đổi khi xây dựng hệ thống nhúng. Thứ nhất, hầu hết hệ thống nhúng đều có những phần cứng chuyên biệt để gắn với các bộ cảm ứng hoặc để điều khiển, và chỉ có cách duy nhất là thử phần mềm trên phần cứng chuyên biệt đó. Thứ hai, các hệ thống nhúng thường sử dụng các bộ vi xử lý mà chưa bao giờ được sử dụng trên máy trạm. Rõ ràng là chương trình không thể tự nhiên dịch ra được các chỉ thị phù hợp với bộ vi xử lý lựa chọn cho hệ thống và chương trình cũng không thể tự nhiên nhẩy vào trong bộ nhớ của hệ nhúng để thực hiện được. Phần
Các máy chủ và đích
Trong thế giới nhúng, có nhiều lý do để thực hiện những công việc lập trình ứng dụng trên một hệ thống khác với hệ thống mà chương trình chạy. Hệ thống phát triển có thể không có bàn phím, màn hình, ổ đĩa và các thiết bị ngoại vi cần thiết cho lập trình. Do đó, hầu hết công việc lập trình cho hệ thống nhúng được thực hiện trên một máy tính (host) có cài đặt các công cụ lập trình. Chỉ sau khi chương trình được viết, biên dịch và liên kết nó mới được chuyển tới máy đích.
Trình biên dịch chéo
Hầu hết hệ thống máy tính để bàn được dùng như là các host cùng với bộ biên dịch, asssembler, bộ liên kết … để xây dựng chương trình chạy trên host. Những công cụ này được gọi là những công cụ địa phương. Bộ biên dịch trên hệ thống Window NT được dựa trên kiến trúc của Intel Pentium, chúng được sử dụng để xây dựng những chương trình chạy trên nền tảng Intel Pentium. Bộ biên dịch này có thể hữu dụng khi chúng ta dùng bộ vi xử lý Pentium để xây dựng hệ thống, nhưng nó hoàn toàn không có ích lợi gì nếu như chúng ta sử dụng một bộ xử lý đích khác, ví dụ như: Motorola 68000, MIPS hay Zilog Z80. Những bộ xử lý mới hơn này không hiểu được các chỉ thị nhị phân của Pentium. Nhưng trong trường hợp này thì các chỉ thị Pentium là cái mà bộ biên dịch sinh ra. Vậy nên những gì chúng ta cần là một bộ biên dịch chạy trên hệ thống host nhưng có thể sinh ra những chỉ thị nhị phân mà bộ xử lý đích trên hệ thống nhúng có thể hiểu được. Những bộ biên dịch như vậy được gọi là bộ biên dịch chéo.
Về môi trường lý tưởng, nếu viết một chương trình bằng C hoặc C++, ta có thể biên dịch trên bộ biên dịch địa phương và chạy trên host, thì cũng có thể dịch chương trình thông qua bộ biên dịch chéo và có được chương trình chạy trên môi trường đích. Thật không may, điều này không đúng như vậy thậm chí là trong lý thuyết. Trong lý thuyết, một chương trình biên dịch không có lỗi với bộ biên dịch địa phương cũng biên dịch không có lỗi trên bộ biên dịch chéo. Những qui tắc xây dựng chương trình đã được xác định trong bộ biên dịch. Tuy nhiên, trong thực tế ta sẽ thấy rằng những cấu trúc được chấp nhận ở một trình biên dịch này có thể sẽ không được chấp nhận ở trình biên dịch khác. Chúng ta sẽ không gặp vấn đề với những câu lệnh như if, switch hay vòng do loop; nhưng lỗi sẽ xảy ra nếu chúng ta sử dụng hàm mà không khai báo hoặc sử dụng một kiểu khai báo cũ. Các nhà cung cấp bộ biên dịch vẫn đang làm việc để tối thiểu hoá vấn đề này nhưng nó vẫn đang tồn tại.
Thực tế là nếu chương trình làm việc tốt trên host và được biên dịch thành công với bộ biên dịch chéo nhưng cũng không có gì đảm bảo là nó sẽ hoạt động trên hệ thống đích. Những vấn đề thường gặp phải khi chuyển một chương trình C từ nền này sang nền khác như những biến được khai báo kiểu int có thể có 1 kích cỡ trên host nhưng khi đưa sang máy đích lại có một kích cỡ khác.
Bởi vì những điều này nên chúng ta mong muốn có những cảnh báo từ bộ biên dịch chéo. Ví dụ, nếu mã gán một con trỏ void cho một phần tử int, bộ biên dịch địa phương có thể hiểu hai thực thể đó là cùng một kích thước và không đưa ra cảnh báo.
Ngược lại bộ biên dịch chéo có thể cảnh báo rằng int và con trỏ void không cùng kích thước trên hệ thống đích.
Bộ Assembler chéo và chuỗi công cụ
Một công cụ khác chúng ta sẽ cần khi xây dựng chương trình với ngôn ngữ Assembler là bộ Assember chéo. Tức là bộ Assembler chạy trên host nhưng sinh ra các chỉ thị nhị phân thích hợp với máy đích tương tự như với bộ biên dịch chéo. Hình 2.13 dưới đây mô tả qui trình xây dựng phần mềm cho hệ thống nhúng. Chúng ta có thể thấy những file đầu ra của công cụ này sẽ trở thành file đầu vào của công cụ tiếp theo do đó các công cụ này phải tương thích với nhau và hình thành một chuỗi công cụ (tool chain) cho phát triển ứng dụng.
Bộ liên kết/ bộ định vị (Linker/Locator) cho phần mềm nhúng
Công việc của bộ biên dịch chéo cũng giống như bộ biên dịch địa phương là đọc một file mã nguồn và sinh ra một object file phù hợp cho bộ liên kết. Một bộ liên kết cho hệ nhúng sẽ làm những công việc khác với bộ liên kết địa phương do bản chất hai chương trình khác nhau. Bộ liên kết cho hệ thống nhúng thường gọi đến bộ định vị hoặc bộ liên kết định vị. Điểm khác nhau cơ bản giữa một bộ liên kết địa phương và bộ định vị là ở chính các file mà chúng tạo ra. Bộ liên kết địa phương tạo ra một file trên ổ đĩa của hệ thống Host và nó được đọc bởi bộ loader của hệ điều hành khi người sử dụng yêu cầu chạy chương trình. Loader sẽ tìm tới đoạn bộ nhớ để nạp chương trình và copy chương trình từ đĩa vào trong bộ nhớ trong và thực hiện một số xử lý khác trước khi chạy chương trình. Locator thì ngược lại, tạo ra một file và file đầu ra này sẽ được copy vào hệ thống đích. Sau đó nó sẽ phải tự thực thi. (Chú ý rằng trong hệ thống nhúng sẽ không có hệ điều hành tách biệt; locator sẽ gắn mã chương trình của chúng ta với RTOS và sự kết hợp này được copy tới hệ thống đích chỉ trong một lần).
Trong hầu hết các hệ thống nhúng đều không có loader. Khi locator thực hiện xong file đầu ra của nó sẽ được copy vào hệ thống đích. Do đó, locator phải biết được vị trí chương trình nằm trong bộ nhớ và sắp đặt địa chỉ. Và một vấn đề khác mà locator cũng cần giải quyết đó là trong môi trường nhúng thì một số phần của chương trình được kết thúc trong ROM và một số phần trong RAM.
Đưa phần mềm nhúng vào trong hệ thống đích
Locator sẽ xây dựng một file mô tả ảnh của phần mềm đích và sau đó đưa file đó lên hệ thống đích. Có nhiều cách để thực hiện điều này:
Bộ lập trình PROM
Cách cổ điển là dùng file đó để tạo ra một ROM hoặc PROM do việc tạo ROM chỉ thích hợp khi đã hoàn thành xây dựng phần mềm do chi phí cho công cụ xây dựng ROM khá cao. Để đưa chương trình vào PROM đòi hỏi một thiết bị được gọi là bộ lập trình PROM. Cái này phù hợp với có những thay đổi trong phần mềm hoặc trong khi đang gỡ lỗi.
Hình 2.13 Quá trình phát triển và biên dịch phần mềm nhúng
Việc đặt PROM vào một socket trên hệ thống đích thay vì hàn chặt nó vào mạch sẽ tiện lợi hơn cho quá trình gỡ lỗi và thay đổi chương trình nếu như chúng ta tìm thấy lỗi và cần xoá nội dung trong PROM. Khi định sử dụng một bộ lập trình PROM thì cần xem xét kỹ rằng bộ đó có thể hiểu được file đầu ra mà locator tạo ra.
ROM Emulator
Một cách phổ biến khác cho việc đưa phần mềm vào hệ thống máy đích để gỡ lỗi đó là sử dụng một thiết bị ROM emulator, một thiết bị dùng để thay thế ROM ở hệ thống đích. Emulator này sẽ có chức năng giống như ROM trên máy đích. Tuy nhiên ROM Emulator bao gồm một hộp điện tử lớn và một cổng tuần tự hoặc một kết nối mạng để kết nối với host. Phần mềm chạy trên host có thể gửi file được tạo ra bởi locator cho ROM Emulator và thiết bị này hoạt động giống như ROM trên máy đích.