在 ARM 上的 Linux 中写入和读取内存映射设备寄存器

2023-11-23

我正在尝试按照以下步骤读取和写入 ARM9 (SAM9X25) 上的寄存器:http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka3750.html
我以以下代码结束:

#include "stdio.h"

#define PIO_WPMR_BANK_D                     0xFFFFFAE4  // PIO Write Protection Mode Register Bank D
#define PIO_PUER_BANK_D                     0xFFFFFA64  // PIO Pull-Up Enable Register Bank D
#define PIO_PUSR_BANK_D                     0xFFFFFA68  // PIO Pull-Up Status Register Bank D

#define MASK_LED7                           0xFFDFFFFF  // LED7 Mask
#define DESABLE_WRITE_PROTECTION_BANK_D     0x50494F00  // Desable write protection Bank D

int main(void) {
    printf("test");
    unsigned int volatile * const register_PIO_WPMR_BANK_D = (unsigned int *) PIO_WPMR_BANK_D;

    unsigned int volatile * const register_PIO_PUSR_BANK_D = (unsigned int *) PIO_PUSR_BANK_D;

    unsigned int volatile * const port_D = (unsigned int *) PIO_PUER_BANK_D;

    *register_PIO_WPMR_BANK_D = DESABLE_WRITE_PROTECTION_BANK_D;

    *port_D = *register_PIO_PUSR_BANK_D & MASK_LED7;

    return 0; }


我在 Ubuntu 16.04 中交叉编译了我的代码,如下所示arm-linux-gnueabi-gcc gpio.c -o gpio
但我有一个Segmentation Fault就在之后printf在我的主板上执行程序期间。
我知道地址是正确的...那么为什么我会出现此错误?
这是好方法吗?
感谢您的帮助 !

解决方案 :
谢谢@vlk,我可以让它工作!下面是一个切换 LED 的小例子:

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>


#define handle_error(msg) \
           do { perror(msg); exit(EXIT_FAILURE); } while (0)

#define _PIOD_BANK_D                            0xA00

#define _PIO_OFFSET                             0xFFFFF000

/* When executing this on the board :
    long sz = sysconf(_SC_PAGESIZE);
    printf("%ld\n\r",sz);
   We have 4096.
*/
#define _MAP_SIZE                           0x1000  // 4096 

#define _WPMR_OFFSET                        0x0E4   // PIO Write Protection Mode Register Bank D

#define _PIO_ENABLE                         0x000
#define _PIO_DISABLE                        0x004
#define _PIO_STATUS                         0x008
#define _OUTPUT_ENABLE                      0x010
#define _OUTPUT_DISABLE                     0x014
#define _OUTPUT_STATUS                      0x018
#define _FILTER_ENABLE                      0x020
#define _FILTER_DISABLE                     0x024
#define _FILTER_STATUS                      0x028
#define _OUTPUT_DATA_SET                    0x030
#define _OUTPUT_DATA_CLEAR                  0x034
#define _OUTPUT_DATA_STATUS                 0x038
#define _PIN_DATA_STATUS                    0x03c
#define _MULTI_DRIVER_ENABLE                0x050
#define _MULTI_DRIVER_DISABLE               0x054
#define _MULTI_DRIVER_STATUS                0x058
#define _PULL_UP_DISABLE                    0x060
#define _PULL_UP_ENABLE                     0x064
#define _PULL_UP_STATUS                     0x068
#define _PULL_DOWN_DISABLE                  0x090
#define _PULL_DOWN_ENABLE                   0x094
#define _PULL_DOWN_STATUS                   0x098

#define _DISABLE_WRITE_PROTECTION           0x50494F00  // Desable write protection

#define LED_PIN                                 21

int main(void) {

    volatile void *gpio_addr;
    volatile unsigned int *gpio_enable_addr;
    volatile unsigned int *gpio_output_mode_addr;
    volatile unsigned int *gpio_output_set_addr;
    volatile unsigned int *gpio_output_clear_addr;
    volatile unsigned int *gpio_data_status_addr;
    volatile unsigned int *gpio_write_protection_addr;

    int fd = open("/dev/mem", O_RDWR|O_SYNC);
    if (fd < 0){
        fprintf(stderr, "Unable to open port\n\r");
        exit(fd);
    }


    gpio_addr = mmap(NULL, _MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, _PIO_OFFSET);


    if(gpio_addr == MAP_FAILED){
        handle_error("mmap");
    }


    gpio_write_protection_addr = gpio_addr + _PIOD_BANK_D + _WPMR_OFFSET;

    gpio_enable_addr = gpio_addr + _PIOD_BANK_D + _PIO_ENABLE;

    gpio_output_mode_addr = gpio_addr + _PIOD_BANK_D + _OUTPUT_ENABLE;

    gpio_output_set_addr = gpio_addr + _PIOD_BANK_D + _OUTPUT_DATA_SET;

    gpio_output_clear_addr = gpio_addr + _PIOD_BANK_D + _OUTPUT_DATA_CLEAR;

    gpio_data_status_addr = gpio_addr + _PIOD_BANK_D + _OUTPUT_DATA_STATUS;


    *gpio_write_protection_addr = _DISABLE_WRITE_PROTECTION;

    *gpio_enable_addr = 1 << LED_PIN;
    *gpio_output_mode_addr = 1 << LED_PIN; // Output


    // If LED
    if((*gpio_data_status_addr & (1<<LED_PIN)) > 0){
        *gpio_output_clear_addr = 1 << LED_PIN;
    }else{
        *gpio_output_set_addr = 1 << LED_PIN;
    }

    return 0;
}

EDIT :
回答为3)在评论中。如果您希望它能够处理所有偏移量,则必须像这样更改 mmap 和分配(即:映射示例):

#define _PIO_OFFSET                         0xFFFFFA00 // Instead of 0xFFFFF000
#define _MAP_SIZE                           0x1000  // 4096 
#define _MAP_MASK                           (_MAP_SIZE - 1)
#define _PA_OFFSET                          _PIO_OFFSET & ~_MAP_MASK

和映射:

gpio_addr = mmap(NULL, _MAP_SIZE + _PIO_OFFSET - _PA_OFFSET, PROT_READ | PROT_WRITE, MAP_SHARED, fd, _PA_OFFSET);

对于分配:

gpio_enable_addr = gpio_addr + _PIO_OFFSET - (_PA_OFFSET) + _PIO_ENABLE;

您无法直接访问寄存器,因为 Linux 使用 MMU,这会为您的应用程序创建与物理 MCU 地址空间不同的虚拟地址空间,并且访问该虚拟地址空间之外会导致分段错误。

在 Linux 中访问这些寄存器的唯一方法(如果您不想编写内核驱动程序)是将文件 /dev/mem 作为文件打开并将其映射为mmap

例如,我有一个小型 python 库,用于访问 Atmel SAM MCU 上的 GPIO 寄存器gpiosam。您可以激发灵感并将其移植到 C。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 ARM 上的 Linux 中写入和读取内存映射设备寄存器 的相关文章

随机推荐

  • jQuery 可移动模态对话框

    我一直在寻找可拖动模式框的所有可用 jQuery 插件 唯一的问题是我发现的每个可拖动的模式框都需要标题栏 有谁知道有什么 jQuery 插件可以让我创建一个没有标题栏的可拖动模式框吗 在这种情况下 您可以通过框的边框拖动它 有什么方法可以
  • 无法访问 attr_accessor 定义的变量

    我正在使用 Thinking Sphinx 来运行搜索 并且我得到了适当的 ActiveRecord 模型 问题是 我想在每个模型上创建适当的链接路径和文本 然后通过 AJAX 将信息以 JSON 形式发送到浏览器 我使用以下内容来构建这些
  • 如何限制cakephp中的分页

    如何限制 cakephp 中的分页 假设我有 400 条记录 我只需要获取从第50条记录到第75条记录的25条记录 每页需要显示5条记录 我如何在分页中做到这一点 示例代码 this gt paginate array contain gt
  • Google App Engine Node.js 应用程序不健康

    我正在尝试在谷歌应用程序引擎上测试一个相当简单的node js应用程序 如下所示 它要做的就是监听 Firebase 数据库中的更改 然后向用户发送 GCM 消息 var Firebase require firebase var gcm
  • Apache HTTP BasicScheme.authenticate 已弃用?

    在 Apache HTTP Component 4 类 org apache http impl auth BasicScheme 中 我注意到该方法 public static Header authenticate final Cred
  • 动画边距/厚度

    我只是以为我已经知道 WPF 和 XAML 语法是如何工作的 呜呜 我收到消息 WithEvents variables can only be typed as classes interfaces or type parameters
  • 我可以在类外部初始化“constexpr static”成员吗?

    我正在使用可变宽度通信格式 处理它的结构看起来像这样 struct Header int msgType 1 len Header len sizeof this struct A public Header int x char y A
  • 每次更改 Rails 代码时都必须重新启动 Apache

    我正在使用 Apache 和 Passenger 运行 Rails 3 自从我从 Mongrel 切换到 Passenger 后 我发现每次更改代码时都必须重新启动 Apache 这是预期的行为吗 在开发中使用 Mongrel 是避免这个问
  • SwiftUI 将 TupleView 转换为 AnyView 数组

    Code 我有以下代码 struct CustomTabView View where Content View let children AnyView init ViewBuilder content escaping gt Conte
  • PyPlot 将替代 y 轴移动到背景

    在 pyplot 中 您可以使用以下命令更改不同图形的顺序zorder选项或通过更改顺序plot 命令 但是 当您通过添加替代轴时ax2 twinx 新轴将始终覆盖旧轴 如文档 是否可以更改轴的顺序以将替代 孪生 y 轴移动到背景 在下面的
  • “视觉继承”的现状如何

    我们有一个应用程序 它必须灵活地向用户显示其主表单 根据用户的不同 表单应该略有不同 也许这里或那里有一个额外的按钮 或者其他一些细微差别 为了停止编写代码来显式删除或添加控件等 我转向视觉继承来解决问题 在我认为是一种整洁 干净和逻辑的
  • 有没有办法在Python中创建类属性?

    由于某种原因 以下内容不起作用 gt gt gt class foo object property classmethod def bar cls return asdf gt gt gt foo bar
  • SimpleDateFormat toPattern 在 java 9 中的行为有所不同

    DateFormat dateFormat DateFormat getDateInstance DateFormat SHORT new Locale SV SE SimpleDateFormat dateFormat toPattern
  • std::string::npos == -1 总是 true 吗?

    标题相对来说是不言自明的 我认识到与其他答案的相似之处 但所有这些答案都有不同的运算符安排 因此也有不同的转换规则 所以我需要一个能够澄清这个特殊情况的答案 如果有人可以指出标准中解释这一点的部分 我会很乐意投票并接受答案 NO 这并不总是
  • 在 Rails 4 中使用单个表单保存多条记录

    我有一个模型叫Family which belongs to user我想让用户能够在一个表单中添加多个家庭成员 该表单位于 views families new html erb 因此用户会看到一张为一个 user id 创建 3 个家庭
  • SKPaymentTransactionObserver 在应用程序切换时未收到回调

    我设置了应用内购买 以便当用户单击购买按钮时 会出现 请稍候 视图并将付款添加到付款队列中 这总是会导致队列观察者立即回调 表示交易进入 购买 状态 当用户在弹出确认购买对话框之前返回主屏幕然后取消时 就会出现我的问题 如果我在主屏幕上等待
  • 在 Razor 中使用 Html.EditorForModel 渲染时,ASP.Net [HiddenInput] 数据属性不起作用?

    我有以下模型 public class Product HiddenInput DisplayValue false public int ProductID get set Required ErrorMessage Please ent
  • 如何在 QWidget 周围添加边框?

    我在用PyQT4为潜在客户创建示例应用程序 我正在寻找某种方法来在特定小部件周围放置边框 请给我一些寻找的指示 更新 class CentralWidget QtGui QWidget def init self mainWindow su
  • 如何获取android中所有非系统应用程序的列表

    我正在开发一个应用程序 我想在其中获取所有非系统应用程序的列表 这是我的代码部分 TextView tv new TextView this this setContentView tv ActivityManager actvityMan
  • 在 ARM 上的 Linux 中写入和读取内存映射设备寄存器

    我正在尝试按照以下步骤读取和写入 ARM9 SAM9X25 上的寄存器 http infocenter arm com help index jsp topic com arm doc faqs ka3750 html我以以下代码结束 in