AVR CPU Core 學習筆記
AVR CPU Core
AVR 的核心處理器為了獲得最大的效能和並行處理,因此採用哈佛架構(Harvard architecture) 的設計,哈佛架構的程式指令儲存空間和資料儲存空間是分開的,程式指令儲存和資料儲存可以並行處理 。在程式指令的架構的指行階段有配置一階的 Pipeline,當指令執行時,同時可以去提取(Fetched)下個的指令碼,一般程式執行需要三階段(Fetch,Decode,Execute) 也就是三個時脈時間,加入 Pipeline 後,每個程式指令還是需要三個時脈的流程,但是在執行階段,每個時脈都會有一個指令被執行,等同於每個指令只需要一個時脈。程式碼就儲存在晶片內部的可以重覆程式化的記憶體空間 (Flash)。
快速儲存的區塊包含了 32 個 8-bit 的工作暫存器,資料儲存只需要一個時脈時間。Arithmetic Logic Unit (ALU) 接收兩個暫存器的輸出,經過處理後,再寫回目的暫存器也只需要一個時脈時間。在 32 個 8-bit 的工作暫存器,其中有 6 個 8 位元的暫存器可以將兩個暫存器的值,組成一個 16-bit 的位址來儲存記憶體的空間。這三個組成 16-bit 位址的暫存器,其中有一個是用來儲存重覆程式化的記憶體空間 (Flash)。
ALU可以做算術運算和邏輯運算。運算輸入可以都是暫存器或者是暫存器和常數的運算,狀態暫存器內的旗標會依據運算結果變更旗標的值。
在程式流程的控制方式包含有條件和無條件的跳越及呼叫副程序的指令,這些指令都可以存取 16-bit 的位址空間。
在程式指令方面,大部分的 AVR 指令長度是 16-bit 的,但是也有 32-bit 長度的。有部分的晶片僅只支援部分的指令集而已。
中斷服務程式及副程序的呼叫的返迴位址 (Program Counter“PC”) 都儲存在堆疊(Stack) 裡面。堆疊位於靜態記憶體 (SRAM) 裡面的一塊連續空間,堆疊空間大小的限制在於靜態記憶體的大小和靜態記憶體的使用情況。堆疊的大小,起始位址都在程式碼的一開端就要規畫完成(切記一定要在呼叫任何副程式或中斷之前,因為它們會使用到堆疊的空間)。堆疊指標 (Stack Pointer “SP”) 位放I/O的記憶體空間,用來指示堆疊空間的使用情況。AVR 提供了五種方法來存取靜態記憶體空間,AVR 記憶體空間都是線性和定期更動記憶體的配置情形。
中斷模組由控制暫存器位於 I/O 空間,和狀態暫存器的 Global Interrupt Enable 位元來開關中斷。許有的中斷在中斷向量表(Interrupt Vector table) 上都有一個自己的中斷向量(Interrupt Vector),中斷向量的位址愈小,中斷的權限也相對比較高。
在 I/O 記憶體空間中,有 64 個位址分配給 CPU 的週邊的控制暫存器,SPI和其他的 I/O 功能。I/O 記憶體空間可以直接存取或者透過資料空間的暫存器 0x20 到 0x5F。
另外,ATtiny48/88 使用額外到 I/O 記憶體空間位於靜態記憶體的 0x60 到 0xFF,只有 ST/STS/STD 和 LD/LDS/LDD 的程式指令才能使用到這些空間。
ALU - Arithmetic Logic Unit
AVR 高效率的算術邏輯單元的輸入/輸出端都和 32 個工作暫存器連結,因此,只需要一個時脈的時間,算術邏輯單元就可以完成一次暫存器對暫存器的運算或者暫存器和立即值的運算。算術邏輯單元可以分成三個部分,包含算術,邏輯和位元運算,有一部分的架構是提供功能強大的乘法運算,可以做有符號數格式/無符號數格式及分數格式。
Status Register
狀態暫存器是一群旗標的集合,它紀錄了最近一次算術指令的運算結果,運算結果可以提供程式流程的控制。整個順序由 ALU 做算術運算,算術運算的結果變動狀態暫存器的值,程式流程的指令參考狀態暫存器的值,決定程式的流程。有些使用比較指令來控制程式流程的情形,有很多情形可以使用算術邏輯運算再參考狀態暫存器旗標來取代,不但執行速度會更快,程式碼也能更為嚴謹。
需要注意的事,狀態暫存器被不會自動儲存,在進入中斷服務程式前也不會被備份在堆疊,所以離開中斷服務程式沒有狀態暫存器的資料。如果程式設計者會在中斷服務程式期間使用到狀態旗標,需先備份到記憶體。
General Purpose Register
一般用暫存器 (R0 - R31) 是經過最佳化設計用於 AVR 的增強型精簡指令(Enhanced RISC) ,為了提升它的效能和方便各種狀況的運用,運算元輸入位元和輸出位元可分為四種情況:
- 一個 8 位元的運算元輸入和一個 8 位元的運算元輸出
- 一個 8 位元的運算元輸入和二個 8 位元( 16 位元)的運算元輸出
- 一個 16 位元的運算元輸入和二個 8 位元( 16 位元)的運算元輸出
- 一個 16 位元的運算元輸入和一個 16 位元的運算元輸出
Address
|
Register
|
Special Function
|
0x00
|
R0
| |
0x01
|
R1
| |
0x02
|
R2
| |
0x03
|
R3
| |
...
| ||
0x1A
|
R26
|
XL b[7:0]
|
0x1B
|
R27
|
XH b[15:8]
|
0x1C
|
R28
|
YL b[7:0]
|
0x1D
|
R29
|
YH b[15:8]
|
0x1E
|
R30
|
ZL b[7:0]
|
0x1F
|
R31
|
ZH b[15:8]
|
Stack Pointer
堆疊器的功能是在程式進入中斷服務程式或者副程式呼叫前,用來暫時儲存資料,變數和迴返位址。堆疊指標 (SPH:SPL) 用來告知堆疊使用的情形,永遠指向下一筆資料儲存的地方。堆疊器儲存資料的方向是由高位址往低位址儲存。也就是說,使用 PUSH 指令把資料存入堆疊區時,堆疊指標的值會減少。使用 POP 指令由堆疊區取出資料時,堆疊指標的值會增加。
堆疊指標是指向記憶體的某一塊區域(堆疊器),也是中斷服務程式和副程式所使用的堆疊。堆疊在記憶體內的空間宣告必須在程式呼叫副程式或中斷功能開啟之前。
當程式使用PUSH指令把一個資料存入堆疊區時,堆疊指標就會減一;當程式使用POP指令由堆疊區把一個資料取出時,堆疊指標就會加一。當主程式要進入中斷服務程或者呼叫副程式前,會先將返迴位址存入堆疊區時,因為返迴位址是 16 bits,所以堆疊指標就會減 二,再進入中斷服務程式或者副程式;當中斷服務程式或者副程式執行完成,副程式使用 RET 指令,中斷服務程式使用RETI,返迴主程式,會從堆疊區把返迴位址取出時,堆疊指標就會加二,再跳回主程式。
AVR 的堆疊指標一般是由兩個 8 bit 的暫存器(SPH/SPL),裝置會依據設計需要去製訂堆疊指標的寬度和位元數,有些 AVR 的裝置只有 256 Bytes 的記憶體,所以只需要有 SPL 就可以存取整個記憶體,並不需要 SPH。
堆疊指標必須設計在 I/O 暫存器的上面,堆疊指標最小的值必須為 SRAM 的最低的位址。
Instruction Execution Timing
一般指令執行所需的時間,是指CPU讀取指令開始,到指令被執行結束,所需要的時脈數量。AVR CPU 的工作時脈是直接來自晶片內部的時脈來源,沒有經過內部除頻器,有了時脈數量和工作時脈就能算出指令執行的時間。
如上圖,採用 Harvard architecture 和快速存取暫存器方法,在取得下個指令的同時,上個指令也會被執行在同一個工作時脈裡。這是因為使用 Pipeline 才有辦法在取得指令同時執行指令,因此指令執行時間為 2 個工作時脈。
如上圖,假如 CPU 的執行速度為 1MHz,CPU 每個工作時脈都會執行一個指令,CPU 執行一個指令所花的時間為 1 / 1M = 1μ sec,所以一秒可以執行 1 sec / 1μ sec = 1M 個指令,也就是 1MIPS (Millions of Instructions Per Second)。 因此假設 CPU 的頻率為 4MHz 的話,效能變成 4MIPS 了。通常會使 MIPS 來判斷 CPU 的效能,進而評估需要多少費用,多快的工作時脈和多少功率來完成功能。
上圖顯示內部暫存器和 ALU 做運算所需要的時間,只需要一個工作時脈,ALU 的運算元就可以從兩個來源暫存器取出運算值,經過 ALU 運算,再把結果存入目的暫存器。
Reset and Interrupt Handling
AVR 可以接收很多不同的中斷來源,這些中斷來源和每個Reset Vector 在中斷向量的記憶體空間都有一個可程式化的中斷向量。所有的中斷都會有一個位元來開關中斷功能,還有一個總開關在狀態暫存器的 Global Interrupt Enable 來開啟中斷功能。 因此需要開啟總開關和相對的位元開關才能開啟中斷。
在軟體機密功能中,LB1 或 LB2 會進入 proclk grammed,程式會依據程式碼位址( Program Counter ”PC”) 自動開關中斷功能。
在程式記憶體空間最低的位址,預計是儲存 Reset 和中斷向量的服務程式。每個中斷都有不同的優先等級,中斷向量值愈小的中斷,優先等級會比較高。
中斷信號處理的流程如下:
- 當中斷信號發生,Global Interrupt Enable I-bit 會被關閉(clear)而且所有的中斷也會被關閉(disable)。使用者程式仍可以去修改 I-bit 的值去開啟中斷。
- 主程式儲存返迴位址,進入中斷服務程式執行。執行完成後,使用 RETI 返迴主程式。
- 在執行 RETI 的指令時,Global Interrupt Enable I-bit 會自動被開啟(set)
中斷信號可以分成二個種類:
- 中斷事件觸發,中斷旗標也會被設定。主程式會依中斷向量值,進入正確的中斷向量執行中斷服務程式,硬體會主動清除對映的中斷旗標。
接著分析兩種情形 -
- 如果中斷事件發生時,對映的中斷開關是關閉的,中斷旗標將會被設起來,並且紀錄直到對映的中斷開關開啟,或者中斷旗標被程式所清除。
- 如果多個中斷事件發生時,總開關是關閉的,相對映的中斷旗標會被設起來,並且紀錄直到中斷總開關被開啟,再依據優先順序執行。
- 中斷觸發條件發生就啟動中斷,直到中斷條件消失。不需要中斷旗標,如果中斷消失在中斷開啟之前,因為沒有任何旗標紀錄,所以中斷會被乎略。
在 AVR 完成中斷服務程式之後,返迴主程式之後,如果當時還存有其他的中斷並未處理的話,AVR 仍會先執行幾個指令之後,再進入未處理的中斷服務程式。進入或離開中斷服務程式,並不會備份或回復狀態暫存器的值,所以程式設計者需要自行處理。
當程式使用 CLI 指令去關閉中斷功能時,中斷功能會立即被關閉。在 CLI 指令之後或者同時發生的中斷觸發都不會被執行。
<範例> 在填寫 EEPROM 值前,先關閉所有中斷觸發
當程式要恢復中斷功能時,使用 SEI 指令,未處理的中斷觸發信號會依優先順序處理。
<範例> 啟動中斷功能
Interrupt Response Time
AVR 中斷開啟的中斷執行反應時間至少需要 4 個工作時脈的時間,4 個工作時脈之後,中斷才能正確的在中斷向量的中斷服務程式執行,在這 4 個工作時脈週期,Program Count “PC”會儲存在堆疊裡。
一般由中斷向量進入中斷服務程式是需要 3 個工作時脈,如果中斷是發生在連續性指令之前,會等連續性指令完成,才會處理中斷事件。如果中斷是發生在 睡眠模式,需要先喚醒 CPU,所以中斷執行反應時間需要再加 4 個工作時脈週期。
由中斷服務程式返迴的工作需要 4 個工作時脈,在這 4 個工作時脈的期間,Program Counter 的值會由堆疊中 POP 出來,堆疊指標需要加 2 (16-bits 的位址) 而且 SREG 的 I-bit 會被設起來。
Register Description
SPH/SPL - Stack Pointer Register
- Bits 9:0 – SP[10:0]: Stack Pointer
堆疊指標會指向堆疊內部資料的最頂端,資料的儲放由高位址記憶體空間往低位址的記憶體空間存放。PUSH 指令會減少堆疊指標的值。
堆疊空間位於資料的 SRAM,必須在中斷功能開啟前或者呼叫任何副程式之前要設置完成。
SREG – Status Register
- Bit 7 – I: Global Interrupt Enable
所有中斷功能的總開關,如果 I-bit 設為High,中斷功能由各對映的控制位元決定,如果 I-bit 設為Low,所有中斷都是關閉的和對映的控制位元無關。中斷發生後,I-bit 就會被硬體自動清為 Low,當 RETI 指令執行時,I-bit 就會自動被設為 High。程式也可以使用 SEI 指令把 I-bit 設為High 和使用 CLI 指令把 I-bit 設為Low。
- Bit 6 – T: Bit Copy Storage
用來支援位元拷貝指令 BLD (Bit LoaD) 和 BST (Bit STore)。
BST 就是把暫存器的某一個位元愎製到這個 T 位元;BLD 正好相反,把這個 T 位元的值複製到暫存器的某一個位元。
- Bit 5 – H: Half Carry Flag
The Half Carry Flag H indicates a Half Carry in some arithmetic operations.
- Bit 4 – S: Sign Bit, S = N ⊕ V
The S-bit is always an exclusive or between the Negative Flag N and the Two’s Complement Overflow Flag V.
- Bit 3 – V: Two’s Complement Overflow Flag
The Two’s Complement Overflow Flag V supports two’s complement arithmetics.
- Bit 2 – N: Negative Flag
The Negative Flag N indicates a negative result in an arithmetic or logic operation.
- Bit 1 – Z: Zero Flag
The Zero Flag Z indicates a zero result in an arithmetic or logic operation.
- Bit 0 – C: Carry Flag
The Carry Flag C indicates a carry in an arithmetic or logic operation.
留言
張貼留言