RT-thread 用宏进行自动初始化
摘要:rt-thread 有一个机制是在main函数在运行已经将外设和组件自动用宏INIT_EXPORT(fn, level)初始化外设,接下来就要分析一下原理并模仿这种自动化初始化机制自己实现。
实现原理:1.将初始化函数注册到自定义的段中,然后分层级自动初始化设备
2.$sub$$main $supur$$main 在main运行之前实现自动初始。
具体实现可以参考文章:https://www.cnblogs.com/King-Gentleman/p/4570559.html
在这里贴一下自己实现的代码(MDK):
1 #include "init.h" 2 #if 0 3 static init_func_t *init_list_begin; 4 static init_func_t *init_list_end; 5 6 void sys_init(void) 7 { 8 init_func_t *index; 9 #if defined(__CC_ARM) || defined(__CLANG_ARM) 10 extern const int INIT_LIST$$Base; 11 extern const int INIT_LIST$$Limit; 12 init_list_begin = (init_func_t *)&INIT_LIST$$Base; //获得段起始地址 13 init_list_end = (init_func_t *)&INIT_LIST$$Limit; //获得结束段地址 14 #elif defined(__ICCARM__) /* IAR ARMCC Complier */ 15 16 #elif defined(__GNUC__) /* GNUC Complier */ 17 18 #endif 19 for(index = init_list_begin; index < init_list_end; index++) 20 { 21 index->_init_func(); 22 } 23 } 24 #else 25 26 27 28 29 #ifdef RT_USING_COMPONENTS_INIT 30 /* 31 * Components Initialization will initialize some driver and components as following 32 * order: 33 * rti_start --> 0 34 * rti_board_start --> 0.end 35 * BOARD_EXPORT --> 1 36 * rti_board_end --> 1.end 37 * 38 * DEVICE_EXPORT --> 2 39 * COMPONENT_EXPORT --> 3 40 * FS_EXPORT --> 4 41 * ENV_EXPORT --> 5 42 * APP_EXPORT --> 6 43 * 44 * rti_end --> 6.end 45 * 46 * These automatically initialization, the driver or component initial function must 47 * be defined with: 48 * INIT_BOARD_EXPORT(fn); 49 * INIT_DEVICE_EXPORT(fn); 50 * ... 51 * INIT_APP_EXPORT(fn); 52 * etc. 53 */ 54 static int rti_start(void) 55 { 56 return 0; 57 } 58 INIT_EXPORT(rti_start, "0"); 59 60 static int rti_board_start(void) 61 { 62 return 0; 63 } 64 INIT_EXPORT(rti_board_start, "0.end"); 65 66 static int rti_board_end(void) 67 { 68 return 0; 69 } 70 INIT_EXPORT(rti_board_end, "1.end"); 71 72 static int rti_end(void) 73 { 74 return 0; 75 } 76 INIT_EXPORT(rti_end, "6.end"); 77 78 /** 79 * RT-Thread Components Initialization for board 80 */ 81 void components_board_init(void) 82 { 83 #if RT_DEBUG_INIT 84 int result; 85 const struct rt_init_desc *desc; 86 Printk(RT_DEBUG_INIT,("do components board initialization.\r\n")); 87 for (desc = &__rt_init_desc_rti_board_start; desc < &__rt_init_desc_rti_board_end; desc ++) 88 { 89 result = desc->fn(); 90 Printk(RT_DEBUG_INIT,(" %s init..,return code:%d \r\n", desc->fn_name,result)); 91 } 92 #else 93 volatile const init_fn_t *fn_ptr; 94 95 for (fn_ptr = &__rt_init_rti_board_start; fn_ptr < &__rt_init_rti_board_end; fn_ptr++) 96 { 97 (*fn_ptr)(); 98 } 99 #endif 100 } 101 102 /** 103 * Thread Components Initialization 104 */ 105 void components_init(void) 106 { 107 #if RT_DEBUG_INIT 108 int result; 109 const struct rt_init_desc *desc; 110 111 Printk(RT_DEBUG_INIT,("do components initialization.\r\n")); 112 for (desc = &__rt_init_desc_rti_board_end; desc < &__rt_init_desc_rti_end; desc ++) 113 { 114 result = desc->fn(); 115 Printk(RT_DEBUG_INIT,("%s init..,return code:%d \r\n", desc->fn_name,result)); 116 } 117 #else 118 volatile const init_fn_t *fn_ptr; 119 120 for (fn_ptr = &__rt_init_rti_board_end; fn_ptr < &__rt_init_rti_end; fn_ptr ++) 121 { 122 (*fn_ptr)(); 123 } 124 #endif 125 } 126 #endif /* RT_USING_COMPONENTS_INIT */ 127 128 #endif
1 typedef int (*init_fn_t)(void); 2 3 #if RT_DEBUG_INIT 4 struct rt_init_desc 5 { 6 const char* fn_name; 7 const init_fn_t fn; 8 }; 9 #define INIT_EXPORT(fn, level) \ 10 const char __rti_##fn##_name[] = #fn; \ 11 RT_USED const struct rt_init_desc __rt_init_desc_##fn SECTION(".init_fn." level) = \ 12 { __rti_##fn##_name, fn}; 13 #else 14 #define INIT_EXPORT(fn, level) \ 15 RT_USED const init_fn_t __rt_init_##fn SECTION(".rti_fn." level) = fn 16 #endif 17 18 19 /* board init routines will be called in board_init() function */ 20 #define INIT_BOARD_EXPORT(fn) INIT_EXPORT(fn, "1") 21 22 /* pre/device/component/env/app init routines will be called in init_thread */ 23 /* components pre-initialization (pure software initilization) */ 24 #define INIT_PREV_EXPORT(fn) INIT_EXPORT(fn, "2") 25 /* device initialization */ 26 #define INIT_DEVICE_EXPORT(fn) INIT_EXPORT(fn, "3") 27 /* components initialization (dfs, lwip, ...) */ 28 #define INIT_COMPONENT_EXPORT(fn) INIT_EXPORT(fn, "4") 29 /* environment initialization (mount disk, ...) */ 30 #define INIT_ENV_EXPORT(fn) INIT_EXPORT(fn, "5") 31 /* appliation initialization (gui application etc ...) */ 32 #define INIT_APP_EXPORT(fn) INIT_EXPORT(fn, "6") 33 34 35 36 void components_board_init(void); 37 void components_init(void);
1 void show_version(void) 2 { 3 Printk(SYSTERM_INFO_DEBUG,("\n \\ | /\n")); 4 Printk(SYSTERM_INFO_DEBUG,("- ST - Thread Operating System\n")); 5 Printk(SYSTERM_INFO_DEBUG,(" / | \\ %s.%s.%d build %s\n", 6 PCB_VERSION, SW_VERSION, APP_OPTIONS, __DATE__)); 7 Printk(SYSTERM_INFO_DEBUG,(" 2020 - 2020 Copyright by ST team\n")); 8 } 9 10 11 int hw_board_init(void) 12 { 13 __set_PRIMASK(0); 14 SystemCoreClockUpdate(); 15 __set_PRIMASK(1); 16 17 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); 18 19 /* all usart initlization */ 20 usart_Initialize_all(); 21 22 #ifdef LOGDEBUG_TTL_USART_INDEX 23 usart_Initialize(LOGDEBUG_TTL_USART_INDEX,LogUsartRcvCB); 24 #endif 25 26 /* show Thread version */ 27 show_version(); 28 29 TimerInitialize(CYCLE_TASK_TIMER_INDEX,CycleTask); 30 31 32 33 34 components_board_init(); 35 36 return ARM_EOK; 37 } 38 39 40 void main_thread_entry( void ) 41 { 42 extern int main(void); 43 extern int $Super$$main(void); 44 45 components_init(); 46 47 $Super$$main(); /* 代指main函数 */ 48 49 50 } 51 52 int application_init(void) 53 { 54 bool bRet = false; 55 static TaskHandle_t xGeneralTaskHandle = NULL; 56 if(NULL == xGeneralTaskHandle) 57 { 58 bRet = xTaskCreate((TaskFunction_t)main_thread_entry,(const char*)"main task",configMINIMAL_STACK_SIZE * 10,NULL,(UBaseType_t)1,(TaskHandle_t*)&xGeneralTaskHandle); 59 if(bRet != NULL) 60 { 61 62 } 63 } 64 return bRet; 65 } 66 67 int thread_startup(void) 68 { 69 /* board level initialization 70 * NOTE: please initialize heap inside board initialization. 71 */ 72 hw_board_init(); 73 74 /* create init_thread */ 75 application_init(); 76 77 /* start scheduler */ 78 vTaskStartScheduler(); 79 80 /* never reach here */ 81 return 0; 82 } 83 84 /* re-define main function */ 85 int $Sub$$main(void) /* 相当于补丁,在main函数之前运行的函数 */ 86 { 87 thread_startup(); 88 return 0; 89 }