реклама на сайте
подробности

 
 
> Массив портов ввода PINx, вопрос к знатокам GCC
singlskv
сообщение Nov 27 2006, 21:57
Сообщение #1


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Контроллеры от ATmega8 до Atmega128, и т.д.

Есть такой массив:
Код
BYTE PIN_[3]={
    (BYTE)(&PINB),
    (BYTE)(&PINF),
    (BYTE)(&PING)
  };


Доступ к нему присходит вот так:
Код
  PIN_tmp=_SFR_IO8(PIN_[0]-0x20);
  ......
  PIN_tmp=_SFR_IO8(PIN_[2]-0x20);


Все работает, более того мне даже нравится код который генерит при этом GCC,
НО, осадок остается sad.gif smile.gif

Собствено вопросы:

1. Есть ли в GCC другие варианты доступа к массиву PINx, без использования _SFR_IO8 ?

2. Насколько такой вариант портируем на более старые/новые реализации GCC AVR ?

3. 0x20 режет глаз, а что с этим делать ?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Lem
сообщение Nov 28 2006, 00:06
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 37
Регистрация: 20-03-05
Пользователь №: 3 533



сделайте структуру
Код
typedef struct
{
   unsigned char *pinr;
   unsigned char *port;
   unsigned char *ddr;
   unsigned char  pinNumb : 3;
} PIN;

PIN pins[2] = {{&PINA, &PORTA, &DDRA, 2}, {&PINB, &PORTB, &DDRB, 7}};


А обращаться можно, например, так:
Код
for(unsigned char index = 0; index < 2; index++)
{
    *pins[index].port |= (1 << pins[index].pinNumb);
    *pins[index].port |= (1 << pins[index].pinNumb);
}
Go to the top of the page
 
+Quote Post
aesok
сообщение Nov 28 2006, 00:35
Сообщение #3


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Цитата(Lem @ Nov 28 2006, 01:06) *
сделайте структуру
[code]
typedef struct
{
unsigned char *pinr;
unsigned char *port;
unsigned char *ddr;
unsigned char pinNumb : 3;
} PIN;

PIN pins[2] = {{&PINA, &PORTA, &DDRA, 2}, {&PINB, &PORTB, &DDRB, 7}};


НЕВЕРНО. pinr, port и ddr - ДОЛЖНЫ обязательно быть volatile!!!

В противном случае на высоких уровнях оптимизации компиллятор оптимизирует следующий код:
*pins[index].port = 0xAA;
*pins[index].port = 0x55;

Он выкинит первую запись в порт. Оставит только вторую. Для обычных переменых это правильная оптимизация, но доступ к портам оптимизироваться не должен.


Для 16-битных портов все намного страшнее - бутет неправильнай порядок обращения байтам.

Анатолий.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Nov 28 2006, 00:55
Сообщение #4


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(aesok @ Nov 28 2006, 00:35) *
НЕВЕРНО. pinr - ДОЛЖНЫ обязательно быть volatile!!!

В противном случае на высоких уровнях оптимизации компиллятор оптимизирует следующий код:
*pins[index].port = 0xAA;
*pins[index].port = 0x55;

Он выкинит первую запись в порт. Оставит только вторую. Для обычных переменых это правильная оптимизация, но доступ к портам оптимизироваться не должен.

а должно ли PINx быть volatile ?
Go to the top of the page
 
+Quote Post
aesok
сообщение Nov 28 2006, 01:04
Сообщение #5


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Цитата(singlskv @ Nov 28 2006, 01:55) *
Цитата(aesok @ Nov 28 2006, 00:35) *


НЕВЕРНО. pinr - ДОЛЖНЫ обязательно быть volatile!!!

В противном случае на высоких уровнях оптимизации компиллятор оптимизирует следующий код:
*pins[index].port = 0xAA;
*pins[index].port = 0x55;

Он выкинит первую запись в порт. Оставит только вторую. Для обычных переменых это правильная оптимизация, но доступ к портам оптимизироваться не должен.

а должно ли PINx быть volatile ?


???

avr/iom128.h
...
/* Input Pins, Port D */
#define PIND _SFR_IO8(0x10)
...
/* Timer/Counter 3 Control Register C */
#define TCCR3C _SFR_MEM8(0x8C)
...

avr/port_def.h
....
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
#define _MMIO_WORD(mem_addr) (*(volatile uint16_t *)(mem_addr))
.....

...
#define _SFR_MEM8(mem_addr) _MMIO_BYTE(mem_addr)
#define _SFR_MEM16(mem_addr) _MMIO_WORD(mem_addr)
#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + 0x20)
#define _SFR_IO16(io_addr) _MMIO_WORD((io_addr) + 0x20)
.....


Как видете все SFR обявлены как volatile.

Анатолий.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Nov 28 2006, 01:12
Сообщение #6


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



чтение и запись(volatile переменных) - это две большие разницы
Go to the top of the page
 
+Quote Post
aesok
сообщение Nov 28 2006, 02:06
Сообщение #7


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Цитата(singlskv @ Nov 28 2006, 02:12) *
чтение и запись(volatile переменных) - это две большие разницы


чтение и запись volatile и не volatile переменых ничем не отличаеться.

Модификатор volatile делает только одно - он указывае компилятору не при каких условиях и ни на каких уровнвх оптимизации не оптимизировать доступ к этой переменной!! Другими словами, везде где в тексте программы встречаеться запись или чтение из этой переменой отавлять их без изменения.

Пример:

int i;

i = 1;
i = 0;


Оптимизатор компилятора оптимизирует этот код и выкидывает первое присваивание переменной i (=1), потомучто это значение нигде не используеться и оставляет только второе i = 0.

А теперь представте что i это выходной порт и вам надо надо вывести вначале 1 затем 0. Вас устроит что компилятор удалит операцию вывода 1. НЕТ. Вот для этого и используеться volatile.

volatile int i;

i = 1;
i = 0;

Все теперь оба обращения к переменной i останутся в скомпилированом коде.


Те кто не понимают значение модификатора volatile обрекают себя на то что их программы работают только при выключеной оптимизации, а всех других на чтение топиков со словами "Глюкавый компилятор .....".

Анатолий.

PS: Если быть совсем точным то ассемблерный код для 16-битных volatile и не volatile переменных в AVR-GCC различаеться, но обьяснение этого выходит за рамки этого топика.
Go to the top of the page
 
+Quote Post
Lem
сообщение Nov 28 2006, 10:38
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 37
Регистрация: 20-03-05
Пользователь №: 3 533



Да нет, в процедуре доступа (обработки) обращения портов лучше прагмой компилятору указывать на отсутствие оптимизации в данном куске кода (для каждого компилятора по-разному, я так понял). а с волатайл вы замучаетесь явно типы преобразовывать.

+ такое определение, как я указал выше, есть компромисс между удобством и универсальностью, с одной стороны, и произовдительностью, с другой. То есть, при разыменовывании указателей к регистрам доступ осуществляется с помощью обычных команд обращения к памяти (через общее адресное пространство), а не с помощью специальных команд для регистров ввода/вывода, что требует, если я не ошибаюсь, в два раза больше времени. Так что, работать с такими конструкциями надо осторожно, именно, в специально созданных для этого и проверенных (контролируемых на дизассемблере) функциях.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- singlskv   Массив портов ввода PINx   Nov 27 2006, 21:57
- - aesok   Во первых посмотрите в avr-libc-user-manual: FAQ -...   Nov 27 2006, 23:06
|- - singlskv   Цитата(aesok @ Nov 27 2006, 23:06) Во пер...   Nov 27 2006, 23:45
|- - aesok   Я бы сделал чтото вроде этого: 1. Объявил структу...   Nov 28 2006, 00:04
|- - singlskv   Цитата(aesok @ Nov 28 2006, 00:04) Я бы с...   Nov 28 2006, 14:40
|- - singlskv   На первый вопрос отвечу сам себе Цитата(singlskv ...   Nov 28 2006, 16:56
|- - IgorKossak   Цитата(singlskv @ Nov 28 2006, 13:40) Цит...   Nov 28 2006, 18:05
|- - aesok   Цитата(Lem @ Nov 28 2006, 11:38) Да нет, ...   Nov 28 2006, 13:33
|- - IgorKossak   Цитата(Lem @ Nov 28 2006, 09:38) Да нет, ...   Nov 28 2006, 13:52
- - singlskv   Цитата(aesok @ Nov 28 2006, 00:35) Цитата...   Nov 28 2006, 17:25
- - aesok   Цитата(singlskv @ Nov 28 2006, 18:25) Обя...   Nov 28 2006, 18:10
- - singlskv   Цитата(aesok @ Nov 28 2006, 18:10) Цитата...   Nov 28 2006, 18:23
- - aesok   Созрело 2 решения: 1. Ваше. BYTE PIN_[2]={ (B...   Nov 28 2006, 18:49
- - singlskv   Цитата(aesok @ Nov 28 2006, 18:49) Созрел...   Nov 28 2006, 19:08


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 16th July 2025 - 13:25
Рейтинг@Mail.ru


Страница сгенерированна за 0.01448 секунд с 7
ELECTRONIX ©2004-2016