1. K10 BSP包的創建
在基于MQX4.0對Kinetis系列MCU進行開發時,通常需要相應MCU的BSP的支持。但是在MQX4.0中,并沒有針對K10的現成的BSP包,所以需要由用戶進行創建。比較簡便的創建方法是從現有的Kinetis BSP包中選擇一個型號最接近的MCU的BSP作為模板,然后在其基礎上進行修改和移植。本文介紹了對BSP進行修改和移植的具體步驟和方法。
目前已有的典型的BSP包包括:
? 支持Kinetis 50MHz 的器件的BSP包為twrk20d50m
? 支持Kinetis 72MHz 的器件的BSP包為twrk20d72m
? 支持Kinetis 100MHz的器件,針對版本1.x的BSP有3個,分別是twrk40x256,twrk53n512和twrk60n512
? 支持Kinetis 100MHz的器件,針對版本2.x可選擇的BSP有2個,分別是twrk40d100m和twrk60d100m
? 支持Kinetis 120MHz的器件的BSP包有2個,分別是twrk60f120m和twrk70f120m
例如對于K10DN512ZVLQ10,其掩膜號為 4N30D,對應版本是1.x,而且其主頻是100MHz,所以可使用twrk60n512的BSP為模板,在此基礎上進行修改和移植。
2. BSP包代碼的生成
首先從Freescale官網 https://www.freescale.com/mqx下載并安裝MQX4.0。在這里也可以找到其他的早期版本,如MQX3.8、 MQX3.7等,其中都帶有MQX BSP Cloning Wizard工具。可以使用此工具,參照如下步驟進行BSP的創建和移植。
2.1新建BSP
在File菜單中選擇NEW MQX BSP Clone后,出現如下圖1所示的界面,在Name中輸入取名為K10DN512,然后選擇twrk60n512作為其Board Base,最后點擊Finish完成。
圖1. 新建一個BSP
緊接著會出現如圖2所示的窗口,可以在該界面下選擇CW10.x或者IAR或者KEIL作為開發平臺,以及是否需要生成BSP,PSP,MFS,RTCS,USB等庫和例程的選擇項。需要注意的是,由于K10本身不包括USB和以太網模塊,所以不要選擇相應的選項。
圖2. 選擇開發平臺和相關的軟件庫
2.2 生成BSP包
為了簡化操作,這里只選擇IAR的開發環境,而且只選擇生成BSP,PSP以及MQX例程,然后點擊Generate MQX Projects,開始創建新的BSP代碼,如圖 3所示。
圖3 點擊生成BSP包的工程
接著在C:FreescaleFreescale_MQX_4_0configK10DN512目錄中,找到剛才生成的針對IAR的BSP代碼,使用IAR開發環境選擇File-》Open-》Workspace,打開build_libs.eww工程。如圖4所示。
圖4 打開IAR BSP工程
注意: 在 打開此工程時會提示RTCS、 MFS、 USB等庫是否要加載。由于本文檔只針對基本的BSP、PSP包進行移植,而且在圖2中只勾選了這兩項,所以這里可以忽略除BSP、 PSP以外的 MFS、 RTCS、USB等包的加載,直接點擊確認完成就可以了。如果在實際應用中需要使用其他的包,需要將圖2中相應的Libraries庫和參考代碼的選項勾選上,然后再進行代碼生成即可。
3. BSP包代碼的修改
在C:FreescaleFreescale_MQX_4_0mqxsourcepspcortex_m文件夾里的psp_cpudef.h文件中可以找到支持Kinetis K10/K20/K30/K40/K50/K60/K70等相關芯片的PSP宏定義,例如支持K10DN512的宏定義為:
#define PSP_CPU_MK10DN512Z (PSP_CPU_NUM(PSP_CPU_ARCH_ARM_CORTEX_M4, PSP_CPU_GROUP_KINETIS_K1X, 2))
同時在該文件中還可以找到所有Freescale指定PSP處理器支持包所支持內核的宏定義,如ColdFire,PPC,Cortex-A5,Cortex-A8等。
在本文中,我們創建的是針對K10DN512的BSP開發包,所以需要用上述的宏定義,將user_config.h文件中的MQX_CPU定義
#define MQX_CPU PSP_CPU_MK60DN512Z
修改為:
#define MQX_CPU PSP_CPU_MK10DN512Z
此時點擊編譯按鈕會出現錯誤提示,如下圖5所示。
圖5. 頭文件錯誤
出現這個錯誤是由于在C:FreescaleFreescale_MQX_4_0mqxsourcepspcortex_mkinetis.h中找不到頭文件MK10DZ10.h,需要從以下的IAR安裝目錄中尋找:
C:Program FilesIAR SystemsEmbedded Workbench 6.5armincFreescale
然后將該文件拷貝到C:FreescaleFreescale_MQX_4_0mqxsourcepspcortex_mcpu中進行編譯。
編譯仍有錯誤出現,如下圖6所示。
這個錯誤主要是由于移植使用的是K60的BSP包,因此里面含有以太網ENET部分和USB部分的代碼,而在K10芯片中是沒有這些功能模塊的,在IAR IDE Workspace工作臺環境下,需要將外圍I/O驅動(Peripheral IO Drivers)中的ENET和USB等文件夾刪除,同時將K10DN512 BSP Files文件夾中的 init_usb.c和init_enet.c文件刪除。另外在K10DN512 BSP Files中,由于在MQX安裝目錄C:FreescaleFreescale_MQX_4_0mqxsourcespK10DN512 文件下的init_gpio.c和bsp.h中初始化了ent和usb部分的,需要打開這兩個文件,找到_bsp_ent_io_init和bsp_usb_io_init的代碼部分,然后直接進行刪除。此時再進行編譯,則應該沒有錯誤出現了。
圖6以太網及USB相關的文件編譯錯誤
下一步需要修改的,是系統的時鐘設置。針對K60DN512, MQX默認的外部時鐘是50MHz。 對于K20系列MQX默認的外部時鐘是8MHz,如果目標板的時鐘和默認的外部時鐘不一樣,則需要重新配置。例如,如果這里選擇25MHz的無源晶體作為外接時鐘,那么就需要修改bsp_cm.h中的時鐘設置,將CPU_XTAL_CLK_HZ的時鐘修改為25MHz。當然根據實際項目設計有時也需要配置不同的總線時鐘頻率,內核時鐘頻率等,可以參照如下的代碼對bsp_cm.h中的宏定義進行相應的修改:
#define CPU_BUS_CLK_HZ 48000000U /*初始化總線時鐘頻率為48MHz*/
修改為
#define CPU_BUS_CLK_HZ 50000000U /*初始化總線時鐘頻率為50MHz*/
#define CPU_CORE_CLK_HZ 96000000U /* 初始化內核、系統時鐘頻率為96MHz */
修改為
#define CPU_CORE_CLK_HZ 100000000U /* 初始化內核、系統時鐘頻率為100MHz */
#define CPU_CLOCK_CONFIG_NUMBER 0x03U /* 定義時鐘配置的個數,時鐘配置有0,1和2,共3種可以選擇*/
#define CPU_BUS_CLK_HZ_CLOCK_CONFIG0 48000000U /*在時鐘配置0中的總線時鐘頻率為48MHz */
修改為
#define CPU_BUS_CLK_HZ_CLOCK_CONFIG0 50000000U /*在時鐘配置0中的總線時鐘頻率為50MHz */
#define CPU_CORE_CLK_HZ_CLOCK_CONFIG0 96000000U /* 在時鐘配置0中的內核、系統時鐘頻率為96MHz*/
修改為
#define CPU_CORE_CLK_HZ_CLOCK_CONFIG0 100000000U /* 在時鐘配置0中的內核、系統時鐘頻率為100MHz*/
#define CPU_XTAL_CLK_HZ 50000000U /* 外部晶體或者振蕩器的時鐘頻率為50MHz*/
修改為
#define CPU_XTAL_CLK_HZ 25000000U /* 外部晶體或者振蕩器的時鐘頻率為25MHz*/
相應的,對于使用的時鐘配置0或者1或者2也需要修改,如果目標配置使用的是時鐘配置0,可以參照如下代碼修改。如果不使用時鐘配置1或者2,則不需要做修改。
/* 在時鐘配置0中的CPU時鐘頻率 */
#define CPU_CLOCK_CONFIG_0 0x00U /* 時鐘配置0的定義 */
修改內核時鐘頻率,默認的是96MHz,改為100MHz。
#define CPU_CORE_CLK_HZ_CONFIG_0 100000000UL /* 內核時鐘頻率為100MHz*/
修改總線時鐘頻率,默認是48MHz,修改為50MHz。
#define CPU_BUS_CLK_HZ_CONFIG_0 50000000UL /* 總線時鐘頻率為50MHz*/
修改Flash時鐘頻率,默認是24MHz,修改為25MHz。
#define CPU_FLASH_CLK_HZ_CONFIG_0 25000000UL /* FLASH時鐘頻率為25MHz*/
#define CPU_PLL_FLL_CLK_HZ_CONFIG_0 100000000UL /* PLL/FLL時鐘頻率為100MHz*/
#define CPU_OSCER_CLK_HZ_CONFIG_0 50000000UL
/*在時鐘配置0中的系統OSC 外部參考時鐘 */
手工書寫代碼相對繁瑣,更方便的方法是使用Freescale的Processor Expert 工具,根據硬件的需要來設置時鐘,生成的如下的代碼。通過PE工具來對CPU和各種外設進行設置,只需了解它的原理和用法,而不用把精力花在了解寄存器的具體細節上。打開PE后,參照圖7的配置進行設置,點擊Project-》Generator Processor Expert Code即可生成代碼。記住重新修改配置后需要點擊Project-》Clean,清掉上次生成的代碼,然后再執行生成代碼的操作。
void __pe_initialize_hardware(void)
{
_bsp_watchdog_disable();
/* 關閉 WDOG 模塊 */
WDOG_UNLOCK = WDOG_UNLOCK_WDOGUNLOCK(0xC520);
WDOG_UNLOCK = WDOG_UNLOCK_WDOGUNLOCK(0xD928);
WDOG_STCTRLH = WDOG_STCTRLH_STNDBYEN_MASK | WDOG_STCTRLH_WAITEN_MASK | WDOG_STCTRLH_STOPEN_MASK | WDOG_STCTRLH_ALLOWUPDATE_MASK | WDOG_STCTRLH_CLKSRC_MASK;
/* 系統時鐘初始化 */
/* SIM_SCGC5: PORTA=1 */
SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV2(0x01) | SIM_CLKDIV1_OUTDIV3(0x03) |
SIM_CLKDIV1_OUTDIV4(0x03); /* 更新系統預分頻器 */
SIM_SOPT1 &= (uint32_t)~(uint32_t)(SIM_SOPT1_OSC32KSEL_MASK);
PORTA_PCR18 &= (uint32_t)~(uint32_t)((PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x07)));
PORTA_PCR19 &= (uint32_t)~(uint32_t)((PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x07)));
/*切換到FBE 模式*/
OSC_CR = OSC_CR_ERCLKEN_MASK;
SIM_SOPT2 &= (uint32_t)~(uint32_t)(SIM_SOPT2_MCGCLKSEL_MASK);
MCG_C2 = (MCG_C2_RANGE(0x02) | MCG_C2_EREFS_MASK);
MCG_C1 = (MCG_C1_CLKS(0x02) | MCG_C1_FRDIV(0x05) | MCG_C1_IRCLKEN_MASK);
MCG_C4 &= (uint8_t)~(uint8_t)((MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS(0x03)));
MCG_C5 = MCG_C5_PRDIV(0x07);
MCG_C6 = MCG_C6_VDIV(0x08);
while((MCG_S & MCG_S_OSCINIT_MASK) == 0x00U) { /*判斷晶振是否運行?*/
}
while((MCG_S & MCG_S_IREFST_MASK) != 0x00U) {
/* 判斷FLL參考源是否為外部參考時鐘 */
}
while((MCG_S & 0x0CU) != 0x08U) { //等待,直到外部參考時鐘作為MCG的輸出
}
/* 切換到 PBE 模式*/
OSC_CR = OSC_CR_ERCLKEN_MASK;
SIM_SOPT2 &= (uint32_t)~(uint32_t)(SIM_SOPT2_MCGCLKSEL_MASK);
MCG_C1 = (MCG_C1_CLKS(0x02) | MCG_C1_FRDIV(0x05) | MCG_C1_IRCLKEN_MASK);
MCG_C2 = (MCG_C2_RANGE(0x02) | MCG_C2_EREFS_MASK);
MCG_C5 = MCG_C5_PRDIV(0x07);
MCG_C6 = (MCG_C6_PLLS_MASK | MCG_C6_VDIV(0x08));
while((MCG_S & 0x0CU) != 0x08U) { /*等待,直到外部參考時鐘作為MCG輸出*/
}
while((MCG_S & MCG_S_LOCK_MASK) == 0x00U) { /* 等待直到鎖住*/
}
/* 切換到 PEE模式 */
OSC_CR = OSC_CR_ERCLKEN_MASK;
SIM_SOPT2 &= (uint32_t)~(uint32_t)(SIM_SOPT2_MCGCLKSEL_MASK);
MCG_C1 = (MCG_C1_FRDIV(0x05) | MCG_C1_IRCLKEN_MASK);
MCG_C2 = (MCG_C2_RANGE(0x02) | MCG_C2_EREFS_MASK);
MCG_C5 = MCG_C5_PRDIV(0x07);
MCG_C6 = (MCG_C6_PLLS_MASK | MCG_C6_VDIV(0x08));
while((MCG_S & 0x0CU) != 0x0CU) { /* 等待,直到PLL輸出*/
}
}
圖7. PE設置
MQX4.0中PE的時鐘初始化代碼在bsp_cm.c文件的void __pe_initialize_hardware(void)函數中。可以將上述PE生成的代碼直接粘貼在該文件中。調試可能會出現系統時鐘配置錯誤。當出現此類錯誤時,程序可能會停在圖8所示的dispatch.s文件中的等待中斷的語句cpsid.n i處。這種錯誤往往是由于只修改了部分的時鐘寄存器設置或者是直接使用其他系列的Kinetis的BSP包中的時鐘配置,而沒有做相應的修改所造成的。例如,直接使用K60 BSP包的默認時鐘部分代碼,在K10的25Mhz外部時鐘環境中進行調試就會出現上述錯誤。這里不建議手工書寫代碼或者直接拷貝其他Kinetis系列的不同時鐘配置的代碼,建議使用PE來配置生成時鐘代碼,對于有錯誤的部分PE中會有相關的紅色提示符標示出來,因此不用擔心那些時鐘寄存器配置錯誤或被遺漏了。
圖8. dispatch.s代碼
一般地,在user_config.h配置中,RTC是默認使能的,也就是外部的32.768Khz晶振是需要外接的,如果不外接,可以將配置文件user_config.h中的宏定義語句:
#define BSPCFG_ENABLE_RTCDEV 1 修改為
#define BSPCFG_ENABLE_RTCDEV 0
另外由于K10中不包含USB和以太網的代碼,所以需要將相關的USB,Ethernet的文件刪除,并將user_config.h頭文件中的宏定義修改為:
#define RTCSCFG_ENABLE_ICMP 0
#define RTCSCFG_ENABLE_UDP 0
#define RTCSCFG_ENABLE_TCP 0
#define RTCSCFG_ENABLE_STATS 0
#define RTCSCFG_ENABLE_GATEWAYS 0
#define FTPDCFG_USES_MFS 0
#define RTCSCFG_ENABLE_SNMP 0
#define TELNETDCFG_NOWAIT FALSE
#define HTTPDCFG_POLL_MODE 0
#define HTTPDCFG_STATIC_TASKS 0
#define HTTPDCFG_DYNAMIC_TASKS 0
4. BSP包代碼的調試
4.1. 創建一個 簡單任務并運行
為了證明所創建的BSP是可以正常工作的,這里建一個最簡單的IAR的工程,如圖9所示,它包含了我們所創建的基于MQX 4.0的 K10DN512 的BSP庫。
圖9 建立一個IAR工程
選擇保存工程的文件目錄位置如下:C:FreescaleFreescale_MQX_4_0demoK10DN512 Demo。在main.c中添加如下的代碼:
#include
#include
#define MAIN_TASK 15
#define STACK_SIZE 1024
#define MAIN_STACK STACK_SIZE
extern void main_task(uint_32);
extern “C” const TASK_TEMPLATE_STRUCT MQX_template_list[] =
{
// Task Index, Function, Stack, Priority, Name, Attributes, Param, Time Slice */
{ MAIN_TASK, main_task, MAIN_STACK, 11, “main_task”, MQX_AUTO_START_TASK, 0, 0 },
{ 0 }
};
void main_task(uint_32 parameter)
{
while(1)
{
puts(“A”);
}
}
需要將C:FreescaleFreescale_MQX_4_0libK10DN512.iardebugsp中的bsp.a庫文件,以及C:FreescaleFreescale_MQX_4_0libK10DN512.iardebugpsp中的psp.a庫文件添加到工程中去。如下圖10所示,點擊main選擇右鍵option for node “main”,并在C/C++ Compiler的預處理器preprocessor和Assembler中設置文件的路徑如下。
C:FreescaleFreescale_MQX_4_0libK10DN512.iardebugsp
C:FreescaleFreescale_MQX_4_0libK10DN512.iardebugpsp
C:FreescaleFreescale_MQX_4_0libK10DN512.iardebugspGenerated_Code
C:FreescaleFreescale_MQX_4_0libK10DN512.iardebug
圖10. 在Option選項中設置
注意需要將 文件拷貝到C:FreescaleFreescale_MQX_4_0libK10DN512.iardebugpsp文件夾中。
編譯完成后,通過JLINK等燒寫工具將軟件下載到目標板后開始運行,系統運行的界面如圖11所示。如果系統進不了main函數,說明MQX bsp系統移植還有問題,需要按照前面介紹的步驟進行仔細的檢查。
圖11 復位后運行進入main函數
系統進入main函數,在mqx函數處設置斷點,點擊圖標go運行,程序進入mqx初始化部分,如圖12所示。
圖12 mqx初始化
在main_task中設置斷點,再次運行,如圖13所示,在IAR 的JLINK任務欄中可以找到TASK LIST列表。這里需要注意的是,需要在IAR的環境下,將option下debug插件的MQX勾選,如圖14所示,勾選后才可以看到MQX的TASK等任務信息。
圖13 主任務運行
圖14 選取MQX
4.2 GPIO配置與任務調試
在MQX4.0安裝目錄C:FreescaleFreescale_MQX_4_0mqxexamples下可以找到很多參考例程,包括ADC、 Hello、 I2C、 Lowpower、 Timer等。這里采用使用的最多的GPIO例程來驗證BSP是否能正常工作。
由于在默認的bsp包中user_config.h中沒有配置使能BSPCFG_ENABLE_GPIODEV外設,需要在該文件中加入語句#define BSPCFG_ENABLE_GPIODEV 1,如下圖15所示。
圖15 使能GPIO任務配置
在這里,為了驗證MQX4.0版本操作系統對于MQX3.8等早期版本軟件代碼的兼容性,本例使用的源程序 代碼,可以在MQX3.8版本的安裝目錄中C:FreescaleFreescale MQX 3.8mqxexamplesgpio找到。直接將該文件添加到工程中,如圖16所示,在IAR的主程序中,在讀IO狀態處設置斷點,系統執行到此斷點處,如果開啟IAR任務欄的TASK List, 在Stack Uage Summary窗口可以看到任務和棧的運行情況。
圖16 GPIO任務 運行
這里需要注意的是,代碼中用到了一些BSP_BUTTON1,BSP_LED1等宏定義,這些宏定義在MQX4.0的安裝目錄C:FreescaleFreescale_MQX_4_0mqxsourcespK10DN512的K10DN512.H文件中可以找到,例如BSP_LED1中的宏定義如下:
#define BSP_LED1 (GPIO_PORT_A | GPIO_PIN11)
如果目標板中的LED引腳和默認的設置不一樣,需要對其進行修改,然后重新編譯。
另外在通過下載工具調試代碼的時候,需要指定icf配置文件,如圖17所示。這里K10DN512和K60DN512的Flash大小一樣,不需要做修改。如果使用其他不同配置的芯片則需要對Memory Region進行調整。
圖17 ICF文件的位置指定
5. 總結
本文介紹了如何基于飛思卡爾的MQX操作系統,創建并移植目標MCU的 BSP包,并可以針對不同的開發平臺(CW, KEIL, IAR)定制適合目標芯片的BSP。
評論