Hệ thống nhúng và các thành phần
Mình xin giới thiệu một chút về hệ thống nhúng và các thành phần của nó, một số khái niệm về thanh ghi, tập lệnh,… các kiến trúc Harvard và Von neumann.
Mục tiêu
- Hiểu về vi điều khiển (microcontroller) và máy tính (computer)
- Hiểu về các cổng I/O
- Hiểu về các khái niệm ALU, CU, thanh ghi, bus, Von neumann, Harvard
Hệ thống nhúng
Để có thể hiểu hơn về hệ thống nhúng (embedded microcomputer system) thì mình sẽ phân tích từng chữ một, đầu tiên “embedded” có nghĩa là ẩn bên trong mà không ai có thể thấy được, “micro” nghĩa là nhỏ và “computer” nghĩa là máy tính, mà máy tính thì thường sẽ gồm bộ xử lý, ram, và nó có thể trao đổi thông tin với thế giới bên ngoài, “system” có nghĩa là hệ thống gồm nhiều thành phần tương tác với nhau.
Trong hệ thống nhúng thì chúng ta thường sử dụng ROM để lưu các phần mềm (thường gọi là firmware) và các giá trị dữ liệu hằng số, và thường được giữ nguyên khi mất điện, chip ngày nay thường dùng là Flash EEPROM do nó có khả năng lập trình lại, còn RAM được sử dụng để lưu các thông tin tạm thời.
Ví dụ như với một chiếc đồng hồ Casio điện tử chẳng hạn, mỗi khi bạn thay pin mới vào thì hầu như là giờ không bị sai, lý do bởi vì thông tin được lưu ở trong ROM là không bị bay hơi (nonvolatile).
Như hình trên thì các bạn có thể hình dung ra một hệ thống nhúng sẽ có một hoặc nhiều microcomputer bên trong. Một vi điều khiển (microcontroller) là một microcomputer kết hợp với bộ xử lý(Processor), RAM, ROM, và các cổng I/O thành một khối duy nhất. Đây là loại thường được dùng cho các hệ thống nhúng rất nhiều bởi vì nó rẻ, kích thước nhỏ và đáp ứng được các yêu cầu về tiêu thụ năng lượng thấp.
Ví dụ: như dòng vi điều khiển của Texas Instruments là TM4C (TIVA) thì có rất nhiều I/O như các cổng song song, các cổng nối tiếp, các timer, bộ ADC,DAC,… Các I/O này là phần cực kỳ quan trọng của các hệ thống nhúng, nó giúp tạo nên sự khác biệt của một hệ thống nhúng cũng như tạo ra khả năng giao tiếp giữa các vi điều khiển với nhau, giữa vi điều khiển với con người thông qua HCI( human-computer interface) hoặc MMI(man-machine interface)
Máy tính và vi điều khiển
Để hiểu rõ hơn về máy tính(computer) và vi điều khiển(microcomputer) thì mình sẽ đi thêm 1 chút về các khái niệm
Computer là sự kết hợp giữa bộ xử lý, RAM, ROM và các cổng I/O. Chúng ta có thể xem hình sau
Với dạng bus như hình trên là đặc trưng của kiến trúc Von Neumann. Thông thường computer không được “thông minh” cho lắm, nó có thể lưu được rất nhiều thông tin nhưng nó chỉ thực hiện công việc khi chúng ta bảo nó phải làm gì, làm việc A, việc B, việc C.
Software (Phần mềm) ở đây là một chuỗi các thao tác để sắp xếp thông tin vào bộ nhớ, xác định chính xác những cộng việc cần phải thực hiện.
Processor (bộ xử lý) sẽ thực hiện phần mềm sau mỗi chu kỳ máy nhất định.
Microprocessor là một bộ xử lý nhỏ, nhỏ ở đây là nhỏ về kích thước chứ không phải là nhỏ về khả năng tính toán. Ví dụ cụ thể rõ ràng nhất là các dòng chip của Intel và AMD, Sun SPARC.
Microcomputer là máy tính nhỏ. Ta có thể xem các máy tính cá nhân hiện nay là một microcomputer.
Port là kết nối vật lý giữa máy tính và thế giới bên ngoài, nó có thể cho thông tin vào/ ra hệ thống.
Bus có thể hiểu là nhiều dây nối để vận chuyển thông tin giữa các modul khác nhau.
Microcontroller là vi điều khiển, nhỏ hơn mức microcomputer, nó sẽ bao gồm tất cả các thành phần của microcomputer(bộ xử lý, bộ nhớ, I/O) trong 1 con chip duy nhất.
Ví dụ: như ATtiny, MSP430, TM4C123 là microcontroller.
Thông tin lưu trữ trong ROM sử dụng một công nghệ phức tạp hơn trong RAM rất nhiều. Nhưng ở góc độ lập trình thì việc lấy thông tin từ ROM hoàn toàn tương tự như RAM, ROM là nonvolatile, nghĩa là nghĩa mất nguồn thì thông tin ở ROM vẫn sẽ còn lại ở đó. Với một số ROM thì có thể được lập trình từ lúc sản xuất và không thể thay thế.
PROM (Programmable ROM) có thể xóa và lập trình lại bởi người dùng, tuy nhiên tối đa chỉ được 10000 lần.
Flash ROM là một dạng EEPROM khá phổ biến hiện nay, chúng ta có thể xóa và lập trình từng byte riêng biệt hoặc xóa theo block.
Với hình sơ đồ khối ở trên là các thành phần cơ bản nhất của bộ xử lý ARM® Cortex™-M. Đây là kiến trúc Harvard, với kiến trúc này thì nó sẽ có các đường bus cho dữ liệu và tập lệnh riêng biệt. Tập lệnh (instruction) được lấy từ flash ROM thông qua bus ICode. Dữ liệu được trao đổi với bộ nhớ và I/O thông qua System bus. Trong Cortex-M4 có 2 bus I/O cho các device tốc độ cao như USB. Các tính năng debug được thực hiện thông qua DCode bus. Bộ NVIC dùng để quản lý ngắt, và được kết nối trực tiếp với bộ xử lý thông qua bus riêng gọi là PPB (private peripheral bus), với việc kết nối này sẽ giảm thiểu được độ trễ khi xảy ra ngắt.
Mặc dù dữ liệu và tập lệnh nhận 32 bit 1 lần nhưng mỗi byte gồm 8bit lại có một địa chỉ duy nhất, điều này có nghĩa là bộ nhớ và các cổng I/O có thể xác định theo địa chỉ byte và bộ xử lý có thể đọc và ghi các dữ liệu 8-bit, 16-bit, 32-bit. Mình sẽ trình bày cụ thể hơn ở các phần sau.
I/O Port
Vi điều khiển thông thường sẽ có 2 loại port
Input port để giao tiếp nhận thông tin từ thế giới bên ngoài.
Output port để gửi thông tin ra ngoài thế giới.
Chúng ta có thể xem mô tả về các cổng IO có ở một vi điều khiển ở hình sau
Có một khái niệm là interface chỉ các thành phần được kết nối với các cổng I/O để giúp vi điều khiển có thể tương tác được với thế giới hiện tại. Chẳng hạn như nút nhấn là một input interface, khi chúng ta nhấn nút thì với phần mềm có trên vi điều khiển có thể nhận biết là nút có được nhấn hay không. Với output interface thì ta có LED, khi lập trình LED bật hoặc tắt thì ta có thể quan sát được LED sáng hay là không sáng.
Có rất nhiều input và output khác nhau, cái thì tồn tại ở dạng số, cái thì ở dạng tương tự. Vì thế mà ta có thể chia ra thành 4 nhóm
Parallel – có nghĩa là song song, dữ liệu sẽ được gửi liên tục trên một nhóm dây.
Serial – có nghĩa là nối tiếp, dữ liệu đợc gửi từng bit trên 1 dây.
Analog – có nghĩa là tương tự, dữ liệu được mã hóa dưới dạng điện áp, dòng điện hoặc công suất.
Time – dữ liệu sẽ được mã hóa dưới dạng thời gian, tần số, độ rộng xung hoặc độ lệch pha.
Ví dụ: Thường thì khi làm quen một vi điều khiển thì điều đầu tiên là chúng ta phải đọc được datasheet, với người đã làm quen rồi thì việc đọc datasheet sẽ giúp chúng ta nắm rõ hơn được về con chip hoạt động như thế nào và cách để làm việc với nó. Với con chip như Tiva TM4C123 thì bạn có thể làm quen cách đọc như sau
- Tải datasheet tại đây
- Tới trang 46 tìm xem RAM và ROM của chip là bao nhiêu ?
- Tìm tới trang 649 để kiểm tra xem chip có bao nhiêu chân I/O ?
Thanh ghi CPU
Thanh ghi (register) là các ô nhớ tốc độ cao bên trong bộ xử lý. Có 13 thanh ghi với mục đích chung (general purpose register) từ R0-R12
và 3 thanh ghi với mục đích đặc biệt (special purpose register) là R13,R14,R15
.
Chúng ta có thể xem qua hinh minh họa
Ở đây thanh ghi từ R0 tới R12 là thanh ghi dùng chung (general purpse register) bao gồm cả dữ liệu và địa chỉ.
Thanh ghi R13 (được gọi là thanh ghi con trỏ SP) sẽ trỏ tới thành phần nằm trên đỉnh của stack.
Thanh ghi R14 (được gọi là thanh ghi liên kết LR) sử dụng để lưu và trả lại vị trí của hàm. LR cũng được sử dụng trong các trường hợp ngoại lệ như ngắt.
Thanh ghi R15 (được gọi là thanh ghi bộ đếm chương trình PC) sẽ trỏ tới tập lệnh tiếp theo được lấy từ bộ nhớ. Bộ xử lý sẽ thực hiện lệnh này sử dụng PC sau đó sẽ tăng PC lên.
Với cấu trúc của ARM là AAPCS(ARM Architecture Procedure Call Standard), một phần của ABI (Application Binary Interface) sẽ sử dụng các thanh ghi R0, R1, R2 để đưa các tham số đầu vào vào hàm C, các tham số được trả lại nằm trong thanh ghi R0. Trong bài viết này và các bài tiếp theo thì SP sẽ luôn là MSP (Main Stack Pointer) chứ không phải là PSP (Process Stack Pointer)
Có 3 trạng thái của thanh ghi là APSR(Application Program Status Register), IPSR(Interrupt Program Status Register) và EPSR(Execution Program Status Register) như hình sau
Thanh ghi có thể tác động riêng biệt hoặc kết hợp như PRS(Program Status Register). Các bit N,Z,V,C,Q
đưa thông tin về kết quả của quá trình tính toán ALU trước đó. Thông thường N bit sẽ được set sau một phép tính số học hoặc logic để xác định kết quả có là âm hay không. Z bit được set nếu kết quả là 0. C bit được set khi tràn giá trị unsigned và V bit được set khi tràn giá trị signed. Q bit khi trạng thái “bão hòa” xảy ra. T bit luôn là 1 thực hiện các tập lệnh Thumb® của ARM®Cortex™-M.
Nói thêm 1 chút về ngắt, ngắt là thành phần rất quan trọng trong một hệ thống nhúng. Ngắt là phần mềm kích hoạt phần cứng hoạt động. Ví dụ chúng ta có thể tạo ra ngắt mỗi 1 ms. Trong trường hợp này thì chúng ta có thể chạy được đoạn mã gọi là ISR (interrupt service routine) 1000 lần 1 giây. Ta còn có thể tạo ngắt khi có dữ liệu mới ở đầu vào. Ví dụ như cấu hình vi điều khienr chạy một chức năng nào đó khi nút nhấn được tác động.
ISR_NUMBER
cho thấy ngắt nào đang được xử lý. Bit 0 của thanh ghi đặc biệt PRIMASK
là bit ngắt mặt nạ ( mask bit). Nếu bit này là 1 thì hầu hết ngắt và các exception không được cho phép. Nếu nó là 0 thì các ngắt được cho phép. Bit 0 của FAULTMASK
là bit măt nạ lỗi. Nếu bit này bằn 1 thì tất cả ngắt và lỗi (fault) không được cho phép và ngược lại. Các bit NMI
(nonmaskable interrupt) không bị ảnh hưởng bởi bit mặt nạ (mask bit).
Việc ưu tiên cũng là phần quan trọng trong ngắt. Với chip TM4C123 thì có 8 mức ưu tiên được đánh số từ 0 tới 7. Mức 0 là mức cao nhất và 7 là thấp nhất. Khi cấu hình phần cứng để có thể ngắt thì thường phải xác định mức độ ưu tiên của nó. Thanh ghi BASEPRI
định nghĩa độ ưu tiên khi thực hiện chương trình. Nó sẽ ngăn các ngắt có mức độ ưu tiên bằng hoặc thấp hơn và cho phép các ngắt có mức ưu tiên lớn hơn hoạt động.
Ví dụ với BASEPRI
bằng 3 thì có nghĩa là khi bộ xử lý thực hiện ISR để tạo ra ngắt ở mức 3. Trong quá trình thực hiện mức 3 nếu có yêu cầu ngắt ở mức 0, 1, 2 thì các mức này sẽ được ưu tiên thực hiện trước. Ngược lại thì sẽ bỏ qua nếu có yêu cầu ngắt khác ở mức 3 4 5 …
Tạm kết
Bài này khá nhiều khái niệm, mình cũng đã tô đậm và để nguyên tiếng anh để các bạn có thể theo dõi và tìm kiếm thêm. Các bạn có thể xem qua để mình có thể nắm được các ý chính. Trong các bài sau mình sẽ đi kỹ hơn và lật lại, nhắc lại vấn đề cho mọi người.