2017-06-02 19 views
-1

私のARM(https://4donline.ihs.com/images/VipMasterIC/IC/ATML/ATML-S-A0001248554/ATML-S-A0001248554-1.pdf)の物理アドレスレジスタにmmapでアクセスしようとしていますが、どのような長さを入れるべきか分かりません。
例えば、私が32ビットにアクセスできるアドレス0xFFFFFCE8にレジスタがあるとします。
mmap size_tに何を入れる必要がありますか?

ありがとうございました!

EDIT:
Herehere我々は、彼らが4096を入れて見て、それはほとんどの鉱山と同じSAM9である最初のものにすることができます。
なぜ、彼らは4096を置いたのですか?私がしなければ
多分ので:マップサイズとmmap無効な引数エラー

#include <unistd.h> 
long sz = sysconf(_SC_PAGESIZE); 
printf("%ld",sz); 

Thの答えは4096です...

EDIT 2:
this postに基づいて、私はこの記述することができます。

#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_START_ADDR      0xFFFFFA00 
#define PIOD_STOP_ADDR      0xFFFFFC00 
#define PIOD_SIZE       (PIOD_STOP_ADDR-PIOD_START_ADDR) 

#define PIO_WPMR_OFFSET      0xE4 // PIO Write Protection Mode Register Bank D 

#define PIO_PUER_OFFSET      0x64 // PIO Pull-Up Enable Register Bank D 
#define PIO_PUSR_OFFSET      0x68 // PIO Pull-Up Status Register Bank D 

#define LED7_ON        0xFFDFFFFF // LED7 Mask ON 
#define LED7_OFF       0xFFFFFFFF // LED7 Mask OFF 
#define DESABLE_WRITE_PROTECTION_BANK_D  0x50494F00 // Desable write protection 

int main(void) { 
    volatile void *gpio_D_addr; 
    volatile unsigned int *gpio_pullup_enable_addr; 
    volatile unsigned int *gpio_pullup_status_addr; 
    volatile unsigned int *gpio_enable_write_addr; 

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

    gpio_D_addr = mmap(0, PIOD_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, PIOD_START_ADDR); 
    gpio_addr = mmap(0, GPIO1_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO1_START_ADDR); 

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

    gpio_enable_write_addr = gpio_D_addr + PIO_WPMR_OFFSET; 
    gpio_pullup_enable_addr = gpio_D_addr + PIO_PUER_OFFSET; 
    gpio_pullup_status_addr = gpio_D_addr + PIO_PUSR_OFFSET; 

    *gpio_enable_write_addr = DESABLE_WRITE_PROTECTION_BANK_D; 

    *gpio_pullup_enable_addr = *gpio_pullup_status_addr & LED7_ON; 

    return 0; 
} 

をしかし、私はmmap: Invalid argumentを持っていますエラー。 - >しかし、これ(このthreadに感謝)のようにmmapを変更することによって:mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, PIOD_START_ADDR & ~MAP_MASK);と:

#define MAP_SIZE       4096UL 
#define MAP_MASK       (MAP_SIZE - 1) 

私はもはやエラーを持っていませんが、何も起こらなかった...

任意のアイデア?

答えて

1

@vlk、彼に感謝したアドレスにlibraryでPython私はそれを動作させることができます!ここでは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; 
} 

それはmmap: Invalid argumentになったので、私は0xFFFFF000_PIO_OFFSETを入れて、代わりに0xFFFFFA00の、アドレスにD銀行(0xA00)の値を追加する必要がありました。
mmap exampleと解決策を見つけた:

#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 

とmmap:

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

と逢引のために:

なぜ...

EDITを知ってはいけません

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

リンクとして提供したデータシートの第5章をお読みください。このデバイスのさまざまなメモリとメモリマッピングについて説明します。指定したアドレスは32ビットですが、そのマッピングについて確認する必要があります。それがpのチャートです。これらのSAMデバイスを低レベルでプログラムしたい場合は、1200ページのデータシート全体に精通しながら、

あなたも(マップに基づいて)PMC(電源管理コントローラ)のメモリ空間のためのようですので、私はそのセクションを確認したい、章21

+0

助けていただきありがとうございます。私はすでにこの章を見ましたが、上の私の記事のEDITを見てください。 – Tagadac

+1

私は4096値について考えていません。それを理解するためにはもっと研究が必要です。しかし、今、仕事の呼び出し:( – TomServo

+1

これを行うことによって '#include 長いsz = sysconf(_SC_PAGESIZE); \t printf("%ld "、sz);'私たちは '4096'を持っています。 4096。 – Tagadac