文章

顯示從 2021 起發佈的文章

[筆記] 漫談 ARM cross compiler 環境

圖片
        在 Windows 環境下,如果要開發軟體,我們只需安裝微軟的 Visual Studio IDE,接著在這 IDE 編譯我們的程式就能在 x86 的環境下運行。由於 Visual Studio 編譯器是專為 x86/x64 晶片設計的,實際上它編譯出來的機器碼並不能放到 ARM 晶片上執行,所以我們需要找其他編譯器編譯出 ARM 能看得懂的機器碼。 機器碼         目前可編譯 ARM 晶片的編譯器以 GCC 為主,當然有些付費版的 IDE 也能編譯 ARM,如:KEIL 、IAR  (有專人管理的編譯器),  不過都還是源自 ARM compiler 網站 ,從網站上取得編譯器的原始碼,經過編譯後產生一套能編譯 ARM 晶片的編譯器 (說的有點複雜 !!)。簡單說,最終目的是製造出一個 ARM 編譯工具,但是要先取得原料後,再自行製造出這個工具。所幸現在網上有不少開發環境都能提供這 ARM 編譯的工具了,不需要我們重頭開始打造工具。然而,這類工具大多在 Linux 的環境下,所以想編譯成 ARM 機器碼只能到 Linux 環境下?         在 Windows 環境下,如果也想要 Linux 的環境,需要在 Win 系統安裝類 Unix 環境的軟體,如:cygwin 、MSYS2 、MinGW...等。底下以 MSYS2 軟體為例,其實它就是一個在 Win 系統的命令列,但是和 Win 系統提供的有何不同呢?請看圖一和圖二的環境變數,兩者環境變數完全不一樣,MSYS2 就是模擬一個 Linux 環境的命令列,操作指令也是 Linux 指令,但實際上指令已經轉為 Win 系統能執行了。有了這類 Linux 環境當然是對熟悉 Win 系統的人操作起來比較便利。 圖一:Windows的命令列 圖二:MSYS2的命令列 Unix-like環境         在 MSYS2 環境,我們要先安裝 ARM 相關的編譯工具,從 MSYS2 官網 下載安裝 package ,安裝這幾個套件  arm-none-eabi-gcc 、 arm-none-eabi-newlib 、 arm-none-eabi-binutils ... (執行指令 pacman -S xxx),我們就能用這套編譯工具編譯成 ARM 機器碼,如下圖三所示。既然安裝

[筆記] 笙泉 Megawin 微控制器(ARM Cortex-M0)的系統開發

圖片
        Megawin 公司 推出的 MG32F02x 系列晶片是以 ARM Cortex-M0 為核心的微控制器,內建至少 32KB flash 存放程式碼與資料,包含常用的介面,如:UART 、 I2C 、 SPI 、 ADC...等,算是具備完整周邊的 MCU。 準備工作:         軟體套件 KEIL uVision5 ARM 版本,注意 ARM compiler 版本必須是5.06 update 7,筆者測試過update 6,會造成 ISP 代碼運行時出現異常。而 KEIL v5.34版本裡面就包含ARM compiler 5.06 update 7,所以下載最新的 KEIL 版本即可避開此問題。此外,開發過程還需要準備一個 M-Link Cortex-M0 的除錯器,以方便我們開發時可以設斷點 、 step by step 、 debug...。         安裝 KEIL ARM 軟體後,需要再載入 Megawin 的工具包。開啟 KEIL IDE,在選單上點選 Pack Installer工具按鈕,從這工具去載入 Megawin.CM0_DFP.2.0.8.pack 或最新版。成功後,這樣的 KEIL 開發環境才能支援 Megawin 晶片。這個 pack 裡面包含晶片所有介面的驅動程式碼,以及範例程式,我們可以從工具的選單複製所需的範例程式碼。 韌體燒錄方式:         在開發韌體時,透過 KEIL IDE 加上 M-Link debugger 便能下載韌體到晶片上,但是一般實用場景下不可能每次都用 KEIL 套件去燒錄韌體。目前 Megawin 提供兩種燒錄韌體的方式: ICP (In-Circuit Programming) 和 ISP (In-System Programming)。         ICP方式就是M-Link除錯器連接到晶片的SCL (PC4)和SDA (PC5)接腳,利用 ICP32_Programmer.exe 軟體工具將韌體燒錄到指定 AP flash記憶體區,如下圖。首先載入我們的韌體(稱為 app),再按下 “Insert ISP-Code” 插入原廠提供的 ISP 碼,組成完整的 binary code,最後按下 Update Target 鈕,這樣 M-Link debug

[筆記] Firmware 開發過程中, 最難發現的問題之一

圖片
        過去開發 TI DSP 韌體時,遇過最詭異的問題就是程式跑到某一行就會出現異常情況,將這行移除後,程式又能正常運行。後來把編譯器的版本更新後,相同的程式碼經過重新 compile 居然能正常運行,很神奇吧?這類問題算是開發時期最難解決的問題之一,因為不容易發現,即使發現異常也不會懷疑與編譯器版本有關,於是自己會陷入一種迷惘的狀況,到底要怎麼 debug 解決。 [源由]           最近在開發 ARM-based MCU 晶片時,也是遇到奇怪現象。我寫一段 ISP 程式碼,每次運行到某一行就會發生晶片硬體出錯。於是,將這段程式碼交給原廠的 FAE 檢查,FAE 說在他的環境重現不出來,不過他把他的編譯產生的 map 也傳給我了。比對了雙方的 map 檔,唯一值得懷疑的是 compiler 版本不太一樣。         如下面的影片所呈現, 相同的 code,在不同的版本的編譯下,居然會出現不同的結果。影片中,先以 ARM compiler update 6 編譯,設定中斷點,當運行到某一行時,系統就出現錯誤。之後,我們將編譯工具升級為 update 7 版本後,相同的代碼就能通過運行,這種與 compiler 版本有關的問題是開發程式最難找的問題之一。 當 compiler 轉譯成機器碼之後,由晶片執行,有可能轉譯的過程有 bug (指令有錯?) 或者晶片本身有 bug (不認機器嗎?),遇上這類問題,要嘛等待晶片廠商修正,釋出下一版晶片,要嘛更新編譯器,或者自己修改代碼的寫法避開有問題的寫法。 影片: Firmware 開發時, 最難發現的問題之一

[應用] 在 ESP32 Audio 開發板的 VoIP 範例

圖片
開發板介紹         安信可 公司(Ai-Thinker)基於 ESP32 晶片推出一塊具有語音功能的 ESP32 Audio Kit 開發板,簡稱 ESP32-A1S,它與原廠的 ESP32 Lyrat 開發板都使用同一套 ESP-ADF SDK 軟體,但是開發板的電路有些差異,底層的驅動程式需要替換才能順利開發。         首先,最大的差異在 ESP32-A1S 語音編碼晶片採用 AC101 ,不過晶片被封裝在 ESP32 模組上,所以我們在開發板上面看不到這顆晶片,然而 ESP32 Lyrat 板採用 ES8388 晶片,因此在 ESP-ADF 中語音編碼的驅動程式需要更替。另外,其他不一樣的地方都在 GPIO 接腳的連接上,整理後,如下表所示,我們需要調整 ADF 底層的 HAL 和 Board 的配置,SDK 才能正常使用。 表一:ESP32-Lyrat 與 Audio Kit 開發板的差異         第一步,下載 ESP-ADF。在 VS Code 開發環境下[1],按 F1 後,選取 "Install ESP-ADF",VS Code 會自動從 GitHub 下載,並安裝 ADF 開發套件。如果是使用 ESP32-Lyrat 板子,可以直接跳到第四步,創建範例開始開發了。使用 ESP32-A1S 板子前,需要調整一下底層代碼,接續前面動作,我們從 GitHub 下載 A1S 的驅動程式, ESP32-A1S-AudioKit  程式碼,其目錄結構與 ADF 一樣,方便我們相互比對兩者差異。         第二步,到  \esp-adf\components\ audio_hal \driver 目錄下,將下載 A1S 裡的 AC101 驅動程式放進來。接著,要將 ac101 目錄和 ac101.c 加到  CMakeLists.txt 文件,同樣也要加到  component.mk 文件裡 ,這樣編譯過程就會把 AC101 驅動程式加進來編譯了。         第三步,我們再到  \esp-adf\components\ audio_board \lyrat_v4_3 目錄下(因為我們沒想要在 menuconfig 裡新增 A1S 配置,打算借用 lyrat 原配置),將 board.c、board

[應用] ESP32 BLE 藍芽體感搖桿

圖片
目標         之前我們實作過 USB 體感搖桿[1]  參考:ADXL335 三軸加速計的 USB 體感搖桿 ,那是一個有線的搖桿,這次我們將有線改為無線方式。以 ESP32 為控制核心,使用其內建藍芽 BLE 功能,再外接 ADXL335 加速計晶片,開啟 ESP32 ADC 的功能,讀取加速計晶片的電壓變化量,如圖一所示。最後,ESP32 Bluetooth BLE 連接到筆電上,現在的筆電幾乎能支援 BLE 連線,因此我們實作的結果能清楚地在電腦上呈現出來。 圖一:系統架構圖 開發過程         我們到 ESP32 官網下載 ESP-IDF,這提供完整的 ESP32 各種範例的原始碼,並在 Visual Studio Code (VS Code)環境上面進行開發[2]。在 ESP-IDF 的藍芽範例很多個,當初因為選錯源碼,一直無法做到搖桿滑鼠的功能,入了不少坑,後來找到合適的範例源碼。我們選用   esp-idf\examples\ bluetooth\bluedroid\ble\ble_hid_device_demo ,源碼可以提供藍芽 BLE 鍵盤、搖桿、滑鼠 、選單...等 功能,只要熟悉一下 API 函數就能做到 BLE 搖桿。         因為新增了 ADC 功能,所以我們必須調整 CMake 的配置,如下圖所示。在編譯過程中,因找不到一些 .h 標頭檔而出錯,於是在配置文件 CMakeLists.txt 裡把參照到的 include 路徑加入,還有我們用到 ADC 函數,所以在 link 階段需要把函式庫 esp_adc_cal 也加進來,這樣才能編譯成功 。 圖二:CMake的配置         在程式碼中,除了原本藍芽 BLE 所創建的 task 之外,我們新增另一個處理 ADC 運算的 task,如下圖所示。留意一點,因為 ESP32 為雙核心的控制器[3],我們在創建 task 時候可以指定將 task 放在哪一個核心上運行,這是很不錯的功能。 圖三:兩個 Task 分別運行在兩個核心 影片:ESP32 藍芽模組的體感搖桿 參考資料 [1]  ADXL335 三軸加速計的 USB 體感搖桿 [2]  ESP32 在 VS Code 開發環境的編譯與除錯 [3]  整理控制器 STM32 與無線晶片 ESP32

[應用] App Inventor 2 之語音辨識元件

圖片
        過去我們研究各種平台上的語音辨識功能,像是雲端服務的一文  雲運算之語音辨識 (Speech To Text)  [1],或者單晶片的離線辨識一文  LD3320 離線語音辨識晶片與 ESP32 無線傳輸  [2]。這次我們研究安卓系統的語音辨識,在 APP Inventor 2 的多媒體選單中提供語音辨識元件,元件屬性有 "UseLegacy",如果勾選它,每當調用這個元件時,手機畫面會彈出一個畫面,準備運行語音辨識。這個屬性只能允許一次性的辨識過程,需要再次調用元件才能進行下次辨識,如果要連續辨識的話,我們就必須 uncheck 這個屬性。         底下的積木流程圖採用連續語音辨識的屬性所設計的,不過開發過程中遇到一個問題,系統會不斷地彈跳出錯誤訊息,然後語音辨識過程就中斷了。在網路上也有人遇到同樣的情況[3][4], 現階段 處理的方式是把這些錯誤訊息抓出來,其中編號 3806 錯誤 (No Match) 出現時,重新呼叫語音辨識元件,讓系統再次進入辨識的狀態,但是每次出現錯誤訊息手機就會發出嗶嗶聲,有點惱人。或許,未來安卓系統會提供這個元件有更好的解決辦法,目前就先用上述的方式 work around 吧!最後一點,這個元件需要用到手機的網路,因為語音辨識的服務放在雲端上,如果沒有公眾網路,辨識是不起作用的。 圖一:APP 語音辨識積木流程圖 影片: App Inventor 語音辨識元件 參考資料 [1]  雲運算之語音辨識 (Speech To Text) [2]  LD3320 離線語音辨識晶片與 ESP32 無線傳輸 [3]  錯誤訊息 3806 [4]  App inventor : SpeechRecognizer 語音辨識

[筆記] ESP32 apptrace logging 方便於除錯

圖片
        開發設計任何系統,日誌 logging 是很重要的基礎工作。少了日誌,系統出錯將不容易除錯、分析、解決問題,所以第一步要先學會如何產生日誌。在開發 ESP32 / Arduino 這類系統時,一般常見產生日誌的方法是呼叫 printf 函數將想要紀錄的內容傳到 UART 介面,再從電腦的 COM port 上來查看。         採用 printf 將日誌輸出到 COM port 雖然簡單方便,但是呼叫過多的 printf 會影響運算的 timing,也不適合輸出大量數據到日誌。還有,當遇到系統崩潰的問題時,COM port 方式是很難幫我們解決這類棘手問題的。因此,ESP-IDF 提供另一種方式 apptrace 應用層追蹤函數庫 [2],日誌資料先存放到記憶體,再透過 OpenOCD 傳送到 PC 端。底下,我們以 blink 範例說明產生 apptrace 日誌的步驟。         首先,在 VS Code 的項目中打開 SDK 配置,如圖一所示。左下角的圖示按下,出現 SDK 配置後,找到 " Application Level Tracking " 選項,將選單設為 Trace memory ,儲存後再編譯 blink 範例。 圖一:開啟日誌系統的配置         第二步,在程式碼中,我們可以設定日誌輸出到 COM port 或者輸出到 OpenOCD 的電腦端。如圖二所示,當呼叫 esp_log_set_vprintf ( esp_apptrace_vprintf ) 時,代表之後的日誌都會輸出到 OpenOCD,所以紅色標示的日誌資料會輸出到電腦端。程式碼需要定期再加呼叫 esp_apptrace_flash 才能將日誌輸出。         當呼叫 esp_log_set_vprintf ( vprintf ) 時,代表之後的日誌輸出到 COM port,我們在電腦端直接打開終端機連線(115200bps 8-N-1)就能看到日誌,下圖所示。 圖二:在程式碼新增日誌         程式碼已經調用了 apptrace 函數庫,但是還沒真正讀取到日誌資料或開啟日誌。我們必須在電腦端打開 telnet 連線到 OpenOCD,連線參數:telnet localhost 4444 。連線成功後,輸入

[筆記] 整理控制器 STM32 與無線晶片 ESP32 資料

圖片
        整理自己常使用的 MCU 控制器,下表是 STM32 系列晶片,F1/F2 核心是 ARM Cortex-M3,適用在網路或 USB 2.0 等周邊控制。F3/F4 核心為 ARM-M4,核心工作時脈更高, 適用在 ADC 資料擷取等控制 。F7/H7 系列是目前最高等級的控制器,H7 為雙核心,適用於影像或顯示方面的控制。         另外,常使用的無線網路控制器是樂鑫 ESP 晶片,下表是 ESP32 系列晶片,最早推出的晶片是 ESP8266 系列,不包含藍芽功能,網路傳輸速度為 75Mbps。後來推出 ESP32 系列,工作時脈較高,網路傳輸也較快,並且多了藍芽功能。         從 espressif 官網資料來看,ESP32-C3 ADC 具有 DMA 功能,之前 ESP32 和 S2 的 ADC 並沒有 DMA 模式。C3 有 DMA 模式,可以減少 CPU 功耗,在省電方面應能表現更佳。 應用 [1]  以 ESP32 無線網為基礎,存取共享CF卡的FTP系統 [2]  LD3320 離線語音辨識晶片與 ESP32 無線傳輸 [3]  以 STM32 晶片的 ADC 為基礎, 設計一個簡易示波器 [4]  在 STM32 控制器上實現一個 FTP server [5]  ESP8266 WiFi to RS485 (MODBUS TCP to RS232) [6]  STM32F373 控制板之自我測試程式

[應用] 以 ESP32 無線網為基礎,存取共享CF卡的FTP系統

圖片
系統架構         與虎尾科大教授合作開發 "以無線網路為基礎,透過 FTP 的方式存取共享的CF卡" 的系統,本系統由數個主要元件所組成,如下圖一所示,控制的核心為  ARM Cortex-M3  的晶片  STM32F207 ,無線通訊採用外接  ESP32S  的模組,參考 [1][2] ,模組韌體負責處理  FTP socket 連線。 STM32F207  與無線模組之間的介面採用  UART  或  SPI  通訊,負責雙向的傳送資料。         CF 卡介面採用硬碟的  IDE  介面,參考 [3] ,系統規劃兩個不同來源的訊號可以存取  CF 卡,但是同一時間只能允許其中一個訊號可存取,於是設計上規劃一個  bus  切換電路。 圖一:系統方塊圖         CF 卡介面說明: 首先,系統存取需檢查 CF 卡是否插在介面上面,可以透過  CF_nCD1  和 CF_nCD2  腳位訊號得知情況。 CF_nCS0 和 CF_nCS1 腳位用來區分不同位址空間,控制 IDE 的暫存器被定義在不同的位址空間。 CF_SA0~2 就是位址線, CF_D0~15 是資料線。        CF 卡的存取對應到  STM32F207 的 FMSC 介面,在韌體程式裡,將  FMSC 介面規劃為 16-bit Memory I/O 存取介面, 0x68000000 這個位址範圍分配給 CF_nCS0 使用,而 0x6C000000 這個位址範圍分配給 CF_nCS1 使用。 當硬體規劃好線路後,控制 CF 卡需要驅動程式才能進行讀寫,首先要把 CF 卡當成一個 IDE 硬碟來看待,然後設計驅動程式時需要了解如何存取 IDE 硬碟的指令,請參考 [5][6]。 圖二:電路板俯視圖       無線模組 ESP32 的韌體架構使用 FreeRTOS 做為系統的作業系統,韌體創建三個 task : TaskBlink 、 TaskWiFiConn 、 TaskFtp ,如下圖所示。第一個用來讓模組上的燈號每秒閃爍一次,第二個是 WiFi client 連線到 WiFi AP ,成功後,板子上的 D5 燈號會亮。原始碼提供兩種方式,一種是 WiFi station 模式,另一種是 WiFi AP 模式,端看環境適合哪一種使用方式。 第三

[筆記] ESP32 在 VS Code 開發環境的編譯與除錯

圖片
#  ESP32 評比與教學推薦 NodeMCU-32s 的理由 準備工作 1) 安裝 Visual Studio Code (VS Code),並安裝其他 C/C++ 插件。 2) 安裝 Python 套件 3) 下載並執行 Setup ESP-IDF Tools:檢查電腦系統的環境,並幫我們把編譯的工具鏈 tool chain 安裝起來。 4) 在 VS Code 安裝 ESP-IDF 插件,點選插件後,看到下圖一並設定路徑後,點擊安裝 ESP-IDF。安裝 v4.2 版本後,會詢問是否下載安裝工具鏈,如果系統已經有安裝,那就設好路徑即可。最後,再安裝 python 虛擬環境給 ESP-IDF,便完成整個環境設定。 圖一:ESP-IDF 擴充插件 建立專案 1) 從 ESP-IDF 選範例專案:按 F1 後,上方的選單輸入 " ESP-IDF: Show Examples Projects ",出現下圖二的範例專案列表,我們可以從中選一個範例來創建,例如我從當中選了 blink 或 hello_word。按下右上方的創建,就會在左半邊出現專案。 圖二:ESP-IDF 範例專案的列表 2) 編譯專案:按 F1 後,上方的選單輸入 " ESP-IDF: Build your project ",VS Code 環境就會開發進行編譯的工作,在下方的欄位會顯示編譯的過程。 3)  設定模組型號:按 F1 後,上方的選單輸入 " ESP-IDF: Device configuration ",彈出選項後,我們選擇 EPS32 為裝置的型號。 4) 電腦接上 ESP32 模組:按 F1 後,上方的選單輸入 " ESP-IDF: Select port to use ",在 VS Code 會自動彈出 COM port 讓我們選擇,點選 EPS32 連接的 COM 即可。 5)  燒錄程式碼到 ESP32:按 F1 後,上方的選單輸入 " ESP-IDF: Select Flash Method and Flash ",彈出選項 JTAG 或 UART,我們選擇 UART 為下載燒錄的方式 (前面我們已經設定 COM 了)。下載燒錄的方式設好了,下次只要

[模組] LD3320 離線語音辨識晶片與 ESP32 無線傳輸

圖片
#  ESP8266 WiFi to RS485 (MODBUS TCP to RS232) #  環境品質監控系統 實驗說明         使用離線語音辨識晶片 LD3320 ,獲得辨識結果後透過 ESP32S 無線模組傳輸到另一塊無線模組上顯示出結果,如下圖一所示。 無線模組 ESP32         無線模組 ESP 系列是上海樂鑫所開發,經由安信可二次開發後推廣,模組提供 AT command (UART) 的方式進行控制,但這種方式使用起來總是覺得隔了一層紗,有層距離感,操控上反應或速度不夠即時。幸運的是,隨著這塊模組的生態系越來越成熟,使用者也越多了,ESP 模組已經能像 Arduino 一樣,可以在 Arduino IDE 環境下開發編譯並下載,同時不少開發者也分享各類無線模組的案例,方便我們拿來參考 [1][2]。         研究過程中,發現 ESP32S 上面的 FLASH 所屬的接腳不能直接拿來當作 GPIO 使用,因為這樣會影響到 IDE 燒錄,FLASH D0-D3 + CMD + SCK 正好對應到 GPIO 6-11,電路規劃時得避開使用這幾根 I/O。另外,這塊 ESP32S 模組有提供 3.3V 和 5V 輸出,正好 LCD_I2C 模組需要吃 5V 電壓,而語音辨識晶片吃 3.3V 電壓,能同時滿足開發的需求。 圖一:以無線傳輸語音辨識的結果         ESP32S 是同時具有 WiFi 和藍芽功能的模組,實驗中,我們使用模組的藍芽傳輸功能,並參考範例中的 BluetoothSerial 程式,通訊的一端代碼是 Bluetooth Master,另一端為 Bluetooth Slave,下圖二是兩邊代碼的說明。將 Slave 端設定藍芽名稱 (ESP32-ASR) 後,等待 Master 來連接,在 Master 端則對名稱 (ESP32-ASR) 發出連線請求,接著雙方就會自動連接成功。 圖二:藍芽通訊雙方的原始碼 離線語音辨識         LD3320 是十年前的語音辨識晶片 [3],主要辨識中文,已不是新鮮貨。它不需要連上雲端,只要設定好辨識的字句儲存到晶片的暫存器內,它就能進行離線辨識。優點是辨識過程很快,而且是不特定人的辨識方式,對於設定後的字句,其辨識準確率算不錯的 (在無噪音干擾環境下)。