avr c/c++ препроцессор для макроса PORT_x

Обсуждаем контроллеры компании Atmel.
Ответить
Вымогатель припоя
Аватара пользователя
Сообщения: 625
Зарегистрирован: Ср дек 08, 2010 19:03:17

Сообщение sunjob »

добрый день

есть ли возможность использовать препроцессор подобным образом? (пример в коде, естестенно "как есть" не прокатывает)

т.е. необходимо в зов-ти от определения порта (PORTB, PORTC, or PORTD) - вставлять соответствующие функции прерывания

AVR/Arduino

спасибо
Спойлер

Код: Выделить всё

#define PORT_XXX = PORTC

// ...

#if   (PORT_XXX == PORTB)
ISR(PCINT0_vect)
#elif (PORT_XXX == PORTC)
ISR(PCINT1_vect)
#elif (PORT_XXX == PORTD)
ISR(PCINT2_vect)
#endif 
{ 
// ...
}
Енот - это кот, только инкогнито!
p.s. держитесь обоими руками, а то прорвет...
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

увы, нельзя - я это проходил уже...

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

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 625
Зарегистрирован: Ср дек 08, 2010 19:03:17

Сообщение sunjob »

с дополнительные определением "кучи всего" - это мне понятно...
хотел сделать локонично/короко/понятно

может кто обьяснить почему не катит условие:

Код: Выделить всё

#if (PORT_XXX == PORTB)
Енот - это кот, только инкогнито!
p.s. держитесь обоими руками, а то прорвет...
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

sunjob писал(а):может кто обьяснить почему не катит условие:

Код: Выделить всё

#if (PORT_XXX == PORTB)
Посмотри как объявлен PORTB, для препроцессора это темный лес, он синтаксическим анализом не занимается.
Реклама
Эиком - электронные компоненты и радиодетали
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

как мне объясняли, для препроцессора все нечисловые макросы одинаково не равны нулю, вот и все. т.е. если макрос определен типа так
#define MACRO 10, то препроцессор знает, что это 10. а если в определении макроса имя другого макроса, препроцессор знает только, что этот макрос определен и не равен нулю. поэтому любое сравнение таких макросов ВСЕГДА будет истинным.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 625
Зарегистрирован: Ср дек 08, 2010 19:03:17

Сообщение sunjob »

порты определены как указатели, поэтому, "по идее" - все должно работать правильно, но при использовании такой конструкции выдается ошибка на предыдушее определение порта, т.е. на

Код: Выделить всё

#define PORT_XXX PORTC
                 ^
encoder.h:42: error: operator '*' has no left operand
уточняю, код пишется под AVR-ARDUINO (по моему там куча подводных камней... возможно, блин, это "ардуиновский подход" к работе с макросами ... )

п.с.
суть препроцессора - проще не бывает, брать "то что ему подсунули/определили" и "вставлять" эти определения, где он "повстречает", а если используются "условные операции", то обрабатывать их "как есть"... т.е. в данном случае идет сравнение указателей, по идее, такое сравнение должно быть корректным... но, видимо, ардуиновский "препроцессор" действует по своему... листинг препроцессора смотрел, вроде все нормально...
Енот - это кот, только инкогнито!
p.s. держитесь обоими руками, а то прорвет...
Реклама
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

sunjob писал(а):порты определены как указатели
PORTB имеет тип uint8_t, по крайней мере в gcc.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

Мой уютный бложик... заходите!
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

ARV писал(а):на уровне препроцессора идет сравнение констант. на этапе сравнения слева и справа от == два макроса, т.е. две ненулевые величины, и это сравнение всегда истинно. раскрутки макросов на этом этапе не происходит. если слева макрос-число, то справа от == должно быть другое число, а не макрос. во всяком случае, я так понял...

Код: Выделить всё

#define a(x, y) (x + y)
#define b(x, y) (x + y)
#if a(10, 5) == b(10, 5)
Какие тут проблемы? Никаких, значение имеет что именно внутри макросов, а не сам факт их наличия.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

возможно, я что-то не так понял или не правильно передал смысл понятого...

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

Мой уютный бложик... заходите!
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

ARV писал(а):PORTB, например, это не число-константа, а значение по указателю, поэтому на этапе препроцессора проанализиорвано быть не может
Естественно. И адрес у PORTB тоже брать нельзя, т.к. препроцессор для таких вещей слишком примитивен.
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

Сообщение Siarzhuk »

Reflector писал(а):PORTB имеет тип uint8_t, по крайней мере в gcc.
За PORTB скрывается обычно сложная синтаксическая конструкция из приведения абсолютного адреса регистра к структуре описывающей, ээээ, компоненты регистра. Препроцессор такие конструкции сравнивать не способен - только подставлять их текст в месте использования макроса. Компилятор и препроцессор - это по сути разные программы.
В любом случае не помешаетз заглянуть в файл определения регистров - возможно базовые регистры заданы как абсолютные адреса - а вот их сравнивать можно. И даже в качестве параметров в C++ template использовать. ;)
Кстати, "гадания на препроцессоре" значительно облегчаются после нахождения и включения в настройках тулчейна опции "не удалять промежуточные файлы препроцессора" или "только препроцессить" (preprocess only). После чего в папке с объектными файлами ищется результат работы препроцессора с конкретным .с файлом до передачи его компилятору - и проблема сводится лишь к поиску соответствующего куска в портянке развёрнутого кода.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

Siarzhuk писал(а): За PORTB скрывается обычно сложная синтаксическая конструкция из приведения абсолютного адреса регистра к структуре описывающей, ээээ, компоненты регистра. Препроцессор такие конструкции сравнивать не способен - только подставлять их текст в месте использования макроса. Компилятор и препроцессор - это по сути разные программы.
Это собственно то, о чем я написал в своем первом посте этой темы :)
Вымогатель припоя
Аватара пользователя
Сообщения: 625
Зарегистрирован: Ср дек 08, 2010 19:03:17

Сообщение sunjob »

PORTB имеет тип uint8_t, по крайней мере в gcc.
если я не ошибаюсь :
Спойлер

Код: Выделить всё

//
// hardware/tools/avr/avr/include/avr/sfr_defs.h
//

#if _SFR_ASM_COMPAT

#ifndef __SFR_OFFSET
/* Define as 0 before including this file for compatibility with old asm
   sources that don't subtract __SFR_OFFSET from symbolic I/O addresses.  */
#  if __AVR_ARCH__ >= 100
#    define __SFR_OFFSET 0x00
#  else
#    define __SFR_OFFSET 0x20
#  endif
#endif

#define _SFR_IO8(io_addr)  ((io_addr) + __SFR_OFFSET)
#define _SFR_IO_ADDR(sfr)  ((sfr) - __SFR_OFFSET)
#define _SFR_MEM_ADDR(sfr) (sfr)
#define _SFR_IO_REG_P(sfr) ((sfr) < 0x40 + __SFR_OFFSET)

#else  /* !_SFR_ASM_COMPAT */

#ifndef __SFR_OFFSET
#  if __AVR_ARCH__ >= 100
#    define __SFR_OFFSET 0x00
#  else
#    define __SFR_OFFSET 0x20
#  endif
#endif

#define _SFR_IO8(io_addr)  _MMIO_BYTE((io_addr) + __SFR_OFFSET)
#define _SFR_IO16(io_addr) _MMIO_WORD((io_addr) + __SFR_OFFSET)

#define _SFR_MEM_ADDR(sfr) ((uint16_t) &(sfr))
#define _SFR_IO_ADDR(sfr)  (_SFR_MEM_ADDR(sfr) - __SFR_OFFSET)
#define _SFR_IO_REG_P(sfr) (_SFR_MEM_ADDR(sfr) < 0x40 + __SFR_OFFSET)

//
// hardware/tools/avr/avr/include/avr/iom328p.h
//

#define PINB _SFR_IO8(0x03)
#define PINB0 0
#define PINB1 1
#define PINB2 2
#define PINB3 3
#define PINB4 4
#define PINB5 5
#define PINB6 6
#define PINB7 7

#define DDRB _SFR_IO8(0x04)
#define DDB0 0
#define DDB1 1
#define DDB2 2
#define DDB3 3
#define DDB4 4
#define DDB5 5
#define DDB6 6
#define DDB7 7

#define PORTB _SFR_IO8(0x05)
#define PORTB0 0
#define PORTB1 1
#define PORTB2 2
#define PORTB3 3
#define PORTB4 4
#define PORTB5 5
#define PORTB6 6
#define PORTB7 7

Кстати, "гадания на препроцессоре" значительно облегчаются после нахождения и включения в настройках тулчейна опции "не удалять промежуточные файлы препроцессора" или "только препроцессить" (preprocess only). После чего в папке с объектными файлами ищется результат работы препроцессора с конкретным .с файлом до передачи его компилятору - и проблема сводится лишь к поиску соответствующего куска в портянке развёрнутого кода.
ну собственно, ан-дурина это все и предоставляет по умолчанию... смотрел я "конечный результат" ... не помогло, :о) вот и обратился к котам :о))
Енот - это кот, только инкогнито!
p.s. держитесь обоими руками, а то прорвет...
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

sunjob писал(а):если я не ошибаюсь :
А что есть _MMIO_BYTE?
Если порты - это адреса, тогда пришлось бы писать:

Код: Выделить всё

*PORTC = val;
ps. Если объявлен _SFR_ASM_COMPAT, то похоже можно сделать как ты хочешь, но это облегчил жизнь в этом конкретном случае, но усложнит в большинстве остальных.
Вымогатель припоя
Аватара пользователя
Сообщения: 625
Зарегистрирован: Ср дек 08, 2010 19:03:17

Сообщение sunjob »

_MMIO_BYTE :

Код: Выделить всё

#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
...

дак вот!!! еще одно, что до сих пор я не понял, по идее ДА, для доступа к данным по указателю нужно использовать операцию разыменования... ага, а вот нихренашечки :о) везде втч и в хелпах/учебниках обращаемся непосредственно в порт:

блин, и это работает

Код: Выделить всё

PORTC = <BLAH-BLAH-BLAH>

ешкин кот, и это тоже работает...едренть :о)

Код: Выделить всё

<BLAH-BLAH-BLAH> = PORTC

...

ну это применительно, конечно же к avr/дурина-андурина

нигде про "эти кошачьи загашнички" не написано, точнее нашел что то подходящее на западных сайтах, но смысл не был доступен мому разуму... вот, было бы неплохо, если найдутся такие, пару строк черкануть с дотошным описанием/обьяснением... а то как то "типизация" данного фрукта как "порт" не совсем понятна... :о) гипотетически ясно куда нас посылают, но все же хотелось бы уточнить.. :о)
Енот - это кот, только инкогнито!
p.s. держитесь обоими руками, а то прорвет...
Вымогатель припоя
Аватара пользователя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Сообщение ptr128 »

sunjob писал(а): т.е. необходимо в зов-ти от определения порта (PORTB, PORTC, or PORTD) - вставлять соответствующие функции прерывания
Спойлер

Код: Выделить всё

#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
#  define __INTR_ATTRS used, externally_visible
#else /* GCC < 4.1 */
#  define __INTR_ATTRS used
#endif

#ifdef __cplusplus
#  define ISR(vector, ...)            \
    extern "C" void vector (void) __attribute__ ((signal,__INTR_ATTRS)) __VA_ARGS__; \
    void vector (void)
#else
#  define ISR(vector, ...)            \
    void vector (void) __attribute__ ((signal,__INTR_ATTRS)) __VA_ARGS__; \
    void vector (void)
#endif

#define _PORTB_SEQ_NUMBER_ 1
#define _PORTC_SEQ_NUMBER_ 2
#define _PORTD_SEQ_NUMBER_ 3

#define PORT_XXX _PORTC_SEQ_NUMBER_

// ...

#if  PORT_XXX == _PORTB_SEQ_NUMBER_
ISR(PCINT0_vect)
#elif PORT_XXX == _PORTC_SEQ_NUMBER_
ISR(PCINT1_vect)
#elif PORT_XXX == _PORTD_SEQ_NUMBER_
ISR(PCINT2_vect)
#endif 
{ 
// ...
}
Результат:
Спойлер

Код: Выделить всё

# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "test.c"
# 28 "test.c"
void PCINT1_vect (void) __attribute__ ((signal,used, externally_visible)) ; void PCINT1_vect (void)



{

}
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Вымогатель припоя
Аватара пользователя
Сообщения: 625
Зарегистрирован: Ср дек 08, 2010 19:03:17

Сообщение sunjob »

не помешали бы комментарии :о) если не сложно, муррр
Енот - это кот, только инкогнито!
p.s. держитесь обоими руками, а то прорвет...
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

какие еще комментарии? я с самого первого поста вам сказал
ARV писал(а):можно извратиться, если определить кучу собственных констант
вот вам и сделали кучу собственных констант
ptr128 писал(а):#define _PORTB_SEQ_NUMBER_ 1
#define _PORTC_SEQ_NUMBER_ 2
#define _PORTD_SEQ_NUMBER_ 3

#define PORT_XXX _PORTC_SEQ_NUMBER_
делать вектор прерывания в зависимости от выбранного порта вы все равно не можете - вам предлагают вместо порта выбирать свою константу. все, что выше - это лишнее для вашей задачи.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Вымогатель припоя
Аватара пользователя
Сообщения: 625
Зарегистрирован: Ср дек 08, 2010 19:03:17

Сообщение sunjob »

хрюн, ты чего так нервничаешь? если тебя тут что то бесит, пожалуйста, не заходи сюда ...


> с дополнительные определением "кучи всего" - это мне понятно...
> хотел сделать локонично/короко/понятно


че да как мы тут с хозяином имели изначально "полную чашку всяких сущностей"...

Код: Выделить всё

#define ID_PORTB     0
#define ID_PORTC     1
#define ID_PORTD     2
#define XXX_ID_PORT  ID_PORTC            

...

#if   (XXX_ID_PORT == ID_PORTB)
ISR(PCINT0_vect)
#elif (XXX_ID_PORT == ID_PORTC)
ISR(PCINT1_vect)
#elif (XXX_ID_PORT == ID_PORTD)
ISR(PCINT2_vect)
#endif
{ 
//...
}
p.s.
если че не понятно, это наш выкус из кода, кот. мы хотели упростить... из-за чего и появилась тема...

...

если будут более локоничные и красивые идеи, пишите, пожалуйста, надеюсь, обществу пригодится

всем спасибо
Последний раз редактировалось sunjob Ср ноя 23, 2016 13:43:55, всего редактировалось 2 раза.
Енот - это кот, только инкогнито!
p.s. держитесь обоими руками, а то прорвет...
Ответить

Вернуться в «AVR»