Làm thế nào để tạo ra source code, compile nó và nạp xuống MCU ? Làm sao để có thể mô phỏng cũng như kiểm tra lại code của mình có thể chạy được như thế nào ? Những bước cơ bản để có thể đọc được datasheet của ARM cũng như các tài liệu tham khảo về các instruction trong ARM ? Trong bài viết này mình sẽ chia sẻ một cách sơ lược nhất để các bạn nắm được
IDE
IDE viết tắt của cụm từ Integrated Development Environment là phần mềm cung cấp cho các lập trình viên một môi trường tích hợp bao gồm nhiều công cụ khác nhau như chương trình viết mã lệnh hay code editor, chương trình sửa lỗi hay debugger, chương trình mô phỏng ứng dụng khi chạy thực tế hay simulator…. Nói cách khác thì IDE là một phần mềm bao gồm những gói phần mềm khác giúp phát triển ứng dụng phần mềm.
Để phát triển được một phần mềm với C thì chúng ta cần có một IDE. Với các dự án về embedded thì quá trình phát triển phần mềm với code assembly và C đều sử dụng IDE để rút ngắn thời gian, loại IDE phổ biến và thông dụng nhất thường thấy và được support trực tiếp từ ARM là ARM Keil™ uVision®, với các dòng chip của TI thì ta có thể sử dụng Texas Instruments Code Composer Studio™ (CCStudio), STM32 thì có thể sử dụng STM32CubeIDE. Tùy mục đích và thói quen sử dụng mà các bạn có thể chọn cho mình các IDE khác nhau, với mình thì làm các demo hay ứng dụng nhỏ thì bản lite của Keil C là đã đủ làm mình thỏa mãn rồi, nên trong bài viết này mình chọn Keil là IDE để làm ví dụ luôn.
Tất cả các IDE này đều bao gồm editor, assembler, compiler, và simulator, thêm nữa nó có thể dùng để download và debug software trên một vi điều khiển thật. Một ví dụ cụ thể toàn bộ quá trình phát triển sẽ được thực hiện trên một ứng dụng như hình bên dưới.
Để phát triển một phần mềm thì chúng ta cần dùng có editor để tạo và chỉnh sửa source code. Sau khi code xong thì assembler hoặc compiler sẽ dịch source code của mình thành các object code. Trong ARM Keil™ uVision® chúng ta compile/assemble bằng cách chọn Project->Build Target (phím tắt F7).
Với các ngôn ngữ cấp cao như C hoặc Java thì một dòng của chương trình sẽ được dịch thành vài dòng machine instruction. Ngược lại, một dòng code assembly thường được dịch thành duy nhất 1 machine instruction và map 1-1 với object code. Đó cũng là lý do vì sao code C của bạn sau khi build ra sẽ có size lớn hơn so với code assembly rất nhiều.
Sau khi thực hiện Build Target thì Assembler/ compiler sẽ tạo ra các listing file bao gồm address và các object code tương ứng với mỗi line của chương trình. Object code hoặc các instruction machine(mã máy) sẽ bao gồm các command mà máy có thể đọc và execute(thực thi) được. Tùy vào từng platform khác nhau mà chúng ta sẽ chạy object code này.
Ví dụ khi test software với simulator thì chúng ta sẽ chọn Simulator là target, lúc này chúng ta không cần phải download chương trình xuống mà chạy luôn bằng cách chọn Debug->Start, đây là cách đơn giản và rẻ tiền khi bắt đầu dự án, tuy nhiên nó không hữu ích với trường hợp I/O phức tạp.
Còn nếu muốn test software trong hệ thống thực, chúng ta sẽ chọn vi điều khiển với JTAG debugger là target. Hầu hết vi điều khiển sẽ chứa các tính năng tích hợp cho phép lập trình trên EEPROM nên ta có thể dùng JTAG debugger để download object code xuống EEPROM và debug chương trình. Để làm được điều này với Keil C thì ta chọn Flash->Download. Sau khi download thì chúng ta có thể start hệ thống bằng cách ấn nút reset, sau đó thì debug thoải con gà mái bằng nút Debug->Start Debug
Ngược lại, loader trên máy tính thông thường sẽ đọc object code từ file trên ổ cứng sau đó store code này vào RAM. Khi chương trình chạy, các instruction sẽ được lấy từ RAM, vì RAM là volatile(bay hơi) nên chương trình ở các máy tính thông thường phải được load mỗi khi hệ thống khởi động
Quá trình phát triển các ứng dụng trên thiết bị thực là giống nhau ngoại trừ target chuyển từ một vi điều khiển mô phỏng sang một vi điều khiển thực. Dù là vi điều khiển nào đi chăng nữa thì ngoài việc biết sử dụng thư viện thì cách tốt nhất là nên có một tài liệu tham khảo (reference manual hay thường gọi là datasheet) khi viết code. Với Cortex M4 processor của TI thì ta có các tài liệu sau
CortexM_InstructionSet.pdf Instruction Set Reference Manual
CortexM4_TRM_r0p1.pdf Cortex-M4 Technical Reference Manual
LaunchPadUsersManual.pdf LaunchPad Manual
tm4c123gh6pm.pdf Data Sheet for the TM4C123 microcontroller
Mô tả cho mỗi instruction có thể được tìm thấy ở trang Contents hoặc mục help của ARM Keil™ uVision®.
Datasheet
Khi có các tài liệu về hardware manual (datasheet) của một vi điều khiển bất kỳ thì nên làm thế nào để hiểu và sử dụng được nó để phục vụ coding ?
- Đọc mục lục: ít nhất thì bạn cũng phải biết được trong tài liệu nó có những cái gì ? thường Table of Contents sẽ chứa tất cả nội dung mà ta cần có, cần gì tìm nấy
- Phần overview là bắt buộc phải đọc để nắm. Ví dụ trong file tm4c123gh6pm.pdf đầu tiên mình sẽ đọc Architectural Overview để xem nó giải thích rõ hơn về con chip, những thứ được tích hợp bên trong, Peripherals có gì ? Pins Diagram ra làm sao, …
- Với module mà chúng ta đang cần phải code, ví dụ mình đang quan tâm tới việc đọc dữ liệu cảm biến có liên quan tới ADC, mình sẽ tìm tới phần 13 Analog-to-Digital Converter (ADC), đọc overview, sau đó đọc đến phần 13.1 Block Diagram để nhìn thấy rõ hơn các khối, bus dữ liệu chạy từ đâu về đâu, cái gì được nối với cái gì, cái gì là input, cái gì là output, các module có quan hệ với nó là gì ?.Ở đây thường là hình vẽ minh họa rất dễ quan sát, mỗi tội sẽ có nhiều từ viết tắt cũng như các thanh ghi liên quan làm ta bối rối, nhưng ko sao cả, hiểu được tới đâu hay tới đó.
- Sau đó đọc tiếp phần Signal Description, phần này nó sẽ mô tả về chân cẳng, chân nào số mấy, kiểu là input hay output, để enable lên và select mode thì tác động tới thanh ghi nào ?
- Tiếp theo phần quan trọng nhất là module này có chức năng gì ? hỗ trợ như thế nào thì ta có thể xem chi tiết ở mục 13.3 Functional Description, phần này họ nói rát rõ về các function của ADC, thanh ghi liên quan, thậm chí là họ highlight lên luôn. Ví dụ For a given sample sequence, each sample is defined by bit fields in the ADC Sample Sequence Input Multiplexer Select (ADCSSMUXn) and ADC Sample Sequence Control (ADCSSCTLn) thì có 2 thanh ghi chúng ta cần phải quan tâm là ADCSSMUXn và ADCSSCTLn
- Để sử dụng được các module ngoại vi thì chúng ta cần biết được cách khởi tạo và cấu hình, nó nằm ở phần 13.4 Initialization and Configuration, bạn phải đảm bảo là theo đúng sequence init và config thì chắc chắn 100% module của bạn sẽ chạy. Nếu bạn dùng thư viện có sẵn thì cũng phải map được phần init này với các function API được cung cấp, còn nếu nghề nghiệp bạn có dính tới việc làm driver thì phải dựa vào phần này để viết ra các API cần thiết cho người dùng
- Register Map và Register Descriptions sẽ chứa tất cả các thanh ghi mà chúng ta có thể sử dụng được, tùy nhu cầu mục đích mà ta sẽ read hoặc write lên từng bit của thanh ghi, ví dụ với ADCSSMUXn, ta có thể tìm thấy nó được mô tả ở trang 867, có mô tả cho từng bit, sơ sơ ta có thể thấy MUX0 – MUX3 là có thể RW, nghĩa là khi code chúng ta có thể tác động được lên các bit này để chọn Sample input
- Đọc Instruction Set. Trong Instruction Set Reference Manual sẽ list ra tập lệnh ASM. Nếu ta có lập trình ASM thì cần phải lưu ý phần này.
Tạm kết
Có rất nhiều cách để tạo ra project khi bắt đầu. Tuy nhiên mình khuyến khích những người mới nên bắt đầu với nhiều dự án đã có sẵn. Sau đó chọn một dự án có sẵn mà giống với solution của bạn, tạo ra một bản copy của dự án này. Cuối cùng tạo ra các sự thay đổi trên bản sao đó trước khi ốp giải pháp của mình vào. Hãy đảm bảo rằng nó vẫn tiếp tục chạy mỗi khi bạn có sự thay đổi. Nếu bạn tạo ra hàng trăm sự thay đổi trên nó mà không test lại thì tới lúc nó tạch, bạn sẽ không biết được sự thay đổi nào gây ra lỗi, là thay đổi thứ 1 hay thay đổi thứ 100? Và một điều quan trọng nữa là reference manual hay thường gọi là datasheet luôn là bí kíp dẫn đường cho mọi vấn đề chúng ta gặp phải.
Về cụ thể đọc datasheet để tự code một cái gì đó “made by tui” thì mình đã nói sơ qua phía trên, cụ thể sẽ có bài viết tiếp theo để các bạn có thể tham khảo và thực hành.
Tham khảo
[1]