您好,登錄后才能下訂單哦!
這篇文章給大家介紹如何分析RT-Thread中的$Sub$main函數,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
int rtthread_startup(void) { rt_hw_interrupt_disable(); /* board level initialization * NOTE: please initialize heap inside board initialization. */ rt_hw_board_init(); /* show RT-Thread version */ rt_show_version(); /* 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 /* create init_thread */ rt_application_init(); /* 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; }
rtthread_startup函數又分了是一個子函數:
1、關全局中斷
2、板級初始化rt_hw_board_init,在\bsp\stm32f10x\drivers\board.c中。
/** * This function will initial STM32 board. */ void rt_hw_board_init(void) { /* NVIC Configuration */ NVIC_Configuration(); /* Configure the SysTick */ SysTick_Config( SystemCoreClock / RT_TICK_PER_SECOND ); #if STM32_EXT_SRAM EXT_SRAM_Configuration(); #endif rt_hw_usart_init(); rt_console_set_device(RT_CONSOLE_DEVICE_NAME); #ifdef RT_USING_COMPONENTS_INIT rt_components_board_init(); #endif }
又分成了好幾個小程序。
第一個函數NVIC__Configuration設置嵌套向量中斷控制器,也在\bsp\stm32f10x\drivers\board.c里。這里先不做操作,后面會用到這個函數的同名靜態函數來初始化各個外設的中斷控制器。
/******************************************************************************* * Function Name : NVIC_Configuration * Description : Configures Vector Table base location. * Input : None * Output : None * Return : None *******************************************************************************/ void NVIC_Configuration(void) { #ifdef VECT_TAB_RAM /* Set the Vector Table base location at 0x20000000 */ NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); #else /* VECT_TAB_FLASH */ /* Set the Vector Table base location at 0x08000000 */ NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); #endif
第二個函數SysTick_Config設置了系統滴答計數器。系統滴答計數器負責喚醒rtt的線程調度器,也就是操作系統的“心跳”。
第三個函數rt_hw_usart_init負責初始化串口外設,可以初始化串口1到4。這個函數定義在\bsp\stm32f10x\drivers\usart.c中。這個函數引用了同文件里的靜態函數NVIC__Configuration,與board.c里的函數同名,但是含參。這個函數負責設置串口中斷的初始化。
void rt_hw_usart_init(void) { struct stm32_uart* uart; struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; RCC_Configuration(); GPIO_Configuration(); #if defined(RT_USING_UART1) uart = &uart1; config.baud_rate = BAUD_RATE_115200; serial1.ops = &stm32_uart_ops; serial1.config = config; NVIC_Configuration(uart); /* register UART1 device */ rt_hw_serial_register(&serial1, "uart1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_DMA_RX, uart); #endif /* RT_USING_UART1 */ #if defined(RT_USING_UART2) uart = &uart2; config.baud_rate = BAUD_RATE_115200; serial2.ops = &stm32_uart_ops; serial2.config = config; NVIC_Configuration(uart); /* register UART2 device */ rt_hw_serial_register(&serial2, "uart2", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_DMA_RX, uart); #endif /* RT_USING_UART2 */ #if defined(RT_USING_UART3) uart = &uart3; config.baud_rate = BAUD_RATE_115200; serial3.ops = &stm32_uart_ops; serial3.config = config; NVIC_Configuration(uart); /* register UART3 device */ rt_hw_serial_register(&serial3, "uart3", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_DMA_RX, uart); #endif /* RT_USING_UART3 */ #if defined(RT_USING_UART4) uart = &uart4; config.baud_rate = BAUD_RATE_115200; serial4.ops = &stm32_uart_ops; serial4.config = config; NVIC_Configuration(uart); /* register UART4 device */ rt_hw_serial_register(&serial4, "uart4", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_DMA_RX, uart); #endif /* RT_USING_UART4 */ }
static void NVIC_Configuration(struct stm32_uart* uart) { NVIC_InitTypeDef NVIC_InitStructure; /* Enable the USART1 Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = uart->irq; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); }
第四個函數rt_console_set_device定義在\bsp\stm32f10x\drivers\board.c里。有說明,可以看出是控制臺的設置函數。
/** * This function will set a device as console device. * After set a device to console, all output of rt_kprintf will be * redirected to this new device. * * @param name the name of new console device * * @return the old console device handler */ rt_device_t rt_console_set_device(const char *name) { rt_device_t new, old; /* save old device */ old = _console_device; /* find new console device */ new = rt_device_find(name); if (new != RT_NULL) { if (_console_device != RT_NULL) { /* close old console device */ rt_device_close(_console_device); } /* set new console device */ rt_device_open(new, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM); _console_device = new; } return old; }
第五個函數rt_components_board_init定義在\bsp\stm32f10x\drivers\components.c里。負責初始化板級組件。
/** * 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 done\n", 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 }
3、rt_show_version,打印版本信息。
4、rt_system_timer_init,初始化系統時鐘,應該是日期什么的。
5、rt_system_scheduler_init,初始化線程調度器。這個以后詳細學習。
6、rt_application_init,初始化應用線程,也就是主線程。定義在\bsp\stm32f10x\drivers\components.c里。負責創建或初始化主線程,然后啟動主線程。
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); }
系統主線程的定義也在這個文件里。而$Super$$main函數就在這里面了。
/* the system main thread */ void main_thread_entry(void *parameter) { extern int main(void); extern int $Super$$main(void); /* RT-Thread components initialization */ rt_components_init(); #ifdef RT_USING_SMP rt_hw_secondary_cpu_up(); #endif /* invoke system main function */ #if defined(__CC_ARM) || defined(__CLANG_ARM) $Super$$main(); /* for ARMCC. */ #elif defined(__ICCARM__) || defined(__GNUC__) main(); #endif }
關于如何分析RT-Thread中的$Sub$main函數就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。