Successfully reported this slideshow.

Arduino 底層原始碼解析心得

353

Share

Loading in …3
×
1 of 564
1 of 564

Arduino 底層原始碼解析心得

353

Share

Download to read offline

投影片講解視訊影片網址:
http://www.youtube.com/playlist?list=PLFL0ylDooClTXfy-cFbq7rV1iwP57JFaF

This slide is made by the RoBoard team of DMP Electronics Inc.:
https://www.facebook.com/roboard.fans

投影片講解視訊影片網址:
http://www.youtube.com/playlist?list=PLFL0ylDooClTXfy-cFbq7rV1iwP57JFaF

This slide is made by the RoBoard team of DMP Electronics Inc.:
https://www.facebook.com/roboard.fans

More Related Content

Related Books

Free with a 30 day trial from Scribd

See all

Arduino 底層原始碼解析心得

  1. 1. Arduino 原始碼讀書會 (I) : Overview
  2. 2. 簡單複習 Arduino
  3. 3. Arduino 硬體配置
  4. 4. 開啟 .ino 程式檔 Arduino IDE 的使用
  5. 5. 編輯程式
  6. 6. 編譯
  7. 7. 燒錄到 Arduino 上執行
  8. 8. 複習完畢! 收工…(毆)
  9. 9. 進入 Arduino 原始碼的世界
  10. 10. Q: Arduino 0023、1.0.5、1.5.2 原始碼, 要 推倒哪一個? A: 我們將以 Arduino 1.0.5 為主要推倒對 象
  11. 11. 原始碼住哪裡? https://github.com/arduino/Arduino
  12. 12. 原始碼目錄介紹 改過的 Processing IDE 原始碼 (Arduino 相關) Processing IDE 原始碼 存放編譯結果的目錄 Arduino Bootloader, Standard API 原始碼 Arduino Library 原始碼
  13. 13. app → src → processing → app → debug 處理 Arduino 韌體燒錄動作 處理 Arduino 韌體燒錄動作 處理 .ino 編譯動作 今天不談這裡
  14. 14. hardware → arduino 各種版本 bootloader 原始碼 Standard API 原始碼(共用部分) 各種周邊配套的處理器韌體 Standard API 不共用部分 定義 Board 選單及編譯參數 定義 Programmers 選單及燒錄參數 今天只談它
  15. 15. 如何編譯 Arduino 原始碼? http://code.google.com/p/arduino/wiki/BuildingArduino
  16. 16. Windows 下編譯 Arduino 原始碼 下載 JAVA JDK 並完成安裝 下載 cygwin並完成安裝 ◦Linux-like environment for Windows ◦安裝 cygwin 過程中, 選擇安裝下列套件 git make, gcc-mingw, and g++ perl unzip, zip
  17. 17. Windows 下編譯 Arduino 原始碼 下載 Apache Ant 程式 ◦JAVA base 編譯器 設定 Apache Ant 和 JAVA JDK 的環境變 數 執行 cygwin, 使用 git 指令下載 Arduino 最新原始碼
  18. 18. Windows 下編譯 Arduino 原始碼 使用指令 ant/ant run 開始編譯 Arduino 原始碼
  19. 19. Windows 下編譯 Arduino 原始碼 編譯完成的結果會存放在 (DIR) buildwindowswork 資料夾內
  20. 20. Linux、Mac 下編譯 Arduino 原始碼 Orz… 目前還沒時間試… (哭~~~)
  21. 21. .ino 程式的編譯原理概觀
  22. 22. .ino: 偽裝過的 C++ 一切都是幻覺, 嚇不倒我滴!! ◦Arduino 會先將 .ino 檔轉換為 .cpp 檔再進 行編譯 ◦可在 .ino 檔中使用 C++ 語法 (但不能使用 C++ standard library 內的某些物件或函式, 例如: cout, cin) ◦可使用 avr-gcc 的所有語法
  23. 23. IDE 會將 .ino 轉換成 .cpp 加入 include ” Arduino.h” 加入所有.ino 內函式的原型宣告 加入編譯指示詞#line, 重新定義與原始.ino 檔一致的 行號
  24. 24. .ino 的編譯流程概觀 Arduino IDE 會先建立一個暫存目錄 把 .ino 轉成 .cpp, 複製到暫存目錄下並 進行編譯 掃描並編譯 .ino 所 include 到的每個 library, 編譯結果輸出到暫存目錄下 所有編譯結果連結成一個 .hex 的韌體 燒錄檔 若編譯過程出錯, 會直接停止編譯並 show 出錯誤訊息
  25. 25. 進入 Arduino Standard API (樓還沒歪…無誤)
  26. 26. Standard API 概觀 Digital I/O ◦pinMode( ) ◦degitalWrite( ) ◦degitalRead( ) Analog I/O ◦analogReference() ◦analogRead() ◦analogWrite()
  27. 27. Standard API 概觀 Advanced I/O ◦tone ( ) ◦noTone ( ) ◦shiftOut( ) ◦shiftIn( ) ◦pulseln( )
  28. 28. Standard API 概觀 時間函式 ◦millis( ) ◦micros( ) ◦delay( ) ◦delayMicroseconds( )
  29. 29. Standard API 概觀 基本數學函式 ◦min( ) ◦max( ) ◦abs( ) ◦constrain( ) ◦map( ) ◦pow( ) ◦sqrt( )
  30. 30. Standard API 概觀 三角函式 ◦sin( ) ◦cos( ) ◦tan( ) 隨機數函式 ◦randomSeed( ) ◦random( )
  31. 31. Standard API 概觀 位元操作 ◦lowByte( ) ◦highByte( ) ◦bitRead( ) ◦bitWrite( ) ◦bitSet( ) ◦bitClear( ) ◦bit( )
  32. 32. Standard API 概觀 中斷相關函式 ◦attachInterrupt( ) ◦detachInterrupt( ) ◦Interrupts( ) ◦noInterrupts( )
  33. 33. Standard API 概觀 串列通訊 ◦serial.begin( ) ◦serial.available( ) ◦serial.read( ) ◦serial.write( )
  34. 34. 從進入的觀點看 Standard API 接著重新用嘿客的眼光來分類 Standard API 直接來自 C/C++ standard library 的函式 ◦pow( ) ◦sqrt( ) ◦sin( ) ◦cos( ) ◦tan( )
  35. 35. 從進入的觀點看 Standard API 直接使用 C 語言巨集定義的函式 ◦min( ) ◦max( ) ◦constrain( ) ◦abs( ) Arduino.h
  36. 36. 從進入的觀點看 Standard API 直接使用 C 語言巨集定義的函式 ◦lowByte( ) ◦highByte( ) ◦bitRead( ) ◦bitWrite( ) ◦bitSet( ) ◦bitClear( ) ◦bit( ) Arduino.h
  37. 37. 從進入的觀點看 Standard API 平台獨立函式 ◦randomSeed( ) ◦random( ) ◦map( ) WMath.cpp
  38. 38. 從進入的觀點看 Standard API 硬體相關函式 ◦pinMode( ) ◦degitalWrite( ) ◦degitalRead( ) ◦analogReference() ◦analogRead() ◦analogWrite() ◦tone ( ) ◦noTone ( )
  39. 39. 從進入的觀點看 Standard API 硬體相關函式 ◦shiftOut( ) ◦shiftIn( ) ◦pulseln( ) ◦millis( ) ◦micros( ) ◦delay( ) ◦delayMicroseconds( )
  40. 40. 從進入的觀點看 Standard API 硬體相關函式 ◦attachInterrupt( ) ◦detachInterrupt( ) ◦Interrupts( ) ◦noInterrupts( ) ◦serial.begin( ) ◦serial.available( ) ◦serial.read( ) ◦serial.write( )
  41. 41. 硬體相關函式實作解析 pinMode (pin, mode) ◦函式功能: 設定腳位為輸出或輸入模式 ◦函式實作內容: 1. 由指定的 pin 編號來取得對應的 port 2. 由 port 找到對應的暫存器 3. 依照輸入的 mode, 修改暫存器設定
  42. 42. wiring_digital.c
  43. 43. 硬體相關函式實作解析 digitalWrite (pin, value) ◦函式功能: 設定腳位輸出電位為 HIGH/LOW ◦函式實作內容: 1. 由指定的 pin 編號來取得對應的 port 2. 檢查指定 pin 上的硬體 PWM 是否正在被使用, 如果是則停止它 3. 由 port 找到對應的暫存器 4. 依照輸入的 value, 修改暫存器設定
  44. 44. wiring_digital.c
  45. 45. 硬體相關函式實作解析 digitalRead (pin) ◦函式功能: 讀取指定腳位的輸入電位, 回傳 HIGH/LOW ◦函式實作內容: 1. 由指定的 pin 編號來取得對應的 port 2. 檢查指定 pin 的硬體 PWM 是否正在被使用, 如 果是則停止它 3. 由 port 找到對應的暫存器, 讀取並判斷暫存器 值, 回傳 HIGH/LOW
  46. 46. wiring_digital.c
  47. 47. 硬體相關函式實作解析 analogReference (mode) ◦函式功能: 設定 A/D 的參考電壓 ◦函式實作內容: 把指定的 mode 傳給內部宣告的變數 wiring_analog.c
  48. 48. 硬體相關函式實作解析 analogRead (pin) ◦函式功能: 讀取 A/D 的電壓數值 ◦函式實作內容: 1. 依照不同的 Arduino 版本, 由輸入的 pin 編號來 取得對應的 analog IN 腳位 2. 設定 analog reference 和 PIN 3. 開始做 A/D 轉換並等待完成 4. 回傳轉換後的值
  49. 49. wiring_analog.c
  50. 50. wiring_analog.c
  51. 51. 硬體相關函式實作解析 analogWrite (pin, val) ◦函式功能: 使用 Arduino 的 PWM 硬體送出指定 duty 的 PWM ◦函式實作內容: 1. 先將指定 pin 切成 OUTPUT 2. 再從指定 pin 編號, 找到相對應的 timer 3. 把 val 設定到 timer 暫存器 (藉由 timer 和 PWM generator 的硬體行為輸出指定 duty 的 PWM)
  52. 52. wiring_analog.c
  53. 53. 硬體相關函式實作解析 tone (pin, frequency, duration) ◦函式功能: 從指定的 pin 送出 frequency 頻率的 pulse (duty 為 50%) 並持續一段 duration 時間 ◦函式實作內容: 1. 依據輸入的 pin 編號, 初始化對應的 timer 2. 計算輸入的 frequency 並將結果填入 timer 暫 存器 3. 將 duration 與 frequency 換算成 timer counter 4. 開啟 timer 中斷, 在 ISR 中進行/停止 pulse 輸出
  54. 54. Tone.cpp
  55. 55. … Tone.cpp
  56. 56. 硬體相關函式實作解析 noTone (pin) ◦函式功能: 停止指定 pin 的 pulse 輸出 ◦函式實作內容: 1. 依據輸入的 pin 編號, 取得正在使用中的 timer 2. 關閉 timer 中斷 3. 將輸出 pin 的電位設定為 0
  57. 57. Tone.cpp
  58. 58. 硬體相關函式實作解析 shiftOut (datapin, clockpin, bitorder, val) ◦函式功能: 選用兩個 pin 作為 datapin 與 clockpin, 將 8-bit val 用指定的 bitorder 送出 ◦函式實作內容: 1. 依照指定的 bitorder 將 val 從 datapin 輸出 2. 改變 clockpin 電位, 使其 high、low 各一次
  59. 59. wiring_shift.c
  60. 60. 硬體相關函式實作解析 shiftIn (datapin, clockpin, bitorder) ◦函式功能: 選用兩個 pin 作為 datapin 與 clockpin, 用指定的 bitorder 讀取 8-bit 的 value ◦函式實作內容: 1. 設定 clockpin 電位為 high 2. 用指定的 bitorder 從 datapin 讀取 1bit value 3. 設定 clockpin 電位為 low 4. 以上三個步驟重複 8 次
  61. 61. wiring_shift.c
  62. 62. 硬體相關函式實作解析 PulseIn (pin, state, timeout) ◦函式功能: 對指定的 pin 去計算輸入 state (high/low) 的持續時間 ◦函式實作內容: 1. 由指定的 pin 編號來取得對應的 port 2. 設定 state 的 timeout 時間 3. 等待 pin 的電位變化到非指定的 state 4. 等待 pin 的電位變化到指定的 state 並開始計時 5. 等待 pin 的電位變化到非指定的 state 並停止計時 6. 回傳指定 state 持續的總時間
  63. 63. wiring_pulse.c
  64. 64. 硬體相關函式實作解析 millis ( ) ◦函式功能: 回傳 Arduino 運行後所經過的時間, 單位是 millisencond, resolution 是 1ms ◦函式實作內容: 1. 關中斷 2. 讀取目前的 timer0_millis 變數值 3. 開中斷 4. 回傳其值
  65. 65. wiring.c
  66. 66. 硬體相關函式實作解析 micros ( ) ◦函式功能: 回傳 Arduino 運行後所經過的時間, 單位是 microsencond, resolution 是 4us (for 16MHz) ◦函式實作內容: 1. 關中斷 2. 先讀取 timer overflow 的次數 3. 判斷此時 timer 是否 overflow, 若是則加一次 4. 讀取目前的 timer counter 5. 開中斷 6. 計算 timer overflow 次數與 counter 值 7. 將計算結果回傳
  67. 67. wiring.c
  68. 68. 硬體相關函式實作解析 delay (ms) ◦函式功能: 延長一段指定的時間, 單位是 ms, resolution 是 1ms ◦函式實作內容: 1. 調用 micros ( ) 得到目前的時間 count 值 2. 每經過 1ms 後把指定的 ms 值減一, 直到 ms 等於 0 為止
  69. 69. wiring.c
  70. 70. 硬體相關函式實作解析 delayMicroseconds (us) ◦函式功能: 延長一段指定的時間, 單位是 us, resolution 是 1us ◦函式實作內容: 1. 依據 CPU 時脈與輸入的 us, 算出需要的 count 總數 2. 將 count 減一, 直到 0 為止
  71. 71. wiring.c
  72. 72. 硬體相關函式實作解析 interrupts ( ) ◦函式功能: 打開 global 中斷 ◦函式實作內容: 對 SREG 的第 7 bit (Global Interrupt Enable) 填 1 Arduino.h interrupt.h
  73. 73. 硬體相關函式實作解析 nointerrupts ( ) ◦函式功能: 關閉 global 中斷 ◦函式實作內容: 對 SREG 的第 7 bit (Global Interrupt Enable) 填 0 Arduino.h interrupt.h
  74. 74. 硬體相關函式實作解析 attachInterrupt(intnum, userFunc, mode) ◦函式功能: 掛載使用者的 callback function, 並依據輸入 mode 決定觸發外部中斷的條件 ◦函式實作內容: 1. 掛載 user function 2. 設定觸發 mode 3. 依據指定的 intnum, 啟用可作為外部觸發功能 的腳位
  75. 75. WInterrupts.c
  76. 76. 硬體相關函式實作解析 detachInterrupt(intnum) ◦函式功能: 卸載指定 intnum 的外部中斷功能 ◦函式實作內容: 依據使用的 Arduino 版本, 關閉指定的外部中斷
  77. 77. WInterrupts.c
  78. 78. 硬體相關函式實作解析 Serial.begin (baud) ◦函式功能: 設定串列傳輸的 buadrate ◦函式實作內容: 依據使用的 Arduino 版本, 把指定的 baudrate 設 定到 baudrate 暫存器中 啟用 RX、 TX、RX complete 中斷、Data Register Empty 中斷
  79. 79. HardwareSerial.cpp
  80. 80. 硬體相關函式實作解析 Serial.available ( ) ◦函式功能: 判斷 COM port 是否收到數據 ◦函式實作內容: 回傳 rx buffer 中的 data 個數 HardwareSerial.cpp
  81. 81. 硬體相關函式實作解析 Serial.read ( ) ◦函式功能: 讀取 COM port 讀到的數據 ◦函式實作內容: 判斷 rx buffer 是否為空, 如果是則回傳 -1, 如果 不是則讀取一個 data, 回傳給使用者
  82. 82. HardwareSerial.cpp
  83. 83. 硬體相關函式實作解析 Serial.write ( ) ◦函式功能: 寫入 data 到 COM port ◦函式實作內容: 判斷 tx buffer 是否為已滿, 如果是, 則等到有空 間時把一個 data 丟進 tx buffer, 如果不是則立 刻把一個 data 丟進去
  84. 84. HardwareSerial.cpp
  85. 85. 下一個推倒對象: 86Duino
  86. 86. 86Duino硬體配置 多功能 外部中 斷 I/O USB 2.0 Arduino Leonardo 相容 I/O Arduino Leonardo 相容 I/O Arduino Leonardo 相容 I/O
  87. 87. 86Duino硬體配置 MicroSD LAN PCI-e target
  88. 88. 86Duino 軟體設計概觀 IDE 設計原則 ◦不改變 Arduino IDE 原有功能的前提下, 加 入對 86Duino 的編譯及燒錄支援 移植 coreboot + SeaBIOS 做為 86Duino 的開源 BIOS 韌體使用 FreeDOS 做為 OS ◦快速開機: 通電 2 秒內 run 起使用者程式 ◦中斷掛載容易實現 ◦架構上最接近 Arduino 韌體架構
  89. 89. 86Duino 軟體設計概觀 採用 DJGPP 做為 86Duino 的編譯系統 ◦DJGPP: 第一款出現在 x86 上的 GUN gcc ◦相容大部分 avr-gcc 的語法 ◦執行於 x86 保護模式下, 無記憶體使用限制 使用 DJGPP 的問題 ◦DJGPP 為 DOS 程式, 無法直接在 Linux, Mac, 64-bit Win7/Win8 下執行 ◦目前解決方法: 86Duino IDE 調用 DOSBOX 執行 DJGPP
  90. 90. 軟體開發背後堅持的原則 在軟體系統每個環節, 只使用歐噴壽司 工具 ◦BIOS: coreboot + SeaBIOS (open source) ◦OS: FreeDOS (open source) ◦編譯系統: DJGPP & DOSBOX (open source) ◦程式庫: DJGPP & Arduino上各種第三方開 源程式庫 (ex: Allegro) ◦IDE: Processing/Arduino IDE (open source) ◦燒錄軟體: 自己寫 (open source)
  91. 91. Arduino Standard API 在 86Duino 上的移植 直接來自 C/C++ standard library 的 API ◦DJGPP 與 avr-gcc 相容, 無需移植 直接使用 C 語言巨集定義的 API ◦直接沿用 Arduino 原始碼 平台獨立 API ◦直接沿用 Arduino 原始碼 硬體相關 API ◦重新改寫至 x86 平台
  92. 92. 硬體相關 API 在 86Duino 上的實作 pinMode( ) ◦函式功能: 用以配置腳位為輸出或輸入模式 ◦程式設計流程: 與 Arduino 流程相同 改填屬於 86Duino 自己的暫存器
  93. 93. wiring_digital.cpp
  94. 94. 硬體相關 API 在 86Duino 上的實作 digitalWrite (pin, value) ◦函式功能: 設定腳位輸出電位為 HIGH/LOW ◦函式實作內容: 1. 檢查指定 pin 上的硬體 PWM 是否正在被使用, 如果是則停止它 2. 由 pin 編號找到對應的暫存器 3. 依照輸入的 value, 修改暫存器設定
  95. 95. wiring_digital.cpp
  96. 96. digitalRead (pin) ◦函式功能: 讀取指定腳位的輸入電位, 回傳 HIGH/LOW ◦函式實作內容: 1. 檢查指定 pin 的硬體 PWM 是否正在被使用, 如 果是則停止它 2. 由 pin 編號找到對應的暫存器, 讀取並判斷暫存 器值後, 回傳 HIGH/LOW 硬體相關 API 在 86Duino 上的實作
  97. 97. wiring_digital.cpp
  98. 98. 硬體相關 API 在 86Duino 上的實作 analogRead (pin) ◦函式功能: 讀取 A/D 的電壓數值 ◦函式實作內容: 1. 初始化 A/D 2. 設定 PIN 3. 開始做 A/D 轉換 4. 回傳轉換後的值
  99. 99. wiring_analog.cpp
  100. 100. 硬體相關 API 在 86Duino 上的實作 analogWrite (pin, val) ◦函式功能: 使用 86duino 中的 MCM 之 PWM 硬體送出指定 duty 的 PWM ◦函式實作內容: 1. 從指定 pin 編號, 找到相對應的 MCM 2. 將指定 pin 切成 PWM 輸出 3. 把 val 設定至 PWM 相關暫存器 4. Enable PWM
  101. 101. wiring_analog.cpp
  102. 102. wiring_analog.cpp
  103. 103. 硬體相關 API 在 86Duino 上的實作 tone (pin, frequency, duration) ◦函式功能: 從指定的 pin 送出 frequency 頻率的 pulse (duty 為 50%) 並持續一段 duration 時間 ◦函式實作內容: 1. 計算輸入的 frequency 並將結果填入設定 PWM 相關暫存器 2. 將 duration 與 frequency 換算成 PWM period 的總個數 3. 開啟 MCM 中斷, 在 ISR 中進行/停止 pulse 輸出 Tone ( ) 的 PWM 主要作為 timer 用, 指定腳位上不會輸出 PWM pulse
  104. 104. Tone.cpp
  105. 105. Tone.cpp
  106. 106. 硬體相關 API 在 86Duino 上的實作 noTone (pin) ◦函式功能: 停止指定 pin 的 pulse 輸出 ◦函式實作內容: 1. 關閉 MCM PWM 2. 將輸出 pin 的電位設定為 0
  107. 107. Tone.cpp
  108. 108. 硬體相關 API 在 86Duino 上的實作 shiftOut (datapin, clockpin, bitorder, val) ◦函式功能: 選用兩個 pin 作為 datapin 與 clockpin, 將 8-bit val 用指定的 bitorder 送出 ◦函式實作內容: 內容與 Arduino 相同, 未做任何修改
  109. 109. 硬體相關 API 在 86Duino 上的實作 shiftIn (datapin, clockpin, bitorder) ◦函式功能: 選用兩個 pin 作為 datapin 與 clockpin, 用指定的 bitorder 讀取 8-bit 的 value ◦函式實作內容: 內容與 Arduino 相同, 未做任何修改
  110. 110. 硬體相關 API 在 86Duino 上的實作 PulseIn (pin, state, timeout) ◦函式功能: 對指定的 pin 去計算輸入 state (high/low) 的持續時間 ◦函式實作內容: 1. 設定硬體 PWM 參數 2. 等待 pin 的電位變化到非指定的 state 3. 等待 pin 的電位變化到指定的 state 並開始計時 4. 等待 pin 的電位變化到非指定的 state 並停止計時 5. 回傳硬體 PWM 的 sample cycle 6. 計算時間並回傳數值
  111. 111. wiring_pulse.cpp
  112. 112. 硬體相關 API 在 86Duino 上的實作 millis ( ) ◦函式功能: 回傳 86duino 運行後所經過的時間, 單位是 millisencond, resolution 是 1ms ◦函式實作內容: 回傳 timer_nowtime ( ) 的值 timer_nowtime() 函式實作內容: 在 DOS DJGPP 環境底下調用 uclock(), 取得的時間換算成 millisecond 後回傳
  113. 113. wiring.cpp common.cpp
  114. 114. 硬體相關 API 在 86Duino 上的實作 micros ( ) ◦函式功能: 回傳 86duino 運行後所經過的時間, 單位是 microsencond, resolution 是 1us ◦函式實作內容: 1. 取得 CPU clock count 2. 將 count 以 CPU 時脈換算後回傳
  115. 115. wiring.cpp common.cpp
  116. 116. 硬體相關 API 在 86Duino 上的實作 delay (ms) ◦函式功能: 延長一段指定的時間, 單位是 ms, resolution 是 1ms ◦函式實作內容: 1. 將 timer_nowtime ( ) 得到的數值加上輸入的 ms 計算出目標時間 2. 無限等待, 直到超過/到達目標時間
  117. 117. wiring.cpp common.cpp
  118. 118. 硬體相關 API 在 86Duino 上的實作 delayMicroseconds (us) ◦函式功能: 延長一段指定的時間, 單位是 us, resolution 是 1us ◦函式實作內容: 將目前時間減去進入此 function 的時間, 將結果 轉換成 microsecond 單位後與輸入的 us 值比較, 直到值大於 us 為止
  119. 119. wiring.cpp common.cpp
  120. 120. 硬體相關 API 在 86Duino 上的實作 interrupts ( ) ◦函式功能: 打開 global 中斷 ◦函式實作內容: 對 EFLAGS 的 IF bit 填 1 Arduino.h io.c
  121. 121. 硬體相關 API 在 86Duino 上的實作 nointerrupts ( ) ◦函式功能: 關閉 global 中斷 ◦函式實作內容: 對 EFLAGS 的 IF bit 填 0 Arduino.h io.c
  122. 122. 硬體相關 API 在 86Duino 上的實作 attachInterrupt(intnum, userFunc, mode) ◦函式功能: 掛載使用者的 callback function, 並依據輸入 mode 決定觸發外部中斷的條件 ◦函式實作內容: 1. 掛載 user function 2. 設定觸發 mode 3. 依據指定的 intnum, 啟用可作為外部觸發功能 的腳位
  123. 123. WInterrupts.cpp
  124. 124. 硬體相關 API 在 86Duino 上的實作 detachInterrupt(intnum) ◦函式功能: 卸載指定 intnum 的外部中斷功能 ◦函式實作內容: 關閉指定的 intnum 中斷
  125. 125. WInterrupts.cpp
  126. 126. 硬體相關 API 在 86Duino 上的實作 Serial.begin (baud) ◦函式功能: 設定串列傳輸的 buadrate ◦函式實作內容: 1. 設定鮑率。 2. 設定傳輸資料長度、同位元檢查、停止位元。 3. 清空 TX、RXQueue。 4. 設定 timeout。
  127. 127. HardwareSerial.cpp
  128. 128. 硬體相關 API 在 86Duino 上的實作 Serial.available ( ) ◦函式功能: 判斷 COM port 是否收到數據 ◦函式實作內容: 回傳 rx queue中的 data 個數 HardwareSerial.cpp
  129. 129. 硬體相關 API 在 86Duino 上的實作 Serial.read ( ) ◦函式功能: 讀取 COM port 讀到的數據 ◦函式實作內容: 調用 com lib 中的 com_Read ( ) 讀取一個 rx buffer 中的值並回傳 HardwareSerial.cpp
  130. 130. 硬體相關 API 在 86Duino 上的實作 Serial.write ( ) ◦函式功能: 寫入 data 到 COM port ◦函式實作內容: 調用 com lib 中的 com_Write ( ), 傳送一個 8-bit 值 HardwareSerial.cpp
  131. 131. Arduino 原始碼讀書會 (II) : Bootloader 解析
  132. 132. 找出 bootloader 原始碼
  133. 133. 讓我們再次回到熟悉的地方 https://github.com/arduino/Arduino
  134. 134. Arduino 原始碼根目錄 改過的 Processing IDE 原始碼 (Arduino 相關) Processing IDE 原始碼 存放編譯結果的目錄 Arduino Bootloader, Standard API 原始碼 Arduino Library 原始碼
  135. 135. hardware → arduino 各種版本 bootloader 原始碼 Standard API 原始碼(共用部分) 各種周邊配套的處理器韌體 Standard API 不共用部分 定義 Board 選單及編譯參數 定義 Programmers 選單及燒錄參數
  136. 136. hardware → arduino → bootloaders Duemilanove , Diecimila , Nano , Fio ....... Arduino NG or older w/ ATmega8 BT ATmega328 , BT ATmega168 Arduino Robot LilyPad Arduino USB Leonardo , Micro , Esplora LilyPad Arduino ATmega168 Uno , Mini ATmega328 , Ethernet Mega 2560 , Mega ADK 本次原始碼解析目標 (其它bootloaders可以此類推)
  137. 137. UNO Bootloader optiboot source code 已編譯好的各種 版本 16 進位檔
  138. 138. Leonardo Bootloader caterina source code 已編譯好的各種 版本 16 進位檔 各種版本 bootloader 說明
  139. 139. Serial Bootloader 解析 --- 以 UNO 為例
  140. 140. Arduino UNO Bootloader Arduino UNO 使用了 optiboot,優點: ◦佔用空間只有1.5kB ◦鮑率115200,上傳程序速度較舊版 ATmega bootloader 快 ◦程式碼進行了優化,運行效率較舊版提高, 並且無看門狗問題 ◦支持較多的 ATmega 晶片
  141. 141. 與 Bootloader 有關的電路 USB to Serial bridge Arduino 主晶片 USB 接頭 PC USB Serial
  142. 142. 與 Bootloader 有關的電路 Serial TX/RX 資料傳輸線 Serial DTR (用於 reset Arduino) Arduino 主晶片 USB to Serial bridge
  143. 143. UNO Bootloader 程式流程 UART init Watchdog init 是否由 RESET Pin 引起 執行 Arduino F/W 否 是 依命令把 Arduino F/W寫入 Flash 把 watchdog 設定成 16ms, 並等待系統自行 reset reset 每接收一個字元都會 重設 watchdog Watchdog 預設 1s (timeout 自行 reset) TX, RX 燈號是由 Atmega16U2(USB to Serial bridge) 控制 由 serial port 接收 Host 命令 是 否 收到 exit bootloader 命令
  144. 144. Bootloader 原始碼重要細節 判斷 reset 來源, 如果不是 reset button 或 serial DTR reset, 就呼叫 appStart() 直 接執行 Arduino F/W 初始化 watchdog timer = 1s, (如果一秒內 bootloader 沒有從 serial 收到任何資 料, 將會自動跳出並執行 Arduino F/W)
  145. 145. Bootloader 原始碼重要細節 從 serial port 讀取字元 Bootloader main loop 進行 STK500 通訊協定的命令處理 (STK500協定規範請自行參考 Atmel 文件: http://www.atmel.com/Images/doc2591.pdf) 如果收到 exit 命令, 則設定 watchdog timer = 16ms, 並 呼叫 verifySpace() 等待系 統自行 reset
  146. 146. Bootloader 重要函式註解 getch ( ) ◦從 serial port 讀取一字元 putch ( ) ◦由 serial port 送出一字元 verifySpace ( ) ◦接受並回應 STK500 命令結尾 token
  147. 147. Bootloader 重要函式註解 watchdogReset ( ) ◦Reset watchdog timer watchdogConfig ( ) ◦設定 watchdog timer appStart ( ) ◦執行使用者燒錄的 Arduino 韌體程式
  148. 148. Arduino IDE 對 Bootloader 的操作 IDE 將編譯程 式, 並透過 bootloader 將 編譯結果 上傳到 Arduino 板子上
  149. 149. Arduino IDE 對 Bootloader 的操作 IDE 上傳程式的流程 取得要燒錄的檔案所在路徑 和檔案名稱 由板子版本決定燒錄參數 取得燒錄程式路徑與檔名 執行燒錄程式 avrdude.exe 是否燒錄成 功? 回傳失敗 是 (由 avrdude.exe 的回傳值決定) 否 (IDE 這部分的原始碼等之後 的讀書會再進行詳細解析) 回傳成功 Avrdude 會自行透過 DTR 重啟 Arduino, 以進入 bootlaoder
  150. 150. USB Bootloader 解析 --- 以 Leonardo 為例
  151. 151. Arduino Leonardo Bootloader Arduino Leonardo 使用 caterina bootloader ◦透過 USB 直接與 PC 通訊, 省掉 USB to Serial bridge, 降低成本 ◦使用 LUFA library 來進行 USB 通訊 LUFA 是一套 AVR 系列微處理機專用的通訊程式 庫, 支援各種 USB Class caterina 只用到 CDC Class 的功能
  152. 152. 與 Bootloader 有關的電路 USB 通訊線 Arduino 主晶片
  153. 153. 與 Bootloader 有關的電路 USB 通訊線 USB 電源輸入 USB 接頭
  154. 154. Leonardo Bootloader 程式流程 HW init Timer LUFA init 是否有 POWER-ON reset Detach USB 並執行 Arduino F/W 否 是 Timer 中斷設定成每 1ms 觸發 一次, 裡面處理 TX/RX LED 與 bootloader timeout 依命令把 Arduino F/W 寫入 flash, 並重置 timeout count (timeout count > 8000) 把 timeout count 設 定為 7500 等待 timeout timeout count 不累加 Arduino F/W 是否存 在? timeout count ++ 是 否 點滅 TX/RX LED 是否 timerout 是 否 Timer 中斷副程式 Bootloader 主程式 由 USB 接收 Host 命令, 點亮 TX/RX LED 收到 exit bootloader 命令 是 否
  155. 155. Bootloader 原始碼重要細節 如果是由 reset button 引 起的 reset, 則進入 bootloader 如果不是軟體 reset, 則直接執行 Arduino F/W 如果是 POWER-ON reset, 則直接執行 Arduino F/W
  156. 156. Bootloader 原始碼重要細節 Bootloader main loop 執行 AVR910 通訊協定命令 LUFA library 的 USB 通訊處理 超過 8 秒沒從 host 收到資 料, 則跳出 bootloader 執行 Arduino F/W 執行 Arduino F/W 切斷 USB 連結 (Arduino F/W 會自己再一次進 行 USB 連接行為)
  157. 157. Bootloader 原始碼重要細節 Bootloader timer 中斷副程式, 每隔 1ms觸發執行一次 Bootloader 使用的 timerout count 變數
  158. 158. Bootloader 原始碼重要細節 AVR910 通訊協定處理函式 指定 USB 資料讀取通道 從 USB 讀取字元 判斷 USB 通道是否有資料存在 如果收到 exit 命令, 則等待 0.5 秒再跳出執行 Arduino F/W 進行 AVR910 通訊協定 的命令處理 (AVR910協定請自行參 考 Atmel 文件: http://www.atmel.com/images/doc0943.pdf)
  159. 159. Bootloader 重要函式註解 FetchNextCommandByte ( ) ◦從 USB port 讀取一字元 WriteNextResponseByte ( ) ◦由 USB port 送出一字元 SetupHardware ( ) ◦硬體初始化函式
  160. 160. Bootloader 重要函式註解 StartSketch ( ) ◦執行使用者的 Arduino 韌體程式 EVENT_USB_Device_ConfigurationChanged ( ) ◦USB 事件處理 callback EVENT_USB_Device_ControlRequest ( ) ◦USB 事件處理 callback
  161. 161. Arduino IDE 對 Bootloader 的操作 IDE 上傳程式的流程 取得要燒錄的檔案所在路徑 和檔案名稱 由板子版本決定燒錄參數 取得燒錄程式路徑與檔名 執行燒錄程式 avrdude.exe 是否燒錄成 功? 對目前的 USB serial port 設定 1200 bps baudrate 後再關閉 等待 bootloader USB serial port 出現 Timeout?(5s) 等待 Arduino sketch USB serial port 出現 將 Arduino sketch USB serial port baudrate 改 成正常值, 並回傳燒錄 成功 Timeout?(2s) 回傳燒錄成功 回傳失敗 回傳失敗 是 否 是 (由 avrdude.exe 的回傳值決定) 否 是 否 Arduino 自行切斷 USB 再重新連線 (IDE 這部分的原始碼等之後的讀 書會再進行詳細解析) (對 Arduino 做軟體 reset)
  162. 162. Leonardo 軟體 RESET 機制的實作 在 IDE 上傳 Arduino F/W 之前, 會先將 USB serial port 設定成 1200bps baudrate, 然後再關閉 serial port 上述行為會讓 Leonardo 上的 F/W 對一個 指定記憶體空間填入 bootkey, 然後再自己 reset reset 後進入 bootloader, 會去判斷是否為 軟體 reset (檢查 bootkey), 如果是, 則進入 bootloader main loop 開始接收資料
  163. 163. 輕鬆小品, 休息一下~~ 複習 Arduino Bootloader 燒錄
  164. 164. 接線路(Arduino to Arduino)
  165. 165. 接線路(Arduino to MCU)
  166. 166. 開啟 ArduinoISP程式檔
  167. 167. 將程式上傳到Arduino板子上
  168. 168. 選擇板子種類
  169. 169. 開始燒錄bootloader
  170. 170. 86Duino 的 Bootloader 實作
  171. 171. 86Duino Bootloader 行為 86Duino Bootloader 只是開機第一個執行 的 DOS 執行檔 行為大部分與 Arduino Leonardo 相同 只有軟體 reset 可以啟動 Arduino 韌體燒 錄機制 ◦Arduino Leonardo 則是軟體 reset 和 reset button 皆會啟動 Adruino 韌體燒錄機制
  172. 172. 86Duino Bootloader 行為 86Duino F/W 先整個被接收到記憶體內, 再一次寫入 flash ◦當傳輸過程出錯, 不會破壞原有韌體程式 86Duino F/W 會先燒錄至暫存空間, 成功 後再映射至韌體存放空間 ◦當寫入過程出錯, 不會破壞原有韌體程式
  173. 173. Bootloader 原始碼重要細節 86Duinio F/W 最大 SIZE Bootloader timeout 時間 可燒錄的程式類型
  174. 174. Bootloader 原始碼重要細節 初始化 I/O port 決定 bootloader 的運作模式 判斷是否有軟體 reset
  175. 175. Bootloader 原始碼重要細節 初始化 USB device port 配置存放 86Duino F/W 的記憶體陣列
  176. 176. Bootloader 原始碼重要細節 Bootloader main loop 開始
  177. 177. Bootloader 原始碼重要細節 讀取要燒錄的 86Duino F/W 大小
  178. 178. Bootloader 原始碼重要細節 從 USB 接收 86Duino F/W 檔案
  179. 179. Bootloader 原始碼重要細節 86Duino F/W 燒錄
  180. 180. Bootloader 原始碼重要細節 若是執行 Bootloader 燒錄則 reboot, 反之 則執行 86Duino F/W
  181. 181. 初版程式燒錄的 protocol 沒有使用 protocol (未來會新增) 初版是直接傳送特定格式的資料 TYPE Data length Data 1 Byte 4 Bytes N Bytes 1: 檔案是 bootloader 2: 檔案是 user program
  182. 182. 86Duino 軟體 RESET 機制的實作 由 IDE 把 USB serial port 開啟為 1200bps baudrate 後再關閉 (與 Arduino Leonardo 相同) 86Duino 收到上述行為後, 會對一個 I/O 空間寫入特定值, 然後自己 reset reset 後進入 bootloader, 判斷上次是否 為軟體 reset, 如果是, 則開始接收新的 F/W
  183. 183. Arduino 原始碼讀書會(III) : Arduino IDE 解析
  184. 184. Arduino IDE 的編譯
  185. 185. 取得 Arduino Source Code 第一種方式: ◦使用 git 軟體 下載: http://git-scm.com/downloads ◦指令: git clone https://github.com/arduino/Arduino.git
  186. 186. 取得 Arduino Source Code 第二種方式: ◦直接下載 source code 點選這裡可直接下載
  187. 187. ●Arduino IDE Source Code https://github.com/arduino/Arduino ●Cygwin http://cygwin.com/install.html ●Sun Java JDK(Java SE Development Kit) http://www.oracle.com/technetwork/java/javase/downloads/index.html ●Apache Ant Binary Distributions http://ant.apache.org/bindownload.cgi ●git http://windows.github.com/ Windows-下載相關應用程式
  188. 188. Setup steps(1) 安裝 Cygwin 安裝 Java JDK 解壓縮apache-ant-x.x.x-bin.zip至 ProgrmFiles