一、前言
rt_components_board_init
被rt_hw_board_init
调用。
#ifdef RT_USING_COMPONENTS_INIT
rt_components_board_init();
#endif
二、rt_components_board_init
函数分析
#define RT_DEBUG_INIT 0
/**
* 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
}
因为RT_DEBUG_INIT
未定义,所以以上代码等价于:
void rt_components_board_init(void)
{
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)();
}
}
1、__rt_init_rti_board_start分析
static int rti_board_start(void)
{
return 0;
}
INIT_EXPORT(rti_board_start, "0.end");
#define INIT_EXPORT(fn, level) RT_USED const init_fn_t __rt_init_##fn SECTION(".rti_fn."level) = fn
RT_USED
:__attribute__((used))
,标识不允许编译器进行优化init_fn_t
:typedef int (*init_fn_t)(void)
,函数指针##
:连接符SECTION
:__attribute__((section(x)))
,执行输入节名称
通过以上分析:
INIT_EXPORT(rti_board_start, "0.end");
等价于
__attribute__((used)) const init_fn_t __rt_init_rti_board_start __attribute__((section(".rti_fn.""0.end"))) = rti_board_start
以上语句含义为:创建一个函数指针变量__rt_init_rti_board_start
,变量中保存rti_board_start
函数首地址。并将__rt_init_rti_board_start
变量放在.rti_fn.0.end
节中。
2、__rt_init_rti_board_end分析
static int rti_board_end(void)
{
return 0;
}
INIT_EXPORT(rti_board_end, "1.end");
#define INIT_EXPORT(fn, level) RT_USED const init_fn_t __rt_init_##fn SECTION(".rti_fn."level) = fn
INIT_EXPORT(rti_board_end, "1.end");
等价于
__attribute__((used)) const init_fn_t __rt_init_rti_board_end __attribute__((section(".rti_fn.""1.end"))) = rti_board_end
以上语句含义为:创建一个函数指针变量__rt_init_rti_board_end
,变量中保存rti_board_end
函数首地址。并将__rt_init_rti_board_end
变量放在.rti_fn.1.end
节中。
3、函数调用过程分析
void rt_components_board_init(void)
{
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)();
}
}
以上源码含义为依次执行__rt_init_rti_board_start
到__rt_init_rti_board_end
之间函数。
如何确保想要执行函数放在他们之间?
三、自动初始化原理
1、链接器节放置规则
__rt_init_rti_board_start
放置在.rti_fn.0.end
节中
__rt_init_rti_board_end
放置在.rti_fn.1.end
节中
2、INIT_BOARD_EXPORT分析
/* board init routines will be called in board_init() function */
#define INIT_BOARD_EXPORT(fn) INIT_EXPORT(fn, "1")
rt-thread源码中提供以上宏,指定节.rti_fn.1
,根据链接器节放置规则,将放置在.rti_fn.0.end
节和.rti_fn.1.end
节之间。
rt-thread
使用INIT_BOARD_EXPORT
进行初始化函数有2个。
INIT_BOARD_EXPORT(rt_hw_pin_init);
INIT_BOARD_EXPORT(rt_hw_usart_init);
四、rt_hw_pin_init函数分析
int rt_hw_pin_init(void)
{
int result;
result = rt_device_pin_register("pin", &_stm32_pin_ops, RT_NULL);
return result;
}
INIT_BOARD_EXPORT(rt_hw_pin_init);
1、rt_device_pin_register
int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void *user_data)
{
_hw_pin.parent.type = RT_Device_Class_Miscellaneous;
_hw_pin.parent.rx_indicate = RT_NULL;
_hw_pin.parent.tx_complete = RT_NULL;
_hw_pin.parent.init = RT_NULL;
_hw_pin.parent.open = RT_NULL;
_hw_pin.parent.close = RT_NULL;
_hw_pin.parent.read = _pin_read;
_hw_pin.parent.write = _pin_write;
_hw_pin.parent.control = _pin_control;
_hw_pin.ops = ops;
_hw_pin.parent.user_data = user_data;
/* register a character device */
rt_device_register(&_hw_pin.parent, name, RT_DEVICE_FLAG_RDWR);
return 0;
}
2、rt_device_register
rt_device_register(&_hw_pin.parent, name, RT_DEVICE_FLAG_RDWR);
1、初始化_hw_pin
对象
2、将_hw_pin
对象添加到rt_object_container[RT_Object_Class_Device]
链表中.
五、rt_hw_usart_init函数分析
int rt_hw_usart_init(void)
{
struct stm32_uart *uart;
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
#if defined(RT_USING_UART1)
uart = &uart1;
config.baud_rate = BAUD_RATE_115200;
serial1.ops = &stm32_uart_ops;
serial1.config = config;
MX_USART_UART_Init(&uart->huart);
/* register UART1 device */
rt_hw_serial_register(&serial1, "uart1",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
uart);
#endif /* RT_USING_UART1 */
}
INIT_BOARD_EXPORT(rt_hw_usart_init);
rt_err_t rt_hw_serial_register(struct rt_serial_device *serial,
const char *name,
rt_uint32_t flag,
void *data)
{
rt_err_t ret;
struct rt_device *device;
RT_ASSERT(serial != RT_NULL);
device = &(serial->parent);
device->type = RT_Device_Class_Char;
device->rx_indicate = RT_NULL;
device->tx_complete = RT_NULL;
device->init = rt_serial_init;
device->open = rt_serial_open;
device->close = rt_serial_close;
device->read = rt_serial_read;
device->write = rt_serial_write;
device->control = rt_serial_control;
device->user_data = data;
/* register a character device */
ret = rt_device_register(device, name, flag);
return ret;
}
rt_err_t rt_device_register(rt_device_t dev,
const char *name,
rt_uint16_t flags)
{
if (dev == RT_NULL)
return -RT_ERROR;
if (rt_device_find(name) != RT_NULL)
return -RT_ERROR;
rt_object_init(&(dev->parent), RT_Object_Class_Device, name);
dev->flag = flags;
dev->ref_count = 0;
dev->open_flag = 0;
#if defined(RT_USING_POSIX)
dev->fops = RT_NULL;
rt_wqueue_init(&(dev->wait_queue));
#endif
return RT_EOK;
}
RTM_EXPORT(rt_device_register);
void rt_object_init(struct rt_object *object,
enum rt_object_class_type type,
const char *name)
{
register rt_base_t temp;
struct rt_object_information *information;
#ifdef RT_USING_MODULE
struct rt_dlmodule *module = dlmodule_self();
#endif
/* get object information */
information = rt_object_get_information(type);
RT_ASSERT(information != RT_NULL);
/* initialize object's parameters */
/* set object type to static */
object->type = type | RT_Object_Class_Static;
/* copy name */
rt_strncpy(object->name, name, RT_NAME_MAX);
RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
/* lock interrupt */
temp = rt_hw_interrupt_disable();
#ifdef RT_USING_MODULE
if (module)
{
rt_list_insert_after(&(module->object_list), &(object->list));
object->module_id = (void *)module;
}
else
#endif
{
/* insert object into information object list */
rt_list_insert_after(&(information->object_list), &(object->list));
}
/* unlock interrupt */
rt_hw_interrupt_enable(temp);
}