Arduino / ATmega 328P fuse setting
透過 fuse setting 你可以設定以下功能
- 選擇不同的時脈來源和決定晶片時脈速度
- 在晶片開始運作之前設置最小電壓水平
- 決定是否使用bootloader
- 配置多少記憶體給bootloader
- disable reset
- disable serial programming
- 在上傳新的 sketch 時停止 eeprom數據被刪除
總共分成3個bytes
- low byte fuse
- high byte fuse
- extended fuse
ps.還有第四個byte用來lock bit,在此不討論。
fuse bit表示方式為二進位,數值1代表 not set / not programmed,數值0代表 set / programmed。當有一個byte表示成
B11111111時也可表示成 0xFF。
ATmega 328P 28PDIP diagram
LOW BYTE Fuses
主要用來處理時脈來源、決定晶片時脈速度、等待多久時間去start-up。
ATmega 晶片可運作在不同頻率下,時脈來源可以透過 CKSEL fuse bit 設定。
CKSEL (Clock Sources / Clock Selection)
時脈訊號可以透過內部的振盪器(oscillator)、外部的 crystal / resonator,Arduino 使用外部的16Mhz的 crystal 。
以上是16MHz的 crystal 被用來連接麵包板上的ATmega處理器,連接到 XTAL1 跟 XTAL2 腳位,要告訴處理去使用外部 crystal 時,要去設定 CKSEL fuse bits,最常犯的錯誤就是忘記去設定 fuse bits ,告訴處理器去使用。
下列是對於 CKSEL 設定
Arduino 使用 "Low Power Crystal Oscillator" 選項,ATmega 內建兩個振盪器(oscillator),128kHz RC oscillator 跟 calibrated RC oscillator。"EXternal Clock" 選項,允許晶片使用外部方波時脈訊號,當電路上有自己本身的時脈訊號時,你想要去同步ATmega,或你想要使用單獨的時脈晶片時,都可以使用此選項,External clock 訊號必須連接到時脈接腳。
Crystal Oscillator Options
CKSEL[3:0] = 1111 ,代表選擇8.0Mhz ~ 16.0Mhz的crystal,為arduino 的 normal setting。假如你想要使用比較慢的 crystal 時,假設時脈為6MHz,則設定 CKSEL[3:0] = 1101。假如要使用內部的 RC oscillator 8MHz時,則設定 CKSEL[3:0] = 0010。
SUT1 / SUT0 (Start Up Time)
Crystals 跟 Oscillators 都需要足夠的工作電壓去運作正常,當電壓水平到最大值時需要一點時間,當電壓提升時,時脈可能沒辦法運作在正常速度,為了保持時脈可以運作在正常速度,可以設定 Start Up Time 去避免。
CKSEL0 根據 SUT1 / SUT0 的結果去設置。
BOD 為 Brown Out Detection, 我們稍後在討論。
arduino 使用了最大 startup delay of 14CK + 65ms (CKSEL0 = 1, SUT1 = 1, SUT0 = 1),這也是 ATmega 328 / 328P 晶片的預設值。
CKDIV8 (Clock Devide)
ATmega 328 / 328P 晶片有內建的 RC oscillator @ 8.0MHz ,新的晶片出廠時,CKDIV8已經被設置為0(programmed)了,所以時脈從 8MHz 變成了 1MHz。(CKSEL = 0010, SUT = 10, CKDIV8 = 0)此設定使得所有的使用者可以使用任何的 programming interface進行所需的時脈設置。
當時脈超出ATmega 晶片的最大值時,CKDIV8 應該被使用。
ATmega 晶片可以工作在非常低的電壓環境下,當在低電壓環境時,也需要較低的時脈,使用CKDIV8可以讓時脈變低,正常工作在低電壓環境。
CKOUT (Clock Output)
時脈訊號可以從PB0腳位輸出,當你需要時脈訊號去驅動其他電路時,你可以設置此數值為0(programmed),出廠預設值為1(not programmed)。
High Byte Fuses
有關於 watchdog timer、eeprom 操作以及 bootloader 相關設定。
RSTDISBL (External reset disable)
腳位PC6 是 reset pin,保持低電位,晶片將執行 rest 指令,在 arduino 上,當你按壓開關後,實際上PC6會被接地,然後 reset 晶片。
腳位PC6 也可以被當作一般IO使用,如果當作一般IO使用後,代表 reset 功能不能被使用,而 inline programming 需要 reset ,則導致不能再對晶片 inline programming了。
RSTDISBL 是基於安全措施所實施的功能,用來停止重新編程晶片。
當 RSTDISBL 被 programmed(被設定成0)時,Startup time(SUT1 SUT0)會被設定成14CK + 4.1ms 以確保可以進入programming 模式。
RSTDISBL 預設值為 not programmed。
DWEN (debugWire enable)
ATmega 晶片有內建的 debugging tools ,預設值為關閉。DWEN fuse 被使用來使用此工具。
DWEN使用跟 reset 一樣的腳位(PC6),當DWEN 被啟用後(lock bits not set),reset 腳位會變成 communication 腳位,正常的 reset功能則不能再使用,舉個例子,當你啟用 DWEN 在 arduino上,reset 功能則不能被使用了。
為了去使用 on-chip debugging 你需要可相容的 programmer,像是AVR Dragon。更多相關資訊:http://www.hilltop-cottage.info/blogs/adam/debugging-arduino-using-debugwire-atmel-studio-and-an-avr-dragon/
假如你啟用了 DWEN 但也啟用 lock bits 你不能再以正常方式燒錄晶片了。
如果你只是初學者,就把他設定成 not set,甚麼都不用管,畢竟 reset 還是非常有用的。
SPIEN (Enable Serial programming and Data Downloading)
ATmega 晶片可以透過使用 serial programming 去 programmed。 Serial programming 被使用在 board programming 透過 serial protocol 藉由 ISP(inline serial programmer) 或 UART。
正常方法去 programming ATmega 晶片 是透過藉由 SPI 介面使用 SCK(clock)、MOSI(input)、MISO(output)腳位。假如你停用 serial programming 你將不能再使用 SPI 介面去 program,你也可以透過 lock bits 去停用 serial programming。
為了去正常使用,就把 SPIEN 設定成啟用就行,除非你的裝置已無需再 programming 的時候,你可以停用此功能,防止有人從 serial communication 存取你的裝置。
SPIEN 預設為0(programmed)。
RSTDISBL、SPIEN、DWEN fuses 都有可能會造成 ATmega 晶片鎖死,很難再度去使用此晶片。對於一般用途,如果你是剛開始 programming 此晶片,你更不應該更改這些 fuse setting,你也應該檢查這些 fuse setting 有沒有被更改過。
WDTON( Watchdog Timer Always on)
- watchdog 基本上是一個 timer ,當它沒有接收到 ok 訊號時,它會 reset 晶片。
- 當你寫了一個不穩定的 code 或者系統可能沒有被允許永久鎖死時,它非常的有用。
- 當 watchdog 啟用時,有個 sketch 導致崩潰或凍結,使得 watchdog 計時結束還沒有收到 ok 訊號時,它會 reset 晶片,就像arduino上的 reset 按鈕功能差不多。
watchdog timer 可以透過軟體啟用,所以 fuse setting 不怎麼需要被使用,預設值為1(not programmed)。
這裡有個迷你教學關於watchdog timer:https://forum.arduino.cc/index.php?topic=63651.0
EESAVE (Preserve EEPROM memory)
- 當ATmega 晶片被 programming 的時候,eeprom memory 會在新的 code 上傳前,被抹除之前的儲存的資訊,EESAVE fuse 可以被用來告訴晶片不要抹除,當你想要更新你的 code 但是也想保留留在eeprom上的使用者的設定,這非常有用。
- EESAVE預設值為1(not programmed),當 programming 時,eeprom memory會被抹除。
- 當你有使用到eeprom儲存資料時,當programming時,記得設置此fuse以保存資料。
BOOTSZ1 & BOOTSZ0 (Boot loader Size)
- ATmega 晶片可以使用bootloader,當晶片啟動或 reset 時,它是第一個被執行的小型程式,它通常被用來初始化裝置跟檢查外部通訊。arduino 使用bootloader 去跟電腦通訊,並檢查是否有新 code 要被上傳,那也就是為什麼arduino要在你上傳新的 code時,reset 晶片,透過 reset 此動作,它會再次執行 bootloader 檢查是否有新 code 要上傳。
- bootloader 儲存在 program memory(flash),bootloader 因為有不同 size,而可以告訴晶片有多少空間我需要儲存。較舊的 arduino bootloader 需要2KB,但是新的 Optiboot (used on the UNO)只需要0.5KB,但如果需要更大的 program memory 的話,可以把 bootloader給刪掉,騰出更多 program memory(flash)。
- bootloader 被儲存在 program memory(flash) 的頂端。
- 假如你有一個 bootloader ,那麼 BOOTSZ 跟 BOOTRST 必須一起結合使用,BOOTRST 告訴 晶片 bootloader 的記憶體位址,如果 BOOTRST 沒有設置時,不論 BOOTSZ 的設定如何,uer application 都可以使用整個 program memory。
- Boot Size Configuration for the 328 / 328P
注意以上的 Boot Size 單位為 words,而一個 words 等同於兩個 bytes,所以 256 words 就是 512 bytes 。
- BOOTSZ1 跟 BOOTSZ0 的預設值都是0,也就是說有 4KB 的空間保留給 bootloader。
BOOTRST (Select reset vector)
- ATmega 晶片可以使用 bootloader ,它就像是小型程式,當晶片 reset 時,它是第一支被執行的程式,假如你有使用 bootloader的話,你必須要設置此 BOOTRST ,當 BOOTRST 被設置時,假如晶片被 reset 時,它會跳到 bootloader 的記憶體位址,開始運行 bootloader ,假如沒有設置,則晶片 reset 後,會直接從記憶體位址為0x0000開始執行。
- BOOTRST 的預設值為1(not programmed)。
- 假如 BOOTRST 沒有被設置時,則可以忽略 BOOTSZ 的 fuse setting。
Extended Fuse Bits
- extended fuse 只有被用來設定 brown-out detection level (BOD)。
當電壓不足時,ATmega 晶片會很不穩聽,舉例來說,328 / 328P 可以運行在 16MHz ,但條件是電壓水平至少需要 4V,只要電壓不足 4V,晶片都可能會不穩定,當你的裝置被用來連接感測器去測量或需要準確時間時,這將會產生很大的問題。
為了確保晶片運行在最小電壓水平之上,假設晶片上的電壓下降到最小電壓水平以下時,晶片將會自己 reset,這種方式稱為 brown-out detector,基本上,只要供應電壓低於 BOD 所設定的電壓,晶片將會一直把 reset 設定為低電位(保持 reset )。
- BODLEVEL[2:0]預設值為111,代表為 BOD disabled。
Default Fuse Settings
New ATmega 328P Chip 設定如下
Low fuse = 0x62 (B01100010)
High fuse = 0xD9 (B11011001)
Extended fuse = 0XFF (B11111111)
Arduino Duemilanove or Nano w/ ATmega328 Default Fuse Settings
Low fuse = 0xFF (B11111111)
High fuse = 0xDA (B11011110)
Extended fuse = 0x05 (B00000101)
Optiboot Boot Loader
假如你使用 Optiboot bootloader的話,要把 BOOTSZ1 跟 BOOTSZ0 都設置成1,使得bootloader size 為256個 words(512bytes),差別在使用的 bootloader 比較小。
如果你想要看 arduino 所有開發板的預設 fuse settings,請參照:http://www.codingwithcody.com/2011/06/25/arduino-default-fuse-settings/
Lock Bits
- lock bits 用來限制記憶體的存取, boot section 跟 application 都有他們自己的 lock bits。
- 當你啟用 lock bits 時,有可能會把晶片給鎖死(brick),所以最好不要更改。