RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

RT-Thread啟動流程?RT-Thread如何支持不同開發(fā)板?

冬至子 ? 來源:dejavudwh ? 作者:dejavudwh ? 2023-08-10 15:29 ? 次閱讀

啟動流程
一個開發(fā)板上的RT-Thread的啟動流程可能是首先從bsp?當中鏈接腳本指定的startup_xxx.S?中的入口函數(shù)(ENTRY)或者復位異常處理函數(shù)(ResetHandler)開始運行,這部分我們在講?bsp?支持時會詳細講解。

之后跳入entry?函數(shù)(GCC,使用不同編譯器會進入不同的函數(shù))執(zhí)行,這里也可以跳入用戶自己的main函數(shù),但是需要用戶自己完成rtthread_startup?的工作。

這個函數(shù)十分簡單,首先先關中斷(關中斷操作由cpu支持部分提供),然后進入RT-Thread的全局初始化中。

#if defined (__CC_ARM)
extern int Super$main(void);
/* re-define main function /
int Sub$main(void)
{
rt_hw_interrupt_disable();
rtthread_startup();
return 0;
}
#elif defined( ICCARM )
extern int main(void);
/
__low_level_init will auto called by IAR cstartup /
extern void __iar_data_init3(void);
int __low_level_init(void)
{
// call IAR table copy function.
__iar_data_init3();
rt_hw_interrupt_disable();
rtthread_startup();
return 0;
}
#elif defined( GNUC )
extern int main(void);
/
Add -eentry to arm-none-eabi-gcc argument */
int entry(void)
{
rt_hw_interrupt_disable();
rtthread_startup();
return 0;
}
#endif

?rtthread_startup?是啟動流程當中的關鍵,首先rtthread_startup?會先調用rt_hw_board_init?,這個函數(shù)也由bsp支持部分提供,一般來說主要完成例如初始化中斷向量表、系統(tǒng)時鐘的初始化,設置輸出控制臺,同時初始化系統(tǒng)堆內存。

緊接著會調用rt_show_version?打印RT-Thread內核的系統(tǒng)版本信息,其中主要是利用控制臺(rt_printf?)進行輸出,通常來說是用戶在bsp支持中提供串口的注冊來實現(xiàn)的。以RT-Thread Simulator 例程來說,會通過設備驅動一路調用到bsp支持部分提供的串口輸出。

void rt_kprintf(const char *fmt, ...) ->
rt_size_t rt_device_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) ->
static rt_size_t rt_serial_write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t size) ->
rt_inline int _serial_poll_tx(struct rt_serial_device *serial, const rt_uint8_t *data, int length) ->

  • static int stm32_putc(struct rt_serial_device *serial, char c)
    

然后會調用rt_system_timer_init?初始化系統(tǒng)定時器鏈表,這個函數(shù)比較簡單,主要就是數(shù)據(jù)結構進行初始化。

緊接著會調用rt_system_scheduler_init?初始化RT-Thread系統(tǒng)調度器相關的數(shù)據(jù)結構:

線程優(yōu)先級鏈表:每一個優(yōu)先級對應一個鏈表,通過rt_thread?結構中的tlist?成員來進行相同優(yōu)先級線程的連接
當前線程優(yōu)先級
當前線程控制塊
?rt_thread_ready_priority_group?中的每一位代表1個優(yōu)先級,該位為1表示該優(yōu)先級下有就緒線程,該位為0表示該優(yōu)先級下沒有就緒線程
僵尸線程鏈表
void rt_system_scheduler_init(void)
{
register rt_base_t offset;
rt_scheduler_lock_nest = 0;
RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("start scheduler: max priority 0x%02xn",
RT_THREAD_PRIORITY_MAX));
for (offset = 0; offset < RT_THREAD_PRIORITY_MAX; offset ++)
{
rt_list_init(&rt_thread_priority_table[offset]);
}
rt_current_priority = RT_THREAD_PRIORITY_MAX - 1;
rt_current_thread = RT_NULL;
/* initialize ready priority group /
rt_thread_ready_priority_group = 0;
#if RT_THREAD_PRIORITY_MAX > 32
/
initialize ready table /
rt_memset(rt_thread_ready_table, 0, sizeof(rt_thread_ready_table));
#endif
/
initialize thread defunct */
rt_list_init(&rt_thread_defunct);
}
接下來會調用rt_application_init?初始化一個main主線程(并不會馬上運行),主要完成組件的初始化以及多核的處理,最后跳入用戶的main?函數(shù)

完成組件初始化的實現(xiàn)與rt_components_board_init?類似,在BSP支持部分講解。

void rt_application_init(void)
{
rt_thread_t tid;
#ifdef RT_USING_HEAP
tid = rt_thread_create("main", main_thread_entry, RT_NULL,
RT_MAIN_THREAD_STACK_SIZE, RT_MAIN_THREAD_PRIORITY, 20);
RT_ASSERT(tid != RT_NULL);
#else
rt_err_t result;
tid = &main_thread;
result = rt_thread_init(tid, "main", main_thread_entry, RT_NULL,
main_stack, sizeof(main_stack), RT_MAIN_THREAD_PRIORITY, 20);
RT_ASSERT(result == RT_EOK);
/* if not define RT_USING_HEAP, using to eliminate the warning */
(void)result;
#endif
rt_thread_startup(tid);
}
void main_thread_entry(void parameter)
{
extern int main(void);
extern int Super$main(void);
/
RT-Thread components initialization /
rt_components_init();
/
invoke system main function /
#if defined (__CC_ARM)
Super$main(); /
for ARMCC. */
#elif defined( ICCARM ) || defined( GNUC )
main();
#endif
}
void rt_components_init(void)
{
#if RT_DEBUG_INIT
int result;
const struct rt_init_desc *desc;
rt_kprintf("do components intialization.n");
for (desc = &__rt_init_desc_rti_board_end; desc < &__rt_init_desc_rti_end; desc ++)
{
rt_kprintf("initialize %s", desc->fn_name);
result = desc->fn();
rt_kprintf(":%d donen", result);
}
#else
const init_fn_t *fn_ptr;
for (fn_ptr = &__rt_init_rti_board_end; fn_ptr < &__rt_init_rti_end; fn_ptr ++)
{
(*fn_ptr)();
}
#endif
}

然后,rt_system_timer_thread_init?主要是初始化軟件定時器的列表,并且創(chuàng)建軟件定時器線程。而rt_thread_idle_init?創(chuàng)建空閑線程,在系統(tǒng)沒有任何用戶線程調度的時候,就會被調度起來,這個空閑線程主要是檢查系統(tǒng)有沒有已經消亡的線程,如果有,則把消亡線程的資源進行回收,如果系統(tǒng)使能了電源管理,則會讓系統(tǒng)進行低功耗模式。

最后通過rt_system_scheduler_start?開啟調度器。

BSP支持
首先需要提供startup_xxx.S?類似的啟動文件,一般來說可能包含中斷向量表以及默認的中斷服務函數(shù),以及選擇入口函數(shù),一般可能為_start?或者ResetHandler?。

AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
; External Interrupts
DCD WWDG_IRQHandler ; Window Watchdog
DCD PVD_IRQHandler ; PVD through EXTI Line detect
DCD TAMPER_IRQHandler ; Tamper
DCD RTC_IRQHandler ; RTC
DCD FLASH_IRQHandler ; Flash
DCD RCC_IRQHandler ; RCC
DCD EXTI0_IRQHandler ; EXTI Line 0
DCD EXTI1_IRQHandler ; EXTI Line 1
DCD EXTI2_IRQHandler ; EXTI Line 2
DCD EXTI3_IRQHandler ; EXTI Line 3
DCD EXTI4_IRQHandler ; EXTI Line 4
DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1
DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2
DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3
DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4
DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5
DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6
DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7
DCD ADC1_2_IRQHandler ; ADC1_2
DCD USB_HP_CAN1_TX_IRQHandler ; USB High Priority or CAN1 TX
DCD USB_LP_CAN1_RX0_IRQHandler ; USB Low Priority or CAN1 RX0
DCD CAN1_RX1_IRQHandler ; CAN1 RX1
DCD CAN1_SCE_IRQHandler ; CAN1 SCE
DCD EXTI9_5_IRQHandler ; EXTI Line 9..5
DCD TIM1_BRK_IRQHandler ; TIM1 Break
DCD TIM1_UP_IRQHandler ; TIM1 Update
DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation
DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare
DCD TIM2_IRQHandler ; TIM2
DCD TIM3_IRQHandler ; TIM3
DCD 0 ; Reserved
DCD I2C1_EV_IRQHandler ; I2C1 Event
DCD I2C1_ER_IRQHandler ; I2C1 Error
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SPI1_IRQHandler ; SPI1
DCD 0 ; Reserved
DCD USART1_IRQHandler ; USART1
DCD USART2_IRQHandler ; USART2
DCD 0 ; Reserved
DCD EXTI15_10_IRQHandler ; EXTI Line 15..10
DCD RTC_Alarm_IRQHandler ; RTC Alarm through EXTI Line
DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend
__Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors
AREA |.text|, CODE, READONLY
; Reset handler routine
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
bsp支持主要提供對開發(fā)板的硬件初始化(通過rt_hw_board_init?向上提供接口)以及各類外設的驅動。

以RT-Thread Simulator 例程為例:rt_hw_board_init?中主要完成HAL庫的初始化、時鐘配置和RT-Thread系統(tǒng)堆的初始化,以及rt_components_board_init?會完成硬件的初始化。

#define RT_DEBUG_INIT 0
/**

  • RT-Thread Components Initialization for board
    */
    void rt_components_board_init(void)
    {
    #if RT_DEBUG_INIT
    int result;
    const struct rt_init_desc *desc;
    for (desc = &__rt_init_desc_rti_board_start; desc < &__rt_init_desc_rti_board_end; desc ++)
    {
    rt_kprintf("initialize %s", desc->fn_name);
    result = desc->fn();
    rt_kprintf(":%d donen", result);
    }
    #else
    const init_fn_t *fn_ptr;
    for (fn_ptr = &__rt_init_rti_board_start; fn_ptr < & **rt_init_rti_board_end; fn_ptr++)
    {
    (fn_ptr)();
    }
    #endif
    }
    ?RT_USED?: attribute ((used))?,標識不允許編譯器進行優(yōu)化
    ?init_fn_t?:typedef int (init_fn_t)(void)?,函數(shù)指針
    ?##?:連接符
    ?SECTION?: attribute ((section(x)))?,執(zhí)行輸入節(jié)名稱
    所以INIT_EXPORT(rti_board_start, "0.end")?等價于__attribute
    ((used)) const init_fn_t __rt_init_rti_board_start attribute ((section(".rti_fn.""0.end"))) = rti_board_start?

static int rti_board_start(void)
{
return 0;
}
INIT_EXPORT(rti_board_start, "0.end");
#define INIT_EXPORT(fn, level) RT_USED const init_fn_t _ rt_init ##fn SECTION(".rti_fn."level) = fn
?rt_board_end?同理,所以rt_components_board_init?的含義則為執(zhí)行__rt_init_rti_board_start?到__rt_init_rti_board_end?之間函數(shù)

指定節(jié).rti_fn.1?,根據(jù)鏈接器節(jié)放置規(guī)則,將放置在.rti_fn.0.end?節(jié)和.rti_fn.1.end?節(jié)之間。

#define INIT_BOARD_EXPORT(fn) INIT_EXPORT(fn, "1")
所以RT-Thread提供了另一個宏,它的主要作用就是用來在初始化硬件時調用相應的函數(shù)。所以一些外設驅動初始化都展開了這個宏。以RT-Thread Simulator 例程為例:

INIT_BOARD_EXPORT(rt_hw_usart_init);
INIT_BOARD_EXPORT(rt_hw_pin_init);
總的來說,一個基本的BSP主要任務是建立讓操作系統(tǒng)運行的基本環(huán)境,所以大致需要完成的主要工作是:

初始化CPU內部寄存器,設定RAM工作時序。
實現(xiàn)時鐘驅動及中斷控制器驅動,完善中斷管理。
實現(xiàn)串口和 GPIO 驅動。
初始化動態(tài)內存堆,實現(xiàn)動態(tài)堆內存管理。
CPU支持
這部分官方文檔很詳細,可參考內核移植 (rt-thread.org)

嵌入式領域有多種不同 CPU 架構,例如 Cortex-M、ARM920T、MIPS32、RISC-V 等等。為了使 RT-Thread 能夠在不同 CPU 架構的芯片上運行,RT-Thread 提供了一個 libcpu 抽象層來適配不同的 CPU 架構。libcpu 層向上對內核提供統(tǒng)一的接口,包括全局中斷的開關,線程棧的初始化,上下文切換等。

RT-Thread 的 libcpu 抽象層向下提供了一套統(tǒng)一的 CPU 架構移植接口,這部分接口包含了全局中斷開關函數(shù)、線程上下文切換函數(shù)、時鐘節(jié)拍的配置和中斷函數(shù)、Cache 等等內容。下表是 CPU 架構移植需要實現(xiàn)的接口和變量。

libcpu 移植相關 API
1.jpg

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 電源管理
    +關注

    關注

    115

    文章

    6177

    瀏覽量

    144443
  • 定時器
    +關注

    關注

    23

    文章

    3246

    瀏覽量

    114719
  • RT-Thread
    +關注

    關注

    31

    文章

    1285

    瀏覽量

    40081
  • gcc編譯器
    +關注

    關注

    0

    文章

    78

    瀏覽量

    3378
  • 調度器
    +關注

    關注

    0

    文章

    98

    瀏覽量

    5245
收藏 人收藏

    評論

    相關推薦

    RT-Thread記錄(一、版本開發(fā)環(huán)境及配合CubeMX)

    RT-Thread 學習記錄的第一篇文章,RT-Thread記錄(一、RT-Thread 版本、RT-Thread Studio開發(fā)環(huán)境 及
    的頭像 發(fā)表于 06-20 00:28 ?5225次閱讀
    <b class='flag-5'>RT-Thread</b>記錄(一、版本<b class='flag-5'>開發(fā)</b>環(huán)境及配合CubeMX)

    RT-Thread記錄(二、RT-Thread內核啟動流程

    在前面我們RT-Thread Studio工程基礎之上講一講RT-Thread內核啟動流程.
    的頭像 發(fā)表于 06-20 00:30 ?5027次閱讀
    <b class='flag-5'>RT-Thread</b>記錄(二、<b class='flag-5'>RT-Thread</b>內核<b class='flag-5'>啟動</b><b class='flag-5'>流程</b>)

    如何使用RT-Thread Studio創(chuàng)建支持HPM6750開發(fā)板RT-Thread項目

    StudioRT-Thread Studio安裝程序下載頁面RT-Thread Studio安裝程序下載完成后,運行安裝程序,一路下一步即可完成RT-Thread Studio的安裝。添加HPM6750
    發(fā)表于 06-08 11:22

    RT-Thread編程指南

    RT-Thread編程指南——RT-Thread開發(fā)組(2015-03-31)。RT-Thread做為國內有較大影響力的開源實時操作系統(tǒng),本文是RT
    發(fā)表于 11-26 16:06 ?0次下載

    RT-Thread開發(fā),如何有效學習RT-Thread的五個步驟

    RT-Thread推出RT-Thread Inside戰(zhàn)略開放RT-Thread開發(fā)平臺授權合作,與硬件十萬個為什么合作首次推出第一款RT-
    的頭像 發(fā)表于 09-25 09:55 ?3.5w次閱讀
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>開發(fā)</b>,如何有效學習<b class='flag-5'>RT-Thread</b>的五個步驟

    RT-Thread Studio驅動SD卡

    總結前言硬件平臺:RT-Thread ART-Pi STM32H750XBH6開發(fā)板 H750開發(fā)板開發(fā)軟件:RT-Thread Studi
    發(fā)表于 12-27 19:13 ?20次下載
    <b class='flag-5'>RT-Thread</b> Studio驅動SD卡

    RT-Thread學習筆記 RT-Thread的架構概述

    的種種優(yōu)越之處。RT-Thread 是一款完全由國內團隊開發(fā)維護的嵌入式實時操作系統(tǒng)(RTOS),具有完全的自主知識產權。經過 16 個年頭的沉淀,伴隨著物聯(lián)網的興起,它正演變成一個功能強大、組件豐富的物
    的頭像 發(fā)表于 07-09 11:27 ?4545次閱讀
    <b class='flag-5'>RT-Thread</b>學習筆記 <b class='flag-5'>RT-Thread</b>的架構概述

    RT-Thread文檔_RT-Thread 簡介

    RT-Thread文檔_RT-Thread 簡介
    發(fā)表于 02-22 18:22 ?5次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> 簡介

    RT-Thread文檔_RT-Thread 潘多拉 STM32L475 上手指南

    RT-Thread文檔_RT-Thread 潘多拉 STM32L475 上手指南
    發(fā)表于 02-22 18:23 ?9次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> 潘多拉 STM32L475 上手指南

    RT-Thread文檔_RT-Thread SMP 介紹與移植

    RT-Thread文檔_RT-Thread SMP 介紹與移植
    發(fā)表于 02-22 18:31 ?9次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> SMP 介紹與移植

    基于RT-Thread Studio學習

    前期準備:從官網下載 RT-Thread Studio,弄個賬號登陸,開啟rt-thread學習之旅。
    的頭像 發(fā)表于 05-15 11:00 ?3930次閱讀
    基于<b class='flag-5'>RT-Thread</b> Studio學習

    機智云設備移植RT-Thread

    開發(fā)環(huán)境:Keil版本:V5.30RT-Thread版本:3.1.5STM32cubeMX:V6.0.1開發(fā)板MCU:STM32F103機智云平臺生成的應用代碼是裸機版本的,而在實際應用過
    的頭像 發(fā)表于 04-19 18:39 ?970次閱讀
    機智云設備移植<b class='flag-5'>RT-Thread</b>

    RT-Thread框架下的SMP支持

    最近報名參加了恩智浦社區(qū)的 LPC55S69 開發(fā)板測評活動,由于其搭載的是一顆 Cortex-M33 Dual Core 的 CPU,而且有大佬已經支持RT-Thread 的 BSP,就考慮
    的頭像 發(fā)表于 10-11 10:34 ?1126次閱讀
    <b class='flag-5'>RT-Thread</b>框架下的SMP<b class='flag-5'>支持</b>

    基于rt-thread的socket通信設計

    最近再研究 rt-thread 的通信 ,想設計出 eps8266(多個) rt-thread(作為中控) 服務器的通信框架,使用的開發(fā)板是 潘多拉
    的頭像 發(fā)表于 10-13 15:02 ?1357次閱讀
    基于<b class='flag-5'>rt-thread</b>的socket通信設計

    rt-studio潘多拉開發(fā)板最新rt-thread不能運行解決辦法

    rt-studio 上 選擇基于開發(fā)板的項目,選擇潘多拉,rt-thread選擇lasted ,如下圖
    的頭像 發(fā)表于 10-16 14:50 ?1332次閱讀
    <b class='flag-5'>rt</b>-studio潘多拉<b class='flag-5'>開發(fā)板</b>最新<b class='flag-5'>rt-thread</b>不能運行解決辦法
    RM新时代网站-首页