【问题标题】:Reading from register of Allwinner H3 ARM processor读取全志 H3 ARM 处理器的寄存器
【发布时间】:2020-05-02 02:05:24
【问题描述】:
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>


static void foo(void){
    volatile  uint32_t *temp_addr;
    temp_addr = (uint32_t*)(0x01C20C00);
    *temp_addr =0;
}
int main(){
    tinit();

};

它编译但返回Segmentation fault 消息作为结果。我只想重置寄存器0x01c200c00 中的所有位。

【问题讨论】:

  • 对。但是您是从 Linux 用户空间运行它的。你得到了Segmentation fault,因为该地址没有映射到进程的内存中。
  • 作为普通用户,您无法访问硬件,AFAIK。这就是@dragosht 所说的。
  • 这样想,你有 kernel-spaceuser-space 其中 kernel-space 受到保护用户空间中发生的任何事情。这是一项安全功能,可保护内核免受任何错误或恶意 user-space 进程的影响。 (现在有权限提升机制允许 user-space 代码与 kernel-space 进程交互)。您正试图绕过所有 kernel-space 保护直接访问 kernel-space TIMER 地址。那是行不通的,(如果这样做了,就不会有 kernel-spaceuser-space 之间的分隔)
  • 内核和运行时库可能通过包含适当的标头并使用提供的计时器函数之一来提供与该计时器正确交互的能力。由于上述原因,查找计时器的地址并尝试直接访问它可能会失败。在控制台窗口中输入 apropos timer 以查看可用的计时器功能列表:getitimer, settimer, timer_create, ...
  • 您需要编写内核驱动程序,使用 mmap() 或者如果工具/库已经可用于该处理器/平台,请使用那些(首先因为它们会干扰您尝试的任何其他操作)。

标签: c raspberry-pi arm hardware-programming


【解决方案1】:

您的程序无法运行,因为 0x01C20C00 是物理地址,但您的程序使用虚拟地址。对于实验,您无需编写内核驱动程序即可访问 GPIO、定时器或其他外围设备。为此,您需要创建一个内存映射,如下所示:

#define ALLWINNER_TIMER_BASE 0x01C20C00

struct allwinner_timer
{
  volatile uint32_t IRQ_EN_REG;
  // add other registers from the datasheet, or find a kernel driver source with these definitions
};

int fd = open("/dev/mem", O_RDWR);
struct allwinner_timer *t = (struct allwinner_timer *)mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, ALLWINNER_TIMER_BASE);
// TODO: check for errors
t->IRQ_EN_REG = 0;

注意:

  • 如果内核限制对/dev/mem 的访问,它可能无法工作。这可以通过查看内核选项来找到,例如CONFIG_STRICT_DEVMEM 和dmesg;
  • 显然,它必须在超级用户下运行;
  • 您的代码可能会干扰系统的其他部分,例如内核驱动程序访问相同的外围设备,导致不可预测的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-03
    • 2014-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-29
    • 2014-07-19
    • 1970-01-01
    相关资源
    最近更新 更多