3.4 rt_hw_interrupt_disable
硬件
初始化前关闭中断,防止初始化失败,只有语言实现,该函数操作了某个地方的中断屏蔽屏蔽PRIMASK。
/*
* rt_base_t rt_hw_interrupt_disable();
* interrupt mask register
* This register has only one bit, and when set to 1, it will turn off all interrupt-masking exceptions,
* leaving only NMI and hard fault. The default value is 0
*
* operating instructions:
* MRS R0, PRIMASK ; R0=PRIMASK
* MSR PRIMASK, R0 ; PRIMASK=R0
* CPSID I ; PRIMASK=1
* CPSIE I ; PRIMASK=0
*/
.global rt_hw_interrupt_disable
.type rt_hw_interrupt_disable, %function
rt_hw_interrupt_disable:
MRS r0, PRIMASK
CPSID I
BX LR
/*
* void rt_hw_interrupt_enable(rt_base_t level);
*/
.global rt_hw_interrupt_enable
.type rt_hw_interrupt_enable, %function
rt_hw_interrupt_enable:
MSR PRIMASK, r0
BX LR
3.4 rt_hw_board_init
该函数中的堆初始化函数涉及到内存管理,具体实现复杂的复杂性,这里不展开,讲解,算法的请自行学习
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);
/* Heap initialization */
#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);
/* Set the shell console output device */
#if defined(RT_USING_DEVICE) && defined(RT_USING_CONSOLE)
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif
/* Board underlying hardware initialization */
#ifdef RT_USING_COMPONENTS_INIT
rt_components_board_init();
#endif
}
3.5 hw_board_init
板级驱动初始化,包括设备初始化,系统定时器Systick初始化,PuP设备初始化,USART_串口初始化。其中设备初始化了设备驱动框架,会在开发阶段展开讲解。
void 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
/* Enable I-Cache---------------------------------------------------------*/
SCB_EnableICache();
#endif
#ifdef SCB_EnableDCache
/* Enable D-Cache---------------------------------------------------------*/
SCB_EnableDCache();
#endif
/* HAL_Init() function is called at the beginning of the program */
HAL_Init();
/* enable interrupt */
__set_PRIMASK(0);
/* System clock initialization */
clk_init(clock_src, clock_src_freq, clock_target_freq);
/* di***ale interrupt */
__set_PRIMASK(1);
rt_hw_systick_init();
/* Pin driver initialization is open by default */
#ifdef RT_USING_PIN
extern int rt_hw_pin_init(void);
rt_hw_pin_init();
#endif
/* USART driver initialization is open by default */
#ifdef RT_USING_SERIAL
extern int rt_hw_usart_init(void);
rt_hw_usart_init();
#endif
}
3.6 rt_console_set_device
设备绑定,这里在创建工程的时候指定为UART1(PA9、PA10),也涉及到了设备驱动框架,通过rt_device_t rt_device_find(const char *name) 找到命名的设备,然后函数设备的设备描述结构体赋值给一个变量_console_device,然后在调用void rt_kprintf(const char *fmt, ...)等输出函数时,通过设备初始化时的编写函数进行具体的输出行为。
rt_device_t rt_console_set_device(const char *name)
{
rt_device_t new_device, old_device;
/* save old device */
old_device = _console_device;
/* find new console device */
new_device = rt_device_find(name);
if (new_device != RT_NULL)
{
if (_console_device != RT_NULL)
{
/* close old console device */
rt_device_close(_console_device);
}
/* set new console device */
rt_device_open(new_device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM);
_console_device = new_device;
}
return old_device;
}
rt_kprintf部分源码,着重理解rt_device_write()函数调用,指定了输出设备的具体行为。
void rt_kprintf(const char *fmt, ...)
{
va_list args;
rt_size_t length;
static char rt_log_buf[RT_CONSOLEBUF_SIZE];
va_start(args, fmt);
/* the return value of vsnprintf is the number of bytes that would be
* written to buffer had if the size of the buffer been sufficiently
* large excluding the terminating null byte. If the output string
* would be larger than the rt_log_buf, we have to adjust the output
* length. */
length = rt_vsnprintf(rt_log_buf, sizeof(rt_log_buf) - 1, fmt, args);
if (length > RT_CONSOLEBUF_SIZE - 1)
length = RT_CONSOLEBUF_SIZE - 1;
#ifdef RT_USING_DEVICE
if (_console_device == RT_NULL)
{
rt_hw_console_output(rt_log_buf);
}
else
{
rt_uint16_t old_flag = _console_device->open_flag;
_console_device->open_flag |= RT_DEVICE_FLAG_STREAM;
/* by rt_console_set_device() function bound output device */
rt_device_write(_console_device, 0, rt_log_buf, length);
_console_device->open_flag = old_flag;
}
#else
rt_hw_console_output(rt_log_buf);
#endif
va_end(args);
}
3.7 rt_components_board_init
该函数用于执行通过INIT_BOARD_EXPORT(fn)宏把fn函数的地址.rti_fn.1段,该宏展开步骤如下:
第一步:INIT_EXPORT(fn, "1")
第二步:RT_USED const init_fn_t _rt_init##fn SECTION(".rti_fn." level) = fn
第三步:__attribute__((used)) const init_fn_t__rt_init_##fn SECTION (".rti_fn." level) = fn
第四步:__attribute__((used)) const init_fn_t__rt_init_##fn __attribute__((section(x))) = fn
以drv_clk.c中的INIT_BOARD_EXPORT(clock_information)宏举例,展开后形式如下:
__attribute__((used)) const init_fn_t __rt_init_clock_information __attribute__((section(".rti_fn." "1"))) = clock_information
翻译过来就是clock_information的习惯为__rt_init_clock_information并把函数地址引导.rti_fn.1 section段中
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)();
}
#endif
}
该函数的需要结合.map文件,可以查看该函数共执行了两个函数,int rti_board_start(void) 和 int clock_information(void)。
*(SORT(.rti_fn*))
.rti_fn.0 0x0800d0d8 0x4 ./rt-thread/src/components.o
0x0800d0d8 __rt_init_rti_start
.rti_fn.0.end 0x0800d0dc 0x4 ./rt-thread/src/components.o
0x0800d0dc __rt_init_rti_board_start
.rti_fn.1 0x0800d0e0 0x4 ./drivers/drv_clk.o
0x0800d0e0 __rt_init_clock_information
.rti_fn.1.end 0x0800d0e4 0x4 ./rt-thread/src/components.o
0x0800d0e4 __rt_init_rti_board_end
.rti_fn.6 0x0800d0e8 0x4 ./rt-thread/components/finsh/shell.o
0x0800d0e8 __rt_init_finsh_system_init
.rti_fn.6.end 0x0800d0ec 0x4 ./rt-thread/src/components.o
0x0800d0ec __rt_init_rti_end
0x0800d0f0 __rt_init_end = .
0x0800d0f0 . = ALIGN (0x4)
3.8 rt_show_version
该函数打印输出OS系统版本,编译日期等信息
void rt_show_version(void)
{
rt_kprintf("n \ | /n");
rt_kprintf("- RT - Thread Operating Systemn");
rt_kprintf(" / | \ %d.%d.%d build %sn",
RT_VERSION, RT_SUBVERSION, RT_REVISION, __DATE__);
rt_kprintf(" 2006 - 2019 Copyright by rt-thread teamn");
}
下一步OS内核启动。
3.4 rt_hw_interrupt_disable
硬件
初始化前关闭中断,防止初始化失败,只有语言实现,该函数操作了某个地方的中断屏蔽屏蔽PRIMASK。
/*
* rt_base_t rt_hw_interrupt_disable();
* interrupt mask register
* This register has only one bit, and when set to 1, it will turn off all interrupt-masking exceptions,
* leaving only NMI and hard fault. The default value is 0
*
* operating instructions:
* MRS R0, PRIMASK ; R0=PRIMASK
* MSR PRIMASK, R0 ; PRIMASK=R0
* CPSID I ; PRIMASK=1
* CPSIE I ; PRIMASK=0
*/
.global rt_hw_interrupt_disable
.type rt_hw_interrupt_disable, %function
rt_hw_interrupt_disable:
MRS r0, PRIMASK
CPSID I
BX LR
/*
* void rt_hw_interrupt_enable(rt_base_t level);
*/
.global rt_hw_interrupt_enable
.type rt_hw_interrupt_enable, %function
rt_hw_interrupt_enable:
MSR PRIMASK, r0
BX LR
3.4 rt_hw_board_init
该函数中的堆初始化函数涉及到内存管理,具体实现复杂的复杂性,这里不展开,讲解,算法的请自行学习
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);
/* Heap initialization */
#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);
/* Set the shell console output device */
#if defined(RT_USING_DEVICE) && defined(RT_USING_CONSOLE)
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif
/* Board underlying hardware initialization */
#ifdef RT_USING_COMPONENTS_INIT
rt_components_board_init();
#endif
}
3.5 hw_board_init
板级驱动初始化,包括设备初始化,系统定时器Systick初始化,PuP设备初始化,USART_串口初始化。其中设备初始化了设备驱动框架,会在开发阶段展开讲解。
void 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
/* Enable I-Cache---------------------------------------------------------*/
SCB_EnableICache();
#endif
#ifdef SCB_EnableDCache
/* Enable D-Cache---------------------------------------------------------*/
SCB_EnableDCache();
#endif
/* HAL_Init() function is called at the beginning of the program */
HAL_Init();
/* enable interrupt */
__set_PRIMASK(0);
/* System clock initialization */
clk_init(clock_src, clock_src_freq, clock_target_freq);
/* di***ale interrupt */
__set_PRIMASK(1);
rt_hw_systick_init();
/* Pin driver initialization is open by default */
#ifdef RT_USING_PIN
extern int rt_hw_pin_init(void);
rt_hw_pin_init();
#endif
/* USART driver initialization is open by default */
#ifdef RT_USING_SERIAL
extern int rt_hw_usart_init(void);
rt_hw_usart_init();
#endif
}
3.6 rt_console_set_device
设备绑定,这里在创建工程的时候指定为UART1(PA9、PA10),也涉及到了设备驱动框架,通过rt_device_t rt_device_find(const char *name) 找到命名的设备,然后函数设备的设备描述结构体赋值给一个变量_console_device,然后在调用void rt_kprintf(const char *fmt, ...)等输出函数时,通过设备初始化时的编写函数进行具体的输出行为。
rt_device_t rt_console_set_device(const char *name)
{
rt_device_t new_device, old_device;
/* save old device */
old_device = _console_device;
/* find new console device */
new_device = rt_device_find(name);
if (new_device != RT_NULL)
{
if (_console_device != RT_NULL)
{
/* close old console device */
rt_device_close(_console_device);
}
/* set new console device */
rt_device_open(new_device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM);
_console_device = new_device;
}
return old_device;
}
rt_kprintf部分源码,着重理解rt_device_write()函数调用,指定了输出设备的具体行为。
void rt_kprintf(const char *fmt, ...)
{
va_list args;
rt_size_t length;
static char rt_log_buf[RT_CONSOLEBUF_SIZE];
va_start(args, fmt);
/* the return value of vsnprintf is the number of bytes that would be
* written to buffer had if the size of the buffer been sufficiently
* large excluding the terminating null byte. If the output string
* would be larger than the rt_log_buf, we have to adjust the output
* length. */
length = rt_vsnprintf(rt_log_buf, sizeof(rt_log_buf) - 1, fmt, args);
if (length > RT_CONSOLEBUF_SIZE - 1)
length = RT_CONSOLEBUF_SIZE - 1;
#ifdef RT_USING_DEVICE
if (_console_device == RT_NULL)
{
rt_hw_console_output(rt_log_buf);
}
else
{
rt_uint16_t old_flag = _console_device->open_flag;
_console_device->open_flag |= RT_DEVICE_FLAG_STREAM;
/* by rt_console_set_device() function bound output device */
rt_device_write(_console_device, 0, rt_log_buf, length);
_console_device->open_flag = old_flag;
}
#else
rt_hw_console_output(rt_log_buf);
#endif
va_end(args);
}
3.7 rt_components_board_init
该函数用于执行通过INIT_BOARD_EXPORT(fn)宏把fn函数的地址.rti_fn.1段,该宏展开步骤如下:
第一步:INIT_EXPORT(fn, "1")
第二步:RT_USED const init_fn_t _rt_init##fn SECTION(".rti_fn." level) = fn
第三步:__attribute__((used)) const init_fn_t__rt_init_##fn SECTION (".rti_fn." level) = fn
第四步:__attribute__((used)) const init_fn_t__rt_init_##fn __attribute__((section(x))) = fn
以drv_clk.c中的INIT_BOARD_EXPORT(clock_information)宏举例,展开后形式如下:
__attribute__((used)) const init_fn_t __rt_init_clock_information __attribute__((section(".rti_fn." "1"))) = clock_information
翻译过来就是clock_information的习惯为__rt_init_clock_information并把函数地址引导.rti_fn.1 section段中
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)();
}
#endif
}
该函数的需要结合.map文件,可以查看该函数共执行了两个函数,int rti_board_start(void) 和 int clock_information(void)。
*(SORT(.rti_fn*))
.rti_fn.0 0x0800d0d8 0x4 ./rt-thread/src/components.o
0x0800d0d8 __rt_init_rti_start
.rti_fn.0.end 0x0800d0dc 0x4 ./rt-thread/src/components.o
0x0800d0dc __rt_init_rti_board_start
.rti_fn.1 0x0800d0e0 0x4 ./drivers/drv_clk.o
0x0800d0e0 __rt_init_clock_information
.rti_fn.1.end 0x0800d0e4 0x4 ./rt-thread/src/components.o
0x0800d0e4 __rt_init_rti_board_end
.rti_fn.6 0x0800d0e8 0x4 ./rt-thread/components/finsh/shell.o
0x0800d0e8 __rt_init_finsh_system_init
.rti_fn.6.end 0x0800d0ec 0x4 ./rt-thread/src/components.o
0x0800d0ec __rt_init_rti_end
0x0800d0f0 __rt_init_end = .
0x0800d0f0 . = ALIGN (0x4)
3.8 rt_show_version
该函数打印输出OS系统版本,编译日期等信息
void rt_show_version(void)
{
rt_kprintf("n \ | /n");
rt_kprintf("- RT - Thread Operating Systemn");
rt_kprintf(" / | \ %d.%d.%d build %sn",
RT_VERSION, RT_SUBVERSION, RT_REVISION, __DATE__);
rt_kprintf(" 2006 - 2019 Copyright by rt-thread teamn");
}
下一步OS内核启动。
举报