44 RT-Thread Nano移植到stm32F103CBT6 (STD标准库)
一、前言
最近在學習rt-thread,然后網上有介紹用RT-Thread Studio和stm32cubex結合進行開發,還有用rt-thread nano提供的pack直接開發,但是這種方式真的不太行,對于新手而言,不能很好的了解整個代碼的結構。
為此,就懷著跟前面網友一樣的心思,準備要自己拷貝代碼,一步一步來對rt-thread進行移植,然后發現還是挺簡單的,如果rt-thread已經移植過相應的cpu的話,那簡直移植的方便就超級簡單了。
本文章把rt-thread nano移植到stm32f103c8t6,然后也是基于STD標準庫進行移植的,網上比較多的是基于HAL庫進行移植的,寫該文章一是為了下次自己回來看的時候能記憶起來;二是也為新手提供一種思路,如果他們要學習的話。
然后再說說,為什么選用rt-thread,第一是因為國產;第二是因為它能有像Linux的控制臺;第三我只想要用一個線程調用的核,所以就選用了它!!挺好的加入支持國產的道路。
二、rt-thread移植記錄
本次移植RT-Thread Nano內核到一個stm32f103cBt6標準庫的一個led工程中,所以需要準備一個點燈程序,其目錄如下圖示。
?
?
移植前的led點燈工程主程序,以及編譯后的大小如下圖示。移植前程序所占ROM大小為:2216+268=2484字節;所用RAM:3840+48=3888字節;
2.下載RT-Thread Nano內核
首先,到官網上下載RT-Thread Nano源碼,如下圖示,本次下載的是rt-thread-3.1.3。下載鏈接:https://www.rt-thread.org/page/download.html
3.拷貝文件到目標led工程
首先,在原有的led工程的目錄下,建立一個RT-Thread目錄,如下圖示。
然后打開rt-thread-3.1.3,拷貝下面三個目錄的內容到剛建好的RT-Thread目錄中。
拷貝完成后,刪除掉libcpu里面沒用到的文件,留下有用的。
最后只剩下面這個cortex-m3目錄。
然后打開rt-thread-3.1.3目錄下的dsp木,把拷貝board.c和rtconfig.h到工程的RT-Thread目錄下。
4.添加目錄及文件到led的keil工程。
把board.c和rtconfig.h兩個文件,添加這兩個文件到User目錄下。
5.編譯工程解決錯誤
編譯的時候肯定會出現這三個問題,打開代碼,定位到這三個函數,把led工程原有的這三個函數注釋掉,因為RT-Thread已經實現了這三個函數,所以導致重定義。
注釋:HardFault_Handler,如下圖示:
注釋:PendSV_Handler和SysTick_Handler
然后編譯,發現編譯通過,然后繼續移植。
6.更改board.c文件
RT-Thread系統框架下,設備的時鐘及硬件初始化都是放在board.c文件中的,我們只需要在rt_hw_board_init函數配置好,系統時鐘和滴答定時器。
然后我把自己的main函數的時鐘初始化SystemInit函數拷貝到rt_hw_board_init函數中。
主函數改成這樣。
int main(void) {LED_Init(); //LED 端口初始化 while(1){LED_SetRGBLight(RGBLED_MODE_Y);rt_thread_mdelay(1000);LED_SetRGBLight(RGBLED_MODE_G);rt_thread_mdelay(1000);}return 0; }然后對工程重新編譯,給予RT-Thread 內核的led工程編譯通過,下載到開發板,led正常一閃一閃。
編譯前我把郵箱和信號量的宏注釋掉,關閉了線程通信的方式,所以可以看到移植后,代碼量ROM:4004+576=4580,RAM:4720+112=4832
7.添加Finish控制臺
第一步:在rtconfig.h中確定RT_USING_CONSOLE和RT_USING_FINSH已經打開,如圖所示。
第二步,串口初始化。
首先,在board.c實現rt_hw_console_getchar函數,然后再kservice實現rt_hw_console_output函數,下列使用的是標準庫,如下圖所示。
char rt_hw_console_getchar(void) {int ch = -1;if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET){ch = (int)USART_ReceiveData(USART1);}else{if(USART_GetFlagStatus(USART1, USART_FLAG_ORE) != RESET){USART_ClearFlag(USART1,USART_FLAG_TC);}rt_thread_mdelay(10);}return ch; } RT_WEAK void rt_hw_console_output(const char *str) {/* empty console output */rt_size_t i = 0, size = 0;char a = '\r';USART_ClearFlag(USART1, USART_FLAG_TC);size = rt_strlen(str);for (i = 0; i < size; i++){if (*(str + i) == '\n') {USART_SendByte(USART1, a);}USART_SendByte(USART1, *(str + i));} }?
然后實現串口初始化,如下圖示。但這里有一個坑,因為默認的shell使用的是輪詢的方式實現,所以串口初始化這里,不能啟動中斷接收,否則shell將不正常。
void uart1_init(u32 bound) {//GPIO端口設置GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //使能USART1,GPIOA時鐘//USART1_TX GPIOA.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復用推挽輸出GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9//USART1_RX GPIOA.10初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//浮空輸入GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10 //Usart1 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//搶占優先級3NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子優先級3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能NVIC_Init(&NVIC_InitStructure); //根據指定的參數初始化VIC寄存器//USART 初始化設置USART_DeInit(USART1);USART_InitStructure.USART_BaudRate = bound;//串口波特率USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字長為8位數據格式USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個停止位USART_InitStructure.USART_Parity = USART_Parity_No;//無奇偶校驗位USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無硬件數據流控制USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收發模式USART_Init(USART1, &USART_InitStructure); //初始化串口1//USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//開啟串口接受中斷USART_Cmd(USART1, ENABLE); //使能串口1 USART_ClearFlag(USART1, USART_FLAG_TC); }然后,將初始化放在board.c的rt_hw_board_init函數里面,如下圖示。
void rt_hw_board_init() {SystemInit(); //配置系統時鐘為72M /* System Tick Configuration */_SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);uart1_init(115200); //調試串口/* Call components board initial (use INIT_BOARD_EXPORT()) */ #ifdef RT_USING_COMPONENTS_INITrt_components_board_init(); #endif#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get()); #endif }到此,算是通過拷貝代碼的方式將rt-thread搞到自己的開發板上了吧!
over!
?
總結
以上是生活随笔為你收集整理的44 RT-Thread Nano移植到stm32F103CBT6 (STD标准库)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大数据中心成立ppt_大数据中心建设思路
- 下一篇: CSS flex样式垂直居中