一、startup_stm32f407xx.S 系统进入汇编文件
RT-Thread使用的是GCC
二、不同编译器的启动函数 调用stm32f407_demo3\rt-thread\src\components.c中的$Sub$$main()
三、调用rtthread_startup(void) 在stm32f407_demo3\rt-thread\src\components.c中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 int rtthread_startup (void ) { rt_hw_interrupt_disable(); rt_hw_board_init(); rt_show_version(); rt_system_timer_init(); rt_system_scheduler_init(); #ifdef RT_USING_SIGNALS rt_system_signal_init(); #endif rt_application_init(); rt_system_timer_thread_init(); rt_thread_idle_init(); #ifdef RT_USING_SMP rt_hw_spin_lock(&_cpus_lock); #endif rt_system_scheduler_start(); return 0 ; }
3.1rt_hw_board_init和rt_application_init的 外设初始化的不同
硬件初始化 :初始化硬件资源 ,如 GPIO、串口、SPI、I2C、PWM、ADC、定时器等。
系统时钟配置 :配置系统时钟、外设时钟以及 PLL(锁相环)等,确保系统和外设运行在合适的频率下。
内存初始化 :配置堆栈、堆内存和静态内存区域,确保系统资源可用。
中断配置 :初始化中断控制器,并为特定外设启用中断。
启动引导程序 :执行系统初始化,如配置时钟源、初始化硬件外设等,通常会包括一个初始化阶段的启动代码。
设备驱动注册 :为基础硬件外设(如 UART、SPI、I2C 等)注册驱动,使操作系统能够访问这些外设。
创建应用任务 :创建系统中的应用任务,例如数据采集任务、处理任务等。
初始化外设 :在 应用层 对外设进行更高层次的初始化。例如,在硬件初始化后,可能会初始化一些外设的具体参数 ,如设置 ADC 采样周期、配置传感器等。
启动应用程序逻辑 :进行传感器数据采集、通信协议的初始化、数据处理等应用相关的工作。
任务调度和资源管理 :创建并调度多个任务,管理应用程序层的资源。
3.2rt_hw_board_init() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 RT_WEAK void rt_hw_board_init () { extern void hw_board_init (char *clock_src, int32_t clock_src_freq, int32_t clock_target_freq) ; #if defined(RT_USING_HEAP) rt_system_heap_init((void *) HEAP_BEGIN, (void *) HEAP_END); #endif hw_board_init(BSP_CLOCK_SOURCE, BSP_CLOCK_SOURCE_FREQ_MHZ, BSP_CLOCK_SYSTEM_FREQ_MHZ); #if defined(RT_USING_DEVICE) && defined(RT_USING_CONSOLE) rt_console_set_device(RT_CONSOLE_DEVICE_NAME); #endif #ifdef RT_USING_COMPONENTS_INIT rt_components_board_init(); #endif }
3.2.1hw_board_init() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 oid hw_board_init (char *clock_src, int32_t clock_src_freq, int32_t clock_target_freq) { extern void rt_hw_systick_init (void ) ; extern void clk_init (char *clk_source, int source_freq, int target_freq) ; #ifdef SCB_EnableICache SCB_EnableICache(); #endif #ifdef SCB_EnableDCache SCB_EnableDCache(); #endif HAL_Init(); __set_PRIMASK(0 ); clk_init(clock_src, clock_src_freq, clock_target_freq); __set_PRIMASK(1 ); rt_hw_systick_init(); #ifdef RT_USING_PIN extern int rt_hw_pin_init (void ) ; rt_hw_pin_init(); #endif #ifdef RT_USING_SERIAL extern int rt_hw_usart_init (void ) ; rt_hw_usart_init(); #endif }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 int rt_hw_usart_init (void ) { rt_size_t obj_num = sizeof (uart_obj) / sizeof (struct stm32_uart); struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; rt_err_t result = 0 ; stm32_uart_get_dma_config(); for (int i = 0 ; i < obj_num; i++) { uart_obj[i].config = &uart_config[i]; uart_obj[i].serial.ops = &stm32_uart_ops; uart_obj[i].serial.config = config; result = rt_hw_serial_register(&uart_obj[i].serial, uart_obj[i].config->name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX | uart_obj[i].uart_dma_flag , NULL ); RT_ASSERT(result == RT_EOK); } return result; }
3.3 rt_show_version(void)
3.4 rt_application_init() 创建main()线程
3.5 rt_system_timer_thread_init() 创建rt_thread_timer_entry()线程
3.5.1rt_thread_timer_entry() 专门用于处理软件定时器的线程函数,定期检查并触发到期的定时器回调。当没有定时器超时时,当前线程会被挂起,直到下一个定时器到期为止。
它首先通过 rt_timer_list_next_timeout
获取下一个定时器的超时时间。
如果没有定时器超时,它会挂起当前线程,直到有定时器超时。
如果有定时器将要超时,函数会计算剩余时间,并使线程在该时间段内休眠,直到定时器超时。
每次循环结束时,rt_soft_timer_check()
会检查所有的软件定时器,触发到期的定时器回调。
3.6 rt_thread_idle_init() 初始化 空闲线程 ,是操作系统中的一个特殊线程,它在所有其他任务都没有运行时执行。通常,空闲线程用来降低系统功耗,或者执行一些后台清理任务。
四、宏定义函数执行顺序 1 2 3 4 5 6 7 8 9 10 11 12 #define INIT_BOARD_EXPORT(fn) INIT_EXPORT(fn, "1" ) #define INIT_PREV_EXPORT(fn) INIT_EXPORT(fn, "2" ) #define INIT_DEVICE_EXPORT(fn) INIT_EXPORT(fn, "3" ) #define INIT_COMPONENT_EXPORT(fn) INIT_EXPORT(fn, "4" ) #define INIT_ENV_EXPORT(fn) INIT_EXPORT(fn, "5" ) #define INIT_APP_EXPORT(fn) INIT_EXPORT(fn, "6" )