Как правильно работать с /dev/mem, /dev/fmem Linux ARM

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Как правильно работать с /dev/mem, /dev/fmem Linux ARM

Сообщение mig-31 » 28.03.2013 17:02:54

Добрый день,

Как записать значение в регистр ARM процессора, который отображаеться в /dev/mem.

Адрес регистра $FFFFF800. Такой вот код заканчиваеться ошибкой OUT of Range.
Код: Выделить всё
var
  f:TFileStream;
  value:cardinal;
begin
  value:=1;
  f:=TFileStream.Create('/dev/mem',fmOpenWrite);
  f.Seek($FFFFF800,soFromBegining); 
  f.Write();
end;
mig-31
постоялец
 
Сообщения: 224
Зарегистрирован: 14.07.2011 13:46:48

Re: Как правильно работать с /dev/mem, /dev/fmem Linux ARM

Сообщение Maxizar » 28.03.2013 19:29:22

1. /dev/mem - это устр-во или device
2. Вы на пол пути к истине, а именно вы сказали:
который отображаеться


Вам нужно пробросить адреса которые отображаются в устро-ве в вашу программу тобишь в user space. тобишь в пространство пользователя, при помощи mmap.
Ведь что такое Адрес регистра $FFFFF800 правильно адрес в линейной памяти проца АРМ. в устр-ве /dev/mem они отображены также линейно. А вы работаете (ну не вы а ваша программа) со страничной памятью.. итого вам для адреса регистра нужно для программы построить страницы (отобразить из устр-ва в программу) через которую можно писать уже в регистр.. писать я думаю вы уже поняли через указатель и смещение от-но него :)

Замечание: - проброс в большинстве случаев нужно делать от адреса кратным странице Linux-а а это 4 Кбайта. Тобишь вы не сможете сделать mmap скажем с адреса $FFFFF803.. нужно будет отобразить кратный адрес, получить указатель на него и сместиться и бла бла бла...

Короче долго это писать вот код, он делает проброс GPIO - а если быть точным всего устр-ва GPIO для проца AM37xx от TI. (omap3) ну и в цикле дергает ногой :)
Код на Си, но я думаю все прозрачно:
Код: Выделить всё
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>



#define OMAP24XX_BASE_ADDRES_PER_CM 0x48005000

// omap2+ PER_CM Register Summary
#define CM_FCLKEN_PER     0x0000
#define CM_ICLKEN_PER     0x0010
#define CM_IDLEST_PER     0x0020
#define CM_AUTOIDLE_PER   0x0030
#define CM_CLKSEL_PER     0x0040
#define CM_SLEEPDEP_PER   0x0044
#define CM_CLKSTCTRL_PER  0x0048
#define CM_CLKSTST_PER    0x004C









#define OMAP24XX_BASE_ADDRES_GPIO1 0x48310000
#define OMAP24XX_BASE_ADDRES_GPIO2 0x49050000
#define OMAP24XX_BASE_ADDRES_GPIO3 0x49052000
#define OMAP24XX_BASE_ADDRES_GPIO4 0x49054000
#define OMAP24XX_BASE_ADDRES_GPIO5 0x49056000
#define OMAP24XX_BASE_ADDRES_GPIO6 0x49058000



// omap2+ specific GPIO registers
#define OMAP24XX_GPIO_REVISION          0x0000
#define OMAP24XX_GPIO_SYSCONFIG          0x0010
#define OMAP24XX_GPIO_SYSSTATUS          0x0014
#define OMAP24XX_GPIO_IRQSTATUS1       0x0018
#define OMAP24XX_GPIO_IRQSTATUS2       0x0028
#define OMAP24XX_GPIO_IRQENABLE2       0x002c
#define OMAP24XX_GPIO_IRQENABLE1       0x001c
#define OMAP24XX_GPIO_WAKE_EN            0x0020
#define OMAP24XX_GPIO_CTRL              0x0030
#define OMAP24XX_GPIO_OE                0x0034
#define OMAP24XX_GPIO_DATAIN            0x0038
#define OMAP24XX_GPIO_DATAOUT            0x003c
#define OMAP24XX_GPIO_LEVELDETECT0     0x0040
#define OMAP24XX_GPIO_LEVELDETECT1     0x0044
#define OMAP24XX_GPIO_RISINGDETECT     0x0048
#define OMAP24XX_GPIO_FALLINGDETECT     0x004c
#define OMAP24XX_GPIO_DEBOUNCE_EN       0x0050
#define OMAP24XX_GPIO_DEBOUNCE_VAL     0x0054
#define OMAP24XX_GPIO_CLEARIRQENABLE1   0x0060
#define OMAP24XX_GPIO_SETIRQENABLE1     0x0064
#define OMAP24XX_GPIO_CLEARWKUENA       0x0080
#define OMAP24XX_GPIO_SETWKUENA          0x0084
#define OMAP24XX_GPIO_CLEARDATAOUT     0x0090
#define OMAP24XX_GPIO_SETDATAOUT       0x0094

#define GPIO_MAP_SIZE 4096

#define PIN_MASK  ( (1<<16) | (1<<17) )



struct OMAP3_GPIO{

///           Register Name     Type     Offset
unsigned int  Revision;        // R      0x000
unsigned char Reserv0[12];     // R      0x004
unsigned int  SysConfig;       // RW     0x010
unsigned int  SysStatus;       // R      0x014
unsigned int  IrqStatus1;      // RW     0x018
unsigned int  IrqEnable1;      // RW     0x01C
unsigned int  WakeUpEnable;    // RW     0x020
unsigned char Reserv1[4];      // R      0x024
unsigned int  IrqStatus2;      // RW     0x028
unsigned int  IrqEnable2;      // RW     0x02C
unsigned int  Ctrl;            // RW     0x030
unsigned int  OE;              // RW     0x034
unsigned int  DataIN;          // R      0x038
unsigned int  DataOUT;         // RW     0x03C
unsigned int  LevelDetect0;    // RW     0x040
unsigned int  LevelDetect1;    // RW     0x044
unsigned int  RisingDetect;    // RW     0x048
unsigned int  FallingDetect;   // RW     0x04C
unsigned int  DebouncEnable;   // RW     0x050
unsigned int  DebouncingTime;  // RW     0x054
unsigned char Reserv2[8];      // R      0x058
unsigned int  ClearIrqEnable1; // RW     0x060
unsigned int  SetIrqEnable1;   // RW     0x064
unsigned char Reserv3[8];      // R      0x068
unsigned int  ClearIrqEnable2; // RW     0x070
unsigned int  SetIrqEnable2;   // RW     0x074
unsigned char Reserv4[8];      // R      0x078
unsigned int  ClearWKUENA;     // RW     0x080
unsigned int  SetWKUENA;       // RW     0x084
unsigned char Reserv5[8];      // R      0x088
unsigned int  ClearDataOUT;    // RW     0x090
unsigned int  SetDataOUT;      // RW     0x094
};


int Enable_Clk_GPIO3(void)
{
    int fd;
    void *mapped_base;


    fd = open("/dev/mem", O_RDWR);
   
    if( fd < 0 )
      {
        printf("Cannot open /dev/mem.\n");
        exit(EXIT_FAILURE);
      }
   
    printf("/dev/mem opened.\n");
   
    mapped_base = mmap(0, GPIO_MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, OMAP24XX_BASE_ADDRES_PER_CM);
   
    if (mapped_base == MAP_FAILED)
      {
        printf("Memory mapping error.\n");
        exit(EXIT_FAILURE);
      }
   
    printf("Memory block mapped at address %p.\n", mapped_base);
   
    unsigned int old_val = *(int *)(mapped_base + CM_FCLKEN_PER);
    printf("CM_FCLKEN_PER = 0x%x \n", old_val);
   
    *(int *)(mapped_base + CM_FCLKEN_PER)  = old_val | (1 << 14);

    old_val = *(int *)(mapped_base + CM_ICLKEN_PER);
    *(int *)(mapped_base + CM_ICLKEN_PER) = old_val | (1 << 14);

    printf("CM_ICLKEN_PER = 0x%x \n", *(int *)(mapped_base + CM_ICLKEN_PER));
    close(fd);
}




int main(void)
{
    int fd;
    struct OMAP3_GPIO *GPIO3_Reg;
   
   
    fd = open("/dev/mem", O_RDWR);
   
    if( fd < 0 )
      {
        printf("Cannot open /dev/mem.\n");
        exit(EXIT_FAILURE);
      }
   
    printf("/dev/mem opened.\n");
   
    GPIO3_Reg = mmap(0, sizeof(struct OMAP3_GPIO), PROT_READ | PROT_WRITE, MAP_SHARED, fd, OMAP24XX_BASE_ADDRES_GPIO3);
   
    if (GPIO3_Reg == MAP_FAILED)
      {
        printf("Memory mapping error.\n");
        exit(EXIT_FAILURE);
      }
   
    printf("Memory block mapped at address %p.\n", GPIO3_Reg);
   
   
    printf("OMAP24XX_GPIO_OE = 0x%x \n", GPIO3_Reg->OE);
    unsigned int old_val = GPIO3_Reg->OE;
   
    GPIO3_Reg->OE  = ( old_val & ~(1<< 17) ) ;
   
   
   
    printf("SYSCONFIG = 0x%x \n", GPIO3_Reg->SysConfig);
    printf("SYSSTATUS = 0x%x \n", GPIO3_Reg->SysStatus);
   
    printf("OMAP24XX_GPIO_WAKE_EN = 0x%x \n",    GPIO3_Reg->WakeUpEnable);
    printf("OMAP24XX_GPIO_IRQENABLE1 = 0x%x \n", GPIO3_Reg->IrqEnable1);
    printf("OMAP24XX_GPIO_IRQENABLE2 = 0x%x \n", GPIO3_Reg->IrqEnable2);
   

       
    int val=0;
   
    while (1)
      {
        val = !val;
       
        if (val)
          {
             GPIO3_Reg->SetDataOUT = (1 << 17); // PIN_MASK;
             printf("Set \n");
          }
        else
          {
             GPIO3_Reg->ClearDataOUT = (1 << 17);//PIN_MASK;
             printf("Clear \n");
          }
       
        printf("DATAOUT = 0x%x \n", GPIO3_Reg->DataOUT);
        sleep (1);
      }   
   
    return 0;
}
Maxizar
постоялец
 
Сообщения: 385
Зарегистрирован: 20.03.2010 19:48:14

Re: Как правильно работать с /dev/mem, /dev/fmem Linux ARM

Сообщение mig-31 » 28.03.2013 22:15:37

А можно пример на FreePascale, например для одного регистра в вашем примере?
Как провести mmap на FreePascale? Какой функцией.

Спасибо.
mig-31
постоялец
 
Сообщения: 224
Зарегистрирован: 14.07.2011 13:46:48

Re: Как правильно работать с /dev/mem, /dev/fmem Linux ARM

Сообщение bormant » 29.03.2013 14:40:10

mig-31 писал(а):Как провести mmap на FreePascale? Какой функцией.

http://www.freepascal.org/docs-html/rtl ... pmmap.html
http://www.freepascal.org/docs-html/rtl ... unmap.html
Аватара пользователя
bormant
постоялец
 
Сообщения: 408
Зарегистрирован: 21.03.2012 11:26:01

Re: Как правильно работать с /dev/mem, /dev/fmem Linux ARM

Сообщение mig-31 » 29.03.2013 15:47:02

Большое спасибо. Это то что я хотел.
mig-31
постоялец
 
Сообщения: 224
Зарегистрирован: 14.07.2011 13:46:48


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2

Рейтинг@Mail.ru
cron