Tag*_*dac 5 c linux arm cpu-registers gpio
我正在尝试按照以下步骤在我的 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; }
Run Code Online (Sandbox Code Playgroud)
我过我的编制在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;
}
Run Code Online (Sandbox Code Playgroud)
编辑:在评论中
回答3)。如果您希望它使用所有偏移量(即:mmap example),您必须像这样更改 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
Run Code Online (Sandbox Code Playgroud)
和 mmap :
gpio_addr = mmap(NULL, _MAP_SIZE + _PIO_OFFSET - _PA_OFFSET, PROT_READ | PROT_WRITE, MAP_SHARED, fd, _PA_OFFSET);
Run Code Online (Sandbox Code Playgroud)
对于分配:
gpio_enable_addr = gpio_addr + _PIO_OFFSET - (_PA_OFFSET) + _PIO_ENABLE;
Run Code Online (Sandbox Code Playgroud)
busybox devmem
busybox devmem是一个用于 mmaps 的微型 CLI 实用程序/dev/mem。
你可以在 Ubuntu 中使用: sudo apt-get install busybox
用法:从物理地址读取 4 个字节0x12345678:
sudo busybox devmem 0x12345678
Run Code Online (Sandbox Code Playgroud)
写信0x9abcdef0到那个地址:
sudo busybox devmem 0x12345678 w 0x9abcdef0
Run Code Online (Sandbox Code Playgroud)
有关如何进行测试的一些提示,请参阅此内容:从用户空间访问物理地址
还提到:https : //unix.stackexchange.com/questions/4948/shell-command-to-read-device-registers
| 归档时间: |
|
| 查看次数: |
12182 次 |
| 最近记录: |