Nối tiếp phần 1, Bài giảng Hệ thống nhúng (2019): Phần 2 tiếp tục trình bày những nội dung về phát triển hệ thống nhúng dựa trên hệ vi xử lý nhúng; kiến trúc của hệ vi xử lý nhúng ARM; giới thiệu về dòng vi xử lý ARM Cortex và ARM Cortex M3; thiết lập hệ điều hành nhúng trên nền ARM; lập trình điều chế độ rộng xung - PWM (Pulse-width modulation);... Mời các bạn cùng tham khảo!
HỌC VIỆN CƠNG NGHỆ BƯU CHÍNH VIỄN THƠNG NGUYỄN NGỌC MINH LƯƠNG CÔNG DUẨN BÀI GIẢNG HỆ THỐNG NHÚNG HÀ NỘI – 10.2019 CHƯƠNG 5: PHÁT TRIỂN HỆ THỐNG NHÚNG DỰA TRÊN HỆ VI XỬ LÝ NHÚNG 5.1 Giới thiệu chung Trong hệ thống nhúng nay, vi xử lý lõi ARM sử dụng rộng rãi Trong chương này, kiến thức kiến trúc vi xử lý lõi ARM tập lệnh ARM giới thiệu Sau đó, kiến thức việc thiết kế thành phần hệ thống nhúng đề cập Phần cuối tập trung vào thiết lập hệ điều hành nhúng ARM 5.2 Kiến trúc hệ vi xử lý nhúng ARM Lõi ARM Kiến trúc ARM thiết kế chuyên dụng cho ứng dụng nhúng Do đó, thực hóa chip ARM thiết kế ứng dụng nhỏ có hiệu cao, tiêu thụ lượng Lõi ARM thiết kế theo kiến trúc RISC, chứa kiến trúc RISC chung • Các ghi đồng dạng • Kiến trúc dạng Load-Store Các địa Load/Store xác định từ nội dung ghi lệnh • Các kiểu đánh địa đơn giản • Các lệnh có độ dài cố định đồng dạng, đơn giản hóa việc giải mã câu lệnh • Thay dùng chu kì xung nhịp cho tất lệnh, ARM thiết kế để cho tối giản số chu kì xung nhịp cho lệnh, tăng phức tạp cho lệnh đơn lẻ Ngồi ra, kiến trúc ARM cung cấp: • Điều khiển khối logic số học (ALU) dịch chuyển (shifter) lệnh xử lý liệu để tối đa hóa việc sử dụng ALU dịch chuyển • Các chế độ địa tự tăng tự giảm để tối ưu hóa lệnh vịng lặp • Các lệnh nhân Load/Store để tối đa liệu truyền qua Nhờ tối ưu kiến trúc RISC bản, lõi ARM đạt cân hiệu cao, kích thước mã nguồn ít, cơng suất tiêu thụ thấp 133 Thanh ghi chế độ hoạt động Lõi ARM có 37 ghi có 31 ghi đa dụng Tuy nhiên thời điểm có 16 ghi đa dụng ghi trạng thái hiển thị Các ghi khác dạng ẩn, hiển thị số chế độ hoạt động riêng Các ghi đa dụng dùng để lưu liệu địa Các ghi đánh dấu ký hiệu r Tất ghi 32 bit Trong ghi đa dụng trên, có ghi dùng để chức nhiệm vụ đặc biệt riêng: r13, r14, r15 • Thanh ghi r13 dùng làm stack pointer (SP) • Thanh ghi r14 gọi ghi kết nối (LR) chưa địa quay lại chương trình chương trình chạy hàm • Thanh ghi r15 đếm chương trình (pc) chưa địa lệnh Hai ghi trạng thái bao gồm ghi trạng thái chương trình (CPSR) dùng để giám sát trạng thái hoạt động ghi trạng thái chương trình lưu (SPSR) dùng để lưu trữ giá trị CPSR có trường hợp ngoại lệ xảy Thanh ghi trạng thái chương trình (CPSR) : CPSR có trường, trường có bit: cờ, trạng thái, mở rộng điều khiển Hiện phần trạng thái mở rộng dự trữ cho thiết kế tương lai Hình 1: Cấu trúc ghi trạng thái chương trình Các cờ CPSR sau: • N: Negative- cờ bật bit cao kết xử lý ALU • Z: Zero- cờ bật kết cuối ALU • C: Carry- cờ bật kết cuối ALU lớn giá trị 32bit tràn • V: Overflow-cờ báo tràn sang bit dấu 134 Các ghi Abort Mode r0 r1 r2 Các ghi ẩn r3 r4 r5 r6 User FIQ IRQ SVC Undef r7 r8 r8 r9 r9 r10 r10 r11 r11 r12 r13 (sp) r14 (lr) r15 cpsr spsr r12 r13 r13 r13 r13 r14 r14 r14 r14 r13 (sp) r14 (lr) spsr spsr spsr spsr Hình 2: Các ghi lõi ARM Chế độ hoạt động VXL xác định ghi hoạt động quyền truy cập tới ghi cpsr Mỗi chế độ hoạt động VXL chế độ đặc quyền không đặc quyền: chế độ đặc quyền cho phép đọc ghi tới ghi cpsr Người lại chế độ không đặc quyền cho phép đọc trường điều khiển cpsr cho phép đọc ghi tới cờ điều kiện Có bảy (7) chế độ hoạt động VXL: sáu chế độ đặc quyền (abort, fast interrupt request, interrupt request, supervisor, system, and undefined) chế độ không đặc quyền (user) Sơ đồ ghi chế độ hình 135 User FIQ r0 User mode r0-r7, r15, cpsr r1 r2 r3 r4 IRQ SVC Undef Abort User mode r0-r12, r15, cpsr User mode r0-r12, r15, cpsr User mode r0-r12, r15, cpsr User mode r0-r12, r15, cpsr r12 r13 r13 r13 r14 r14 r14 r13 (sp) r14 (lr) r13 (sp) r14 (lr) spsr spsr spsr spsr spsr r5 r6 r7 r8 r8 r9 r10 r9 r10 r11 r12 r11 r13 r14 r15 (pc) cpsr Hình 3: Các chế độ hoạt động ghi Hoạt động chế độ sau: • Bộ VXL hoạt động chế độ Abort VXL truy cập nhớ • Bộ VXL hoạt động chế độ interrupt request (IRQ) fast interrupt request (FIQ) tương ứng với hai mức ngắt chip ARM • Bộ VXL hoạt động chế độ Supervisor sau hệ thống khởi động (reset) nhân hệ điều hành hoạt động • Bộ VXL hoạt động chế độ System hệ thống truy cập đọc, ghi toàn ghi cpsr Đây chế độ đặc biệt chế độ User • Bộ VXL chuyển sang chế độ Undefined VXL gặp lệnh khơng xác định khơng hỗ trợ • Bộ VXL hoạt động chế độ User để chạy chương trình ứng dụng thơng thường Đối với chế độ, có ghi riêng cho chế độ Pipeline Cách tổ chức nhân ARM không thay đổi nhiều khoảng 1983-1995:đến ARM7-sử dụng dòng chảy lệnh sử dụng tác vụ Từ 1995 trở sau, xuất vài nhân ARM giới thiệu có dịng chảy lệnh sử dụng tác vụ Các dòng ARM 136 sau có dịng chảy lệnh tác vụ (ARM10), tác vụ (ARM11) 13 tác vụ (ARM Cortex) Dòng chảy lệnh tác vụ: Bao gồm tác tác vụ sau: Fetch-decode-Excute (nhận lệnh, giải mã, thực thi) Hình 4: Dịng chảy lệnh tác vụ áp dụng trường hợp lệnh có nhiều chu kì máy Dịng chảy lệnh tác vụ: Bao gồm tác vụ : Fetch-decode-excute-buffer/data-write back Dòng chảy lệnh tác vụ: • • • • • • Fetch đoán nhánh Issue Decode đọc ghi Execute shift ALU, tính địa chỉ, nhân Truy cập nhớ, nhân Ghi vào ghi Dòng chảy lệnh tác vụ: • Ba tác vụ Fetch • Một tác vụ Decode • Một tác vụ Issue • Bốn tác vụ integer execution pipeline 137 Cấu trúc bus: Khi muốn thiết kế riêng vi điều khiển, thiết kế hệ thống nhúng, quan tâm đến chức khối, bus kết nối khối lại với vấn đề nên xem xét kỹ lưỡng Các hệ thống nhúng sử dụng kỹ thuật bus khác với thiết kế PC dựa họ x86 Một dạng bus PC thơng dụng bus PCI kết nối thiết bị card đồ họa, điều khiển đĩa cứng, đến bus vi xử lý x86 Đây loại bus ngồi (off-chip), nghĩa kết nối thiết bị bên tới chip.Ngược lại, thiết bị nhúng sử dụng bus on-chip nằm bên chip cho phép thiết bị ngoại vi kết nối với lõi ARM Có hai loại thiết bị khác gắn với bus: master slave Trong lõi ARM master – có khả điều khiển trình truyền liệu với thiết bị khác bus, thiết bị ngoại vi – slave đáp ứng với điều khiển thiết bị master Kiến trúc bus vi điều khiển tiến tiến gọi tắt AMBA (Advanced Microcontroller Bus Architecture) giới thiệu năm 1996 sử dụng làm kiến trúc bus on-chip dành cho xử lý ARM Các bus AMBA giới thiệu ARM System Bus (ASB) ARM Peripheral Bus (APB) Một thiết kế bus khác ARM giới thiệu sau ARM High Performance Bus (AHB) Với AMBA, nhà thiết kế ngoại vi sử dụng lại thiết kế nhiều project khác Bởi có nhiều ngoại vi thiết kế với giao diện AMBA nên nhà thiết kế phần cứng có nhiều lựa chọn ngoại vi kiểm thử nhằm sử dụng thiết kế họ AHB cung cấp băng thông liệu cao so với ASB thiết kế dựa lược đồ bus ghép kênh tập thiết kế bus hai chiều ASB Sự thay đổi cho phép bus AHB chạy tốc độ clock cao bus ARM hỗ trợ độ rộng bus lên tới 64 128bit ARM giới thiệu biến thể bus AHB Multi-layer AHB AHB-Lite Ngược lại với bus AHB ban đầu cho phép master tích cực bus thời điểm, Multi-layer AHB cho phép nhiều master tích cực úc AHB-Lite tập bus AHB, bị giới hạn có master bus Bus phát triển cho thiết kế không yêu cầu đầy đủ chức bus AHB chuẩn Tập lệnh ARM VXL ARM sử dụng cấu trúc load-store Điều có nghĩa là: tất lệnh thực ghi Các lệnh ARM thường có đến tốn tử Mặc dù phiên kiến trúc ARM khác hỗ trợ tập lệnh khác nhau, phiên thường tương thích ngược với tập lệnh cũ Danh sách lệnh ARM 138 Các lệnh xử lý liệu Các lệnh xử lý liệu thực thi phép tính liệu ghi Các lệnh bao gồm chuyển liệu, phép tính số học, logic, phép so sánh phép nhân Nếu lệnh có thêm S cuối, cập nhật cờ ghi CPRS Các lệnh dịch chuyển phép toán logic cập nhật cờ Carry C, cờ Negative N, cờ Zero Z Các lệnh dịch chuyển MOVE lệnh đơn giản lệnh ARM Lệnh thay copy giá trị N đến ghi đích Rd Cú pháp : {}{S} Rd, N Có lệnh dịch chuyển MOV: Chuyển giá trị 32 bit đến ghi (Rd=N) MVN: Chuyển giá trị đảo 32 bit đến ghi (Rd= ~N) Ví dụ: Trước: r5=5 r7=8 MOV r7, r5 ; let r7 = r5 Sau r5=5 r7=5 MOVCS R0, R1 ; carry SET R0:=R1 MOVS R0, #0 ; R0:=0 Z=1, N=0 ;C, V không thay đổi Các lệnh số học Các lệnh số học thực cộng trừ giá trị 32 bít có dấu khơng có dấu Kết 32 bit đặt ghi Cấu trúc lệnh có địa Cú pháp : {}{S} Rd, Rn, N ADD R0, R1, R2 ADC R0, R1, R2 SUB R0, R1, R2 SBC R0, R1, R2 RSB R0, R1, R2 RSC R0, R1, R2 ; R0 = R1+R2 ; R0 = R1+R2+C ; R0 = R1-R2 ; R0 = R1-R2+C-1 ; R0 = R2-R1 ; R0 = R2-R1+C-1 Ví dụ: 139 Trước: r0 = 0x00000000 r1 = 0x00000002 r2 = 0x00000001 SUB r0, r1, r2 Sau: r0 = 0x00000001 Trước: r0 = 0x00000000 r1 = 0x00000077 RSB r0, r1, #0 ; Rd = 0x0 - r1 (giá trị âm r1) Sau: r0 = -r1 = 0xffffff8 Các lệnh logic Các lệnh logic thực phép toán logic theo bit ghi Cú pháp: {}{S} Rd, Rn, N AND R0, R1, R2 ORR R0, R1, R2 EOR R0, R1, R2 BIC R0, R1, R2 ;R0 = R1 and R2 ; R0 = R1 or R2 ; R0 = R1 xor R2 ; R0 = R1 and (~R2) Ví dụ: Trước; r0 = 0x00000000 r1 = 0x02040608 r2 = 0x1030507056 ORR r0, r1, r2 Sau: r0 = 0x12345678 Trước: r1 = 0b1111 r2 = 0b0101 BIC r0, r1, r2 Sau: r0 = 0b1010 140 Trước: r1=0x11111111 r2=0x01100101 BIC r0, r1, r2 Sau: R0=0x10011010 Các lệnh so sánh Các lệnh so sánh dùng để so sánh kiếm tra ghi với giá trị 32 bit Các lệnh không ảnh hưởng đến ghi, thay đổi cập nhật bit cờ ghi CPRS Các lệnh không cần thêm S Cấu trúc: {} Rn, N CMP R1, R2 CMN R1, R2 TST R1, R2 TEQ R1, R2 ; set cờ cho kết R1-R2 ; set cờ cho kết R1+R2 ; set cờ cho kết R1 and R2 ; set cờ cho kết R1 xor R2 Các lệnh nhân Các lệnh nhận thực phép nhân giá trị hai ghi thực cộng dồn với ghi khác Kết cuối ghi vào ghi đích hai ghi kết 64 bits Cấu trúc: MLA{}{S} Rd, Rm, Rs, Rn MUL{}{S} Rd, Rm, Rs MUL R0, R1, R2 ; R0 = (R1xR2)[31:0] (32 bits) MLA R4, R3, R2, R1 ; R4 = R3xR2+R1 Các lệnh rẽ nhánh Các lệnh rẽ nhánh thay đổi chu trình chạy chương trình, dùng để gọi hàm khác Việc làm thay đổi giá trị ghi chương trình PC làm ghi PC trỏ đến địa Cấu trúc: B{} label BL{} label BX{} Rm BLX{} label | Rm 141 if (y1>y2) { tmp=y1; y1=y2; y2=tmp; } drawVLine(x1, y1, y2-y1); } else if (abs(x2-x1)>abs(y2-y1)) { delta=(double(y2-y1)/double(x2-x1)); ty=double(y1); if (x1>x2) { for (int i=x1; i>=x2; i ) { setPixel(i, int(ty+0.5)); ty=ty-delta; } } else { for (int i=x1; iy2) { for (int i=y2+1; i>y1; i ) { setPixel(int(tx+0.5), i); tx=tx+delta; } } else { 262 for (int i=y1; iabs(y2-y1)) { delta=(double(y2-y1)/double(x2-x1)); ty=double(y1); if (x1>x2) { for (int i=x1; i>=x2; i ) { clrPixel(i, int(ty+0.5)); ty=ty-delta; } } else { for (int i=x1; iy2) { for (int i=y2+1; i>y1; i ) { clrPixel(int(tx+0.5), i); tx=tx+delta; 264 } } else { for (int i=y1; ix2) { tmp=x1; x1=x2; x2=tmp; } if (y1>y2) { tmp=y1; y1=y2; y2=tmp; } drawHLine(x1, drawHLine(x1, drawVLine(x1, drawVLine(x2, y1, y2, y1, y1, x2-x1); x2-x1); y2-y1); y2-y1+1); } void LCD5110::clrRect(int x1, int y1, int x2, int y2) { int tmp; if (x1>x2) { 265 tmp=x1; x1=x2; x2=tmp; } if (y1>y2) { tmp=y1; y1=y2; y2=tmp; } clrHLine(x1, clrHLine(x1, clrVLine(x1, clrVLine(x2, y1, y2, y1, y1, x2-x1); x2-x1); y2-y1); y2-y1+1); } void LCD5110::drawRoundRect(int x1, int y1, int x2, int y2) { int tmp; if (x1>x2) { tmp=x1; x1=x2; x2=tmp; } if (y1>y2) { tmp=y1; y1=y2; y2=tmp; } if ((x2-x1)>4 && (y2-y1)>4) { setPixel(x1+1,y1+1); setPixel(x2-1,y1+1); setPixel(x1+1,y2-1); setPixel(x2-1,y2-1); drawHLine(x1+2, y1, x2-x1-3); drawHLine(x1+2, y2, x2-x1-3); drawVLine(x1, y1+2, y2-y1-3); drawVLine(x2, y1+2, y2-y1-3); 266 } } void LCD5110::clrRoundRect(int x1, int y1, int x2, int y2) { int tmp; if (x1>x2) { tmp=x1; x1=x2; x2=tmp; } if (y1>y2) { tmp=y1; y1=y2; y2=tmp; } if ((x2-x1)>4 && (y2-y1)>4) { clrPixel(x1+1,y1+1); clrPixel(x2-1,y1+1); clrPixel(x1+1,y2-1); clrPixel(x2-1,y2-1); clrHLine(x1+2, y1, x2-x1-3); clrHLine(x1+2, y2, x2-x1-3); clrVLine(x1, y1+2, y2-y1-3); clrVLine(x2, y1+2, y2-y1-3); } } void LCD5110::drawCircle(int x, int y, int radius) { int f = - radius; int ddF_x = 1; int ddF_y = -2 * radius; int x1 = 0; int y1 = radius; char ch, cl; setPixel(x, y + radius); setPixel(x, y - radius); 267 setPixel(x + radius, y); setPixel(x - radius, y); while(x1 < y1) { if(f >= 0) { y1 ; ddF_y += 2; f += ddF_y; } x1++; ddF_x += 2; f += ddF_x; setPixel(x + x1, y setPixel(x - x1, y setPixel(x + x1, y setPixel(x - x1, y setPixel(x + y1, y setPixel(x - y1, y setPixel(x + y1, y setPixel(x - y1, y } + + + + - y1); y1); y1); y1); x1); x1); x1); x1); } void LCD5110::clrCircle(int x, int y, int radius) { int f = - radius; int ddF_x = 1; int ddF_y = -2 * radius; int x1 = 0; int y1 = radius; char ch, cl; clrPixel(x, y + radius); clrPixel(x, y - radius); clrPixel(x + radius, y); clrPixel(x - radius, y); while(x1 < y1) { if(f >= 0) { 268 y1 ; ddF_y += 2; f += ddF_y; } x1++; ddF_x += 2; f += ddF_x; clrPixel(x + clrPixel(x clrPixel(x + clrPixel(x clrPixel(x + clrPixel(x clrPixel(x + clrPixel(x - x1, x1, x1, x1, y1, y1, y1, y1, y y y y y y y y + + + + - y1); y1); y1); y1); x1); x1); x1); x1); } } void LCD5110::drawBitmap(int x, int y, uint8_t* bitmap, int sx, int sy) { int bit; byte data; for (int cy=0; cy