本文來源電子發燒友社區,作者:許鵬虎, 帖子地址:https://bbs.elecfans.com/jishu_2286915_1_1.html
UCM108E二次開發代碼啟動分析
簡介
UCM108E內置了一顆RISC-V核心的UC8188MCU,所以其實也是在分析UC8188的啟動過程。UC8188 是一款高性能 MCU GNSS 多模衛星導航接收機 SoC 芯片。 芯片集成了 RISCV 32 位通用處理器, 數字基帶處理器, 射頻前端, 具有 4Mb 內嵌的閃存。 擁有 SPI、I2C、 UARTx2 以及其它豐富的外設。
啟動過程分析
- MCU啟動一般情況下是從reset中斷開始的,我們拿到的這顆MCU也是這樣,找到它的啟動匯編代碼,找到reset中斷入口
- 分析這段啟動代碼
/* reset 中斷入口 */
reset_handler:
csrw mtvec, x0
csrci mstatus, 0x08
/* 1. 將所有寄存器置位為0 set all registers to zero */
mv x1, x0
mv x2, x1
mv x3, x1
mv x4, x1
mv x5, x1
mv x6, x1
mv x7, x1
mv x8, x1
mv x9, x1
mv x10, x1
mv x11, x1
mv x12, x1
mv x13, x1
mv x14, x1
mv x15, x1
mv x16, x1
mv x17, x1
mv x18, x1
mv x19, x1
mv x20, x1
mv x21, x1
mv x22, x1
mv x23, x1
mv x24, x1
mv x25, x1
mv x26, x1
mv x27, x1
mv x28, x1
mv x29, x1
mv x30, x1
mv x31, x1
#ifdef ARCH_RISCV_FPU
fssr x0
fmv.s.x f0, x0
fmv.s.x f1, x0
fmv.s.x f2, x0
fmv.s.x f3, x0
fmv.s.x f4, x0
fmv.s.x f5, x0
fmv.s.x f6, x0
fmv.s.x f7, x0
fmv.s.x f8, x0
fmv.s.x f9, x0
fmv.s.x f10,x0
fmv.s.x f11,x0
fmv.s.x f12,x0
fmv.s.x f13,x0
fmv.s.x f14,x0
fmv.s.x f15,x0
fmv.s.x f16,x0
fmv.s.x f17,x0
fmv.s.x f18,x0
fmv.s.x f19,x0
fmv.s.x f20,x0
fmv.s.x f21,x0
fmv.s.x f22,x0
fmv.s.x f23,x0
fmv.s.x f24,x0
fmv.s.x f25,x0
fmv.s.x f26,x0
fmv.s.x f27,x0
fmv.s.x f28,x0
fmv.s.x f29,x0
fmv.s.x f30,x0
fmv.s.x f31,x0
#endif
/* 2. 初始化堆棧 stack initilization */
la x2, _stack_start
_start:
.global _start
/* 3. 將bss段清零 clear BSS */
la x26, _bss_start
la x27, _bss_end
bge x26, x27, zero_loop_end
zero_loop:
sw x0, 0(x26)
addi x26, x26, 4
ble x26, x27, zero_loop
zero_loop_end:
/* 4. 運行全局初始化函數 Run global initialization functions */
li a0, 1 /* set app mode */
call set_program_type
call boot_noop
call boot_strap /* 關閉全局中斷 配置時鐘和XIP */
call __libc_init_array
j main_entry /* 跳轉到main_entry 在下面*/
.section .crt0, "ax"
main_entry:
addi x10, x0, 0
/* Baud Rate 156250
*clock divider, SYSCLK/156250/16-1
*5MHZ 1; 50MHZ 19
* 103.68Mhz clk, 115200 sv model 89
* 19.6608Mhz clk, VHD model, value 4. VHD
* 196/2Mhz VHD model value 84 for 115200
*/
//addi x11, x0, 84 //98Mhz, 1152000 for sim
addi x11, x0, 70 //131.072Mhz, 115200 for sim
//addi x11, x0, 22 //26M DCXO, just leave it here, not necessary
//jal uart_set_cfg
/* jump to main program entry point (argc = argv = 0) */
addi x10, x0, 0
addi x11, x0, 0
jal x1, entry /* 跳轉到entry函數 */
jal uart_wait_tx_done;
/* if program exits call exit routine from library */
jal x1, exit
-
通過以上的分析,我們看到最后是跳轉到
entry
函數去了,這個entry
就是rt-thread的入口函數,接下來,我們看在這個函數里做了哪些事情
-
在entry函數里面其實就是調用了
rtthread_startup()
函數,然后,我們重點分析一下這個函數里面都做了哪些事情
int rtthread_startup(void)
{
// 關閉全局中斷
rt_hw_interrupt_disable();
/* board level initialization
* NOTE: please initialize heap inside board initialization.
* 板子相關的初始化,主要是啟動了systick
*/
rt_hw_board_init();
/* show RT-Thread version */
rt_show_version();
/* 系統定時器初始化,后續的任務切換調度都會用到這個timer,timer system initialization */
rt_system_timer_init();
/* 初始化系統調度器 scheduler system initialization */
rt_system_scheduler_init();
#ifdef RT_USING_SIGNALS
/* signal system initialization */
rt_system_signal_init();
#endif
/* 創建main線程并啟動 create init_thread */
rt_application_init();
/* 創建timer線程并啟動 timer thread initialization */
rt_system_timer_thread_init();
/* 創建空閑線程并啟動 idle thread initialization */
rt_thread_idle_init();
#ifdef RT_USING_SMP
rt_hw_spin_lock(&_cpus_lock);
#endif /*RT_USING_SMP*/
/* 啟動調度器 start scheduler */
rt_system_scheduler_start();
/* never reach here */
return 0;
}
- 通過對以上的分析,我們大概知道rt-thread創建了幾個必要的線程并啟動了調度器,這個時候就會啟動剛才創建的線程,其中用戶關心的則是main線程,我們看下main線程里面做了哪些工作
/* the system main thread */
void main_thread_entry(void* parameter)
{
extern int main(void);
#ifdef RT_USING_COMPONENTS_INIT
/* RT-Thread components initialization */
rt_components_init();
#endif
#ifdef RT_USING_SMP
rt_hw_secondary_cpu_up();
#endif
/* invoke system main function */
#if defined(__CC_ARM) || defined(__CLANG_ARM)
{
extern int $Super$$main(void);
$Super$$main(); /* for ARMCC. */
}
#elif defined(__ICCARM__) || defined(__GNUC__) || defined(__TASKING__)
main(); // 運行main函數
#endif
}
-
其實這個線程最終是為了調用
main
函數,也就是我們用戶編程的入口函數
int main(void)
{
int_disable();
REG_INT_PEND = 0x0;
#ifdef _WTG_OPEN_
wdt_init(UC_WATCHDOG, 5000);
wdt_enable(UC_WATCHDOG);
#endif
InitUart(UART_BSP_115200);
GnssStart(get_pos, 0x7f, FALSE, NULL);
g_hTaskUartTx = rt_thread_create("Task Uart Tx", TaskUartTx, NULL, TSK_STACK_SIZE_UART_TX, 10, 10);
if(g_hTaskUartTx == RT_NULL)
printf("tx task create failed!rn");
else
{
rt_thread_startup(g_hTaskUartTx);
printf("tx task is start!rn");
}
g_hTaskUartRx = rt_thread_create("Task Uart Rx", TaskUartRx, NULL, TSK_STACK_SIZE_UART_RX, 10, 10);
if(g_hTaskUartRx == RT_NULL)
printf("rx task create failed!rn");
else
{
rt_thread_startup(g_hTaskUartRx);
printf("rx task is start!rn");
}
#ifdef _WTG_OPEN_
wdt_feed(UC_WATCHDOG);
#endif
}
-
分析到這里我們應該清楚的知道UCM108E從上電到
main
的整個運行流程了。
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
御芯微
+關注
關注
4文章
57瀏覽量
3490 -
開發板試用
+關注
關注
3文章
301瀏覽量
2318 -
UCM108E
+關注
關注
0文章
13瀏覽量
184
發布評論請先 登錄
相關推薦
熱點推薦
DLP6500想調用API進行自主二次開發,怎么構建開發環境?
請問一下,我購置了DLP6500型號產品,想利用該產品進行開發,實現高速投影的功能。
但是我現在只找到了GUI界面,請問一下,如果我想調用API進行自主二次開發,怎么構建開發環境?
最好有相關的技術指導文件,謝謝。
發表于 03-03 07:03
怎么配置dlp6500二次開發的環境,可以使用VS2013嗎?
我想請問一下,怎么配置dlp6500二次開發的環境,可以使用VS2013嗎?有沒有什么可以參考的文件,感謝!
發表于 02-28 06:39
SOLIDWORKS二次開發應用范圍與實例
SOLIDWORKS二次開發為企業和設計師們提供了廣闊的定制化空間,能夠更好地滿足復雜多變的設計需求,幫助工程師和設計師提高工作效率,實現更復雜的自動化任務。如您有SOLIDWORKS二次開發需求,歡迎咨詢Solidkits
什么~FPGA可以自行二次開發了?
什么!FPGA可以自行二次開發了? 目前市場上的標準采集卡通常不支持用戶自行開發FPGA。但因為應用環境的需要,不僅僅只需要單一的數據采集流程,往往還需要在其中嵌入更復雜的運行和分析邏輯。為了解

ARMxy ARM工業邊緣計算網關帶Ubuntu OS支持二次開發
ARMxy系列工業邊緣計算網關,搭載Ubuntu操作系統,不僅提供了強大的數據處理能力,而且通過支持二次開發,為企業提供了定制化解決方案的可能性。本文將深入探討ARMxy網關的技術特性、Ubuntu

5G千兆雙核物聯網模塊 OpenWrt二次開發
HLK-RM20是海凌科2024年推出的首款路由模塊,多端口5G千兆網關,雙核ARM處理器,1.3GHz主頻,支持Openwrt二次開發。高性能、高速率、低延遲,功能強大,應用廣泛。

評論