6

में एक पॉइंटर को भौतिक डिवाइस मैप करना हमारे पास एक एम्बेडेड सिस्टम है जहां एक मेमोरी मैप किए गए डिवाइस को कनेक्ट किया गया है, और एक एआरएम सीपीयू लिनक्स चलाता है। डिवाइस 0x40400000 पते पर स्थित है और मेगाबाइट पर कब्जा कर लेता है (इसमें से अधिकांश को वास्तविक स्मृति द्वारा समर्थित नहीं किया जाता है, लेकिन पता स्थान किसी भी तरह से डिवाइस पर मैप किया जाता है)। वर्तमान में हम इस डिवाइस के लिए डिवाइस ड्राइवर नहीं है।उपयोगकर्ता स्थान

डिवाइस में 0x404f0704 पते पर एक विशेष रीड-ओनली रजिस्टर (सीआईडी ​​कहा जाता है) है। इस रजिस्टर में CID = 0x404 मान है। मैं इस रजिस्टर को एआरएम पर चल रहे कार्यक्रम से पढ़ने की कोशिश कर रहा हूं।

नेट की खोज में मैंने mmap() फ़ंक्शन के बारे में सीखा जो माना जाता है कि मुझे उपयोगकर्ता स्थान से भौतिक पता तक पहुंचने देता है।

 

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

int main(void) 
{ 
    void   *pdev = (void *) 0x40400000; 
    size_t   ldev = (1024*1024); 
    int   *pu; 
    int volatile *pcid; 
    int volatile cid; 

    pu = mmap(pdev, ldev, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); 
    if (pu == MAP_FAILED) 
     errx(1, "mmap failure"); 

    pcid = (int *) (((void *) pu) + 0xf0704); 

    printf("pu = %08p\n", pu); 
    printf("pcid = %08p\n", pcid); 

    cid = *pcid; 
    printf("CID = %x\n", cid); 

    munmap(pu, ldev); 

    return (EXIT_SUCCESS); 
} 
 

एआरएम पार संकलक के साथ संकलन:

a-gcc -O0 -g3 -o mmap-test.elf mmap-test.c 

मैं अपेक्षित परिणाम नहीं मिल सकता है तो, मैंने पाया उदाहरण के एक जोड़े का पालन करने की कोशिश कर, मैं निम्नलिखित परीक्षण लिखा था। क्या मैं देख रहा हूँ यह है कि:

pu = 0x40400000 
pcid = 0x404f0704 
CID = 0 
बजाय अपेक्षित

CID = 404 

मैं क्या याद आ रही है/कर गलत यहाँ की

?


अद्यतन:

मैं एक डेमो कार्यक्रम मिल गया और अपने कोड निम्नलिखित मैं अपने कोड काम कर प्राप्त करने में सक्षम था: फिर भी

 

int main(void) 
{ 
    off_t   dev_base = 0x40400000; 
    size_t   ldev = (1024 * 1024); 
    unsigned long mask = (1024 * 1024)-1; 
    int   *pu; 
    void   *mapped_base; 
    void   *mapped_dev_base; 
    int volatile *pcid; 
    int volatile cid; 
    int   memfd; 

    memfd = open("/dev/mem", O_RDWR | O_SYNC); 
    mapped_base = mmap(0, MAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, memfd, dev_base & ~MAP_MASK); 
    if (mapped_base == MAP_FAILED) 
     errx(1, "mmap failure"); 
    mapped_dev_base = mapped_base + (dev_base & MAP_MASK); 
    pu = mapped_dev_base; 

    pcid = (int *) (((void *) pu) + 0xf0704); 

    printf("pu = %08p\n", pu); 
    printf("pcid = %08p\n", pcid); 

    cid = *pcid; 
    printf("CID = %x\n", cid); 

    munmap(mapped_base, ldev); 
    close(memfd); 

    return (EXIT_SUCCESS); 
} 
 

, मैं इतना यकीन है कि क्यों नहीं कर रहा हूँ 1 संस्करण काम नहीं किया। मेरी समझ यह थी कि एक बार जब आप MAP_ANONYMOUS का उपयोग करते हैं तो आपको मैपिंग के लिए फ़ाइल हैंडल की आवश्यकता नहीं होती है। इसके अलावा, मैंने भौतिक पता होने के लिए स्पष्ट रूप से एडीआर तर्क (pepi) को गलत तरीके से गलत किया है। अगर मैं अभी हूं, तो यह वास्तव में आभासी पता है।

उत्तर

5

एमएमएपी वह कार्य है जो आम तौर पर आभासी पते के साथ काम करता है। जब आप mmap(... MAP_ANONYMOUS) (या mmap/dev/zero फ़ाइल पर कॉल करते हैं) तो यह आपको शून्य से भरे हुए कुछ नए वर्चुअल मेमोरी देगा। लौटाया गया पता वर्चुअल मेमोरी का पता होगा।

आप कुछ फ़ाइल (एमएपी_एएनओएनवाईओयूएस के बिना) को एमएमएपी कर सकते हैं और फिर एमएमएपी कुछ वर्चुअल मेमोरी रेंज में फाइल सामग्री को मैप करेगा।

डिवाइस का पता 0x40400000 पर स्थित है

डिवाइस MMIO शारीरिक स्मृति में स्थित है; कोई भी प्रक्रिया वर्चुअल एड्रेस 0x40400000 का उपयोग कर सकती है; लेकिन उन्हें एमएमयू (मेमोरी मैनेजमेंट यूनिट) द्वारा कुछ मुफ्त भौतिक पृष्ठ पर मैप किया जाएगा (अनुवादित)। आप केवल कुछ वर्चुअल मेमोरी के लिए ओएस से नहीं पूछ सकते हैं और उम्मीद करते हैं कि डिवाइस रेंज के लिए एमएमएपी किया जाएगा (यह नरक का संस्करण होगा)।

लेकिन एक विशेष डिवाइस,/dev/mem है, जिसे फ़ाइल के रूप में उपयोग किया जा सकता है जिसमें सभी भौतिक स्मृति शामिल हैं। जब आप mmap s/dev/mem आप वास्तव में पूछे गए भौतिक सीमा में कुछ वर्चुअल मेमोरी के नए मानचित्रण को बनाने के लिए ओएस से पूछ रहे हैं।

mmap के अपने मंगलाचरण में:

mapped_base = mmap(0, MAP_SIZE, PROT_READ|PROT_WRITE, 
    MAP_SHARED, memfd, dev_base & ~MAP_MASK); 

आप भौतिक स्मृति सीमा [0x40400000 .. 0x4050000-1] (एक मेगाबाइट; बाइट 0x40500000 को छोड़कर) को मैप करने के पूछने आभासी स्मृति (इसके प्रारंभिक पता mmap द्वारा दिया जाता है) में से कुछ मेगाबाइट में।