linux下uboot kernel操作cpu寄存器

简介: 大多数的内核里面都有会对GPIO的操作,而且内核里面对GPIO进行配置也很方便,要什么功能就配置成什么就可以了。 还有一些寄存器是内核没有配置到的,但是我们要操作怎么办,内核里面也定义了相关的接口函数。

大多数的内核里面都有会对GPIO的操作,而且内核里面对GPIO进行配置也很方便,要什么功能就配置成什么就可以了。

还有一些寄存器是内核没有配置到的,但是我们要操作怎么办,内核里面也定义了相关的接口函数。

在u-boot中操作某个寄存器:

 

[cpp]  view plain  copy
 
 print?在CODE上查看代码片派生到我的代码片
  1. reg = readl(IOMUXC_BASE_ADDR + IOMUXC_REG_GPR1);  
  2. reg &= ~IOMUXC_REG_GPR1_ACTCS0_MASK;  
  3. writel(reg, IOMUXC_BASE_ADDR + IOMUXC_REG_GPR1);  

其中IOMUXC_BASE_ADDR是物理地址,跟踪代码发现writel操作如下:

 

#define writel(v,a) __arch_putl(v,a)

#define __arch_putl(v,a) (*(volatile unsigned int *)(a) = (v))

所以在uboot里面配置寄存相当于是给物理地址直接赋值,volatile的意思是提醒编译器需要存储或读取这个变量的时候,都会直接从变量地址中读取数据

 

而在内核中,上面的写法是无法运行的,会提示虚拟地址错误。在内核中通常是通过虚拟地址来给物理地址赋值,所以需要将物理地址转换成虚拟地址

 

[cpp]  view plain  copy
 
 print?在CODE上查看代码片派生到我的代码片
  1. reg = __raw_readl(ioremap(IOMUXC_BASE_ADDR + IOMUXC_REG_GPR1,4));  
  2. reg &= ~IOMUXC_REG_GPR1_ACTCS0_MASK;  
  3. reg &= ~IOMUXC_REG_GPR1_ADDRS0_MASK;  
  4. reg |= ((CS0_NORFLASH_SIZE | IOMUXC_REG_GPR1_ACTCS0));  
  5. __raw_writel(reg, ioremap(IOMUXC_BASE_ADDR + IOMUXC_REG_GPR1,4));  

这里的ioremap是将物理地址IOMUXC_BASE_ADDR转换得到对应的虚拟地址,4表示4个字节,即32位的地址。

 

u-boot下读写gpio:

与读写寄存器类似,u-boot下读写GPIO口是直接给GPIO赋值:

 

[cpp]  view plain  copy
 
 print?在CODE上查看代码片派生到我的代码片
  1. mxc_request_iomux(MX53_PIN_GPIO_8, IOMUX_CONFIG_ALT1);  
  2. mxc_iomux_set_pad(MX53_PIN_GPIO_8, 0x1E4);  
  3.   
  4. reg = readl(GPIO1_BASE_ADDR + 0x0);  
  5.    <span style="white-space:pre"> </span>reg |= 0x100;  
  6. writel(reg, GPIO1_BASE_ADDR + 0x0);  
  7.   
  8. // Set pin direction as output  
  9. reg = readl(GPIO1_BASE_ADDR + 0x4);  
  10. reg |= 0x100;  
  11. writel(reg, GPIO1_BASE_ADDR + 0x4);  


GPIO_8 是GPIO1_8,前面两个配置GPIO_8的功能。

 

查看datasheet可以看到GPIO1的地址配置

53F8_4000 GPIO data register (GPIO-1_DR) 32 R/W 0000_0000h 
53F8_4004 GPIO direction register (GPIO-1_GDIR) 32 R/W 0000_0000h 
53F8_4008 GPIO pad status register (GPIO-1_PSR) 32 R 0000_0000h 
53F8_400C GPIO interrupt configuration register1 (GPIO-1_ICR1) 32 R/W 0000_0000h 
53F8_4010 GPIO interrupt configuration register2 (GPIO-1_ICR2) 32 R/W 0000_0000h
53F8_4014 GPIO interrupt mask register (GPIO-1_IMR) 32 R/W 0000_0000h 
53F8_4018 GPIO interrupt status register (GPIO-1_ISR) 32 w1c 0000_0000h
53F8_401C GPIO edge select register (GPIO-1_EDGE_SEL) 32 R/W 0000_0000h 

 

可以看到它的数据寄存器的偏移地址是0x0,输入输出寄存器的偏移地址是0x4。而reg |= 0x100;是GPIO_8的所在的偏移,即(0x1 << 8)。

读取一个gpio的值,只需要读取它的状态寄存器就可以了,

reg = readl( GPIO1_BASE_ADDR + 0x08 );

if(reg & (0x1 << 8))

printf("it is high\n");

else

printf("it is low\n");

目录
相关文章
|
16天前
|
缓存 监控 Linux
|
3月前
|
缓存 监控 Linux
在Linux中,如何看当前系统有几颗物理CPU和每颗CPU的核数?
在Linux中,如何看当前系统有几颗物理CPU和每颗CPU的核数?
|
21天前
|
缓存 Linux
揭秘Linux内核:探索CPU拓扑结构
【10月更文挑战第26天】
35 1
|
21天前
|
缓存 运维 Linux
深入探索Linux内核:CPU拓扑结构探测
【10月更文挑战第18天】在现代计算机系统中,CPU的拓扑结构对性能优化和资源管理至关重要。了解CPU的核心、线程、NUMA节点等信息,可以帮助开发者和系统管理员更好地调优应用程序和系统配置。本文将深入探讨如何在Linux内核中探测CPU拓扑结构,介绍相关工具和方法。
19 0
|
2月前
|
存储 缓存 编译器
Linux kernel memory barriers 【ChatGPT】
Linux kernel memory barriers 【ChatGPT】
55 11
|
3月前
|
Linux 网络安全 开发工具
内核实验(二):自定义一个迷你Linux ARM系统,基于Kernel v5.15.102, Busybox,Qemu
本文介绍了如何基于Linux Kernel 5.15.102版本和BusyBox创建一个自定义的迷你Linux ARM系统,并使用QEMU进行启动和调试,包括内核和BusyBox的编译配置、根文件系统的制作以及运行QEMU时的命令和参数设置。
290 0
内核实验(二):自定义一个迷你Linux ARM系统,基于Kernel v5.15.102, Busybox,Qemu
|
3月前
|
监控 Linux
性能分析之 Linux 系统中 ps&top 中 CPU 百分比不一致?
【8月更文挑战第18天】性能分析之 Linux 系统中 ps&top 中 CPU 百分比不一致?
170 4
|
3月前
|
Linux Python
在Linux中,如何查找系统中占用CPU最高的进程?
在Linux中,如何查找系统中占用CPU最高的进程?
|
3月前
|
Linux
在Linux中,如何获取CPU的总核心数?
在Linux中,如何获取CPU的总核心数?
|
3月前
|
监控 安全 算法
在Linux中,cpu使用率过高可能是什么原因引起的?排查思路是什么?
在Linux中,cpu使用率过高可能是什么原因引起的?排查思路是什么?