roboforum.ru

Технический форум по робототехнике.

mini2440 Работа с GPIO из Linux

mini2440 Работа с GPIO из Linux

Resident » 16 июл 2010, 18:46

Наш процессор на mini240, а именно S3C2440A имеет 130 входов/выходов, которые раскиданы по 9-ти портам
— Port A(GPA): 25-output port
— Port B(GPB): 11-input/out port
— Port C(GPC): 16-input/output port
— Port D(GPD): 16-input/output port
— Port E(GPE): 16-input/output port
— Port F(GPF): 8-input/output port
— Port G(GPG): 16-input/output port
— Port H(GPH): 9-input/output port
— Port J(GPJ): 13-input/output port
(более подробно смотри даташит)

Итак, запускаем mini и из консоли набираем
Код: Выделить всёРазвернуть
cd /sys/class/gpio

просмотрев содержимое каталога обнаружим там следующее.
export gpiochip128 gpiochip192 gpiochip32 gpiochip96
gpiochip0 gpiochip160 gpiochip224 gpiochip64 unexport

эти каталоги соответствуют портам нашего процессора:
просмотреть какая папка какому порту соотвествует можно следуюшим образом:
Код: Выделить всёРазвернуть
[root@EmbedSky gpio]# cd ./gpiochip0
[root@EmbedSky gpiochip0]# cat label
GPIOA
[root@EmbedSky gpio]# cd ./gpiochip32
[root@EmbedSky gpiochip32]# cat ./label
GPIOB
[root@EmbedSky gpio]# cd ./gpiochip64
[root@EmbedSky gpiochip64]# cat label
GPIOC
[root@EmbedSky gpio]# cd ./gpiochip96
[root@EmbedSky gpiochip96]# cat label
GPIOD
[root@EmbedSky gpio]# cd ./gpiochip128
[root@EmbedSky gpiochip128]# cat label
GPIOE
[root@EmbedSky gpio]# cd ./gpiochip160
[root@EmbedSky gpiochip160]# cat label
GPIOF
[root@EmbedSky gpio]# cd ./gpiochip192
[root@EmbedSky gpiochip192]# cat label
GPIOG
[root@EmbedSky gpio]# cd ./gpiochip224
[root@EmbedSky gpiochip224]# cat label
GPIOH

Итого 8 портов (порт J кудато потерялся, ну и ладно :) )
т.к. процессор 32х разрядный, то по-умолчанию каждый порт имеет 32 пина, начиная с нулевого PORTA (0-31) POTRB (32-63) и т.д. и число в конце названия каждой папки обозначает первый (базовый) пин соответствующего порта. (для удобства подсчета)
но физически пинов меньше.
Посмотрим на разводку нашего 34х пинового разьема в даташите или в приложенном ниже файле и выберем необходмый нам порт и пин.
gpio.png

К примеру возьмем 11й пин разьема GPF2 (2й пин порта F)
Затем расчитаем вычислим его порядковый номер (база)160 + 2 = 162
Теперь в консоли подключим соответствующий пин следующей командой:
Код: Выделить всёРазвернуть
echo 162 > /sys/class/gpio/export

В результате выполнения которой в папке gpio появилась подпапка нашего пина gpio162
Заходим в нее и видим следующее:
direction edge subsystem uevent value
Нас интересуют файлы direction и value который соответствуют направлению пина и его значению.
Теперь читая из файла и записывая в файл можно управлять пином.
Код: Выделить всёРазвернуть
[root@EmbedSky gpio162]# cat direction
out

[root@EmbedSky gpio162]# cat value
0

[root@EmbedSky gpio162]# echo in > ./direction
[root@EmbedSky gpio162]# cat direction
in

[root@EmbedSky gpio162]# echo out > ./direction
[root@EmbedSky gpio162]# echo 1 > ./value
[root@EmbedSky gpio162]# cat value
1

[root@EmbedSky gpio162]# echo 0 > ./value
[root@EmbedSky gpio162]# cat value
0

[root@EmbedSky gpio162]# echo in > ./direction
[root@EmbedSky gpio162]# cat ./direction
in
[root@EmbedSky gpio162]# cat ./value
1

[root@EmbedSky gpio162]# echo 0 > ./value
[root@EmbedSky gpio162]# cat ./value
1

[root@EmbedSky gpio162]# echo out > ./direction
[root@EmbedSky gpio162]# echo 1 > ./value
[root@EmbedSky gpio162]# cat value
1

Как из Си или других языков программирования читать и писать файлы смотрим соответствующий ФАКи :)

После того как мы поработали с пином, почистим за собой, выполнив команду
Код: Выделить всёРазвернуть
echo 162 > /sys/class/gpio/unexport

При этом папка нашего пина исчезнет из каталога /sys/class/gpio

Программка на C дергающая 3пин порта B с частотой 1 Гц
Код: Выделить всёРазвернуть
// Blink pin 3 on port B at 1 Hz
// Just add an LED and see the light! ;)
//
//Created by Dingo_aus, 7 January 2009
//email: dingo_aus [at] internode <dot> on /dot/ net
//
//Created in AVR32 Studio (version 2.0.2) running on Ubuntu 8.04

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

FILE *fp;

int main(int argc, char** argv)
{

   printf("\n**********************************\n"
         "*  Welcome to PIN Blink program  *\n"
         "*  ....blinking pin 3 on port B  *\n"
         "*  ....rate of 1 Hz............  *\n"
         "**********************************\n");
   
   //create a variable to store whether we are sending a '1' or a '0'
   char set_value[4];
   //Integer to keep track of whether we want on or off
   int toggle = 0;
   
   //Using sysfs we need to write "37" to /sys/class/gpio/export
   //This will create the folder /sys/class/gpio/gpio37
   if ((fp = fopen("/sys/class/gpio/export", "ab")) == NULL)
      {
         printf("Cannot open export file.\n");
         exit(1);
      }
   //Set pointer to begining of the file
      rewind(fp);
      //Write our value of "37" to the file
      strcpy(set_value,"37");
      fwrite(&set_value, sizeof(char), 2, fp);
      fclose(fp);
   
   printf("...export file accessed, new pin now accessible\n");
   
   //SET DIRECTION
   //Open the LED's sysfs file in binary for reading and writing, store file pointer in fp
   if ((fp = fopen("/sys/class/gpio/gpio37/direction", "rb+")) == NULL)
   {
      printf("Cannot open direction file.\n");
      exit(1);
   }
   //Set pointer to begining of the file
   rewind(fp);
   //Write our value of "out" to the file
   strcpy(set_value,"out");
   fwrite(&set_value, sizeof(char), 3, fp);
   fclose(fp);
   printf("...direction set to output\n");
   
   //SET VALUE
   //Open the LED's sysfs file in binary for reading and writing, store file pointer in fp
   if ((fp = fopen("/sys/class/gpio/gpio37/value", "rb+")) == NULL)
      {
         printf("Cannot open value file.\n");
         exit(1);
      }
   //Set pointer to begining of the file
   rewind(fp);
   //Write our value of "1" to the file
   strcpy(set_value,"1");
   fwrite(&set_value, sizeof(char), 1, fp);
   fclose(fp);
   printf("...value set to 1...\n");
         
   //Run an infinite loop - will require Ctrl-C to exit this program
   while(1)
   {
      //Set it so we know the starting value in case something above doesn't leave it as 1
      strcpy(set_value,"1");
      
      if ((fp = fopen("/sys/class/gpio/gpio37/value", "rb+")) == NULL)
      {
         printf("Cannot open value file.\n");
         exit(1);
      }   
      toggle = !toggle;
      if(toggle)
      {
         //Set pointer to begining of the file
         rewind(fp);
         //Write our value of "1" to the file
         strcpy(set_value,"1");
         fwrite(&set_value, sizeof(char), 1, fp);
         fclose(fp);
         printf("...value set to 1...\n");
      }
      else
      {
         //Set pointer to begining of the file
         rewind(fp);
         //Write our value of "0" to the file
         strcpy(set_value,"0");
         fwrite(&set_value, sizeof(char), 1, fp);
         fclose(fp);
         printf("...value set to 0...\n");
      }
      //Pause for one second
      sleep(1);
   }
   return 0;
}


ЗЫ Принимается любая разумная критика.

Карта портов и пинов mini2440
GPIO1.png
GPIO2.png

Желтым обозначены пины - выведеные на 34pin разьем
Синим обозначены пины - идущие на экран (к примеру пином GPG4 можно дергать питание и вырубить экран, а можно попробовать заюзать ШИМ)

Смотрите внимательно и не конфигурируйте жизненно-важные пины!!!
Про ПОРТЫ A, C, D лучше вообще забыть :)
Последний раз редактировалось Resident 21 июл 2010, 12:32, всего редактировалось 3 раз(а).

Re: Работа с GPIO из Linux

blindman » 16 июл 2010, 18:52

Замудрено как-то. Чтобы просто дернуть ногой, надо пробиваться через системные вызовы? А просто из того же С нельзя напрямую ногами управлять?

Re: Работа с GPIO из Linux

Resident » 16 июл 2010, 19:17

blindman писал(а):Замудрено как-то. Чтобы просто дернуть ногой, надо пробиваться через системные вызовы? А просто из того же С нельзя напрямую ногами управлять?

Ну так
Код: Выделить всёРазвернуть
main {

...

system("echo 202 > /sys/class/gpio/export");
fd = fopen ("/sys/class/gpio/gpio202","r");
....
поработали с пином
...
fclose(fd);
system("echo 202 > /sys/class/gpio/unexport");

...

}

Куда уж проще!
Стандартное общение в линухе, где каждый девайс - есть файл.
С COM-портами так же работаем ведь. ;)

Я пока нашел только этот способ. :pardon:
Найдешь другой - милости просим.
Я ж не против :)

Добавлено спустя 10 минут 27 секунд:
Добавил примерчик на сях

Добавлено спустя 4 минуты 17 секунд:
Думаю просто на Си - это только на голой плате.
А тут, понимаешь ли, ОСь!
Ну или хакнуть ядро линя, чтобы можно было сразу через регистры (а не через файлы) :)

Re: Работа с GPIO из Linux

Сергей » 16 июл 2010, 19:18

Линукс не позволяет обратиться напрямую к регистрам. Либо через ядро, либо через драйвер.

Re: Работа с GPIO из Linux

Resident » 17 июл 2010, 00:26

Сергей писал(а):Линукс не позволяет обратиться напрямую к регистрам. Либо через ядро, либо через драйвер.
Так вот и я о том же :)

Добавлено спустя 2 минуты 33 секунды:
Дока по gpio в ядре линуха

Добавлено спустя 2 часа 51 минуту 18 секунд:
Меня сейчас интересует один момент.
Те пины, которые могут иметь ф-ю прерывания, в своей папке имеют файл edge, который может показывать 4 состояния: ничего, передний фронт, задний фронт, оба фронта.
Вот интересует вопрос. как с этим работать и как на этом организовать прерывание?
Не опрашивать же этот файл вручную каждый раз? О_о
Тогда теряется весь смысл этот файла. С тем же успехом можно напрямую пин опрашивать и сравнивать с прошлым значением...

Re: Работа с GPIO из Linux

Andrey37 » 18 июл 2010, 11:05

А W1-GPIO ? ;)

Re: Работа с GPIO из Linux

Resident » 18 июл 2010, 11:14

Andrey37 писал(а):А W1-GPIO ? ;)
Ась?

Re: Работа с GPIO из Linux

Palachzzz » 18 июл 2010, 11:35

А как работать с ADC? хоть их всего 4 остается (4 на тачскрин вроде), но все равно..

Re: Работа с GPIO из Linux

Andrey37 » 18 июл 2010, 11:37

драйвер w1-gpio. вот мысля в голову пришла подключить датчик температуры 1820.

Re: Работа с GPIO из Linux

Resident » 18 июл 2010, 13:04

Andrey37 писал(а):драйвер w1-gpio.

Так ты говоришь у тебя голова свежая и погодка хорошая?
Тогда вперед!
Раз
Два (тоже самое только для младшей версии ядра, мож и не отличаются)
Ну и самое интересное: Три
:)
А у меня +35 в тени с северной стороны дома, а еще только утро :crazy:

Добавлено спустя 3 минуты 48 секунд:
Хотя вот здесь народ отжигает с 1820 на уарте. ;)

Добавлено спустя 1 час 9 минут 46 секунд:
Palachzzz писал(а):А как работать с ADC? хоть их всего 4 остается (4 на тачскрин вроде), но все равно..

С-код под ADC
Код: Выделить всёРазвернуть
#define LOOPS 12 // 12 Werte fuer Mittelwert

unsigned int getpoti() {
   int value, i, fd = open("/dev/adc", 0);
   unsigned int add = 0, ret;
   if (fd < 0) { printf("cant open adc device!\n"); return -1; }
   
   for(i = 0; i < LOOPS; i++) {
      char buffer[30];
      int len = read(fd, buffer, sizeof buffer -1);
      if (len > 0) {
         buffer[len] = '\0';
         value = -1;
         sscanf(buffer, "%d", &value);
         add += value;
      } else {
         printf("cant read from adc device!\n");
                        close(fd);
         return -1;
      }
   }
   close(fd);
   ret = add / LOOPS;
   return ret;
}

Сам не проверял, железки в данный момент под рукой нет. Поверю - добавлю в первый пост.
Поидее при open передаете ему номер канала... (но не факт)

Re: Работа с GPIO из Linux

Palachzzz » 18 июл 2010, 13:14

Сменил параметр в open на 1:
read ADC device:: Bad file descriptor
видимо не так :no:
В 2440test AIN1 рандомно колеблится в районе 250-500

Re: Работа с GPIO из Linux

Resident » 18 июл 2010, 13:40

Palachzzz писал(а):Сменил параметр в open на 1:
Ты попытался открыть файл на запись.
Теперь и мне от жары моск выносит (

В папке dev не наблюдается чего-то вроде adc1 adc2 и т.д. ?

Re: Работа с GPIO из Linux

Palachzzz » 18 июл 2010, 14:10

неа.. нет там таких..

Re: Работа с GPIO из Linux

Resident » 21 июл 2010, 12:33

Добавил карту пинов. Обо всех найденных косяках и неточностях просьба сообщать в личку!

Re: Работа с GPIO из Linux

setar » 30 июл 2010, 16:18

есть идея попробовать использовать для работы с GPIO механизм inotify
насколько я понимаю (я не программер ни разу, могу ошибаться) что по этому механизму регистрируется некий файл для контроля и некий обработчик. Когда файл меняется - дергается обработчик (что то типа прерывания на изменение файла).
Посмотреть как это работает можно в исходном коде линукс пакета fail2ban (обработчик логов+ скрипты при обнаружении паттернов)
Вот только не знаю работает ли inotify для sysfs


Rambler\'s Top100 Mail.ru counter