2016年8月2日 星期二

Published 下午4:42 by with 1 comment

[基礎] OpenOCD 與 STM32


在單晶片開發時,大部分都採用燒錄後執行程式,
並且透過UART吐出數據的方式來debug。

不過隨著系統的複雜度上升,這樣的開發方式逐漸會遇到瓶頸。
也因此,比較大的晶片例如32位元的,通常會內建 JTAG 裝置,
也就是一種後門,方便進行debug。

在此我們採用一種 On-Chip debugger 軟硬體搭配,
簡單來說就是能夠單步執行並且隨時能知道記憶體內容。

各家晶片都有自己的 On-Chip Debugger 裝置,對應的 JTAG 硬體也各有不同。

原本打算採用的是 100 ASK 公司出品的 OpenJtag
但是該公司的這支硬體呢,在Win10下的驅動程式似乎怪怪的不能安裝,
搜尋了一些教學顯示有些麻煩的設定要做,所以暫時先算了。

既然打算要用STM32,那就用先前操作 STM8 的 STLink2 繼續用吧。

在 STM32 的開發板都會把 JTAG 介面開出來,根據接腳圖可以確認是這樣:
這是對應標準的 JTAG 的腳位,適用於像是 ULink  或是 JLink 之類的硬體套件。
如果是要用ST公司的 STLink2 去連接,則會有點不一樣。

根據 這邊的說明 ,只要利用四支街腳就足夠了。如圖所示:
也就是把 STLink2 的 SWDIO 接往 TMS、 SWCLK接往TCK。
然後 GND 和 3V 接好即可通訊使用。

我們接好之後如下圖:

單純的只用杜邦線做銜接。

接好之後,只要確定STLink2的驅動沒問題,那麼只要將中介層的軟體弄好即可。

我們這邊採用的中介層是 OpenOCD
使用了這個中介軟體,就可以將 GDB送來的指令轉換到真正的硬體上。

在OpenOCD的原始網站上,提供的基本是原始碼而已,因為要做跨平台,
所以開放給使用者自已下載回去,在自己的作業系統上編譯。

要在Windows下自己編議OpenOCD可以說是相當麻煩,必須先安裝Cygwin,
也就是模擬Linux環境才能做。詳見這個網站有說明。

由於自己編譯太麻煩,所以根據OpenOCD網站的建議,
這裡可以拿到編好的安裝檔。

下載來之後的安裝畫面就像這樣
基本上都按下一步就能安裝完成了。

但是這個OpenOCD是沒有GUI,完全使用文字介面下指令操作的。
安裝的位置如果在  C:\Program Files 底下的話,之後操作讀取script檔時就會因為那個空格而讀不到。所以我們將OpenOCD安裝在 C:\OpenOCD 以利使用,打字也比較不累。

把所有的東西連線做好,當然開發板的電源記得要接上。


啟動命令列視窗,然後下命令

 cd  C:\OpenOCD\bin

進入OpenOCD執行檔的所在位置,接著執行

openocd -f C:\OpenOCD\scripts\interface\stlink-v2.cfg -f C:\OpenOCD\scripts\target\stm32f1x_stlink.cfg

這行的意思就是啟動OpenOCD並且以 stlink2 銜接 STM32F103 的意思,
所以才要隨之讀取附屬 script 檔。

成功啟動後會出現這樣的訊息:
游標停在那邊不是當機,是OpenOCD已經開始執行。
這時要另外啟動一個文字介面的視窗,並且打字輸入

telnet localhost 4444

就會出現

這樣子代表已經可以進入指令模式操作這顆晶片了。
如果使用GDB的話,則不必啟動這個telnet。

如果你的系統沒有telnet,可以參考這邊的教學來啟動Telnet。






Read More
      edit

2016年8月1日 星期一

Published 下午2:23 by with 1 comment

[基礎] STM32與開源軟體

這一次的主角是STM32。

照片中是一塊STM32開發板,搭配的 debugger 是 ST-Link-V2 。
STM32具有優異的性能,各種強大的設計使得開發產品非常容易,而且這晶片也不貴。
這次作為實驗對象的是 STM32F103vet6。

在前面的章節不斷的使用 Code Blocks 這個優秀的 IDE ,而本次的實驗要用 Code Blocks 來進行整合開發環境的建置,並且能夠單步執行。

首先要取得 Compiler 。可以先閱讀 How to install the ARM toolchain 這網站的指示。


然後到 GNU ARM Embedded Toolchain 網站去下載安裝檔


或者去  CodeSourcery 網站取得也行。

接著是STM32要運作時的一些必備函式庫,可以去STM32原廠網站找
下載並且解壓縮後,會有一個名為 STM32F10x_StdPeriph_Lib_V3.5.0 的資料匣
我下載的是3.5版所以會有這樣尾數命名。


在 STM32F10x_StdPeriph_Driver 這個目錄底下有原廠先寫好的函式庫方便操作硬體,我們將複製使用。

在CMSIS目錄下,有著原廠寫好的核心啟動程式碼,也就是STM32這種32位元啟動複雜的行為不必我們自己寫。


以上就是行前預備。


安裝 Compiler 完成之後,啟動 Code Blocks 做點設定。

從 Settings -> Compiler...  進入


Selected compiler 選擇 GNU GCC compiler for ARM  的項目,根據你自己安裝compiler位置設定好。

然後進入 Settings -> Debugger 設定新的 debugger 專門針對STM32的

記得 Do "not" run the debugee 這個項目要打勾,避免在非預期狀態下被啟動。

 然後進入 Tools -> Configure tools ,設定一個快速工具好讓OpenOCD啟動。
這樣就可以在 GDB debugger 啟動前先快速的啟動 OpenOCD 以利連線。

開啟一個新專案來做STM32的範例。
一樣使用空白的專案,但下一步之後的Compiler選項記得點選 ARM 專用的。

專案開好後,專案設定的一些東西要變更。

首先是 Projetc -> Build options


由於選定的晶片,STM32屬於 Cortex-M3 系列的,所以要勾選 M3

然後在 Other options 底下要增加文字
-gdwarf-2 -mthumb -fomit-frame-pointer -Wall -Wstrict-prototypes -fverbose-asm -Os


在 #defines 下要增加
STM32F10X_HD
USE_STDPERIPH_DRIVER


在 Linker settings 的頁籤下,other linker options 要添加
-mthumb -nostartfiles -Tstm32f103vet6.ld -Wl,-Map=main.map,--cref,--no-warn-mismatch


最後是 Pre/post build steps 頁籤項目裡,Post-build steps 要增加
C:\Program Files (x86)\CodeBlocks\GunARM2016q2\bin\arm-none-eabi-objcopy -O ihex ${TARGET_OUTPUT_DIR}${PROJECT_NAME}.elf  ${TARGET_OUTPUT_DIR}${PROJECT_NAME}.hex
cmd /c "C:\Program Files (x86)\CodeBlocks\GunARM2016q2\bin\arm-none-eabi-objdump" -S ${TARGET_OUTPUT_DIR}${PROJECT_NAME}.elf > ${TARGET_OUTPUT_DIR}${PROJECT_NAME}.asm
C:\Program Files (x86)\CodeBlocks\GunARM2016q2\bin\arm-none-eabi-size ${TARGET_OUTPUT_DIR}${PROJECT_NAME}.elf


這段是為了在編譯完成後,自動產生可燒錄檔以及組合語言碼方便找錯誤。

接著進入  Project-> Properties ,在 Build targets 頁籤裡做這樣的設定

在 Debugger 頁籤加上遠端遙控的設定, IP位址是 localhost 而 port 是 3333。

同樣在 Debugger 頁籤下, Additional GDB commands 添加連線後的指令設定
monitor halt
load bin/STM32_Hello.elf
monitor sleep 1000
monitor reset
這段指令的意思就是,啟動後先停止,然後載入執行檔,睡眠 1000mS 再 Reset。

這些設定完成後,預備寫程式的檔案必須要有:
core_cm3.c
core_cm3.h
system_stm32f10x.c
system_stm32f10x.h
stm3210x.h
stm32x.conf.h
startup_stm32f10x_hd.s
stm32f103vet6.ld
以上構成基本的開機啟動功能。然後
main.c  放我們自己的程式
stm32f10x_gpio.c 和  stm32f10x_gpio.h 做 IO操作
stm32f10x_rcc.c 和  stm32f10x_rcc.h 做振盪器控制操作

但是在ARM compiler 裡,似乎有個辨識上的 bug  會使得 compiler 不會過關。
這兩個小小需要修改的點在 core_cm3.c 裡面。分別是
STREXB 和 STREXH

在程式內  "=r" (result)  會導致編譯失敗,因此改為  "=&r" (result)
添加一個 & 符號解決。
該問題的修改法參考來自此
http://www.cesareriva.com/fix-registers-may-not-be-the-same-error/

以上的程式建置進專案後,build 完成,就可以啟動單步除錯器了。

當然硬體要先接好


首先透過 Tools 啟動 OpenOCD
當出現這些訊息時,代表OpenOCD已經成功啟動。等待GDB去做連線。
這時只要按下
紅色的三角鍵,Code Blocks 就會啟動 GDB 去做連線。按下後log視窗會出現


可以看到 load 指令後載程式到晶片的資訊。
再按一次紅色的三角鍵就會開始運作,跑到斷點才會停止
然後可以看見點亮LED的情景

當斷點停止的時候,可以在OpenOCD的視窗內看到被停止的位址


以上範例程式碼放在 GitHub
Code Blocks 的操作設定參考自 http://www.hackvandedam.nl/blog/?p=707
OpenOCD 的操作可參考自 詹姆士酷斯拉





Read More
      edit

2016年6月6日 星期一

Published 下午3:43 by with 0 comment

[筆記] C語言中使用單一位元的做法:Bit Field 位元欄位

在嵌入式的設計中,經常有判斷旗標要被使用。
但使用 char 或是 _Bool 這些宣告則太過浪費記憶體,
而C語言中有個方法可以只需要一個位元就可以做。

這個方法稱為 Bit Field ,現在較新的 C 語言書都不太提到,
確定有談到這個方法的書目前只看過 K & R 與 Pointers on C

做 Bit Field 時必須使用 struct
例如:

先寫好
                                                          struct Flag{
unsigned F1 : 1;
unsigned F2 : 1;
unsigned F3 : 1;
unsigned F4 : 1;
unsigned F5 : 1;
unsigned F6 : 1;
unsigned F7 : 1;
unsigned F8 : 1;
                                                                      };
最尾數的1代表使用一個bit。
然後要使用時則宣告

struct Flag flagexample;

那麼這個叫做flagexample的變數在記憶體內的實況則會是

如此設定和宣告過後,就可以這樣用:
flagexample.F2 = 1;
flagexample.F6 = 0;

並且可以應用在判斷是,例如:
if ( flagexample.F6 == 1 ) {.........}

如果與 union 聯合  混合使用。例如:
                                                         union{
                                                                unsigned char AllMsg;
                                                                struct {
              unsigned bit0:1 ;
              unsigned bit1:1 ;
              unsigned bit2:1 ;
              unsigned bit3:1 ;
              unsigned bit4:1 ;
              unsigned bit5:1 ;
              unsigned bit6:1 ;
              unsigned bit7:1 ;
                                                                           };
                                                                   } Message;

這段程式代表直接宣告一個變數叫做 Message,程式操作時

Message.AllMsg = 0x80;

可等同於

Message.bit7 = 1; Message.bit6 = 0; Message.bit5 = 0; Message.bit4 = 0;
Message.bit3 = 0; Message.bit2 = 0; Message.bit1 = 0; Message.bit0 = 0;

--------------------------------------------------------------------------------------

在 MSP430 操作的情況下,使用 Bit Field 直接操作硬體位元,為了不要再多定義記憶體來搬運所以操作略有點不同。例如:

                                                          struct SFRbitDef{
unsigned B0 : 1;
unsigned B1 : 1;
unsigned B2 : 1;
unsigned B3 : 1;
unsigned B4 : 1;
unsigned B5 : 1;
unsigned B6 : 1;
unsigned B7 : 1;
                                                                      };

先建好結構後,將結構指向實際配合硬體的位址:

#define P2input  ((struct SFRbitDef *) 0x28 );
#define P1output  ((struct SFRbitDef *) 0x21 );

後面的 0x28 和 0x21 分別是搭配硬體用的記憶體位址。

於是存取的時候,以這樣寫成:

if ( (P2input->B1) == 0 )  {  P1output->B4 = 1; }
// 此段程式是讀取 P2 的 B1接腳,若該接腳電位為零則將 P1 的 B4 接腳輸出為 1 。

同樣的也可以這樣應用:
P1output->B4 =  ~(P1output->B4);
// 直接簡單的將該位元反向


Read More
      edit

2016年6月5日 星期日

Published 下午2:56 by with 0 comment

[基礎] Mspdebug 與 Msp430

較早的文章已經談過Msp430使用開源軟體的開發方法了。
但當時沒有提到程式能夠單步執行的作法,
這一次要談的是如何控制msp430的程式單步執行,
也就是 Mspdebug。

Mspdebug 也是個開源的自由軟體,是專門針對msp430製作的,
可以支援各種不同的ICE運轉。

原作者的網站在此:  http://dlbeer.co.nz/mspdebug/

原作者的網站在這段談到了怎麼在windows底下自己建立這套軟體。
根據操作說明,必須要下載安裝下列軟體:

1. 
Download MinGW installer
Install to C:\mingw - install the 'C Compiler', 'MSYS Basic System' and 'MinGW Developer Toolkit'.

下載 MinGW,這是用來把原始碼編成可執行檔的compiler
在安裝的時候必須安裝這些項目:


千萬不能使用CodeBlocks內附的MinGW,基於一些不明的原因,雖然可以編譯成功但執行起來會是錯誤不斷的。

2.
Download regex-2.7-bin.zip
Open the archive - extract the files from the lib directory to c:\mingw\lib, extract files from include directory to c:\mingw\include.

下載 regex-2.7-bin.zip ,解壓縮後,把lib目錄下的東西拷貝到 MinGw 下的 lib 目錄,而 include 內的東西也拷貝到MinGw下的 include 目錄。

3.
Download libusb-win32
Extract lusb0_usb.h to c:\mingw\include, rename to usb.h
Extract lib/gcc/libusb.a to c:\mingw\lib

下載 libusb-win32 ,解壓縮後把 lusb0_usb.h 拷貝到MinGw下的 include 目錄,並且變更檔案名稱為 usb.h。 把解壓所後的 lib/gcc/  目錄下的libusb.a拷貝到 MinGw下的 lib 目錄。

4.
Download readline-5.0-1-bin.zip
Extract the readline directory from include to c:\mingw\include\readline\
Extract the files from the lib subdirectory to c:\mingw\lib

下載 readline-5.0-1-bin.zip,解壓縮後把readline目錄拷貝到MinGw下的 include 目錄,把lib目錄下的東西拷貝到MinGw下的 lib 目錄。

5.
Download the MSPDebug source code, open a command window, change directory to the MSPDebug sourcecode.

下載mspdebug的原始碼,解壓縮擺放。
修改一下目錄下的makefile,把問號消除

打開命令提示字元視窗,切換到mspdebug解壓縮好的目錄下。


切換進去後,打字輸入
set path=c:\mingw\bin;c:\MinGW\msys\1.0\bin\
make
就會建立出一個叫做 mspdebug 的執行檔。

最後,從剛剛下載解壓縮的檔案中,把 regex2.dll、readline5.dll 拷貝進 mspdebug 的目錄下,
以及根據 libusb 的安裝指引--libusb-win32-bin-README 把 libusb0.dll 安裝進系統。

這樣 mspdebug 就可以執行了。但如果要運作在 Launchpad,還需要安裝一個驅動程式:
在 libusb-win32 目錄的bin底下,有個執行檔 inf-wizard ,USB線連接好Launchpad 執行 inf-wizard之後按下一步,則會出現:
其中兩個 Vendor ID 是 0x0451 的就是 Launchpad  ,有一個是UART介面被佔用了,所以點選另一個 (Interface 1) 產生驅動程式。

這個驅動程式安裝之後,mspdebug 才能連到板子。如果系統是win10,則必須參考強制停止數位簽章的安裝法。

在命令列視窗下,執行 mspdebug rf2500 則會出現:

這樣就代表連線成功了。

接下來先鍵入exit,然後啟動CodeBlocks來改設定讓單步執行可以操作。

在Tools設定裡,添加一個啟動 mspdebug 並且燒錄程式檔的功能:

然後在 debugger設定 裡添加 msp430-elf-gdb 的啟動設定:

開啟上一次用過的LED閃爍專案,在 Properties 設定中增加遠端連線設定
跟OpenOCD的情況不同,這裡的 Additional GDB commands 不需要加任何指令。

在專案設定裡,編譯的項目要添加 -g 以產生除錯用的標誌

編譯成功的話會出現
而加了 -g 之後編譯出的組合語言碼則會是這樣
這樣才能夠讓除錯器自動計算斷點產生的位置。

都完成之後,啟動 tools 下的 mspdebug:
這樣就是 mspdebug 正在等待 GDB 的連線。而連線用的 port 是 2000。

在CodeBlocks的Debug功能中,記得Active debuggers點選你所屬的 msp430 gdb 。
按下Star 後,就可以像之前操作STM32一樣操作斷點的設定。

而斷點操作的時候,mspdebug 的文字視窗也會出現對應的活動
以上完成了msp430的單步執行操作。

必須注意的是,在我的實驗中,舊版的mspgcc (4.6.3)對於和mspdebug的連線,不知道為什麼會出現中斷,這方面是變更為新版 (5.3.0.219) 後才得到解決。

而新版必須要多做的事情包括中斷設定有變,然後編譯完會添加一些啟動碼,必須在link的時候使用 -minrt 這個操作來消除。









Read More
      edit