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

 
 
> Порт как параметр функции С/С++ IAR
Errorkpi
сообщение Sep 6 2012, 10:17
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 14-04-09
Пользователь №: 47 659



Собственно вопрос по теме сабжа: как передать имя порта (или любой другой регистр) как параметр в функцию/класс С++ ?

Пишу программный драйвер интерфейса, создал под это дело класс обертку и хочу конфигурировать интерфейс (назначать ноги МК), чтобы можно было поднять несколько интерфейсов параллельно на разных ногах, создав несколько объектов.

Пробовал вот так:
Код
void foo (unsigned char PORTx)
{
  *(unsigned char*)PORTx=0xFF;
}

void main(void)
{
  foo(PORTA);
}


такой вариант не работает.... и компилятор ругается на строку вызова функции:
Код
Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 24)
Непомнящий Евген...
сообщение Sep 6 2012, 10:26
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



1. Например в iar - char * __io или char *__ext_io. В gcc - хз, надо посмотреть как у него объявлены регистры и сделать из этого объявления указатель.
2 Можно сделать интерфейс порта и реализацию (но это вирт вызов на каждое шевеление, годится редко).
3. Еще можно сделать тип-обертку над портом (но над каждым портом будет свой тип - ну или своя специализация одного шаблона), а функцию параметризовать этим типом. Правда при этом сама функция станет шаблоном. На С можно сделать аналогичное на макросах. Последствия одинаковые - больший объем нагенеренного кода (по сравнению с 1 и 2), но высокая скорость работы.
4. Можно функцию писать не относительно порта. а относительно какой-то более высокуровневой логики -
struct SomeLogic
{
virtual void init() = 0;
virtual void generetaImpulse(....) = 0;
virtual void sendSomeData(...) = 0;
...
};
void foo(SomeLogic *);
От варианта 2 отличается большей скоростью (за счет уменьшения кол-ва вызовов)
5. Разновидность варианта 4:
void init(int no);
void generetaImpulse(int no, ....);
void foo(int no)
{
init(no);
generetaImpulse(no, ...);
}
От вариант 4 отличается экономией на виртуальных вызовах.
Go to the top of the page
 
+Quote Post
neiver
сообщение Sep 6 2012, 10:30
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 214
Регистрация: 22-03-10
Из: Саратов
Пользователь №: 56 123



Как обычный указатель.
Код
void foo (volatile unsigned char * PORTx)
{
  *PORTx=0xFF;
}

void main(void)
{
  foo( & PORTA);
}

В этом случае компилятор при работе с портом будет использовать команды LD/ST - которые занимают два такта. И не сможет использовать команды in,out, которые один такт и sbi,cbi, которые за один такт модифицируют значение одного бита в порту.
Плюс еще надо будет передавать указатель на регистры DDRx и PINx.

Для начала хватит, но есть и более интересный способ...
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Sep 6 2012, 10:34
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



neiver, а разве там все регистры мапятся в общее адресное пространство? Вроде бы __io не мапились...
Go to the top of the page
 
+Quote Post
Errorkpi
сообщение Sep 6 2012, 10:37
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 14-04-09
Пользователь №: 47 659



char * __io или char *__ext_io

В чем разница?
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Sep 6 2012, 10:39
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Непомнящий Евгений @ Sep 6 2012, 13:34) *
neiver, а разве там все регистры мапятся в общее адресное пространство? Вроде бы __io не мапились...


Те, которые io два адреса вроде имеют - один для доступа sbi/cbi и второй для ST/LD - на 0x20 больший.
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Sep 6 2012, 10:39
Сообщение #7


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



разные инструкции доступа, помнится. __ext_io - это на 1280 и более старших. На младших только __io
Go to the top of the page
 
+Quote Post
Errorkpi
сообщение Sep 6 2012, 10:45
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 14-04-09
Пользователь №: 47 659



я так понимаю что вы предлагает сделать вот так:

Код
void foo (char* __io Portx)
{
  Portx=0xFF;
}

foo(PORTA);


если так - не работает
Error[Be009]: memory attributes not allowed on auto variables or parameters




Цитата
Как обычный указатель.


Работает, но меня смущает, что компилятор не использует in/out инструкции
Go to the top of the page
 
+Quote Post
neiver
сообщение Sep 6 2012, 10:47
Сообщение #9


Местный
***

Группа: Участник
Сообщений: 214
Регистрация: 22-03-10
Из: Саратов
Пользователь №: 56 123



Цитата(Непомнящий Евгений @ Sep 6 2012, 14:34) *
neiver, а разве там все регистры мапятся в общее адресное пространство? Вроде бы __io не мапились...

Мапятся. Даже регистры общего назначения r0-r31 мапятся начиная с адреса 0. Начиная с адреса 0x20 мапятся обычные IO регистры, следом расширенные.
Go to the top of the page
 
+Quote Post
Errorkpi
сообщение Sep 6 2012, 10:58
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 14-04-09
Пользователь №: 47 659



Код
void classname::init(volatile unsigned char * PORTx)
??init:
        CFI Block cfiBlock0 Using cfiCommon0
        CFI Function ??init
//    6   {
//    7     *PORTx=0xFF;
        LDI     R16, 255
        MOV     R30, R17
        ST      Z, R16
//    8   }
        RET
        CFI EndBlock cfiBlock0

        RSEG CODE:CODE:NOROOT(1)


не ссорьтесь, мапится и работает. но все-таки хочется, чтобы через "out" заработало.

neiver, а можно поподробнее :
Цитата
но есть и более интересный способ...
Go to the top of the page
 
+Quote Post
neiver
сообщение Sep 6 2012, 11:05
Сообщение #11


Местный
***

Группа: Участник
Сообщений: 214
Регистрация: 22-03-10
Из: Саратов
Пользователь №: 56 123



Если хочется чтоб через in,out,sbi,cbi работало - у меня есть библиотечка "для работы с портами".
С её помощью порты, отдельные пины и произвольные группы пинов можно передавать как шаблонные параметры функций и классов:
Код
template<class Port>
void Foo()
{
    Port::SetConfiguration(Port::Out);
    Port::Write(0xff);
}

template<class Pin>
void Bar()
{
    Pin::Set();
    ...
    Pin::Clear();
}

template<class PinGroup>
void Buzz()
{
    PinGroup::SetConfiguration(Port::Out);
    PinGroup::Write(0xff);
}

int main()
{
    Foo<IO::Porta>();
    Bar<IO::Pa1>();

    typedef IO::PinList<IO::Pa1, IO::Pa2, IO::Pb3, IO::Pb2> MyPinGroup;
    Buzz<MyPinGroup>();
}

Тут тестовый пример для IAR AVR
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Sep 6 2012, 11:11
Сообщение #12


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Errorkpi @ Sep 6 2012, 13:58) *
не ссорьтесь, мапится и работает. но все-таки хочется, чтобы через "out" заработало.
А как вы себе представляете это хотя бы на ассемблере? Адрес регистра находится в коде команды out, как функция сможет его заменить?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Errorkpi
сообщение Sep 6 2012, 12:07
Сообщение #13


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 14-04-09
Пользователь №: 47 659



Цитата
А как вы себе представляете это хотя бы на ассемблере? Адрес регистра находится в коде команды out, как функция сможет его заменить?

Имелся ввиду другой вариант реализации.

Насколько я понял из представленных сдесь вариантов, простого и прозрачного способа реализации этой задачи нет, кроме как использовать указатель (с вытекающими накладными расходами).
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Sep 6 2012, 12:12
Сообщение #14


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



Цитата(Errorkpi @ Sep 6 2012, 14:45) *
я так понимаю что вы предлагает сделать вот так:

У ИАРа кривоватая реализация.

void foo (unsigned char volatile __io * adr) - работает
Go to the top of the page
 
+Quote Post
Errorkpi
сообщение Sep 6 2012, 12:22
Сообщение #15


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 14-04-09
Пользователь №: 47 659



Цитата(Непомнящий Евгений @ Sep 6 2012, 15:12) *
У ИАРа кривоватая реализация.

void foo (unsigned char volatile __io * adr) - работает


Неа Error[Ta034]: __io pointer/reference is not allowed.

И даже попытка объявить эту переменную как член класса тоже не получится.
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Sep 6 2012, 12:25
Сообщение #16


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



Странно, у меня работает. IAR 5.12c. Atmega 128, 1280, 2560
Go to the top of the page
 
+Quote Post
Errorkpi
сообщение Sep 6 2012, 12:33
Сообщение #17


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 14-04-09
Пользователь №: 47 659



Цитата(Непомнящий Евгений @ Sep 6 2012, 15:25) *
Странно, у меня работает. IAR 5.12c. Atmega 128, 1280, 2560


5.50.0 - не работает, причем он одинаково относится к любым спецификаторам места хранения (__io, __flash, __eeprom)

Попытка обмана, через ассемблер не прошла sm.gif

void foo (unsigned char adr)
{
asm("CLR r17");
asm("OUT r16, r17"); // первый параметр функции типа char хранится в r16
}

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

Всетаки интересно на счет спецификатора __io, мне так и не удалось его применить. Даже для глобальной переменной ругается вот так:
Error[Ta007]: An __io declared variable must be located.

Сообщение отредактировал Errorkpi - Sep 6 2012, 12:34
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Sep 6 2012, 12:59
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Errorkpi @ Sep 6 2012, 15:33) *
asm("OUT r16, r17"); // первый параметр функции типа char [url="http://electronix.ru/redirect.php?http://netstorage.iar.com/SuppDB/Public/

Новую команду ввели?
У АВР нет такой команды.
Go to the top of the page
 
+Quote Post
Errorkpi
сообщение Sep 6 2012, 13:04
Сообщение #19


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 14-04-09
Пользователь №: 47 659



Цитата(_Артём_ @ Sep 6 2012, 15:59) *
Новую команду ввели?
У АВР нет такой команды.


Да все я понимаю, думал может оптимизатор или линкер додумается подменить параметр PORTB на $18 в асм операторе. Не вышло, но надежда умирает последней.

Все-таки странно, почему нет такой возможности на уровне спецификаторов, или директив препроцессора, все-таки часто используемая вещь (передача регистра I/O в функцию), судя по комментариям.

Сообщение отредактировал Errorkpi - Sep 6 2012, 13:07
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Sep 6 2012, 13:10
Сообщение #20


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



http://www.nongnu.org/avr-libc/user-manual...l#faq_port_pass


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Errorkpi
сообщение Sep 6 2012, 13:16
Сообщение #21


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 14-04-09
Пользователь №: 47 659



Цитата(demiurg_spb @ Sep 6 2012, 16:10) *


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

вынесу сюда, чтобы таких ответов больше не было:
Код
void
set_bits_func (volatile uint8_t *port, uint8_t mask)
{
    *port |= mask;
}

транслируется в:

void
set_bits_func (volatile uint8_t *port, uint8_t mask)
{
  f8:   fc 01           movw    r30, r24
    *port |= mask;
  fa:   80 81           ld      r24, Z
  fc:   86 2b           or      r24, r22
  fe:   80 83           st      Z, r24
}


Сообщение отредактировал Errorkpi - Sep 6 2012, 13:19
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Sep 6 2012, 13:24
Сообщение #22


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Errorkpi @ Sep 6 2012, 16:04) *
Да все я понимаю, думал может оптимизатор или линкер додумается подменить параметр PORTB на $18 в асм операторе. Не вышло, но надежда умирает последней.
Ах вот оно что! Вам нужна встраиваемая функция...

QUOTE (Errorkpi @ Sep 6 2012, 16:04) *
или директив препроцессора
Если на препроцессоре - ищите здесь на форуме "макросы имени Аскольда Волкова".


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Errorkpi
сообщение Sep 6 2012, 14:06
Сообщение #23


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 14-04-09
Пользователь №: 47 659



Цитата(Сергей Борщ @ Sep 6 2012, 16:24) *
Ах вот оно что! Вам нужна встраиваемая функция...

Если на препроцессоре - ищите здесь на форуме "макросы имени Аскольда Волкова".

inline как-бы не помогает...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Sep 6 2012, 21:27
Сообщение #24


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Errorkpi @ Sep 6 2012, 17:06) *
inline как-бы не помогает...
а _Pragma("force_inline") или как ее там в ИАРе? И оптимизация включена?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
ReAl
сообщение Sep 7 2012, 14:10
Сообщение #25


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



_Pragma("inline=always") (и, соответственно, never)


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post

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

 


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


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