Hello China操作系統STM32移植指南(二)

移植步驟詳解

下面就以MDK 4.72爲開發環境,詳細說明Hello China內核向STM32的移植過程。MDK 4.72評估版只支持32K代碼的編譯,這對Hello China的內核來說,裁剪掉一些非核心功能,也足夠了。如果您希望體驗更多功能,請使用非評估版。您可以花錢買,也可以通過其它途徑獲得,具體不細說,你懂的。

首先建立一個新的項目,注意要指定一個項目所在目錄,並選擇合適的STM32芯片。我選擇的是STM32F103R8,如下圖:

 

點擊OK後,MDK會提示是否拷貝startup_stm32f10x_md.S到項目中,選擇“是”。這樣MDK會自動生成一個啓動文件,到所選目錄下。

假設項目所在的目錄是HXOS03,則進入該目錄,創建下列幾個文件夾:


其中HXOS存放Hello China操作系統源文件,Obj&Lst存放MDK編譯生成的過程和目標文件,Startup存放啓動文件(把上圖中startup_stm32f10x_md.s拷貝到Startup文件夾),User則存放用戶應用程序源文件。

然後把Hello China V1.76的源文件拷貝到HXOS目錄下。下面是拷貝之後的結構(HXOS目錄下所包含的文件夾):


其中有幾個文件夾,在STM32下是不需要的,可以把它刪除掉。主要有fs/shell兩個目錄。其中fs存放的是文件系統代碼,我們的移植目標板上沒有存儲系統,故不需要該文件夾內容。Shell是面向PC的一個命令行界面,在STM32下也不需要。

再進入MDK,建立與上述目錄基本對應的文件夾架構,如下圖:


然後把文件夾中的文件,逐一添加到項目中。需要注意的是,MDK只支持二級目錄,即不能繼續在HXOS目錄下再創建子目錄。由於HXOS存放的是Hello China源代碼,分好幾個子目錄存放,因此在添加到項目中的時候,實際目錄結構就消失了,所有文件都統一顯示在MDK的HXOS目錄下。這有點不方便,主要是尋找某個文件的時候,但好消息是,操作系統內核需要修改的地方不多,而且一勞永逸,這個不方便也可以克服。

完成文件的添加後,在MDK中對項目做一些配置。打開項目選項對話框(爲了簡便,就不貼圖了。MDK中按下ALT+F7鍵,即可看到),主要有以下幾點設置:

1.         把編譯生成的中間和目標文件,以及list文件,存放到創建的Obj&Lst目錄下。選擇對話框中的output和listing選項,分別點擊“select folder for objects…”和“select folder for listings…”,即可設置;

2.         選擇項目選項對話框中的“C/C++“頁籤,在”Define“編輯框中,輸入”STM32F10X_MD“。這是一個預定義宏,告訴編譯器,我們的目標STM32平臺是中等密度的(因爲我們選擇的目標是STM32F103RB)。至於什麼是STM32 MD,HD,LD等,請參閱相關資料;

配置完成後,點擊OK。

接下來,需要修改幾個地方的代碼,主要有:

1.        啓動文件中,需要增加鏈接中斷的代碼。打開startup_stm32f10x_md.s文件,找到下列代碼:

………

USART1_IRQHandler

USART2_IRQHandler

USART3_IRQHandler

EXTI15_10_IRQHandler

RTCAlarm_IRQHandler

USBWakeUp_IRQHandler

 

                B       .

 

                ENDP

 

                ALIGN

把上述代碼中的“B .“一行刪除,修改爲下列代碼(斜體部分):

………

EXTI15_10_IRQHandler

RTCAlarm_IRQHandler

USBWakeUp_IRQHandler

 

                IMPORT Int_Entry_Wrapper

                LDR R0,=Int_Entry_Wrapper

                BX R0

                ENDP

                ALIGN

這樣就實現了硬件中斷和Hello China操作系統中斷機制的鏈接。

2. 內存配置。找到HXOS目錄下的mem_scat.c文件,找到下列代碼:

__MEMORY_REGION SystemMemRegion[] = {

     {(LPVOID)KMEM_ANYSIZE_START_ADDRESS,0x00100000},

     {(LPVOID)(KMEM_ANYSIZE_START_ADDRESS+ 0x00100000),0x00100000},

     {(LPVOID)(KMEM_ANYSIZE_START_ADDRESS+ 0x00200000),0x00100000},

     {(LPVOID)(KMEM_ANYSIZE_START_ADDRESS+ 0x00300000),0x00100000},

     //Please add more memoryregions here.

     //The last entry must beNULL and zero,to indicate the end of this array.

     {NULL,0}

};

修改爲下列內容:

__MEMORY_REGION SystemMemRegion[] = {

     {(LPVOID)0x20003000,0x00002000},

     //Please add more memoryregions here.

     //The last entry must beNULL and zero,to indicate the end of this array.

     {NULL,0}

};

這告訴操作系統的內存管理機制,空閒內存是從0x20003000開始,長度是8K。這裏直接使用了固定編碼的方式,告訴操作系統空閒內存起始地址。這種處理方式是不合適的,因爲如何確定空閒內存起始地址,是個問題。這裏的0x20003000是通過分析編譯輸出的map文件,推算出來的。但是要實現自動的空閒內存設定,則需要修改編譯器的散列文件(sct文件),比較複雜。因此暫時先用這種方式替代。如有複雜的場景,再考慮修改sct文件來實現空閒內存的自動界定。如果讀者朋友有更好的方法,也歡迎反饋。

3. 接下來是最後一步,就是修改config.h文件。這是操作系統的核心配置文件,相關功能模塊都在這個文件中進行配置。具體來說,註釋掉某些宏定義,並打開針對STM32的一些宏定義。下列是修改之後,該文件的大致內容(刪除了註釋):

 

#define __CONFIG_H__ //Include switch.

#define __CFG_CPU_LE

//CPU types,the following definitions are exclusive.

//#define __I386__

//#define __ARM7__

//#define __ARM9__

//#define __ARM11__

#define __STM32__

#define SYSTEM_TIME_SLICE  50

#define MIN_STACK_SIZE 128

#define MAX_INTERRUPT_VECTOR 128

#define DEFAULT_STACK_SIZE 0x00000400 //1k space for kernel threadstack.

//#define __CFG_SYS_IS

//#define __CFG_SYS_VMM

//#define __CFG_SYS_BM

#define __CFG_SYS_MMFBL

//#define __CFG_SYS_MMTFA

#define __CFG_SYS_DDF

//Include CPU statistics functions in OS.

//#define __CFG_SYS_CPUSTAT

//#define __CFG_SYS_SHELL

//#define __CFG_SYS_CONSOLE

 

//#define __CFG_DRV_IDE

//#define __CFG_DRV_COM

 

//Include USART driver in OS,specific for STM32 or ARM platform.

#define __CFG_DRV_USART

//#define __CFG_DRV_MOUSE

//#define __CFG_DRV_KEYBOARD

//#define __CFG_FS_FAT32

//#define __CFG_FS_NTFS

//#define __CFG_FS_RAM

//#define __CFG_FS_FLASH

//#define __CFG_NET_IPV4

//#define __CFG_NET_IPV6

#define __CFG_USE_EOS

//User entry point thread's priority if used as EOS.

#define __HCNMAIN_PRIORITY PRIORITY_LEVEL_NORMAL

//User entry point thread's name.

#define __HCNMAIN_NAME     "HCN_Main"

 

從中可以看出Hello China操作系統的裁剪配置思路。只要把對應的宏定義打開,相應的功能就包含在Hello China內核裏面了。註釋掉之後,相應的功能就被裁剪掉,內核尺寸就會變小。

完成上述所有修改和配置之後,直接在MDK中按F7鍵,即可編譯鏈接了。會有一些告警提示,忽略即可。如無意外,應該會編譯成功,生成目標文件。

這時候,可以使用MDK內置的模擬器進行調試。由於我們實現了USART1的驅動程序,也隨之實現了一個簡單的交互界面(在user文件夾下的usermain.c文件中),因此如果用串口鏈接STM32的USART1接口,輸入“m”,即可看到內存使用情況的統計輸出。

下面介紹一個簡單的調試方法。在進入調試狀態後(選擇“debug”菜單,選擇“start/stop debug session”選項),在MDK左下角彈出的command窗口中,輸入下列命令:

mode com3 115200,0,8,1

assign com3 <s1in> s1out

如下圖:


即可把PC機的COM3接口與MDK所虛擬的STM32的USART1鏈接起來(波特率是115200,無校驗,8位數據位,1位停止位)。

這時候使用諸如VSPD等串口虛擬軟件,把COM3(鏈接了STM32的USART1)和COM4環接起來,則使用諸如超級終端等串口軟件(指定COM4串口,並配置與COM3相同的參數),即可與STM32虛擬機交互了。下圖是交互的輸出:

 

用戶編程模型

Hello China在初始化完成之後,如果發現定義了__CFG_USE_EOS宏,則試圖創建一個核心線程,入口函數名稱是_HCNMain。用戶應用程序代碼需要在這個函數中實現。因此,在成功移植Hello China之後,用戶需要在user目錄下,創建自己的源文件,並實現_HCNMain函數。這個函數與缺省的main函數一樣,是用戶功能代碼的入口。在_HCNMain函數中,用戶可以調用Hello China提供的一系列系統服務,比如創建核心線程,申請/釋放內存,讀寫文件等。下面是系統附帶的一個實現,這個實現很簡單,就是不斷讀取USART1的輸入,並回顯出來。如果發現輸入是“m”,則調用ShowMemory函數,輸出內存分配情況。

下面是_HCNMain函數的源代碼,貼到這裏供參考。如果用戶想實現自己的獨特功能,可以直接修改_HCNMain函數:

DWORD _HCNMain(LPVOID pData)

{

     __COMMON_OBJECT* hUsart =NULL;

     DWORD           dwWriteLen = 0;

     CHAR            chCmd;

     CHAR            strInfo[64];

 

     hUsart =IOManager.CreateFile(

         (__COMMON_OBJECT*)&IOManager,

         "\\\\.\\USART1",

         0,

         0,

         NULL);

     if(NULL == hUsart)

     {

           SER_PutString("_HCNMain:Can not open USART object.\r\n");

           return 0;

     }

     SER_PutString("_HCNMain:Open device USART successfully.\r\n");

     while(TRUE)

     {

           if(IOManager.ReadFile(

                 (__COMMON_OBJECT*)&IOManager,

             hUsart,

             1,

             &chCmd,

             NULL))

           {

                 IOManager.WriteFile(

               (__COMMON_OBJECT*)&IOManager,

               hUsart,

               1,

               &chCmd,

               &dwWriteLen);

                 if('m' ==chCmd)

                 {

                      ShowMemory(hUsart);

                 }

           }

     }

     //return 1;

}

 

從上述代碼中可以看出,_HCNMain可以調用Hello China操作系統的API,來實現相應功能。對物理設備的操作也大大簡化,所有設備,都是按照文件的操作接口來統一操作。這樣的好處是,不用關心底層的驅動程序實現,只需要聚焦應用的實現即可。這種模式適合大型軟件的開發,可以把整個任務分爲兩個部分:驅動代碼和應用代碼,並分別由不同的團隊承接,相互不干擾,有利於提升開發效率。

 

其它相關問題的說明

接下來,對操作系統移植過程中的其它相關問題做一番說明。首先是CPU復位後的執行入口點問題。在startup文件中,MDK定義了一個入口點函數Reset_Handler,Hello China的實現方式是,在osadapt.s中重新定義一個Reset_Handler函數,替代MDK定義的這個。因爲MDK在定義的時候,使用了[weak]修飾,因此只要在osadapt.S中定義的Reset_Handler不使用weak修飾即可。這樣CPU復位後,將跳轉到osadapt.S文件定義的Reset_Handler處開始執行。這時候會首先調用SystemInit函數,這個函數是一個缺省實現,從MDK開發環境附帶的例子(位於Keil\ARM\Examples目錄下)中拷貝過來的。SystemInit函數完成系統時鐘的配置等工作,然後再跳轉到MDK定義的__main函數。這個函數內嵌了一些全局數據重定位代碼,把全局變量搬遷到0x200000000開始處(即RAM開始處),然後再調用main函數。Main函數在os_Entry.c文件中實現,調用了操作系統初始化函數_OS_Entry。_OS_Entry完成Hello China操作系統的初始化,並創建用戶線程_HCNMain。_HCNMain得到調度的時候,就正式進入用戶程序了。需要說明的是,在main函數中,調用_OS_Entry之前,首先對Systick進行了初始化,這是產生系統tick的機制。

USART驅動程序在Hello China初始化過程中被加載。驅動程序首先初始化USART1相關的控制器,開啓USART1功能,然後調用ConnectInterrupt函數,把USART1的中斷處理函數鏈接到Hello China的中斷處理機制。這樣USART1就可以被用戶程序通過文件API訪問了。具體例子,可參考上述_HCNMain的實現案例。

通過合適的裁剪,可以把Hello China的內核大小控制在10~20K之間。當然,如果進一步增加其它功能,比如FS,網絡,shell,則內核尺寸會超過40K。如果進一步增加GUI,則需要額外內存支持了。

最後,再把Hello China的擴展機制總結一下,因爲Hello China的應用目標是物聯網操作系統,需要面對各種規格的硬件配置,因此操作系統的伸縮性是非常關鍵的。Hello China的伸縮性,大致表現在下列方面:

1.   內核線程的數量無限制,可以隨便創建,僅受限於物理內存大小;

2.   採用統一的文件API,訪問文件和設備。這樣可以把用戶功能代碼和底層的硬件驅動程序隔離開,方便大型軟件的開發;

3.   採用鏈式中斷機制,對中斷的數量無限制,而且可以動態添加和刪除中斷處理程序;

4.   內嵌靈活擴展的驅動程序管理框架,要增加驅動程序,只需要按照Hello China的驅動程序框架編寫代碼,然後在驅動程序加載列表中註冊一項即可。操作系統在初始化過程中,會加載驅動程序加載列表中的所有驅動程序;

5.   內存管理機制靈活,可以在mem_scat.c文件中添加多個內存塊,比如外部RAM等,實現統一管理;

6.   實現統一的文件系統框架,用戶通過統一的API接口訪問文件,不管文件的底層存儲格式是什麼。同時,文件系統可動態添加或刪除。在動態添加存儲設備的時候,文件系統會得到通知,如果是可識別的文件系統,會實時掛接到系統中,呈現給用戶。這種機制十分適合外設豐富的應用場景。

      總之,通過添加驅動程序,核心線程,文件系統/GUI/網絡功能等模塊,可以快速擴展HelloChina的功能,而且這種功能對用戶來說是完全透明的。相反,通過裁減不需要的功能,也可以把Hello China的尺寸控制在很小的範圍(小於10K)。這樣一種可伸縮性的特徵,符合物聯網操作系統多樣化的需求。

歡迎對物聯網操作系統感興趣的同仁投入,繼續開發。物聯網已經被廣泛看好,支撐物聯網發展的操作系統,必定會越來越受到重視。對參與者個人來說,物聯網操作系統正處於開發的初始階段,這個時候參與進來,持續跟進甚至主導,逐漸積累,在該領域成爲權威,會比其它領域更加容易,效果也會更好。物聯網操作系統給所有系統軟件愛好者提供了一個難得的機會,真誠希望我們都能夠抓住。

同時也歡迎物聯網領域的企業或單位,能夠應用Hello China操作系統。我們會提供更加周到的服務。

任何問題,請聯繫:

QQ/微信:89007638

Email:[email protected]

 

發佈了88 篇原創文章 · 獲贊 168 · 訪問量 51萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章