c. Biến hằng và toán tử
2.1.3.1 Tổ chức của AVR
AVR có cấu trúc Harvard, trong đó đƣờng truyền cho bộ nhớ dữ liệu (data memory bus) và đƣờng truyền cho bộ nhớ chƣơng trình (program memory bus) đƣợc tách riêng. Data memory bus chỉ có 8 bit và đƣợc kết nối với hầu hết các thiết bị ngoại vi, với register file. Trong khi đó program memory bus có độ rộng 16 bits và chỉ phục vụ cho instruction registers. Hình 1 mô tả cấu trúc bộ nhớ của AVR.
Bộ nhớ chƣơng trình (Program memory): Là bộ nhớ Flash lập trình đƣợc, trong các chip AVR cũ (nhƣ AT90S1200 hay AT90S2313…) bộ nhớ chƣơng trình chỉ gồm 1 phần là Application Flash Section nhƣng trong các chip AVR mới chúng ta có thêm phần Boot Flash setion. Boot section sẽ đƣợc khảo sát trong các phần sau, trong bài này khi nói về bộ nhớ chƣơng trình, chúng ta tự hiểu là Application section. Thực chất, application section bao gồm 2 phần: phần chứa các instruction (mã lệnh cho hoạt động của chip) và phần chứa các vector ngắt (interrupt vectors). Các vector ngắt nằm ở phần đầu của application section (từ địa chỉ 0x0000) và dài đến bao nhiêu tùy thuộc vào loại chip. Phần chứa instruction nằm liền sau đó, chƣơng trình viết cho chip phải đƣợc load vào phần này. Xem lại phần đầu của ví dụ trong
Vì chức năng chính của bộ nhớ chƣơng trình là chứa instruction, chúng ta không có nhiều cơ hội tác động lên bộ nhớ này khi lập trình cho chip, vì thế đối với ngƣời lập trình AVR, bộ nhớ này “không quá quan trọng”. Tất cả các thanh ghi quan trọng cần khảo sát nằm trong bộ nhớ dữ liệu của chip.
Hình 20.Tổ chức bộ nhớ của AVR.
Bộ nhớ dữ liệu (data memory): Đây là phần chứa các thanh ghi quan trọng nhất của chip, việc lập trình cho chip phần lớn là truy cập bộ nhớ này. Bộ nhớ dữ liệu trên các chip AVR có độ lớn khác nhau tùy theo mỗi chip, tuy nhiên về cơ bản phần bộ nhớ này đƣợc chia thành 5 phần:
40
Phần 1: là phần đầu tiên trong bộ nhớ dữ liệu, nhƣ mô tả trong hình 1, phần này bao gồm 32 thanh ghi có tên gọi là register file (RF), hay General Purpose Rgegister – GPR, hoặc đơn giản là các Thanh ghi. Tất cả các thanh ghi này đều là các thanh ghi 8 bits nhƣ trong hình 2.
Hình 21. Thanh ghi 8 bits
Tất cả các chip trong họ AVR đều bao gồm 32 thanh ghi Register File có địa chỉ tuyệt đối từ 0x0000 đến 0x001F. Mỗi thanh ghi có thể chứa giá trị dƣơng từ 0 đến 255 hoặc các giá trị có dấu từ -128 đến 127 hoặc mã ASCII của một ký tự nào đó…Các thanh ghi này đƣợc đặt tên theo thứ tự là R0 đến R31. Chúng đƣợc chia thành 2 phần, phần 1 bao gồm các thanh ghi từ R0 đến R15 và phần 2 là các thanh ghi R16 đến R31. Các thanh ghi này có các đặc điểm sau:
Đƣợc truy cập trực tiếp trong các instruction.
Các toán tử, phép toán thực hiện trên các thanh ghi này chỉ cần 1 chu kỳ xung clock. Register File đƣợc kết nối trực tiếp với bộ xử lí trung tâm – CPU của chip.
Chúng là nguồn chứa các số hạng trong các phép toán và cũng là đích chứa kết quả trả lại của phép toán.
Để minh họa, hãy xét ví dụ thực hiện phép cộng 2 thanh ghi bằng instruction ADD nhƣ sau:
ADD R1, R2
Ta thấy trong dòng lệnh trên, 2 thanh ghi R1 và R2 đƣợc sử dụng trực tiếp với tên của chúng, dòng lệnh trên khi đƣợc dịch sang opcode để download vào chip sẽ có dạng:
0000110000010010 trong đó 00001=1 tức thanh ghi R1 và 00010 = 2 chỉ thanh ghi R2. Sau phép cộng, kết quả sẽ đƣợc lƣu vào thanh ghi R1.
Tất cả các instruction sử dụng RF làm toán hạng đều có thể truy nhập tất cả các RF một cách trực tiếp trong 1 chu kỳ xung clock, ngoại trừ SBCI, SUBI, CPI, ANDI và LDI, các instruction này chỉ có thể truy nhập các thanh ghi từ R16 đến R31.
Thanh ghi R0 là thanh ghi duy nhất đƣợc sử dụng trong instruction LPM (Load Program Memory). Các thanh ghi R26, R27, R28, R29, R30 và R31 ngoài chức năng thông thƣờng còn đƣợc sử dụng nhƣ các con trỏ (Pointer register) trong một số instruction truy xuất gián tiếp. Chúng ta sẽ khảo sát vấn đề con trỏ sau này. Hình dƣới mô tả các chức năng phụ của các thanh ghi.
41
Hình 22. Register file.
Tóm lại 32 RF của AVR đƣợc xem là 1 phần của CPU, vì thế chúng đƣợc CPU sử dụng trực tiếp và nhanh chóng, để gọi các thanh ghi này, chúng ta không cần gọi địa chỉ mà chỉ cần gọi trực tiếp tên của chúng. RF thƣờng đƣợc sử dụng nhƣ các toán hạng (operand) của các phép toán trong lúc lập trình.
Phần 2: là phần nằm ngay sau register file, phần này bao gồm 64 thanh ghi đƣợc gọi là 64 thanh ghi nhập/xuất (64 I/O register) hay còn gọi là vùng nhớ I/O (I/O Memory). Vùng nhớ I/O là cửa ngõ giao tiếp giữa CPU và thiết bị ngoại vi. Tất cả các thanh ghi điều khiển, trạng thái…của thiết bị ngoại vi đều nằm ở đây. Xem lại ví dụ trong bài 1, trong đó tôi có đề cập về việc điều khiển các PORT của AVR, mỗi PORT liên quan đến 3 thanh ghi DDRx, PORTx và PINx, tất cả 3 thanh ghi này đều nằm trong vùng nhớ I/O. Xa hơn, nếu muốn truy xuất các thiết bị ngoại vi khác nhƣ Timer, chuyển đổi Analog/Digital, giao tiếp
USART…đều thực hiện thông qua việc điều khiển các thanh ghi trong vùng nhớ này.
Vùng nhớ I/O có thể được truy cập như SRAM hay như các thanh ghi I/O. Nếu sử dụng instruction truy xuất SRAM để truy xuất vùng nhớ này thì địa chỉ của chúng được tính từ 0x0020 đến 0x005F. Nhưng nếu truy xuất như các thanh ghi I/O thì địa chỉ của chúng đựơc tính từ 0x0000 đến 0x003F.
Xét ví dụ instruction OUT dùng xuất giá trị ra các thanh ghi I/O, lệnh này sử dụng địa chỉ kiểu thanh ghi, cấu trúc của lệnh nhƣ sau: OUT A, Rr, trong đó A là địa chỉ của thanh ghi trong vùng nhớ I/O, Rr là thanh ghi RF, lệnh OUT xuất giá trị từ thanh ghi Rr ra thanh ghi I/O có địa chỉ là A. Giả sử chúng ta muốn xuất giá trị chứa trong R6 ra thanh ghi điều khiển hƣớng của PORTD, tức thanh ghi DDRD, địa chỉ tính theo vùng I/O của thanh ghi DDRD là 0x0011, nhƣ thế câu lệnh của chúng ta sẽ có dạng: OUT 0x0011, R6. Tuy nhiên trong 1 trƣờng hợp khác, nếu muốn truy xuất DDRD theo dạng SRAM, ví dụ lệnh STS hay LDS, thì phải dùng địa chỉ tuyệt đối của thanh ghi này, tức giá trị 0x0031, khi đó lệnh OUT ở trên đƣợc viết lại là STS 0x0031, R6.
42
Để thống nhất cách sử dụng từ ngữ, từ bây giờ chúng ta dùng khái niệm “địa chỉ I/O” cho các thanh ghi trong vùng nhớ I/O để nói đến địa chỉ không tính phần Register File, khái niệm “địa chỉ bộ nhớ” của thanh ghi là chỉ địa chỉ tuyệt đối của chúng trong SRAM. Ví dụ thanh ghi DDRD có “địa chỉ I/O” là 0x0011 và “địa chỉ bộ nhớ” của nó là 0x0031, “địa chỉ bộ nhớ” = “địa chỉ I/O” + 0x0020.
Vì các thanh ghi trong vùng I/O không đƣợc hiểu theo tên gọi nhƣ các Register file, khi lập trình cho các thanh ghi này, ngƣời lập trình cần nhớ địa chỉ của từng thanh ghi, đây là việc tƣơng đối khó khăn. Tuy nhiên, trong hầu hết các phần mềm lập trình cho AVR, địa chỉ của tất cả các thanh ghi trong vùng I/O đều đƣợc định nghĩa trƣớc trong 1 file Definition, bạn chỉ cần đính kèm file này vào chƣơng trình của bạn là có thể truy xuất các thanh ghi với tên gọi của chúng. Giả sử trong ví dụ ở bài 1, để lập trình cho chip Atmega8 bằng
AVRStudio, dòng thứ 2 chúng ta sử dụng INCLUDE "M8DEF.INC" để load file định nghĩa cho chip ATMega8, file M8DEF.INC. Vì vậy, trong sau này khi muốn sử dụng thanh ghi DDRD bạn chỉ cần gọi tên của chúng, nhƣ: OUT DDRD,R6.
Phần 3: RAM tĩnh, nội (internal SRAM), là vùng không gian cho chứa các biến (tạm thời hoặc toàn cục) trong lúc thực thi chƣơng trình, vùng này tƣơng tự các thanh RAM trong máy tính nhƣng có dung lƣợng khá nhỏ (khoảng vài KB, tùy thuộc vào loại chip).
Phần 4: RAM ngoại (external SRAM), các chip AVR cho phép ngƣời sử dụng gắn thêm các bộ nhớ ngoài để chứa biến, vùng này thực chất chỉ tồn tại khi nào ngƣời sử dụng gắn thêm bộ nhớ ngoài vào chip.
Phần 5: EEPROM (Electrically Ereasable Programmable ROM) là một phần quan trọng của các chip AVR mới, vì là ROM nên bộ nhớ này không bị xóa ngay cả khi không cung cấp nguồn nuôi cho chip, rất thích hợp cho các ứng dụng lƣu trữ dữ liệu. Nhƣ trong hình 1, phần bộ nhớ EEPROM đƣợc tách riêng và có địa chỉ tính từ 0x0000.
Hình dƣới biểu diễn cấu trong bên trong của 1 AVR. Ta thấy rằng 32 thanh ghi trong Register File đƣợc kết nối trực tiếp với Arithmetic Logic Unit -ALU (ALU cũng đƣợc xem là CPU của AVR) bằng 2 line, vì thế ALU có thể truy xuất trực tiếp cùng lúc 2 thanh ghi RF chỉ trong 1 chu kỳ xung clock (vùng đƣợc khoanh tròn màu đỏ trong hình dƣới).
43
Hình 23. Cấu trúc bên trong AVR.
Các instruction đƣợc chứa trong bộ nhớ chƣơng trình Flash memory dƣới dạng các thanh ghi 16 bit. Bộ nhớ chƣơng trình đƣợc truy cập trong mỗi chu kỳ xung clock và 1 instruction chứa trong program memory sẽ đƣợc load vào trong instruction register, instruction register tác động và lựa chọn register file cũng nhƣ RAM cho ALU thực thi. Trong lúc thực thi chƣơng trình, địa chỉ của dòng lệnh đang thực thi đƣợc quyết định bởi một bộ đếm chƣơng trình – PC (Program counter). Đó chính là cách thức hoạt động của AVR.
AVR có ƣu điểm là hầu hết các instruction đều đƣợc thực thi trong 1 chu kỳ xung clock, vì vậy có thể nguồn clock lớn nhất cho AVR có thể nhỏ hơn 1 số vi điều khiển khác nhƣ PIC nhƣng thời gian thực thi vẫn nhanh hơn.