定制型網(wǎng)站制作明細(xì)報價表百度應(yīng)用中心
一、寫在前面
關(guān)于源碼的下載,以及在KEIL工程里面添加操作系統(tǒng)的源代碼,這里就不再贅述了。需要注意的是RT-thread默認(rèn)里面是會使用串口的,因此需要額外的進行串口的初始化,有些人可能會問,為什么不直接使用CubMAX直接進行系統(tǒng)的移植,經(jīng)過我的嘗試發(fā)現(xiàn),這個玩意移植的RT-thread會有一些小的bug,比如直接生成的代碼FinSH工作不正常,修改方法和第七節(jié)一樣。雖然整個系統(tǒng)的調(diào)度啥的都是正常的。因此我決定另辟蹊徑,其他的功能使用CubMAX進行設(shè)置,因為他簡直太方便了,然后RT-thread的移植采用手動的方法進行。
二、移植前的準(zhǔn)備工作
因為RT-thread的源碼里面有這些中斷處理函數(shù)的實現(xiàn),因此需要將上面的這些都關(guān)閉掉,不然編譯會出現(xiàn)重復(fù)定義的錯誤。
?我這里使用的是串口1,因此先完成他的相關(guān)設(shè)置。
三、將RT-thread的源碼添加到工程里面
都添加進行以后,然后不要忘了設(shè)置頭文件的包含路徑。
四、進行第一次的編譯
?會發(fā)現(xiàn)錯誤很多,不慌。透過查看錯誤發(fā)現(xiàn)是因為va_list沒有定義引起的,我們知道va_list是定義在stdarg.h里面的,然后通過觀察頭文件的包含發(fā)現(xiàn),這個頭文件在下面這個文件里面定義著,顯然是因為RT_USING_LIBC這個宏,沒有打開導(dǎo)致的。在rtconfig.h里面添加這個宏定義即可。
?五、進行第二次編譯
我們發(fā)現(xiàn)編譯很成功,沒有錯誤也沒有警告,這時你可能已經(jīng)覺得成功了,我只能說我當(dāng)時也是這么想的,結(jié)果發(fā)現(xiàn)程序運行那是,相當(dāng)?shù)牟徽?。需要解決這個問題我們得知道RT-thread啟動的流程,其實你只需要知道他在運行我們的main函數(shù)之前,會運行一段自己的代碼,
?然后我們進入這個函數(shù)發(fā)現(xiàn),這里是關(guān)于系統(tǒng)的初始化,有很多。
?接下來我們進入第一個初始化函數(shù)里面。將串口的初始化放在這里,注意需要包含相關(guān)的頭文件。有了串口我們就可以使用printf函數(shù)來進行調(diào)試了。
?當(dāng)我們進入到第二個初始化函數(shù)里面我們發(fā)現(xiàn),這里有一些輸出,但是要想使用這些輸出我們需要實現(xiàn)void rt_hw_console_output(const char *str)這個函數(shù),在board.c里面其實已經(jīng)有關(guān)于這個函數(shù)的實現(xiàn),他是用RT_USING_CONSOLE這個宏來進行控制的,因此需要在trconfig.h里面打開這個宏
?你會發(fā)現(xiàn)串口里面還是沒有我們想要的輸出,通過觀察發(fā)現(xiàn)雖然我們自己將串口進行了初始化,但是系統(tǒng)這里使用的是串口2,因此需要將他改成你初始化的那個串口,我這里改成串口1。
?到這里我們的串口就能正常工作了。下面這個是串口的輸出。
?到這里如果你創(chuàng)建一個任務(wù),然后你會神奇的發(fā)現(xiàn)這個任務(wù)好像并沒有執(zhí)行,也就是說我們的系統(tǒng)并沒有完全初始化成功。因為在RT-thread里面創(chuàng)建任務(wù)的時候有兩種分配內(nèi)存的方式,第一種就是靜態(tài)分配,第二種就是動態(tài)分配。RT-thread默認(rèn)使用的是動態(tài)分配,我想會不會是這里的問題,我就將關(guān)于動態(tài)分配的相關(guān)配置注釋掉了。到這里整個系統(tǒng)就算是初始化完畢,也正常運行起來了。需要注意的是我們這里所有的內(nèi)存分配都是靜態(tài)的,因此創(chuàng)建變量的時候一定要分配它的大小,不然會有很奇怪的問題。
?六、使用靜態(tài)方式創(chuàng)建任務(wù)
static struct rt_thread led1_thread;
/* 線程主體函數(shù) */
static void led1_thread_entry(void* parameter);
/* 定義線程棧 */
static rt_uint8_t rt_led1_thread_stack[1024];static struct rt_thread led0_thread;
/* 線程主體函數(shù) */
static void led0_thread_entry(void* parameter);
/* 定義線程棧 */
static rt_uint8_t rt_led0_thread_stack[1024];int main(void)
{MX_GPIO_Init();/* USER CODE BEGIN 2 */rt_thread_init(&led1_thread, /* 線程控制塊 */"led1", /* 線程名字 */led1_thread_entry, /* 線程入口函數(shù) */RT_NULL, /* 線程入口函數(shù)參數(shù) */&rt_led1_thread_stack[0], /* 線程棧起始地址 */sizeof(rt_led1_thread_stack), /* 線程棧大小 */3, /* 線程的優(yōu)先級 */20); /* 線程時間片 */rt_thread_init(&led0_thread, /* 線程控制塊 */"led0", /* 線程名字 */led0_thread_entry, /* 線程入口函數(shù) */RT_NULL, /* 線程入口函數(shù)參數(shù) */&rt_led0_thread_stack[0], /* 線程棧起始地址 */sizeof(rt_led0_thread_stack), /* 線程棧大小 */4, /* 線程的優(yōu)先級 */20); /* 線程時間片 */rt_thread_startup(&led1_thread);rt_thread_startup(&led0_thread); while (1){}}//LED1線程
static void led1_thread_entry(void* parameter)
{ while(1){LED1 = 0;rt_thread_delay(200); /* 延時200個tick */rt_kprintf("led1_thread running,LED1_ON\r\n");LED1 = 1; rt_thread_delay(500); /* 延時500個tick */rt_kprintf("led1_thread running,LED1_OFF\r\n");}
}static void led0_thread_entry(void* parameter)
{ while(1){LED0 = 0;rt_thread_delay(200); /* 延時200個tick */rt_kprintf("led0_thread running,LED0_ON\r\n");LED0 = 1; rt_thread_delay(500); /* 延時500個tick */rt_kprintf("led0_thread running,LED0_OFF\r\n");}
}
七、實現(xiàn)FinSH
?
?這個頭文件你可以通過CubMAX來生成,也可以在項目例程里面復(fù)制一個。然后運行有可能你的會運行成功,有可能并不會成功。失敗的界面是這樣的;
成功的界面是這樣的
如果失敗了,嘗試調(diào)整下圖的參數(shù)即可。