1. The Wonderful World of HALs
Có nhiều công cụ mà các nhà phát triển phần mềm nhúng có thể sử dụng để phát triển phần mềm một cách nhất quán, nhưng công cụ tốt nhất hiện nay có thể cải thiện khả năng tái sử dụng (reuse) và tính di động (portability) của code là API và HAL. Thiết kế một HAL là bước đầu tiên tuyệt vời để phát triển firmware có thể tái sử dụng và độc lập với phần cứng (hardware). HAL hoặc Lớp Trừu Tượng Phần Cứng (Hardware Abstraction Layer), cung cấp cho nhà phát triển ứng dụng (application developer) một tập hàm tiêu chuẩn để truy cập các chức năng phần cứng mà không cần hiểu chi tiết về cách hoạt động của phần cứng bên dưới. HAL không phải là trí thông minh nhân tạo khét tiếng trong phim 2001: A Space Odyssey. HAL về cơ bản là các API được thiết kế để tương tác với phần cứng chứ không phải để cung cấp các khối chương trình cấp cao (high-level program block) giúp phát triển ứng dụng dễ dàng. Một HAL được thiết kế phù hợp cung cấp nhiều lợi ích cho các nhà phát triển, chẳng hạn như code có thể port, có thể tái sử dụng, chi phí thấp hơn, trừu tượng hóa và có ít lỗi tiềm ẩn hơn. Một HAL được thiết kế kém có thể dẫn đến tăng chi phí, lỗi phần mềm và có thể là cơn ác mộng của developer.
2. APIs Versus HALs
Trước đây, các embedded-software developer rất kém trong việc develop phần mềm mà có thể tái sử dụng và port dễ dàng. Nguyên nhân không hẳn là do lỗi của developer mà gốc rễ thực tế là phần cứng rất hạn chế về tài nguyên, code được biên dịch không hiệu quả, và áp lực từ dự án dẫn đến việc develop phần mềm một cách vội vàng. Vì những lý do này, hầu hết các dự án phần mềm nhúng đều bắt đầu với một phương tiện chặn sạch với ít mã được sử dụng lại.
Một rào cản lớn nhất đối với việc tạo ra phần mềm có thể tái sử dụng (reusable software) chính là công nghệ mà các developer đang sử dụng, cùng với bản thân bộ vi điều khiển (microcontroller) cũng là một thủ phạm lớn. Hai lí do chính bỏ qua API và HAL là vì chúng có thể làm tăng thêm một chút chi phí cho các lệnh gọi hàm (function call) và không gian mã (code space) bị tăng thêm một ít. Khi bộ nhớ flash còn đắt tiền, một đoạn code nhỏ cũng có thể khiến chi phí phần cứng tăng lên đáng kể. Developer cũng coi việc sử dụng HAL là một điều lãng phí vì sự thay đổi trong chức năng, bố cục thanh ghi cấp thấp và memory map làm cho việc tái sử dụng dường như rất khó khăn.
Nhu cầu phát triển phần mềm nhúng trong thế kỷ XXI đang thúc đẩy những thay đổi lớn đối với cách phát triển phần mềm. Năng lực phần cứng đã tăng lên ngoạn mục trong khi chi phí giảm đáng kể. Chi phí lớn của dự án không còn đặt nặng ở thiết kế và sản xuất phần cứng, thay vào đó là phát triển phần mềm. Những yếu tố này đang thúc đẩy nhu cầu tái sử dụng phần mềm nhúng.
Có thể dễ dàng phát triển phần mềm nhúng để tái sử dụng từ ứng dụng này sang ứng dụng khác và thậm chí từ vi điều khiển 8-bit sang vi điều khiển 32-bit. Các nhà khoa học máy tính đã giải quyết vấn đề port hoặc reuse phần mềm từ nhiều thập kỷ trước. Các lập trình viên máy tính để bàn (desktop programmer) đã tận dụng các framework và component kể từ buổi bình minh của máy tính cá nhân (nếu không muốn nói là sớm hơn). Một trong những công cụ quan trọng nhất mà các nhà phát triển hệ thống nhúng (embedded-system developer) có xu hướng bỏ qua là sử dụng API hoặc HAL.
API là Giao Diện Lập Trình Ứng Dụng (Application Programming Interface) định nghĩa một tập hợp các quy trình (routine), giao thức (protocol) và công cụ (tool) để tạo ứng dụng.1 Một API xác định giao diện cấp cao về hành vi và khả năng của component, các input và output của nó. Một API nên được tạo có tính chung (generic) và độc lập với việc triển khai. Điều này cho phép API sử dụng được trong nhiều ứng dụng và các thay đổi chỉ cần làm ở API chứ không phải đụng tới giao diện chung hoặc hành vi chung.
HAL là một Lớp Trừu Tượng Phần Cứng (Hardware Abstraction Layer) xác định một tập hợp các routine, protocol và tool để tương tác với phần cứng. Một HAL tập trung vào việc tạo ra các hàm trừu tượng, cấp cao, được sử dụng để phần cứng thực hiện một việc gì đó mà không yêu cầu phải có kiến thức chi tiết về cách phần cứng đó vận hành như thế nào. HAL có thể cực kỳ hữu ích cho developer nào làm việc với nhiều loại phần cứng vi điều khiển và cần port các ứng dụng từ platform này sang platform tiếp theo.
API và HAL đều liên quan với nhau. Có thể lập luận rằng chúng làm việc gần giống nhau. Chỗ khác biệt là API được thiết kế để cho phần mềm ứng dụng (application software) dễ xài hơn, trong khi HAL được thiết kế để cho việc tương tác với phần cứng cấp thấp (low-level hardware) đơn giản hơn. Một hệ thống nhúng được thiết kế tốt sẽ gồm có một HAL để tương tác với phần cứng cấp thấp và một API tương tác với HAL, để tạo ra một tập các API giúp đơn giản hóa việc phát triển ứng dụng.
3. The API and HAL Landscape
Khi năng lực bộ vi xử lý tăng lên trong những năm gần đây thì những kỹ thuật chuyên môn cần thiết, thời gian để tìm hiểu và chạy bộ vi điều khiển cũng tăng lên nhanh chóng. Cài đặt một UART đơn giản có thể tốn nhiều ngày vì người ta cần phải đọc qua hàng nghìn trang tài liệu kỹ thuật để tìm ra chính xác thanh ghi (register) và bit nào cần được thao tác để thiết lập giao tiếp nối tiếp (serial communication) cơ bản với một hệ thống nhúng. Cung cấp HAL và API tạo nên một lợi thế khổng lồ cho các nhóm phát triển đang chịu nhiều áp lực từ việc phải ra mắt sản phẩm nhanh hơn với chi phí thấp hơn.
Gần như mọi nhà sản xuất vi điều khiển hiện nay đều có một bộ API đi kèm với vi điều khiển của họ. Ngoài các API của nhà sản xuất vi điều khiển (trong nhiều trường hợp, thuật ngữ API và HAL được sử dụng tương đương nhau), còn tồn tại một số API khác mà embedded-systems developer có thể tận dụng. Một số API thậm chí đang trở thành tiêu chuẩn công nghiệp. Trong nhiều trường hợp API, HAL, component và framework được gọi là platform.
THUẬT NGỮ CHUYÊN NGÀNH
Platform là tập hợp các API, HAL, module, component, library và framework được thiết kế để làm việc cùng nhau nhằm tăng tốc độ phát triển phần mềm nhúng và giảm chi phí dự án.
Đầu tiên, và có lẽ là nổi tiếng nhất, là các Arduino API.2 Mỗi board Arduino hoặc bất kỳ board nào dựa trên Arduino đều có thể sử dụng các software component chung và các lệnh gọi hàm từ thư viện phần mềm của Arduino. Arduino cung cấp sự linh hoạt khổng lồ trong việc sử dụng phần cứng và hầu hết các developer sử dụng Arduino đều rất ít hoặc không biết gì về vi điều khiển và đôi khi thậm chí là lập trình. Những thư viện này cung cấp cho những người không-phải-lập-trình-máy-tính một cách tuyệt vời để tạo ra các ứng dụng chức năng (functional application). Vấn đề là các API này nhắm mục tiêu tới việc tạo prototype nhanh, cộng đồng chế tạo (maker community), và thiếu cách tiếp cận chuyên nghiệp để dễ sử dụng trong môi trường phát triển chuyên nghiệp.
Một ví dụ API nổi tiếng khác là nền tảng (platform) mbed của ARM. Mbed giống Arduino ở chỗ nó cung cấp một tập hợp các tính năng (feature) và hàm (function) phần mềm chung được sử dụng để phát triển phần mềm một cách nhanh chóng mà không cần biết nhiều về phần cứng bên dưới. Tuy nhiên, các developer chuyên nghiệp một lần nữa sẽ phải vật lộn với thực tế là platform này không được thiết kế cho mục đích sản xuất (production-intent) vì thiếu các tính năng quan trọng như xử lý lỗi cơ bản và phân tích phần mềm. Việc thiếu những công cụ và năng lực quan trọng này một lần nữa khiến mbed trở thành một nền tảng tạo mẫu (prototyping platform) tuyệt vời nhưng không phải là một hệ thống dành cho mục đích sản xuất. (Đã có những nỗ lực lớn đang được tiến hành để lấp đầy khoảng cách này và khiến mbed hoàn toàn trở thành một platform dành cho mục đích sản xuất bao gồm RTOS).3
Bên cạnh Arduino và mbed, còn có các tiêu chuẩn (standard) dành cho mục đích sản xuất chuyên nghiệp mà các developer có thể tận dụng để phát triển phần mềm nhúng của họ và cải thiện khả năng tái sử dụng cũng như khả năng port của nó. Một ví dụ nổi tiếng là AUTOSAR, được sử dụng trong ngành công nghiệp xe hơi (automotive industry). AUTOSAR cung cấp một HAL tuyệt vời để tương tác với phần cứng cấp thấp. Vấn đề là AUTOSAR hơi phức tạp và tốn tiền sử dụng khi công suất xử lý tăng và không hoạt động tốt trên các hệ thống vi điều khiển hạn chế tài nguyên chạy dưới 200 MHz.
Thật không may, một tiêu chuẩn chung và được chấp nhận rộng rãi trong công nghiệp lại không tồn tại cho các hệ thống dựa trên vi điều khiển. ARM đã cố gắng tạo ra các tiêu chuẩn thông qua các hỗ trợ CMSIS và mbed của họ, nhưng trong hầu hết trường hợp, những tiêu chuẩn này chỉ có thể đưa ra một phương pháp để tương tác với lõi vi điều khiển (microcontroller core) chứ không phải với toàn bộ vi điều khiển. Mỗi nhà sản xuất vi điều khiển vẫn có các thiết bị ngoại vi (peripheral) và tài sản trí tuệ (intellectual property) khác của riêng họ được thiết kế để trở thành nét đặc trưng và khác biệt với sản phẩm của đối thủ cạnh tranh.
Vì lý do này mà trong nhiều trường hợp các “tiêu chuẩn công nghiệp” (industry standard) thất bại, và mỗi công ty sẽ sản xuất tiêu chuẩn độc nhất và tùy chỉnh của riêng họ.
4. The Good, Bad, and Ugly
Khả năng biết tận dụng API hoặc HAL của nhà cung cấp vi điều khiển có thể mang lại cho bạn nhiều lợi thế. Nhà sản xuất là chuyên gia trong cách hoạt động sản phẩm của họ, cho nên họ có kiến thức cần thiết để tạo ra những phần mềm sử dụng đầy đủ và tương thích với vi điều khiển và với chi phí nhỏ nhất. Gần như mọi nhà sản xuất vi điều khiển đều có API riêng của họ. Một vài ví dụ để bạn lựa chọn và khám phá như Renesas Synergy™ Platform, Microchip Harmony, và ST Microelectronics STM32CubeMX toolchain.
Nhiều lợi ích mà developer có thể trải nghiệm bằng cách sử dụng HAL đã được sản xuất bởi nhà cung cấp vi điều khiển. Thứ nhất, nếu nhà cung cấp đã đưa toàn bộ sự hiểu biết của họ vào trong phần cứng, thì các developer sẽ mong đợi những giao diện chạy nhanh và tận dụng thủ thuật khả dĩ cho chính vi điều khiển đó. Thứ hai, một development team không muốn mất hàng tháng trời để develop API và HAL giao tiếp với vi điều khiển. Họ có thể lập trình cho vi điều khiển hoạt động dễ dàng ngay sau khi mở hộp. Khả năng chỉ sử dụng một API và HAL có sẵn là một lợi ích to lớn đối với các developer, đó là lý do tại sao mà các nhà cung cấp vi điều khiển đã bắt đầu cung cấp chúng. Các team có thể ngay lập tức bắt đầu develop code ứng dụng của họ thay vì phải dành hàng tháng trời để đào sâu vào những datasheet kỹ thuật cao nhằm cố gắng hiểu cách thức hoạt động của vi điều khiển.
Một lợi ích khác dành cho các developer là trong nhiều trường hợp, các API và HAL đã được tích hợp vào các công cụ phát triển (development tool) dễ xài. Các công cụ này bao gồm những trình cấu hình (configurator) để giúp giảm bớt gánh nặng develop. Kỹ sư có thể chọn những component rồi include vào trong một application và chỉ định cách những component đó nên được cấu hình như thế nào từ Giao Diện Người Dùng Đồ Họa (Graphical User Interfaces – GUI) đơn giản. Tuy nhiên, những công cụ này có chất lượng phần mềm (software quality) thay đổi đáng kể so với phần mềm được tạo ra từ toolchain.
5. Potential Issues and the Boogeyman
Tất cả API và HAL không được tạo giống nhau. Nếu một nhóm phát triển dự định xài một tiêu chuẩn mã nguồn mở (open soure standard), hoặc một tiêu chuẩn được cung cấp bởi nhà sản xuất vi điều khiển (microcontroller vendor-supplied standard), hoặc quyết định áp dụng tiêu chuẩn của riêng họ, thì sẽ có một số vấn đề cần xem xét nếu không muốn phần mềm gặp hậu quả lớn. Những vấn đề nếu không được cân nhắc từ trên xuống có thể quay lại ám ảnh những nhà lập trình, đem tới những đêm mất ngủ và cơn ác mộng.
Vấn đề có thể bao gồm nhưng không giới hạn như sau:
- Chỉ xài một toolchain
- Vi phạm bản quyền
- Hiệu suất thực thi
- Những hạn chế về chức năng phát sinh từ sự trừu tượng hóa
- Các vấn đề về tích hợp
- Mã nguồn phình to
- Khả năng đọc
Các nhà cung cấp vi điều khiển (vendor) đã bắt đầu kết hợp những API và HAL của họ vào bộ toolchain tự động, cho phép nhà phát triển lựa chọn các thành phần họ cần trong một dự án và dễ dàng cấu hình chúng. Đối với một nhà phát triển sử dụng những toolchain này, cuộc sống trở nên đơn giản và tiết kiệm nhiều thời gian và chi phí rõ ràng hơn trong suốt dự án. Tuy nhiên, với một số người, mọi chuyện không hẳn tốt đẹp. Một vấn đề tiềm ẩn (potential issue) phát sinh khi một nhóm muốn thay đổi các nhà cung cấp vi điều khiển. Đột nhiên, toàn bộ mã ứng dụng của họ bị ràng buộc với API và chức năng của nhà cung cấp, vốn được tích hợp chặt chẽ với nhau. Việc cố gắng chuyển (port) mã ứng dụng đó sang API và HAL mới có thể tốn thời gian và chi phí.
Điều này mang chúng ta đến với một vấn đề thứ hai. Một nhóm phát triển có lẽ sẽ quyết định rằng trong khi bị buộc chặt với toolchain, họ có thể dễ dàng chỉ điều chỉnh lớp cấp thấp (low-level) truy cập thanh ghi (register) để xài một vi điều khiển khác và giữ lại cùng một API. Rắc rối ở chỗ, nếu bạn đọc kỹ các điều khoản nhỏ cho bất kỳ phần mềm nào của nhà cung cấp. Nó đều ghi rõ rằng software, API, HAL, và còn nữa là chỉ được dùng với vi điều khiển của họ! Việc dùng nó với vi điều khiển của đối thủ là một sự vi phạm bản quyền. Kết quả là phải làm lại, viết lại một lượng lớn phần mềm hoặc chịu vi phạm bản quyền và hồi hộp chờ đợi những hậu quả pháp lý tiềm ẩn (tất nhiên đây không bao giờ là giải pháp đúng đắn).
Ngoài những hậu quả tiềm ẩn về mặt kinh doanh và pháp lý khi sử dụng phần mềm được cung cấp bởi những vendor, còn có những câu hỏi về mặt hiểu quả. Code được viết cho một ứng dụng rất chuyên biệt thì rất hiệu quả. Việc trừu tượng hoá phần cứng và cố gắng cung cấp các móc (hook) cho mọi mục đích sử dụng và ứng dụng khả dĩ sẽ thêm nhiều lớp (layer) cho phần mềm. Có càng nhiều lớp thì càng có nhiều cuộc gọi hàm (function call) phải thực thi trước khi công việc được làm. Đồng nghĩa với việc độ trễ hệ thống (system latency) sẽ bắt đầu tăng một chút. Trên một vi điều khiển 32-bit hiện đại ngày nay, đây không phải là vấn đề. Tuy nhiên, với một vi điều khiển 8-bit hoặc 16-bit xưa, đây có thể là một nguy cơ tiềm ẩn lớn. Các nhà phát triển do đó cần nhìn cách phần mềm được kiến trúc như thế nào và làm một số phép đo để chắc chắn rằng hiệu quả thực thi chấp nhận được.
Việc trừu tượng (abstracting) một ngoại vi (peripheral) là một kỹ thuật tuyệt vời cho phép nhà phát triển ứng dụng (application) tập trung vào application và không phải lo ngại về lớp hardware bên dưới. Rắc rối là, trong việc trừu tượng, đôi khi một vài chi tiết nhỏ và chức năng bị mất lại có thể cải thiện hiệu quả thực thi hoặc đơn giản hoá tác vụ (task). Các nhà cung cấp sẽ thường viết những công cụ tự động để khắc phục mỗi thiết bị mặc dù có những thay đổi nhỏ. Thỉnh thoảng, các chi tiết được trừu tượng mà không có phương pháp nào để truy cập chức năng đó thông qua API và HAL. Chúng ta sẽ bàn về cách giải quyết vấn đề này ở một chương khác.
Ngoài ra còn có những vấn đề tích hợp (integration) không thể tránh khỏi. Hầu hết các nhóm phát triển đều sử dụng trộn lẫn giữa phần mềm thương mại và nguồn mở. Trong nhiều trường hợp, những phần mềm này đã không được thiết kế làm việc với nhau hoặc test với nhau. Kết quả làm lãng phí thời gian gỡ lỗi (debug) và tích hợp (integrate) phần mềm mà thoạt nhìn có vẻ tương thích nhưng thực tế lại không phải vậy. Đôi khi, các nhà phát triển còn phải thêm các wrapper hoặc tạo ra những cấu trúc khủng khiếp để nhét một cái chốt vuông vào một lỗ tròn (to make a square peg fit into a round hole).
Kết quả không thể tránh khỏi khi tạo thêm những lớp bổ sung và sự trừu tượng bên trong phần mềm là code bắt đầu lớn hơn, lớn hơn, cuối cùng thì… phình to ra. Ngày nay, bộ nhớ flash đã không còn quá mắc tiền. Nhiều nhà phát triển không cần lo nghĩ nhiều về code size, như đã từng hồi 15 hoặc 20 năm trước. Tuy nhiên, đôi khi nó vẫn cần được cân nhắc.
Cuối cùng, chúng ta có nguy cơ tiềm ẩn về khả năng đọc. Khi kéo những API, HAL, phần tử, v.v, từ phần mềm của những nhà cung cấp vào, khả năng chúng sử dụng chung một chuẩn viết code khá mong manh. Hàm và biến sẽ dùng các quy ước khác nhau, khiến cho nó rắc rối và giảm chức năng của phần mềm. Các nhóm cần quyết định cách đương đầu tốt nhất. Cho dù đó là những thay đổi nhỏ, chỉ cần giải quyết nó, hoặc đưa ra một giải pháp độc đáo và sáng tạo. Một giải pháp tiềm năng là biên dịch những phần của bên thứ ba thành thư viện và include ở dạng nhị phân (binary), để cho phần mã nguồn sẽ không có trong dự án. Tuy nhiên nó có nguy cơ gây ra những vấn đề khi nhà phát triển debug.
Vẫn còn nhiều vấn đề tiềm ẩn khác, nhưng đây là những vấn đề mà các nhà phát triển sẽ thấy có tác động lớn nhất đến nỗ lực của họ. Mỗi vấn đề cần phải được xem xét và cân đo cẩn thận trước khi đi sâu vô nỗ lực phát triển và lựa chọn hoặc xây dựng API.
6. Characteristics Every HAL Should Exhibit
Một framework hoặc platform được cung cấp HAL không có nghĩa là nó chắc chắn dễ xài hoặc sẽ cải tiến phần mềm. Tôi đã gặp nhiều trường hợp nhà thiết kế HAL đã quá đà trong thiết kế của họ, và trừ tượng hoá HAL quá nhiều đến mức phải mất nhiều tuần mới hiểu được cách thức hoạt động của HAL. Những nhà thiết kế đó dường như tin vào sự tối giản, chứ không phải sự trừu tượng. Vậy làm thế nào để các nhà phát triển phân biệt giữa HAL tốt và xấu? Khả năng là có hơn hai chục đặc điểm khác nhau mà chúng ta có thể xem xét. Nhưng có mười đặc điểm chính mang tỉ trọng lớn nhất. Trước khi đi vô chi tiết mỗi đặc điểm, dưới đây là tóm tắt giúp người đọc hiểu được chúng ta sẽ thảo luận tới đâu:
- Chứa một chuẩn viết code được định nghĩa tốt
- Viết tài liệu và chú thích (comment) hợp lý
- Viết theo chuẩn C99
- Biên dịch được với bất kỳ compiler hiện đại nào
- Tóm tắt các tính năng phần cứng hữu ích
- Dễ dàng mở rộng
- Có tính module và khả năng thích ứng
- Hành vi xác định và dễ hiểu
- Khả năng xử lý lỗi và chẩn đoán
- Kiểm thử hồi quy tích hợp
Với khái quát này, chúng ta hãy cùng xem xét các đặc điểm chi tiết hơn.
THUẬT NGỮ CHUYÊN NGÀNH
Tiêu chuẩn mã hóa (coding standards) bao gồm một tập hợp các quy tắc lập trình (programming rules), quy ước đặt tên (naming conventions) và đặc tính lớp (layout specifications) giúp phần mềm nhất quán.
Đặc điểm #1: Chứa Một Chuẩn Viết Code Được Định Nghĩa Tốt
Theo kinh nghiệm của tôi thì hầu hết các HAL đều không có một tiêu chuẩn viết code (coding standard) rõ ràng nào kèm theo. Ý của tôi là, một số HAL do nhà sản xuất vi điều khiển cung cấp đã tuân theo một tiêu chuẩn viết code, nhưng sau khi xem xét và tìm kiếm tài liệu của họ, tôi phát hiện ra rằng tiêu chuẩn này không được công khai hoặc nêu rõ ở đâu cho các nhà phát triển biết. Có vẻ như chuyện này không đáng quan tâm. Nhưng HAL liên quan tới phần cứng và chức năng của vi điều khiển rất mật thiết, đồng thời HAL như những hộp đen nhỏ gọn và dễ sử dụng. Thành ra chuyện yêu cầu một vài trang tài liệu cần thiết để biết tiêu chuẩn viết code là gì, các cơ chế để tạo ra HAL là gì, không có gì là quá đáng. Đặc biệt là khi các nhà phát triển có thể sẽ kết hợp tiêu chuẩn đó vào những tài liệu và việc thực hành của riêng họ để giúp có cái nhìn rõ ràng và nhất quán cho toàn bộ code cơ sở.
Đặc điểm #2: Viết Tài Liệu Và Chú Thích Hợp Lý
Tôi yêu phần mềm nguồn mở (open source software), nhưng tôi cũng ghét nó. Phần mềm nguồn mở thường có rất ít chú thích, buộc nhà phát triển phải suy luận hoặc đoán xem code đang làm gì. Việc tôi có thể nhìn thấy code không có nghĩa là tôi sẽ biết nó đang làm gì, hoặc quan trọng nhất là tại sao nhà phát triển lại làm theo cách đó. Khi gặp phải một trục trặc hoặc vấn đề dù nhỏ nhất cũng sẽ cần một nỗ lực khổng lồ để hiểu và giải quyết vấn đề. Tài liệu hướng dẫn không nhất thiết phải là một cuốn sách, nhưng một vài chú thích (comment) rõ ràng và súc tích nằm rải rác trong mã nguồn nhằm giải thích cho kỹ sư cách cấu hình và xài HAL là rất quan trọng. Chú thích một vài ví dụ chắc chắn cũng không gây hậu quả gì. Hoặc đề cập những tài liệu tham khảo mà có thể làm sáng tỏ code, cũng là một cách hay.
Đặc điểm #3: Viết ở dạng C99
Ngôn ngữ lập trình và phiên bản ngôn ngữ có rất nhiều, đến nỗi có thể khiến các nhà phát triển chóng mặt khi muốn quyết định chọn ngôn ngữ nào. Thông thường, là lập trình viên phần cứng cấp thấp (low-level hardware), ngôn ngữ được lựa chọn sẽ là C hoặc C++, nhưng theo truyền thống, ngôn ngữ lập trình C là lựa chọn tốt nhất. Dẫn đến việc tiếp theo là lựa chọn sử dụng C90, C99 hoặc C11 đơn giản hơn.
7. Evaluating HAL Characteristics
(Còn tiếp)