Easyelectronics.ru

Электроника для всех
Текущее время: 23 сен 2019, 18:33

Часовой пояс: UTC + 5 часов



JLCPCB – Прототипы печатных плат за $2/10pcs (Любой цвет!)
Крупнейший производитель печатных плат и прототипов. Более 600000 клиентов и свыше 10000 заказов в день!
Получите скидку на почтовую отправку при первом заказе в JLCPCB!

Начать новую тему Ответить на тему  [ Сообщений: 11 ] 
Автор Сообщение
 Заголовок сообщения: Указатели и mmap() линукс
СообщениеДобавлено: 02 дек 2014, 15:06 
Старожил
Аватара пользователя

Зарегистрирован: 13 дек 2010, 23:15
Сообщения: 2021
Откуда: Киев
Помогите разобраться с "затупом". Короче ситуация следующая:
Есть арм процессор под embedded linux, который управляет ПЛИСиной. Как из под линукса добраться до gpio? Очень просто, для этого используют функции mmap(). Примерно так:
Код:
m_file_mem = open( "/dev/mem", ( O_RDWR | O_SYNC ) );
   if (m_file_mem != -1){
        virtual_base = mmap( NULL, HW_REGS_SPAN, ( PROT_READ | PROT_WRITE ), MAP_SHARED, m_file_mem, HW_REGS_BASE );
       if (virtual_base == MAP_FAILED)
       {
       }
       else{
            m_led_base= (u_int8_t *)virtual_base + ( ( unsigned long  )( LEDS_BASE ) & ( unsigned long)( HW_REGS_MASK ) );
            }
//LEDS_BASE- адреса GPIO на который повешены светики, HW_REGS_MASK - размер адресного пространства которое мапится.

//Ну и далее где нибудь по коду зажигаем светодиоды
*(u_int32_t *)   m_led_base=0xFF;


Ну я на этот пример посмотрел, да и добавил свои порты. Вот только думаю, а нахрена мне вот этот гемор с преобразованием указателей все равно регистры портов 32 разрядные даже если реальных выводов меньше. Ну вообщем добавил в инициализацию:
Код:
data_in_base= (u_int32_t *)virtual_base + ( ( unsigned long  )(DATA_IN_BASE ) & ( unsigned long)( HW_REGS_MASK ) );//32-х разрядный вход
data_out_base= (u_int8_t *)virtual_base + ( ( unsigned long  )( DATA_OUT_BASE ) & ( unsigned long)( HW_REGS_MASK ) );//8 разрядный выход
strobe_base= (u_int32_t *)virtual_base + ( ( unsigned long  )(STROBE_BASE ) & ( unsigned long)( HW_REGS_MASK ) );//1 разрядный выход

// Ну и где то в коде:
*(u_int32_t *)data_out_base = 0х15// выводим какое то число.
*strobe_base =1; //пинаем плис
temp= *data_in_base; // забираем с плис


Я в коде опустил не существенные моменты. Но думаю смысл ясен. Короче говоря нихрена не получилось на входе стабильно 0. Дальше я как дурак провел почти 3 дня за занимательным переписыванием может и не идеального, но блядь заведомо рабочего дизайна ПЛИС с попыткой решить проблему. И не хрена. Пока к исходу 3 го дня не обратил внимание, что заботливо оставленные светодиоды ( m_led_base) работают как надо. И тут меня пробило переписать инициализацию всех указателей с (u_int32_t *)virtual_base ->на (u_int8_t *)virtual_base, ну а в коде все переменные переписать с *strobe_base -> на *(u_int32_t *)strobe_base.
И ура на входе начали появляться какие то цифры. Правда не на долго, ибо уже на следующую итерацию нихрена не заработало.
Опытным удалось установить что, везде в инициализации должно быть (u_int8_t *)virtual_base. А вот по ходу программы городить преобразование указателей *(u_int32_t *) надо только для 32х разрядных портов, а вот там где вывод 1 надо оставить просто, например *strobe_base .

Понимаю что вопрос, возможно, из сферы телепатии, но что не правильно было в первом случае понять не могу.
ЗЫ Писал на C++ в Qt 5.2.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Указатели и mmap() линукс
СообщениеДобавлено: 02 дек 2014, 15:22 
Старожил

Зарегистрирован: 15 янв 2013, 13:24
Сообщения: 5665
Кстати, в линуксе есть и нормальный драйвер GPIO. Не обязательно через указатель на память обращаться.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Указатели и mmap() линукс
СообщениеДобавлено: 02 дек 2014, 15:33 
Старожил
Аватара пользователя

Зарегистрирован: 13 дек 2010, 23:15
Сообщения: 2021
Откуда: Киев
Да есть, но конкретно в этой сборке его выкинули. А пересобрать ядро... я до этого еще не дорос.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Указатели и mmap() линукс
СообщениеДобавлено: 02 дек 2014, 15:35 
Старожил

Зарегистрирован: 22 мар 2010, 22:54
Сообщения: 3995
я мог что-то неправильно понять, но делая

(u_int32_t *)virtual_base + nnn

мы смещаемся на nnn 32-бит слов вперед. а надо наверняка смещаться на nnn байт.

вот это

u_int32_t *data_in_base= (u_int8_t *)virtual_base + nnn
*data_in_base = xxx

не решит проблему?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Указатели и mmap() линукс
СообщениеДобавлено: 02 дек 2014, 15:57 
Старожил

Зарегистрирован: 15 янв 2013, 13:24
Сообщения: 5665
Ink писал(а):
u_int32_t *data_in_base= (u_int8_t *)virtual_base + nnn
Опасная формула :-)
В ней nnn должно быть кратно четырём.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Указатели и mmap() линукс
СообщениеДобавлено: 02 дек 2014, 15:58 
Старожил
Аватара пользователя

Зарегистрирован: 13 дек 2010, 23:15
Сообщения: 2021
Откуда: Киев
Ink писал(а):
я мог что-то неправильно понять, но делая
(u_int32_t *)virtual_base + nnn
мы смещаемся на nnn 32-бит слов вперед. а надо наверняка смещаться на nnn байт.

Возможно в этом вся проблема и была. Если компилятор (ОС) понимает:
Код:
data_in_base= (u_int8_t *)virtual_base + ( ( unsigned long  )( LEDS_BASE ) & ( unsigned long)( HW_REGS_MASK ) );

как сместится, как вы пишете, на некоторое число nnn байт - в штуках, то при записи (u_int32_t *)virtual_base действительно будет проблема потому что адрес получится умножен на 4.
Я просто понимал это код, как присвоить указателю на 32 разрядное число, адрес порта, а сколько там надо взять байт(слов) для сдвига компилятор сам разберется.

Ink писал(а):
вот это
u_int32_t *data_in_base= (u_int8_t *)virtual_base + nnn
*data_in_base = xxx
не решит проблему?

Так было при (u_int32_t *)virtual_base, и не работало, даже когда я хардварно (то есть когда другие сигналы никак не влияют) установил значение порта.
То есть как я понимаю сдвиг virtual_base всегда должен быть приведен к байту.
Хотя если совсем честно, что делает функция mmap я не очень догоняю.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Указатели и mmap() линукс
СообщениеДобавлено: 02 дек 2014, 16:10 
Старожил

Зарегистрирован: 22 июн 2010, 21:53
Сообщения: 1037
Откуда: Brussels
Ваша система с mmu?

В системах с mmu память устройств отделена от пространства пользователя, управляет этим как раз mmap system.
Можно начать читать тут:
http://www.xml.com/ldd/chapter/book/ch13.html

При no-mmu (ucLinux и др) mmap() тоже бывает, но это отдельная тема.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Указатели и mmap() линукс
СообщениеДобавлено: 02 дек 2014, 16:14 
Старожил
Аватара пользователя

Зарегистрирован: 13 дек 2010, 23:15
Сообщения: 2021
Откуда: Киев
AlexPM писал(а):
Ink писал(а):
u_int32_t *data_in_base= (u_int8_t *)virtual_base + nnn
Опасная формула :-)
В ней nnn должно быть кратно четырём.

Спасибо кажись не много начинает прояснятся. Видимо, когда первый раз у меня кое как начало работать(когда я везде проставил (u_int8_t *)virtual_base ) , я оставил объявление указателей без изменений:
Код:
volatile   u_int8_t * m_led_base;
volatile   u_int32_t * strobe_base;
  volatile   u_int32_t * data_in_base;
volatile   u_int8_t *data_out_base;

Потом (пока компилировлся дизайн ПЛИС) поменял на (так и сейчас):
Код:
volatile   u_int8_t * m_led_base;
volatile   u_int8_t * strobe_base;
  volatile   u_int8_t * data_in_base;
volatile   u_int8_t *data_out_base;

Что вызвало повторную не рабоспособность программы и необходимость переписывания кода на:
*( u_int32_t *)strobe_base =1 -> *strobe_base =1;
temp =* data_in_base -> temp =*( u_int32_t *) data_in_base;

Короче, как тут не вспомнить известную цитату про указатели и выстрел в ногу.

Но касательно 8-ми разрядной m_led_base, реально на плате 10 светодиодов.
А потому конструкция * m_led_base=0хFF зажигает только первые 8. А что бы зажечь остальные надо *( u_int32_t *)m_led_base=0х4FF.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Указатели и mmap() линукс
СообщениеДобавлено: 02 дек 2014, 16:16 
Старожил
Аватара пользователя

Зарегистрирован: 13 дек 2010, 23:15
Сообщения: 2021
Откуда: Киев
//Mt писал(а):
Ваша система с mmu?

В системах с mmu память устройств отделена от пространства пользователя, управляет этим как раз mmap system.
Можно начать читать тут:
http://www.xml.com/ldd/chapter/book/ch13.html

При no-mmu (ucLinux и др) mmap() тоже бывает, но это отдельная тема.

Ну в доке на проц он есть, но не думал что он как то хитро влияет.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Указатели и mmap() линукс
СообщениеДобавлено: 02 дек 2014, 17:34 
Старожил

Зарегистрирован: 22 мар 2010, 22:54
Сообщения: 3995
AlexPM писал(а):
Ink писал(а):
u_int32_t *data_in_base= (u_int8_t *)virtual_base + nnn
Опасная формула :-)
В ней nnn должно быть кратно четырём.

си - вообще опасный язык. надо понимать, что делаешь.
Signaller писал(а):
Так было при (u_int32_t *)virtual_base, и не работало
надо делать все части сразу правильно, а не по одной. если хотите менять содержимое порта сразу 32 бита, то делайте указатель на 32 бита: volatile uint32_t*. но присваивать ему нужно правильный адрес, в формуле должно фигурировать (uint8_t*) либо же смещение должно даваться в словах (т.е. деленное на 4 или >>2).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Указатели и mmap() линукс
СообщениеДобавлено: 02 дек 2014, 17:53 
Старожил
Аватара пользователя

Зарегистрирован: 13 дек 2010, 23:15
Сообщения: 2021
Откуда: Киев
Ну так :
Код:
( ( unsigned long  )( LEDS_BASE ) & ( unsigned long)( HW_REGS_MASK ) );

По факту физ. адрес порта - 0хFF200000. Он не перекрывается с какими то либо другими адресами системы. И я думал, что коль в линукс для пользовательского процесса выделяется виртуальная память. То функцией mmap мы просто говорим ОС, что когда ты будешь обращаться по адресу virtual_base + LEDS_BASE, то запули данные в этот 0хFF200000. Каким образом LEDS_BASE превращается как вы пишете в некий оступ nnn байт мне непонятно. Курю пока ссылку от //Mt.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 11 ] 

Часовой пояс: UTC + 5 часов


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

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


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB