1、將下載的rt-thread-2.0.1解壓后,得到如下圖所示的文件列表。
在bsp目錄下可以找到stm32f40x文件夾,這文件夾里面包括了庫函數,其他芯片平台的文件夾統統刪掉。在libcpu下,只需要將arm文件夾里面的common和cortex-m4留下來,其他的也都統統刪掉。還有其他一些輔助性的文件,如:documentation、examples、tools什么的我們也統統刪掉,處理完這些后,一個干凈的RTT就准備好了。
2、雖然RT-thread將文件分類的很好,但最好還是根據自己的項目習慣將整個項目整理一下。將整個軟件項目分成四個部分:app,bsp,mdk,rt-thread-2.0.1。如下圖所示。
app:應用層,存放項目開發時自己編寫的應用文件
bsp:驅動層,里面主要包括了RT-thread在stm32f40x平台中的底層驅動(applications,drivers,libraries_1.5.0),以及項目所使用的外設驅動(peripheral)
mdk:存放keil mdk5.15的相關工程文件
rt-thread-2.0.1:系統層,存放rt-thread-2.0.1中的components(系統組件),include(系統內核頭文件),libcpu(芯片移植)和src(系統內核源文件)
3、安裝好keil mdk5.15后,新建項目工程文件並保存在mdk文件夾中。根據項目文件分類添加源文件,如下圖所示。
然后向工程添加頭文件目錄,如下圖所示。
4、配置stm32f407vgt6系統時鍾
(1)在stm32f4xx.h文件中選擇#define STM32F40_41xxx以及#define USE_STDPERIPH_DRIVER;
(2)修改stm32f4xx.h文件中默認的系統外部晶振時鍾#define HSE_VALUE ((uint32_t)8000000)
(3)修改system_stm32f4xx.c文件中所選器件有關系統時鍾的PLL_M,PLL_N的值(PLL_P=2)。對於stm32f407xx,系統時鍾為168MHZ,一般只需修改PLL_M,PLL_N。
#if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F401xx)
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
#define PLL_M 8
......
#if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F446xx)
#define PLL_N 336
/* SYSCLK = PLL_VCO / PLL_P */
(4)使用stm32f40_41xxx的FPU,需要在SystemInit函數開頭添加相關語句,同時在keil工程配置中Floating Point Hardware選擇 "Use Single Precision" 。
(在stm32f4xx.h中已默認設置#define __FPU_PRESENT 1,在core_cm4.h中已默認設置__FPU_USED == 1)。
/* FPU settings ------------------------------------------------------------
* If no this settings,it maybe enter HardFault_Handler() interrupt when mdk complier chose "Use Single Precision" to use FPU instruction. */
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
(5)在stm32f4xx_it.h和stm32f4xx_it.c中將HardFault_Handler,PendSV_Handler以及SysTick_Handler三個中斷入口函數注釋掉。
HardFault_Handler,PendSV_Handler在context_rvds.S文件中分別實現RT-thread系統異常處理和線程切換;
SysTick_Handler在board.c中實現RT-thread系統時鍾節拍計數。
(6)在board.h中確定stm32f407的SRAM大小,以及SRAM結束地址。stm32f407vg共有192K的SRAM(其中可被訪問的只有128k,起始地址為0x20000000)。
// <o> Internal SRAM memory size[Kbytes] <8-64>
// <i>Default: 64
#define STM32_SRAM_SIZE 128
#define STM32_SRAM_END (0x20000000 + STM32_SRAM_SIZE * 1024)
5、若需要在項目中啟用finsh組件以及組件初始化函數,為了保證用戶自行編寫的函數不會被keil編譯器優化掉,則需要修改MDK設置,如下:
在Linker->Misc controls標簽下,鍵入”--keep __fsym_* --keep __vsym_* --keep __rt_init_*”這個命令,該命令會保留未被函數主體調用的函數。這樣在使用finsh組件調試時仍然可以運行沒有被調用過的函數。
6、修改系統配置文件rtconfig.h的相關系統參數,如下面所示為系統基礎配置:
/* RT-Thread config file */ #ifndef __RTTHREAD_CFG_H__ #define __RTTHREAD_CFG_H__ /* RT_NAME_MAX*///指定了系統內核對象名稱的最大長度(比如線程,信號量,互斥鎖,事件等),多余部分會自動裁掉 #define RT_NAME_MAX 8 /* RT_ALIGN_SIZE*///大多數系統需要對棧空間地址對齊(例如ARM體系結構中需要向4字節地址對齊),系統默認設置為4字節對齊,這里可設置以8字節對齊 #define RT_ALIGN_SIZE 8 /* PRIORITY_MAX *///RT-thread最大可支持256個線程優先級(0~255,0為最高優先級,255分配給空閑線程)。在資源有限情況下,一般設置為最大支持8個或32個優先級。 #define RT_THREAD_PRIORITY_MAX 32 /* Tick per Second *///系統時鍾每秒節拍數,1000表示1s內rt_tick增加1000,即時鍾節拍為1ms;若設為100,則rt_tick每隔10ms加1,時鍾節拍為10ms。 #define RT_TICK_PER_SECOND 1000 /* Using Hook *///使用鈎子(回調)函數 #define RT_USING_HOOK /* Idle thread stack *///設置空閑線程的棧空間大小為1024字節 #define IDLE_THREAD_STACK_SIZE 1024 /* Using Software Timer *///軟件定時器線程模式(這里不采用該模式)。RT-thread系統時鍾一般默認采用所選芯片平台的硬件定時器中斷模式 // #define RT_USING_TIMER_SOFT #define RT_TIMER_THREAD_PRIO 4 #define RT_TIMER_THREAD_STACK_SIZE 512 /* SECTION: RT_DEBUG *///線程調試以及組件初始化模塊 /* Thread Debug */ #define RT_DEBUG #define RT_DEBUG_INIT 1 //組件初始化調試模式(若不需要通過串口控制台向PC端打印初始化信息,則沒有必要啟用該模式) #define RT_USING_COMPONENTS_INIT //啟用組件初始化功能 #define RT_USING_OVERFLOW_CHECK //啟用線程棧溢出檢查 /* SECTION: IPC *///進程間通信內核對象:信號量,互斥鎖,事件,郵箱,消息隊列 /* Using Semaphore*/ #define RT_USING_SEMAPHORE /* Using Mutex */ #define RT_USING_MUTEX /* Using Event */ #define RT_USING_EVENT /* Using MailBox */ #define RT_USING_MAILBOX /* Using Message Queue */ #define RT_USING_MESSAGEQUEUE /* SECTION: Memory Management *///RT-thread系統內存管理:使用靜態內存池,動態堆(小內存管理算法) /* Using Memory Pool Management*/ #define RT_USING_MEMPOOL
/* Using Dynamic Heap Management */ #define RT_USING_HEAP /* Using Small MM */ #define RT_USING_SMALL_MEM /* SECTION: Device System *///系統組件之I/O設備管理:啟用I/O設備以及設備間通信 /* Using Device System */ #define RT_USING_DEVICE //根據rtdevice.h中所有設備的宏定義,在rtconfig.h中打開相應宏定義,如以下4類設備 /* Using GPIO pin framework *///GPIO設備 #define RT_USING_PIN /* Using serial framework */ //串口設備 #define RT_USING_SERIAL /* Using SPI framework */ //SPI設備 #define RT_USING_SPI /* Using I2C framework */ //I2C設備 #define RT_USING_I2C #define RT_USING_I2C_BITOPS /* SECTION: Console options *///系統控制台:啟用控制台以及設置控制台設備緩存256字節。若使用rt_kprintf向PC端打印信息,則必須啟用控制台並設置控制台設備(如串口)。 #define RT_USING_CONSOLE /* the buffer size of console*/ #define RT_CONSOLEBUF_SIZE 256 /* SECTION: finsh, a C-Express shell *///finsh組件(finsh是RT-thread系統的命令行外殼,提供一套供用戶在命令行的接口,主要用於調試,查看系統信息) #define RT_USING_FINSH /* Using symbol table */ #define FINSH_USING_SYMTAB #define FINSH_USING_DESCRIPTION /* SECTION: device filesystem *///文件系統 /* Using Device file system */ //在項目中沒有使用文件系統 // #define RT_USING_DFS /* the max number of mounted filesystem */ #define DFS_FILESYSTEMS_MAX 2 /* the max number of opened files */ #define DFS_FD_MAX 4 /* Using ELM FATFS *///ELM FATFS文件系統(在項目中沒有使用) // #define RT_USING_DFS_ELMFAT #define RT_DFS_ELM_WORD_ACCESS /* Reentrancy (thread safe) of the FatFs module. */ #define RT_DFS_ELM_REENTRANT /* Number of volumes (logical drives) to be used. Each volumes maybe include one primaly partition and some logical partitions. * If _MULTI_PARTITION is defined to 0 in ffconf.h, each volume can mount only first primaly partition */ #define RT_DFS_ELM_DRIVES 2 /* Long File Name(LFN) with dynamic LFN working buffer on the heap. */ #define RT_DFS_ELM_USE_LFN 3 #define RT_DFS_ELM_MAX_LFN 255 /* The _CODE_PAGE specifies the OEM code page to be used on the target system. 936-Simplified Chinese GBK (DBCS, OEM, Windows); 437 - U.S.(OEM) */ #define RT_DFS_ELM_CODE_PAGE 437 /* Maximum sector size to be handled. It must be the real size(byte) of spiflash sectors. */ #define RT_DFS_ELM_MAX_SECTOR_SIZE 4096 /* Using ROM file system *///ROMFS文件系統(在項目中沒有使用) // #define RT_USING_DFS_ROMFS /* SECTION: lwip, a lighwight TCP/IP protocol stack *///輕型TCP/IP協議棧(在項目中沒有使用) // #define RT_USING_LWIP /* LwIP uses RT-Thread Memory Management */ #define RT_LWIP_USING_RT_MEM /* Enable ICMP protocol*/ #define RT_LWIP_ICMP /* Enable UDP protocol*/ #define RT_LWIP_UDP /* Enable TCP protocol*/ #define RT_LWIP_TCP /* Enable DNS */ #define RT_LWIP_DNS /* the number of simulatenously active TCP connections*/ #define RT_LWIP_TCP_PCB_NUM 5 /* ip address of target*/ #define RT_LWIP_IPADDR0 192 #define RT_LWIP_IPADDR1 168 #define RT_LWIP_IPADDR2 1 #define RT_LWIP_IPADDR3 201 /* gateway address of target*/ #define RT_LWIP_GWADDR0 192 #define RT_LWIP_GWADDR1 168 #define RT_LWIP_GWADDR2 1 #define RT_LWIP_GWADDR3 1 /* mask address of target*/ #define RT_LWIP_MSKADDR0 255 #define RT_LWIP_MSKADDR1 255 #define RT_LWIP_MSKADDR2 255 #define RT_LWIP_MSKADDR3 0 /* tcp thread options */ #define RT_LWIP_TCPTHREAD_PRIORITY 12 #define RT_LWIP_TCPTHREAD_MBOX_SIZE 4 #define RT_LWIP_TCPTHREAD_STACKSIZE 1024 /* ethernet if thread options */ #define RT_LWIP_ETHTHREAD_PRIORITY 15 #define RT_LWIP_ETHTHREAD_MBOX_SIZE 4 #define RT_LWIP_ETHTHREAD_STACKSIZE 512 /* TCP sender buffer space */ #define RT_LWIP_TCP_SND_BUF 8192 /* TCP receive window. */ #define RT_LWIP_TCP_WND 8192 #define CHECKSUM_CHECK_TCP 0 #define CHECKSUM_CHECK_IP 0 #define CHECKSUM_CHECK_UDP 0 #define CHECKSUM_GEN_TCP 0 #define CHECKSUM_GEN_IP 0 #define CHECKSUM_GEN_UDP 0 /* RT_GDB_STUB *///GDB調試工具(在項目中沒有使用) //#define RT_USING_GDB #endif