寄存器地址 - 将第二位(位索引 = 1)的位值更改为 1
Register address - change bit value of the second bit (bit index = 1) to 1
我有以下寄存器地址:0x18040028。由于我对这些东西很陌生,我应该如何访问该寄存器地址,更改一位然后将其写回(所有其他条目应保持不变)?
我需要编写程序,还是可以从终端完成?
我正在 linux (openwrt)
谢谢
快速而肮脏的方法是尝试将内存区域 mmap 出 /dev/mem。看到这两个问题:
Accessing hardware registers in Linux userspace
Accessing physical address from user space
但是,我不建议您对生产系统执行此操作。更干净的是编写内核驱动程序。一种选择是编写一个使用 ioremap 和 ioread/iowrite 操作的常规内核模块,并通过 sysfs 公开寄存器。
在我看来,另一个特别巧妙的选择是通过板支持文件中的 platform_device 系统公开这些寄存器。
基本上你需要读取值,然后做:
readvalue |= 1<<1;
然后将值写回寄存器。
选项 1
在许多 linux 构建中,您可以使用 sysfs 直接访问 GPIO 引脚。特别是在 openwrt 上,它几乎总是暴露出来。
在openwrt设备的终端,查看这个文件夹是否存在:
ls -Al /sys/class/gpio
如果有,你通常需要导出你想要访问的特定GPIO引脚。我看着 http://www.black-swift.ru/files/AR9331.pdf 想不通。问题是我不认为那个寄存器上的特定引脚是以这种方式暴露的——至少我找不到它。我必须在那个系统上四处挖掘 GPIO 控制器才能找到答案。
您要启用的 UART 引脚 已公开 - GPIO9 (RX) 和 GPIO10 (TX)。因此,无论如何,此信息可能都会有所帮助。
下面的选项 2 几乎可以保证有效;我写完这部分后发现。
根据您的内核版本,您可以直接使用该 GPIO #,或添加一个偏移量。
尝试:
cat /sys/class/gpio/gpiochip*/base | head -n1
如果它 returns 是一个数字,那就是偏移量。使用您的 GPIO #,添加该偏移量(例如组成 200)并将其用作您的 GPIO #。
使用您的 GPIO 编号(有或没有偏移量),输入以下内容(以 210 为例;200 偏移量,GPIO10)
echo "210" > /sys/class/gpio/export
那么GPIO引脚就会暴露在这个目录下,还是以210为例,/sys/class/gpio210/
导出后至少会创建两个文件,/sys/class/gpio240/value
和 /sys/class/gpio240/direction
您可以使用 cat 与它们交互以读取它们,例如cat /sys/class/gpio240/value
并使用 echo 修改它:echo 1 > /sys/class/gpio240/value
在我放在底部的链接中有更多关于通过 sysfs 访问 gpio 的信息。
如果您找到正确的 GPIO #,这将很容易工作,但如果没有(或者即使您找到了),请使用:
选项 2
有人已经完成了所有的工作。有关如何与该寄存器交互以禁用/启用 UART 的说明。它需要在你的 openwrt 安装中添加一个名为 io 的包,并且它们提供了一个脚本来切换位的值。如果你只想回显,你可以修改它,总是将它设置为某个值,等等。它写在 bash.
您可以添加脚本的内容或从 /etc/rc.local 调用脚本本身,它会在每次启动时得到 运行;解决这个问题。
既然你已经知道你有AR9331,那么你可以删掉很多脚本,例如:
#!/bin/bash -
# Bitwise operations: & = And, | = Or, ^ = xOr, << = Left Shift
func_addr="0x18040028"
func_value=0x`io -4 $func_addr | cut -f3 -d'
case_bit="1<<1"
# This is where you would make a change if you wanted to
# just set it to 1 every time.
# To always set it to a '1', change from xor ^ to or |; like this
# io -4 $func_addr $(printf "0x%8.8x" $(($func_value | $case_bit)))
# to always be 0 change the operator to and &, and use a mask
# with just bit 1 set to 0
mask32_b1="0xFFFFFFFD"
# io -4 $func_addr $(printf "0x%8.8x" $(($func_value $ $mask32_b1)))
# we using Bitwise xOr operation to switching bit# state (0 or 1)
io -4 $func_addr $(printf "0x%8.8x" $(($func_value ^ $case_bit)))
# read bit# state and depending on the state - print some info
if [ $(($func_value & $case_bit)) = $(($case_bit)) ]; then
echo "Hardware UART is turned OFF"
# You can use this line for automatic configuring GPIOs via sysfs
# or you can load other modules that use these GPIOs
else
echo "Hardware UART is turned ON"
fi
可能是一个衬里(相当难看的一个):
io -4 "0x18040028" $(printf "0x%8.8x" $(("0x"$((io -4 "0x18040028" | cut -f3 -d )) ^ "0x2")))
我无法测试其中的任何一个,所以我可能在任何地方都犯了错误,但是如果您按照该指南进行修改,并将我放在其中的始终设置为 1(目前已注释掉) ), 那你应该是好的。确保只留下一个选项来修改该寄存器。
来源/更多信息:
OpenWrt Wiki
Working with GPIOs
Kernel.org
我有以下寄存器地址:0x18040028。由于我对这些东西很陌生,我应该如何访问该寄存器地址,更改一位然后将其写回(所有其他条目应保持不变)?
我需要编写程序,还是可以从终端完成?
我正在 linux (openwrt)
谢谢
快速而肮脏的方法是尝试将内存区域 mmap 出 /dev/mem。看到这两个问题:
Accessing hardware registers in Linux userspace
Accessing physical address from user space
但是,我不建议您对生产系统执行此操作。更干净的是编写内核驱动程序。一种选择是编写一个使用 ioremap 和 ioread/iowrite 操作的常规内核模块,并通过 sysfs 公开寄存器。
在我看来,另一个特别巧妙的选择是通过板支持文件中的 platform_device 系统公开这些寄存器。
基本上你需要读取值,然后做:
readvalue |= 1<<1;
然后将值写回寄存器。
选项 1
在许多 linux 构建中,您可以使用 sysfs 直接访问 GPIO 引脚。特别是在 openwrt 上,它几乎总是暴露出来。
在openwrt设备的终端,查看这个文件夹是否存在:
ls -Al /sys/class/gpio
如果有,你通常需要导出你想要访问的特定GPIO引脚。我看着 http://www.black-swift.ru/files/AR9331.pdf 想不通。问题是我不认为那个寄存器上的特定引脚是以这种方式暴露的——至少我找不到它。我必须在那个系统上四处挖掘 GPIO 控制器才能找到答案。
您要启用的 UART 引脚 已公开 - GPIO9 (RX) 和 GPIO10 (TX)。因此,无论如何,此信息可能都会有所帮助。
下面的选项 2 几乎可以保证有效;我写完这部分后发现。
根据您的内核版本,您可以直接使用该 GPIO #,或添加一个偏移量。 尝试:
cat /sys/class/gpio/gpiochip*/base | head -n1
如果它 returns 是一个数字,那就是偏移量。使用您的 GPIO #,添加该偏移量(例如组成 200)并将其用作您的 GPIO #。
使用您的 GPIO 编号(有或没有偏移量),输入以下内容(以 210 为例;200 偏移量,GPIO10)
echo "210" > /sys/class/gpio/export
那么GPIO引脚就会暴露在这个目录下,还是以210为例,/sys/class/gpio210/
导出后至少会创建两个文件,/sys/class/gpio240/value
和 /sys/class/gpio240/direction
您可以使用 cat 与它们交互以读取它们,例如cat /sys/class/gpio240/value
并使用 echo 修改它:echo 1 > /sys/class/gpio240/value
在我放在底部的链接中有更多关于通过 sysfs 访问 gpio 的信息。
如果您找到正确的 GPIO #,这将很容易工作,但如果没有(或者即使您找到了),请使用:
选项 2
有人已经完成了所有的工作。有关如何与该寄存器交互以禁用/启用 UART 的说明。它需要在你的 openwrt 安装中添加一个名为 io 的包,并且它们提供了一个脚本来切换位的值。如果你只想回显,你可以修改它,总是将它设置为某个值,等等。它写在 bash.
您可以添加脚本的内容或从 /etc/rc.local 调用脚本本身,它会在每次启动时得到 运行;解决这个问题。
既然你已经知道你有AR9331,那么你可以删掉很多脚本,例如:
#!/bin/bash -
# Bitwise operations: & = And, | = Or, ^ = xOr, << = Left Shift
func_addr="0x18040028"
func_value=0x`io -4 $func_addr | cut -f3 -d'
case_bit="1<<1"
# This is where you would make a change if you wanted to
# just set it to 1 every time.
# To always set it to a '1', change from xor ^ to or |; like this
# io -4 $func_addr $(printf "0x%8.8x" $(($func_value | $case_bit)))
# to always be 0 change the operator to and &, and use a mask
# with just bit 1 set to 0
mask32_b1="0xFFFFFFFD"
# io -4 $func_addr $(printf "0x%8.8x" $(($func_value $ $mask32_b1)))
# we using Bitwise xOr operation to switching bit# state (0 or 1)
io -4 $func_addr $(printf "0x%8.8x" $(($func_value ^ $case_bit)))
# read bit# state and depending on the state - print some info
if [ $(($func_value & $case_bit)) = $(($case_bit)) ]; then
echo "Hardware UART is turned OFF"
# You can use this line for automatic configuring GPIOs via sysfs
# or you can load other modules that use these GPIOs
else
echo "Hardware UART is turned ON"
fi
可能是一个衬里(相当难看的一个):
io -4 "0x18040028" $(printf "0x%8.8x" $(("0x"$((io -4 "0x18040028" | cut -f3 -d )) ^ "0x2")))
我无法测试其中的任何一个,所以我可能在任何地方都犯了错误,但是如果您按照该指南进行修改,并将我放在其中的始终设置为 1(目前已注释掉) ), 那你应该是好的。确保只留下一个选项来修改该寄存器。
来源/更多信息:
OpenWrt Wiki
Working with GPIOs
Kernel.org