pixhawk PX4FMU和PX4IO最底层启动过程分析
pixhawk PX4FMU和PX4IO最底層啟動過程分析
1.1 主處理器和協處理器的固件燒寫和運行流程
首先,大體了解PX4IO 與PX4FMU各自的任務。
PX4IO(STM32F100)為PIXHAWK 中專用于處理輸入輸出的部分,輸入為支持的各類遙控器(PPM,SPKT/DSM,SBUS), 輸出為電調的PWM 驅動信號, 它與PX4FMU(STM32F427)通過串口進行通信。
PX4FMU :各種傳感器數據讀取、姿態解算、PWM控制量的計算、與PX4IO通信。負責飛控最主要的工作。
其中這兩處理器的固件燒寫運行流程如下(也可以搜索相應的文章):
主處理器和協處理器,固件下載到固件運行的流程圖。值得說明的一點是分別給兩個處理器下載blootloader以后,主處理器等待下載飛控固件,用地面站通過USB向飛控固件下載完以后,主處理器的飛控固件啟動,這時候通過串口給協處理器下載固件(固件只是下載一次)。這個工作完成之后,主處理器和協處理器同時開始工作。
詳細可以看到如下代碼
#if defined(CONFIG_ARCH_BOARD_PX4FMU_V1)
fn[0] = "/etc/extras/px4io-v1.bin";
fn[1] = "/fs/microsd/px4io1.bin";
fn[2] = "/fs/microsd/px4io.bin";
fn[3] = nullptr;
#elif defined(CONFIG_ARCH_BOARD_PX4FMU_V2)
fn[0] = "/etc/extras/px4io-v2.bin";
fn[1] = "/fs/microsd/px4io2.bin";
fn[2] = "/fs/microsd/px4io.bin";
fn[3] = nullptr;
#else
#error "unknown board"
#endif
}
up = new PX4IO_Uploader;
int ret = up->upload(&fn[0]);//向協處理器下載固件
delete up;
這段代碼在px4io.cpp中,隨著px4io.cpp進程啟動而啟動。功能就是由主處理器向協處理器燒寫代碼。
其中協處理器的固件源代碼在:
E:\Firmware-master\Firmware\src\modules\px4iofirmware?這里面主要是是一些,IO口的操作和安全開關的操作。他會在編譯飛控固件的時候,一起被編譯成為px4io-v2.bin,放在NUTTX文件系統中,在主處理器運行的時候把這個固件燒寫進入協處理器。具體的燒寫到單片機的FLASH那個位置可以在px4io.cpp相關代碼找到。
在軟件層面的詳細流程圖如下:
1.2 Bootloader和NUTTX啟動詳解
?????在嵌入式操作系統中,BootLoader是在操作系統內核運行之前運行。可以初始化硬件設備、建立內存空間映射圖,從而將系統的軟硬件環境帶到一個合適狀態,以便為最終調用操作系統內核準備好正確的環境。在嵌入式系統中,通常并沒有像BIOS那樣的固件程序(注,有的嵌入式CPU也會內嵌一段短小的啟動程序),因此整個系統的加載啟動任務就完全由BootLoader來完成。Bootloader是嵌入式系統在加電后執行的第一段代碼,在它完成CPU和相關硬件的初始化之后,再將操作系統映像或固化的嵌入式應用程序裝在到內存中然后跳轉到操作系統所在的空間,啟動操作系統運行.
? ?進入px4/Bootloader可以看到main_f1、main_f4,分別對應著PX4IO、PX4FMU的Bootloader.
值得注意的是單片機的二進制代碼在單片機的啟動位置
我們知道Pixhawk硬件使用STM32的芯片,
Cortex M3的內核有三種啟動方式,其分別是:
? ? ? A.通過boot引腳設置可以將中斷向量表定位于SRAM區,即起始地址為0x2000000,同時復位后PC指針位于0x2000000處;? ? ? B.通過boot引腳設置可以將中斷向量表定位于FLASH區,即起始地址為0x8000000,同時復位后PC指針位于0x8000000處;
? ? ? C.通過boot引腳設置可以將中斷向量表定位于內置Bootloader區,
M3單片機復位后,從0x00000000取棧指針(SP),從0x00000004取復位向量(PC),有了棧指針和復位向量后,單片機就按照正常流程運行了,單片機啟動默認先運行BootLoader,所以默認的中斷向量表位置是BootLoader的中斷向量表。我們知道Bootloader是上電執行的第一個代碼, Pixhawk的啟動是通過B的方式來啟動的,所以我們在下Bootloader的時候也是向FLASH這0x8000000地址燒寫的固件(具體可以看固件燒寫這篇文章),Bootloader燒寫成功以后每次上電就會啟動,啟動的起始地址就是FLASH的0x8000000。Bootloader啟動執行到最后,會用匯編語句,自動跳轉到FLASH中固件下載的位置,開始執行固件代碼。
NUTTX啟動(也就是上面的固件代碼,匯編語句就是跳轉到這個位置來執行stm32_start.c):
此部分摘自于pixhawk自學筆記之px4程序啟動順序
代碼位置:Firmware/build_px4fmu-v2_default/px4fmu-v2/Nuttx/nuttx/arch/arm/src/stm32/stm32_start.c
__start-- #處理器執行的第一條指令(px4使用的是stm32,入口在stm32_start.c中)
???stm32_clockconfig() ? #初始化時鐘
? ? rcc_reset() ? ? ? ?#復位rcc
? ? stm32_stdclockconfig() #初始化標準時鐘
? ? rcc_enableperipherals()#使能外設時鐘
------------------------------------------------------------------
? ? stm32_fpuconfig() ? ? ? ?#配置fpu
? ? stm32_lowsetup() ? ? ? ? #基本初始化串口,之后可以使用up_lowputc()
? ? stm32_gpioinit() ? ? ? ? #初始化gpio,只是調用stm32_gpioremap()設置重映射
? ? up_earlyserialinit() ? ? ?#初始化串口,之后可以使用up_putc()
? ? stm32_boardinitialize() ??
? ? stm32_spiinitialize() ? ? #初始化spi,只是調用stm32_configgpio()設置gpio
? ? stm32_usbinitialize() ? ? #初始化usb,只是調用stm32_configgpio()設置gpio
? ? up_ledinit(); ? ? ? ? ?#初始化led,只是調用stm32_configgpio()設置gpio
???----------------------------------------------------------------------------------------------
???在stm32_start.c文件中我們會看到這么一句話:
? ??? /* Then start NuttX */
? ? showprogress('\r');
? ? showprogress('\n');
? ? os_start();系統開始啟動>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
一下是?os_start()內容:
? ? dq_init()? ? ? ? ? ? ? ????? ?? ??? ?????#初始化各種狀態的任務列表(置為null)
? ? ? ? g_pidhash[i]= ? ? ? ? ?????? ?? ???? #初始化唯一可以確定的元素--進程ID
? ? ? ? g_pidhash[PIDHASH(0)]= ? ? ?#分配空閑任務的進程ID為0
? ? ? ? g_idletcb=? ? ? ? ? ? ? ? ? ? ?? ? ? ?#初始化空閑任務的任務控制塊
? ? ? ? sem_initialize()-- ? ? ? ? ? ? ?? ? ?#初始化信號量 ? ? ? ? ? ? ? ?
? ? ? ? dq_init() ? ? ? ? ? ? ? ?? ? ? ? ? ?#將信號量隊列置為null
? ? ? ? sem_initholders() ? ? ? ? ? ? #初始化持有者結構以支持優先級繼承
? ? ? ? up_allocate_heap() ? ? ? ? #分配用戶模式的堆(設置堆的起點和大小)
? ? ? ? kumm_initialize() ? ? ? ? ? ?#初始化用戶模式的堆
? ? ? ? up_allocate_kheap() ? ? ? ?#分配內核模式的堆
? ? ? ? kmm_initialize() ? ? ? ? ? ? ? #初始化內核模式的堆
? ? ? ? task_initialize() ? ? ? ? ? ? ? ?#初始化任務數據結構
? ? ? ? irq_initialize() ? ? ? ? ? ? ? ?? #將所有中斷向量都指向同一個異常中斷處理程序
? ? ? ? wd_initialize() ? ? ? ? ? ? ? ?? #初始化看門狗數據結構
? ? ? ? clock_initialize() ? ? ? ? ? ? ? #初始化rtc
? ? ? ? timer_initialize() ? ? ? ? ? ? ? #配置POSIX定時器
? ? ? ? sig_initialize() ? ? ? ? ? ? ? ?? #初始化信號
? ? ? ? mq_initialize() ? ? ? ? ? ? ? ?? #初始化命名消息隊列
? ? ? ? pthread_initialize() ? ? ? ? ? #初始化線程特定的數據,空函數
? ? ? ? fs_initialize()---? ? ? ? ? ? ? ? #初始化文件系統 ? ? ? ? ? ? ?
? ? ? ? sem_init() ? ? ? ? #初始化節點信號量為1
? ? ? ? files_initialize() #初始化文件數組,空函數
? ? ? ? net_initialize()-- ? ? ? #初始化網絡
? ? ? ? uip_initialize() ??? ??#初始化uIP層
? ? ? ? net_initroute() ??? ???#初始化路由表
? ? ? ? netdev_seminit() ? #初始化網絡設備信號量
? ? ? ? arptimer_init() ? ?? ??#初始化ARP定時器
? ? ? ? up_initialize()--- ? ? ? #處理器特定的初始化
? ? ? ? up_calibratedelay()? ??? ?????#校準定時器
? ? ? ? up_addregion() ??? ?????? ? ?? #增加額外的內存段
? ? ? ? up_irqinitialize()?? ?????? ??? ??#設置中斷優先級,關聯硬件異常處理函數
? ? ? ? up_pminitialize() ?? ?????? ????#初始化電源管理
? ? ? ? up_dmainitialize()?? ?????? ????#初始化DMA
? ? ? ? up_timerinit() ? ??? ?????? ??? ???#初始化定時器中斷
? ? ? ? devnull_register()?? ?????? ??? ?#注冊/dev/null
? ? ? ? devzero_register()?? ?????? ????#注冊/dev/zero
? ? ? ? up_serialinit() ? ?? ?????? ??? ??? ?#注冊串口控制臺/dev/console和串口/dev/ttyS0
? ? ? ? up_rnginitialize()?? ?????? ??? ??#初始化并注冊隨機數生成器
? ? ? ? up_netinitialize()?? ?????? ??? ???#初始化網絡,是arch/arm/src/chip/stm32_eth.c中的
? ? ? ? up_usbinitialize()?? ?????? ??? ???#初始化usb驅動
? ? ? ? board_led_on() ? ??? ?????? ??? ???#打開中斷使能led,但很快會被其它地方的led操作改變狀態
? ? ? ? lib_initialize() ? ? ? ?????? ??? ? ?#初始化c庫,空函數
? ? ? ? group_allocate() ? ? ? ?????? ??#分配空閑組
? ? ? ? group_setupidlefiles() ? ? ? ?#在空閑任務上創建stdout、stderr、stdin
? ? ? ? group_initialize() ? ? ? ? ? ? ??#完全初始化空閑組
? ? ? ? os_bringup()------ ? ? ? ? ? ? ?#創建初始任務
? ? ? ? KEKERNEL_THREAD() ? ?#啟動內核工作者線程
? ? ? ? board_initialize() ? ? ? ? ? #最后一刻的板級初始化
? ? ? ? TASK_CREATE() ? ? ? ? ? ? #啟動默認應用程序
? ? ? ? forup_idle() ? ? ? ? ? ? ? ? ? ?? ? ?#空閑任務循環
? ? ? ? for(;;) ? ? ? ? ? ? ?? ? ? ? ? ? ? ? ?#不應該到達這里
__start 負責STM32 芯片的底層初始化,包括時鐘,FPU,GPIO 等單元的初始化
os_start 負責OS 的底層初始化,包括各種隊列和進程結構的初始化
os_bringup 負責OS 基本進程的啟動以及用戶進程的啟動,用戶啟動入口由(CONFIG_USER_ENTRYPOINT)宏進行指定是執行nsh_main還是user_start。? ??
啟動腳本分析
總結
以上是生活随笔為你收集整理的pixhawk PX4FMU和PX4IO最底层启动过程分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pixhawk原生固件笔记
- 下一篇: C语言指针详解----指针声明定义赋值