前言
- 借鉴rt-thread组件自动初始化功能,实现一个组件初始化的模板
代码
头文件
/*
* Copyright (c) 2024-2024,shchl
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-4-9 shchl first version
*
* @note 链接文件添加
__os_init_start = .;
KEEP(*(SORT(.bsp_init_fn*)))
__os_init_end = .;
*/
#ifndef APP_THREADX_NETXDUO_BSP_AUTO_INIT_H
#define APP_THREADX_NETXDUO_BSP_AUTO_INIT_H
#define bsp_section(x) __attribute__((section(x)))
#define bsp_used __attribute__((used))
typedef int (*init_fn_t)(void);
#define INIT_EXPORT(fn, level) \
bsp_used const init_fn_t __os_init_##fn bsp_section(".bsp_init_fn." level) = fn
void bsp_components_app_init(const init_fn_t *start_ptr,const init_fn_t *end_ptr);
#endif //APP_THREADX_NETXDUO_BSP_AUTO_INIT_H
原文件
/*
* Copyright (c) 2024-2024,shchl
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-4-9 shchl first version
*/
#include "bsp.h"
/**
* @brief 自定义app区间初始化
* @param start_ptr 起始函数指针地址
* @param end_ptr 结束函数指针地址
*/
void bsp_components_app_init(const init_fn_t *start_ptr,const init_fn_t *end_ptr) {
volatile const init_fn_t *fn_ptr;
for (fn_ptr = start_ptr; fn_ptr < end_ptr; fn_ptr++) {
(*fn_ptr)();
}
}
链接文件修改
示例 以netx duo 应用组件为例(模拟tcp client)
相关宏定义
#define NET_X_APP_EXPORT(fn) INIT_EXPORT(fn, "8.1")
源文件
static int net_x_duo_component_init_start() {
/* 初始化NetX */
nx_system_initialize();
return NX_SUCCESS;
}
INIT_EXPORT(net_x_duo_component_init_start, "8.0");
static int nex_x_duo_component_init_end() {
return NX_SUCCESS;
}
INIT_EXPORT(nex_x_duo_component_init_end, "9.0");
/**
* @brief Application NetXDuo Initialization.
* @param memory_ptr: memory pointer
* @retval int
*/
UINT MX_NetXDuo_Init() {
bsp_components_app_init(&__os_init_net_x_duo_component_init_start,
&__os_init_nex_x_duo_component_init_end);
return NX_SUCCESS;
}
组件注入
int app_netx_tcp_client_init() {
tx_log("app_netx_tcp_client_init\r\n");
return NX_SUCCESS;
}
NET_X_APP_EXPORT(app_netx_tcp_client_init);
通过map映射文件也可以观察出函数地址之间的关系
执行结果(解耦成功)
keil里面的话(xxx.sct文件,这个就是连接文件)
验证
将组件注入的代码添加到keil工程中
- 这里为了简单点,直接添加到main文件中
#include "system.h"
#include "SysTick.h"
#include "usart.h"
#include "led.h"
#include "tftlcd.h"
#include "picture.h"
#define bsp_section(x) __attribute__((section(x)))
#define bsp_used __attribute__((used))
typedef int (*init_fn_t)(void);
#define INIT_EXPORT(fn, level) \
bsp_used const init_fn_t __os_init_##fn bsp_section(".bsp_init_fn." level) = fn
#define NET_X_APP_EXPORT(fn) INIT_EXPORT(fn, "8.1")
void bsp_components_app_init(const init_fn_t *start_ptr,const init_fn_t *end_ptr) {
volatile const init_fn_t *fn_ptr;
for (fn_ptr = start_ptr; fn_ptr < end_ptr; fn_ptr++) {
(*fn_ptr)();
}
}
static int net_x_duo_component_init_start() {
/* 初始化NetX */
return 0;
}
INIT_EXPORT(net_x_duo_component_init_start, "8.0");
static int nex_x_duo_component_init_end() {
return 0;
}
INIT_EXPORT(nex_x_duo_component_init_end, "9.0");
int app_netx_tcp_client_init() {
printf("app_netx_tcp_client_init\r\n");
return 0;
}
NET_X_APP_EXPORT(app_netx_tcp_client_init);
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
u8 i=0;
u16 color=0;
HAL_Init(); //初始化HAL库
SystemClock_Init(8,336,2,7); //设置时钟,168Mhz
SysTick_Init(168);
USART1_Init(115200);
bsp_components_app_init(&__os_init_net_x_duo_component_init_start,
&__os_init_nex_x_duo_component_init_end);
while(1)
{
delay_ms(10);
}
}
查看keil的map文件
结论
在keil中,不需要去修改链接文件,也可以实现组件自动注入,唯一的耦合,就是需要在合适的地方调用bsp_components_app_init 函数即可