xx_init()启动顺序

本文详细介绍了Linux内核中各种initcall宏定义及其调用顺序,包括从纯初始化到后期初始化的各种函数调用,这对于理解内核加载过程及驱动加载时机至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

平时看到很多driver放到xx_init启动,所以搜集起来,方便自己查阅


Init.hinitcall的启动次序,在system.map中可看出具体的__initcall指针的前后次序:

我们常用的module_init()

#define module_init(x)     __initcall(x);-->

#define __initcall(fn) device_initcall(fn) -->

#define device_initcall(fn)    __define_initcall("6",fn,6)

根据下列表查找可得顺序……

-----------------------------分割线-----------------------------------------------------


#define pure_initcall(fn) __define_initcall("0",fn,0)

#define core_initcall(fn) __define_initcall("1",fn,1)

#define core_initcall_sync(fn) __define_initcall("1s",fn,1s)

#define postcore_initcall(fn) __define_initcall("2",fn,2)

#define postcore_initcall_sync(fn) __define_initcall("2s",fn,2s)

#define arch_initcall(fn) __define_initcall("3",fn,3)

#define arch_initcall_sync(fn) __define_initcall("3s",fn,3s)

#define subsys_initcall(fn) __define_initcall("4",fn,4)

#define subsys_initcall_sync(fn) __define_initcall("4s",fn,4s)

#define fs_initcall(fn) __define_initcall("5",fn,5)

#define fs_initcall_sync(fn) __define_initcall("5s",fn,5s)

#define rootfs_initcall(fn) __define_initcall("rootfs",fn,rootfs)

#define device_initcall(fn) __define_initcall("6",fn,6)

#define device_initcall_sync(fn) __define_initcall("6s",fn,6s)

#define late_initcall(fn) __define_initcall("7",fn,7)

#define late_initcall_sync(fn) __define_initcall("7s",fn,7s)


#include "stm32f4xx_hal.h" // 全局ADC句柄 ADC_HandleTypeDef hadc1; void Adc1_Channel_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; // 使能时钟 __HAL_RCC_ADC1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); // 配置ADC输入引脚 (PA6, PA7) GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; // 模拟输入模式 GPIO_InitStruct.Pull = GPIO_NOPULL; // 无上下拉 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 配置PB1为推挽输出 (GP2Y相关控制) GPIO_InitStruct.Pin = GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出 GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_50MHz; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET); // GP2Y_High // ADC配置 hadc1.Instance = ADC1; hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; // ADC时钟分频 hadc1.Init.Resolution = ADC_RESOLUTION_12B; // 12位分辨率 hadc1.Init.ScanConvMode = DISABLE; // 关闭扫描模式 hadc1.Init.ContinuousConvMode = DISABLE; // 关闭连续转换 hadc1.Init.DiscontinuousConvMode = DISABLE; // 关闭间断模式 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; // 无外部触发 hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 软件触发 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 右对齐 hadc1.Init.NbrOfConversion = 1; // 转换通道数 hadc1.Init.DMAContinuousRequests = DISABLE; // 关闭DMA请求 hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; // 单次转换结束标志 if (HAL_ADC_Init(&hadc1) != HAL_OK) { Error_Handler(); // 需自行实现错误处理函数 } } uint16_t get_Adc_Value(uint32_t ch) // 通道单次采样值 { ADC_ChannelConfTypeDef sConfig = {0}; // 配置ADC通道 sConfig.Channel = ch; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; // 采样时间 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } // 启动ADC转换 HAL_ADC_Start(&hadc1); // 等待转换完成 HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); // 返回转换结果 return (uint16_t)HAL_ADC_GetValue(&hadc1); } // 错误处理函数(示例) void Error_Handler(void) { while(1) { // 可添加错误指示(如LED闪烁) } }这个有错吗
最新发布
07-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值