寄存器地址 - 将第二位(位索引= 1)的位值更改为1

时间:2016-05-15 15:09:04

标签: linux bit-manipulation bit cpu-registers openwrt

我有以下寄存器地址:0x18040028。由于我对这些东西很新,我应该如何访问该寄存器地址,更改那一位然后将其写回(所有其他条目应该保持不变)? 我是否需要编写程序,还是可以从终端编写程序?

我在linux(openwrt)

上这样做

感谢

2 个答案:

答案 0 :(得分:0)

快速而肮脏的方法是尝试从/ dev / mem中删除内存区域。看到这两个问题:

Accessing hardware registers in Linux userspace

Accessing physical address from user space

但是,我不建议您为生产系统执行此操作。更清洁的是编写内核驱动程序。一种选择是编写一个使用ioremap和ioread / iowrite操作的常规内核模块,并通过sysfs公开寄存器。

Using IO Memory

Sysfs Documentation

我认为另一个特别灵活的选择是通过平台支持文件中的platform_device系统公开这些寄存器。

Platform Devices

基本上你需要读取值,然后执行:

readvalue |= 1<<1;

然后将值写回寄存器。

答案 1 :(得分:0)

选项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

如果它返回一个数字,那就是偏移量。拿你的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的说明。它需要在名为io的openwrt安装中添加一个包,它们提供了一个切换该位值的脚本。你可以修改它,如果你想要回显,总是将它设置为某个值,等等。它是用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")))

Toggle uart_en on AR9331

我无法测试任何这个,所以我可能在任何地方都犯了错误,但是如果你遵循那个指南,并且将修改设置为总是设置为1(我现在注释掉),那你应该好。确保您只留下一个选项来修改该注册表。

来源/更多信息:
OpenWrt Wiki
Working with GPIOs
Kernel.org