当前位置:网站首页>【IMX6ULL笔记】--内核底层驱动初步探究
【IMX6ULL笔记】--内核底层驱动初步探究
2022-07-25 10:51:00 【L_17】
本章简单介绍,imx6ull (cortex-A7)和 imxrt1062(cortex-m7)驱动开发模式对比
前期准备:
1.imx6ull 准备内核文件,这里笔者使用的内核版本是 4.9.88,当然也可以下载其他版本,只要支持就行
2.imxrt1062 官方sdk (实际imx6ull官方给了一套sdk,可基于IAR开发,感兴趣的可以试试,但是一个A核芯片肯定基于linux开发才会发挥其作用)
Select Board | MCUXpresso SDK Builder (nxp.com)
3.两款芯片数据手册
imx6ull 驱动开发模式(linux内核驱动开发):芯片厂商会从 The Linux Kernel Archives下载某版本的linux内核,然后将其移植到自己的CPU上,测试成功后就会将其开放到自己网站上,提供给开发者使用。我们去研读,提供的内核文件,肯定能找到,底层驱动操作(涉及到该芯片寄存器读写)
imxrt1062 驱动开发模式(常规单片机开发,如:stm32这种),官方驱动包sdk上直接调用,基本不用啥驱动框架(近些年,小型嵌入式系统逐渐有了驱动框架形式,如:rt-thread 这类物联网操作系统等等)
驱动开发中如何操作
驱动开发共同点,不论是ARM哪种核,最终操作的肯定是内存读写,对某个驱动的寄存器读写。另外对于一些有IO的外设,都是需要设置IO的复用和电气属性。接下来我们就拿一个SAI(全称:Synchronous Audio Interface )外设简单举例说明
1.imx6ull和rt1062寄存器地址描述
- imx6ull 寄存器
sai1寄存器存在位置,起始地址:0x0202_8000 大小:0x4000(16KB)


寄存器地址描述位置,存在于imx6ull.dtsi文件中,路径: ./arch/arm/boot/dts/,通过该dtsi文件我们可以定制属于自己的dts设备树文件(截图下方:imx6ull-14x14-evk.dts 为官方开发板设备树文件,可以通过官方文件照猫画虎深入学习)

- rt1062 寄存器
sai1 寄存器存在位置


寄存器地址描述位置,存在于MIMXRT1062.h头文件中

2.imx6ull和rt1062驱动函数文件所属位置
- imx6ull 驱动文件
首先我们需要通过imx6ull.dtsi文件找到sai1,其次找到compatible描述位置,我们可以通过:“fsl,imx6ul-sai”,“fsl,imx6sx-sai”,全局搜索,可以找到fsl_sai.c文件,可以看出该文件还支持 imx7imx8等等


研读fsl_sai.c fsl_sai.h文件,我们可以找到很多描述该外设寄存器和读写该外设寄存器的信息,从源码中会找到一些regmap字眼,regmap是很重要的子系统(regmap 用于提供一套方便的 API 函数去操作底层硬件寄存器,以提高代码的可重用性),具体细节可以网上搜索理解。另外还有描述寄存器偏移的信息,用datasheet对比是不是一样。

补:根据如上方法,我们可以试试查阅 adc ,wdog, i2c等外设的信息
/*省略......*/
wdog1: [email protected]020bc000 {
compatible = "fsl,imx6ul-wdt", "fsl,imx21-wdt";
reg = <0x020bc000 0x4000>;
interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_WDOG1>;
};
/*省略......*/
adc1: [email protected]02198000 {
compatible = "fsl,imx6ul-adc", "fsl,vf610-adc";
reg = <0x02198000 0x4000>;
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_ADC1>;
num-channels = <2>;
clock-names = "adc";
status = "disabled";
};
/*省略......*/
i2c1: [email protected]021a0000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c";
reg = <0x021a0000 0x4000>;
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_I2C1>;
status = "disabled";
};
/*省略......*/
在文件底部,将会注册该驱动:module_platform_driver(内核文件中大量使用该函数)
module_platform_driver(fsl_sai_driver);
/*查询......*/
#define module_platform_driver(__platform_driver) \ module_driver(__platform_driver, platform_driver_register, \ platform_driver_unregister)
/*查询......*/
#define module_driver(__driver, __register, __unregister, ...) \ static int __init __driver##_init(void) \ {
\ return __register(&(__driver) , ##__VA_ARGS__); \ } \ module_init(__driver##_init); \ static void __exit __driver##_exit(void) \ {
\ __unregister(&(__driver) , ##__VA_ARGS__); \ } \ module_exit(__driver##_exit);
/*省略......*/
- rt1062 驱动文件
驱动文件可以直接从sdk drivers文件夹中找到

3.imx6ull和rt1062 IO复用配置
注:各家厂商有区别,这里只是描述nxp的
- imx6ull io配置
根据linux内核路劲:./arch/arm/boot/dts/ 可以找到:imx6ul-pinfunc.himx6ull-pinfunc.h 和 imx6ull-pinfunc-snvs.h,根据宏后面的信息可知其相关配置信息

另外在imx6ull.dtsi文件中有个iomux节点的重用信息,同样我们可以通过"fsl,imx6ul-iomuxc"查找到pinctrl-imx6ull.c源码
iomuxc: [email protected]020e0000 {
compatible = "fsl,imx6ul-iomuxc";
reg = <0x020e0000 0x4000>;
};

除此之外配置信息,设备树dts文件中的需要做io配置,这里拿sai2举例
&iomuxc {
pinctrl-names = "default";
/*省略......*/
pinctrl_sai2: sai2grp {
fsl,pins = <
MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK 0x17088
MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC 0x17088
MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA 0x11088
MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA 0x11088
MX6UL_PAD_JTAG_TMS__SAI2_MCLK 0x17088
>;
};
/*省略......*/
}
/*省略......*/
&sai2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai2>;
assigned-clocks = <&clks IMX6UL_CLK_SAI2_SEL>,
<&clks IMX6UL_CLK_SAI2>;
assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
assigned-clock-rates = <0>, <12288000>;
status = "okay";
};
rt1062 io配置
io配置文件可以直接从sdk drivers文件夹中找到 fsl_iomuxc.h

然后调用两个函数,实现最终配置
/*! * @brief Sets the IOMUXC pin mux mode. * @note The first five parameters can be filled with the pin function ID macros. * * This is an example to set the PTA6 as the lpuart0_tx: * @code * IOMUXC_SetPinMux(IOMUXC_PTA6_LPUART0_TX, 0); * @endcode * * This is an example to set the PTA0 as GPIOA0: * @code * IOMUXC_SetPinMux(IOMUXC_PTA0_GPIOA0, 0); * @endcode * * @param muxRegister The pin mux register. * @param muxMode The pin mux mode. * @param inputRegister The select input register. * @param inputDaisy The input daisy. * @param configRegister The config register. * @param inputOnfield Software input on field. */
static inline void IOMUXC_SetPinMux(uint32_t muxRegister,
uint32_t muxMode,
uint32_t inputRegister,
uint32_t inputDaisy,
uint32_t configRegister,
uint32_t inputOnfield)
{
*((volatile uint32_t *)muxRegister) =
IOMUXC_SW_MUX_CTL_PAD_MUX_MODE(muxMode) | IOMUXC_SW_MUX_CTL_PAD_SION(inputOnfield);
if (inputRegister != 0UL)
{
*((volatile uint32_t *)inputRegister) = inputDaisy;
}
}
/*! * @brief Sets the IOMUXC pin configuration. * @note The previous five parameters can be filled with the pin function ID macros. * * This is an example to set pin configuration for IOMUXC_PTA3_LPI2C0_SCLS: * @code * IOMUXC_SetPinConfig(IOMUXC_PTA3_LPI2C0_SCLS,IOMUXC_SW_PAD_CTL_PAD_PUS_MASK|IOMUXC_SW_PAD_CTL_PAD_PUS(2U)) * @endcode * * @param muxRegister The pin mux register. * @param muxMode The pin mux mode. * @param inputRegister The select input register. * @param inputDaisy The input daisy. * @param configRegister The config register. * @param configValue The pin config value. */
static inline void IOMUXC_SetPinConfig(uint32_t muxRegister,
uint32_t muxMode,
uint32_t inputRegister,
uint32_t inputDaisy,
uint32_t configRegister,
uint32_t configValue)
{
if (configRegister != 0UL)
{
*((volatile uint32_t *)configRegister) = configValue;
}
}
补:除次之外还有时钟配置,外设时钟源选择,时钟分频等等,这里就不展开说说了,大家可以试试。
边栏推荐
- WIZnet W5500系列培训活动之“MQTT协议讲解和实践(接入OneNET)”
- 世界上最高效的笔记方法(改变你那老版的记笔记方法吧)
- The most efficient note taking method in the world (change your old version of note taking method)
- Similarity matrix, diagonalization condition
- 绘图==PYQT5
- [MySQL learning 08]
- SQL language (6)
- ESP8266 使用 DRV8833驱动板驱动N20电机
- 基于W5500实现的考勤系统
- 谣言检测文献阅读十一—Preventing rumor spread with deep learning
猜你喜欢

SQL language (I)

如何判断静态代码质量分析工具的性能?这五大因素必须考虑

SQL注入 Less23(过滤注释符)

【leetcode刷题】

WIZnet W5500系列培训活动之“MQTT协议讲解和实践(接入OneNET)”

世界上最高效的笔记方法(改变你那老版的记笔记方法吧)

Reflection reflection

圆角大杀器,使用滤镜构建圆角及波浪效果!
Details of the list of state products that Apple announced to be eligible for the sales tax holiday in the United States

Breadth first traversal (problems related to sequence traversal of graphs and binary trees)
随机推荐
SQL注入 Less17(报错注入+子查询)
小区蔬菜配送的小程序
SQL language (II)
[leetcode brush questions]
Greedy problem 01_ Activity arrangement problem
DICOM medical image viewing and browsing function based on cornerstone.js
Dynamic planning problem 03_ Maximum sub segment sum
工作面试总遇秒杀?看了京东T8大咖私藏的秒杀系统笔记,已献出膝盖
leetcode 剑指 Offer 27. 二叉树的镜像
varest蓝图设置json
Summary of combination problems of Li Kou brush questions (backtracking)
绘图==PYQT5
W5500在处于TCP_Server模式下,在交换机/路由器网络中无法ping通也无法通讯。
教你如何通过MCU配置S2E为TCP Client的工作模式
Miidock Brief
Multiply Floyd "suggestions collection"
大话DevOps监控,团队如何选择监控工具?
Only know that the preform is used to generate objects? See how I use unity to generate UI prefabs
SQL注入 Less23(过滤注释符)
Understanding: idea uses Scala to write wordcount programs and generate jar packages