|
|
  |
возможно ли на Си, объединить биты регистров портов микроконтроллера |
|
|
|
Jun 13 2009, 22:17
|

Местный
  
Группа: Участник
Сообщений: 252
Регистрация: 2-03-08
Пользователь №: 35 557

|
Цитата(DpInRock @ Jun 13 2009, 23:38)  Вы всегда смотрите, как именно ваши фантазии будет реализовыватcя на данной системе команд. Имеет ли смысл? Вариант с опросом разных битов в разных портах не очень удобен. Я как -то делал для одного порта - присваивал структуре адрес регистра саециального назначения с помощью директивы #byte в компиляторе CCS для пиков. Сейчас задача для нека, используя ИАР
--------------------
One Chip is All You Need
|
|
|
|
|
Jun 14 2009, 05:17
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(sergeeff @ Jun 14 2009, 03:20)  Почитайте современные книги..... Прости, господи  , а может просто надо не только "читать современные книги", но и читать просто книги, и просто думать, когда пишешь? Причем пишешь не только макросы, а то возникнут "грабли".
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 14 2009, 10:21
|
Профессионал
    
Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528

|
Цитата(Herz @ Jun 14 2009, 12:47)  Такие книжки читать как раз не нужно, ИМХО. Ибо это из категории вредных советов.  Да нет, сами по себе советы вместо #define использовать const и темплейты - правильные. Просто в тех книгах речь идёт о С++ и типичных его применениях - для ваяния многомегабайтных монстров. А тут случай практически противоположный - манипуляции битами на самом нижнем уровне, никакой переносимости не требуется по определению, зато важна эффективность. Но, разумеется, хотелось бы собрать в одном месте все зависимости от номеров битов в портах, чтобы при правках не искать их по всей программе. Альтернатива - написать пару функций для чтения и для записи, а для эффективности инлайнить их.
--------------------
Russia est omnis divisa in partes octo.
|
|
|
|
|
Jun 14 2009, 10:49
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(SSerge @ Jun 14 2009, 13:21)  Но, разумеется, хотелось бы собрать в одном месте все зависимости от номеров битов в портах, чтобы при правках не искать их по всей программе. Описываю весь доступ к портам через макросы в одном h-файле и не парюсь. В прочих файлах НИКАКОГО упоминания о портах, только макросы с осмысленными названиями. Просто для понимания. Существенно упрощает портирование. К сожалению, есть проблема инлайнить функции, определенные в других модулях, теоретически можно тоже через #include, но это уж точно на изврат похоже.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jun 14 2009, 11:34
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Я бы сделал так:
#define UP(port, bit) port |= (1<<bit) #define DOWN(port, bit) port &= ~(1<<bit)
Далее:
#define LIGHT P1OUT,1 #define MOTOR P2OUT,3 #define BEEPER P3OUT,2
Итого имеем:
UP(LIGHT); DOWN(MOTOR); UP(BEEPER);
Названия регистров взял от МСП, как наиболее актуального для меня
Если хочется именно структуры, то надо немного подумать. Например, определить структуру Pin{}, в которой указать порт, номер пина и т.д. Например, забить туда все регистры порта (OUT,DIR,IE,SEL). А потом уже эту структуру включать внутрь других структур. Но всё равно без макросов не обойтись. Либо класс рисовать.
Хотя, если взять тот же МСП, то там в io.h порты расписаны в том числе и как структуры, и можно написать port1.out.pin3 = 1; port2.out.pin1 = 0; Тогда всё еще проще: #define MOTOR port1.out.pin3; ... MOTOR = 1; C инициализацией других регистров порта опять же, нужно отдельно думать.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Jun 14 2009, 17:09
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(aaarrr @ Jun 14 2009, 14:35)  очень полезный в некоторых случаях прием. ОК, я подумаю. Хотелось бы уточнить случаи. Вопрос то в чем - если придерживаться какой-то структуры проекта, логичного разбиения проекта на модули (файлы), то достаточно сложные инлайновые функции должны быть определены в соответствующих модулях. И им нечего быть включенными в другие модули. Как раз недавно пришлось воспользоваться инлайном и оптимизацией для быстрых операций в прерывании. Если же функция вырождается в дерганье выводом или считывание его состояния, то объясните мне плз, в чем преимущество инлайновой функции по сравнению с простейшим макросом: #define ON_BACKLIGHT (P1OUT|=P1_BACKLIGHT), где #define P1_BACKLIGHT 0x02 //output
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jun 14 2009, 17:16
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Dog Pawlowa @ Jun 14 2009, 21:09)  ОК, я подумаю. Хотелось бы уточнить случаи. Например, есть у меня в модуле display такая функция: Код __forceinline void disp_set_dot_alpha(u_int x, u_int y, DISP_COLOR color, u_char alpha) { u_int c0, c1, mask; if(alpha > 0) { c0 = color; if(alpha < DISP_MAX_ALPHA) { c1 = *((u_short*)&disp_frame + (y * DISP_WIDTH) + x); mask = 0x07e0f81f; c0 = (c0 | (c0 << 16)) & mask; c1 = (c1 | (c1 << 16)) & mask; c0 = ((c0 * alpha) >> 5) & mask; c1 = ((c1 * (DISP_MAX_ALPHA - alpha)) >> 5) & mask; c0 = c0 + c1; c0 |= c0 >> 16; } *((u_short*)&disp_frame + (y * DISP_WIDTH) + x) = c0; } } Тащить всю работу с графикой в один модуль неразумно, до макроса не вырождается, зато как инлайн функция существенно повышает производительность.
|
|
|
|
|
Jun 14 2009, 17:29
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Цитата(Dog Pawlowa @ Jun 14 2009, 20:09)  #define ON_BACKLIGHT (P1OUT|=P1_BACKLIGHT), где #define P1_BACKLIGHT 0x02 //output Это значит, что где-то кто-то может встретить в вашей программе: Код ... ON_BACKLIGHT; ... Вы сами-то как оцениваете читабельность такого выражения?
|
|
|
|
|
Jun 14 2009, 17:36
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(aaarrr @ Jun 14 2009, 20:16)  зато как инлайн функция существенно повышает производительность. ОК, спасибо. Видимо, не сталкивался. Но в таком виде функция не инклюдится, или я не знаю эту среду/компилятор? Цитата(sergeeff @ Jun 14 2009, 20:29)  Вы сами-то как оцениваете читабельность такого выражения? Супер! Превосходная ! Ни у кого такого нет! "Включить подсвет", насколько мне известно... Большие буквы, отсутствие скобок -> значит это макрос для работы с портами -> см файл project_ports.h Лет пят-шесть так работаю, маразм наступает, но вот с этим пока проблем не было.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jun 14 2009, 17:55
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(aaarrr @ Jun 14 2009, 20:41)  Вы имеете в виду __forceinline? Это от RVCT. Нет, я не только это я имею ввиду. Как тут отмечалось, чтобы функция инлайнилась, нужно, чтобы ее текст попадал в область видимости, то есть ее текст должен быть перенесен в модуль, где она используется, как то так: #define DISPL_SET_DOT_ALPHA __forceinline void disp_set_dot_alpha(u_int x, u_int y, DISP_COLOR color, u_char alpha) \ { \ u_int c0, c1, mask; \ if(alpha > 0) \ { \ ... Цитата(aaarrr @ Jun 14 2009, 20:41)  Понятно, что при помощи макросов можно заставить 'C' выглядеть как что-то совсем другое, но, ИМХО, лучше так не делать. Так сложилось в жизни, что был период turbo pascal 6.0/ Pascal Borland 7.0 for embedded applications, so I don't follow strong rules in C
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jun 14 2009, 18:04
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(sergeeff @ Jun 14 2009, 20:48)  Ну это, условный рефлекс, наверное. Форум "электроникс" - 1) достаточно модерируемый и 2) самоорганизующийся форум. Я удивлен тем фактом, что мне приходится отметать Ваш переход на какие-то посторонние от техники аспекты. Или Вы так зашорены, что больше нечего сказать? Цитата(aaarrr @ Jun 14 2009, 20:59)  Только не так, Боже упаси! Функция в header'е display.h, который и подключается. А, ну да, конечно...
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jun 14 2009, 18:41
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Цитата(Dog Pawlowa @ Jun 14 2009, 21:04)  Или Вы так зашорены, что больше нечего сказать? 1. При чем тут зашоренность. Абсолютное большинство программистов, увидев Код ABC() сразу поймет, что вызывается некая функция, т.е. некая локальная обработка данных, а Код ABC; может означать все что угодно. Может это чтение из глобальной переменной ABC в стиле уважаемого гуру zltigo, a может вызов макро. 2. Есть понятие "стиль программирования". Мне кажется, что "стильно" написанная программа это такая, которая легко читается и сопровождается, и не только автором.
|
|
|
|
|
Jun 14 2009, 18:41
|

Местный
  
Группа: Участник
Сообщений: 252
Регистрация: 2-03-08
Пользователь №: 35 557

|
Цитата(MrYuran @ Jun 14 2009, 15:34)  Я бы сделал так: Всем большое спасибо за помощь
Причина редактирования: Нарушение п.3.4 Правил форума.
--------------------
One Chip is All You Need
|
|
|
|
|
Jun 14 2009, 18:59
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Цитата(another_one @ Jun 14 2009, 21:41)  Всем большое спасибо за помощь Небольшой пример для иллюстрации "прелестей" макро. Код #define UP(port, bit) port |= (1<<bit) где-то в программе напишем: Код UP(port,2) + 3; Понятно, что такое можно написать после долгих праздников, но это может быть и результатом типичной ляпы типа "copy/paste". Очевидно, что это ляпа, но препроцессор это преобразует в Код port |= (1<<2) + 3; и компилятор не моргнув никакими error/warning откомпилирует. Очевидно, что это ляпа, но сколько времени вы будете ее искать? Ежели UP оформить в виде inline функции Код inline void UP(char port, char bit) {port &= ~(1<<bit);} компилятор тут же выдаст что-нибудь типа '+' : illegal operand of type 'void' с указанием номера строки (VS 2008). Если не хочется себе жизнь облегчать, то это, конечно, дело каждого уважаемого участника форума.
|
|
|
|
|
Jun 14 2009, 19:05
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(sergeeff @ Jun 14 2009, 22:59)  Ежели UP оформить в виде inline функции Код inline void UP(char port, char bit) {port &= ~(1<<bit);} Ну, с тем же успехом можно сделать и в виде дефайна: Код #define UP(port, bit) {port &= ~(1<<bit);}
|
|
|
|
|
Jun 14 2009, 19:13
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Dog Pawlowa @ Jun 14 2009, 20:36)  Большие буквы, отсутствие скобок -> значит это макрос для работы с портами -> см файл project_ports.h Отсутствующте скобочки они, конечно явно заставляют задуматься а что это такое? Причем задуматься без всякой на то надобности  . Для подчеркивания того, что это макрос достаточным является запись большими буквами (хотя для "функций" я этим практически не пользуюсь - никакой информации это собственно не несет) естественным для 'C' является on_backlight(); Ну или ксли хочется обратить внимание (обычно совсем без надобности) что это псевдофункция: ON_BACKLIGHT(); Но и это излишество в вашем случае. Хотя иногда, явно полезно, например если что-то написано в незамысловатом стиле Код #define DEBUG_PRINT( mask ) if( cfg_debug & (mask) )
DEBUG_PRINT( DL_RAW|DL_FULL ) println( "Hello!" ); Цитата(aaarrr @ Jun 14 2009, 22:05)  Ну, с тем же успехом можно сделать и в виде дефайна: Код #define UP(port, bit) {port &= ~(1<<bit);} Точнее так  : Код #define up(port, bit) {(port) &= ~(1<<(bit));}
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 14 2009, 19:38
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Цитата(zltigo @ Jun 14 2009, 22:16)  Просто макросы, как, впрочем и программы, надо уметь писать. Причем умение писать макросы не бог весть какое великое. Согласитесь уважаемый гуру, что написать "дуракоустойчивый" макрос сложнее (хотя бы с точки зрения отладки) эквивалентной inline функции. Во-вторых, я ведь просто для примера привел первый пришедший на ум пример когда макро, не мной написанное, а приведенное коллегами как пример для подражания, абсолютно молча привело к генерации неправильного С-ного кода.
|
|
|
|
|
Jun 14 2009, 19:54
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(sergeeff @ Jun 14 2009, 22:38)  ... написать "дуракоустойчивый" макрос сложнее ... Я то опираюсь на свою статистику - она более чем удовлетворительная. И вообще, существуют правила, вроде бы очевидные и понятные, например правила проверки равенства (константа на первом месте), затрудняющие чтение программы (по крайней мере лично у меня). Ну а скобочки ... говорю - из Паскаля я. Меня не заставляют задуматься. Те, кто использует мои тексты - тоже вроде не жалуются. Хотя сомнение зародили, если такая точка зрения есть, ничего не стоит попробовать. Кстати, указание inline, насколько я помню, не является безусловным и обязательным для компилятора, или?
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jun 14 2009, 20:05
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Dog Pawlowa @ Jun 14 2009, 23:54)  Кстати, указание inline, насколько я помню, не является безусловным и обязательным для компилятора, или? Не является. Но, во-первых, есть прагмы/модификаторы, настоятельно рекомендующие это компилятору (типа упомянутого __forceinline для RV); во-вторых, вредительством и саботажем компилятор тоже заниматься не станет.
|
|
|
|
|
Jun 14 2009, 20:11
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(sergeeff @ Jun 14 2009, 22:38)  Согласитесь уважаемый гуру, что написать "дуракоустойчивый" макрос сложнее (хотя бы с точки зрения отладки) эквивалентной inline функции. Ну не знаю, не знаю... Сложность очень отностительная, при этом для написания функций тоже надо немного думать и знать механихм заинлайнивания, индивиуальные для компилятора правила требовния (на самом деле просьбы  )принудительного заинлайтивания, принудительное откючение inline при отключении оптимизации что тоже может привести к проблемам (ногомахание по времени вдруг посыпалось, стек в начал больше использоваться). Кроме того макросы могут быть и много более мощными и читаемыми - у меня нередко встречаются макросы просто и естественно работаюшие, напимер, с десятком разных параметров, да, такой макрос не совсем прост, но и inline (точнее любая) функция более, чем уродлива в таких случаях.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 14 2009, 20:46
|

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

|
Цитата(sergeeff @ Jun 14 2009, 21:41)  2. Есть понятие "стиль программирования". Мне кажется, что "стильно" написанная программа это такая, которая легко читается и сопровождается, и не только автором. В общем согласен. Но только с оговорокой "легко читается и сопровождается людьми, имеющими определённый уровень подготовки". Ни в коем случае не всеми, кто написал "Hello, world!". А то ведь и в "человеческих" языках есть всякие там сложноподчинённые предложения, идиомы с прочими тропами, не говорю уже о профессиональной терминологии - тоже ведь не всё сказанное всем понятно будет, причём не только тем, кто только начал язык осваивать, но и многим "носителям". И это нормально. Я немного увожу в сторону от основной темы обсуждения, но когда начинается "указательную арифметику не использовать, плохо читается" и т.п. я думаю - может просто надо уровень читателей поднимать? Ведь в "должно быть понятно" можно докатиться до уровня рекламы стирального порошка или там "ретоны". Когда вижу как бы на С написанное Код if( flag ) { struct.member[index] = a; } else { struct.member[index] = b; } вместо Код struct.member[index] = flag ? a : b; я просто поражаюсь - насколько надо не любить и не знать С, чтобы так писать. А если это политика "чтобы понятно было", то на кого рассчитывается? И сможет ли этот "кто" понять всю программу? Да, с маленькими детьми обычно разговаривают очень упрощённым языком (хотя и тут встречал мнение, что чрезмерное упрощение вредит развитию), но если так разговаривать со школьником... Да, школьнику какую-то не сильно сложную медицинскую/физическую/... проблему можно и нужно уметь объяснить в каких-то базовых понятиях, но если профессионалы между собой начнут исключительно так общаться... Это им будет только мешать, затруднять общение. Конечно, если залезть в "башню из слоновой кости", то можно себя чувствовать крутым профи только потому, что тебя никто не понимает, это другая крайность. Оптимум где-то посредине, и, на мой взгляд, в случае с С в этот оптимум входит понимание возможностей и ограничений макросов, а не вера в то, что они вредны, почёрпнутая из агитации за С++, причём на примерах ошибок, которые более менее грамотный программист просто не должен уже совершать (а на уровне, на котором они совершаются, и на С++ ничего хорошего не будет написано). Уровень их использования, который обсуждается в этой теме, не должен приводить к каким-то ощутимым на фоне всей программы задержкам понимания текста. Любой знающий язык С, а не некое усечённое подмножество "разрешённое к применению в фирме" должен быстро с ним разобраться. Это понимание требует какого-то своего опыта. Начинающим сразу с С++ и не собирающимся работать на С может и можно послабление дать. Но с учётом того, что они (теоретически) должны научиться понимать гораздо более сложные вещи - макросы такого уровня они должны понимать легко. Также в этот оптимум входит достаточное понимание указателей, чтобы не сильно долго задерживаться на строке Код a = (flag ? sin : cos)(fi); Duff's device в него, пожалуй, не включу (хотя для понимания сути switch это весьма полезный пример и он есть в упражнениях у Страуструпа в "Язык программирования С++", причём это упражнение с низким уровнем сложности). Цитата(sergeeff @ Jun 14 2009, 21:59)  Небольшой пример для иллюстрации "прелестей" макро. Код #define UP(port, bit) port |= (1<<bit) где-то в программе напишем: Код UP(port,2) + 3; Можно и без макросов и без указателей и без goto наворотить такое, что никто не разберёт и не сможет сопровождать. Точно так же, как и имея словарный запас в три сотни слов можно нести околесицу. Приведенный Вами пример настолько "букварный", что или он из букваря и взят, или написавшему этот код человеку надо наконец-то вдумчиво прочесть книжку по языку С. Вы никогда не видели примеры "индусского" кода на java, где "корень всех зол" в виде макросов отсутствует? Что бы Вы сказали, если бы кто-то привёл пример такого кода как доказательство того, что с java надо уходить на С ? Означате ли то, что некоторые взрослые не умеют правильно поставить запятые в предложении, необходимость исключения из школьной программы этой части курса родного языка или, как минимум, рекомендации пользоваться всем только простыми предложениями? Цитата(sergeeff @ Jun 14 2009, 21:59)  Ежели UP оформить в виде inline функции Код inline void UP(char port, char bit) {port &= ~(1<<bit);} То на попытку применить эту функцию к порту будет выдано сообщение об ошибке. А так - она вообще ничего полезного не делает, так как модифицирует свой аргумент типа char. Да, для avr-gcc можно написать Код // для С99 так static inline void UP( volatile uint8_t *port, uint8_t bit) { *port |= 1 << bit; }
// а для режима С++ ещё и так static inline void UP2( volatile uint8_t& port, uint8_t bit) { port |= 1 << bit; } Но 1) для IAR это уже не прокатит, там по-другому описаны порты, типы volatile uint8_t * и volatile uint8_t & не подойдут. А вот правильно написанный макрос UP будет работать и там, и там. 2) а с первого раза и inline-функцию не вышло написать правильно  За что боролись? Ага. Вроде бы это должно работать где угодно. Код template<typename PP> inline void UP3( PP & port, uint8_t bit) { port |= 1 << bit; } Но это уже совсем не С, так что может иметь отношение только к разговору о (не)применении макросов в С++, даже к C99 отношения не имеет, а, как тут в параллельной теме выяснилось, и С99 иногда непозволительная роскошь. Постаравшись, можно залудить и что-то соответствующее по функционалу "макросам имени Аскольда Волкова" (тут упоминались несколько раз и приводились версии разного уровня развития идеи, но с лёту нашёл только одно сообщение), но не вижу смысла. У меня в связи с макросами ни аллергии, из-за "перееда" в детстве, ни полной беспомощности нетренированной имунной системы из-за жизни в стерильной среде нет.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Jun 14 2009, 20:52
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Меня как-то никогда не смущало написать пару десятков inline функций с осмысленными названиями, чтобы абстрагироваться от портов полностью. Код static inline void hal_SetRTS0(void) { PORTG |= (1 << RTS0); }
static inline void hal_ClrRTS0(void) { PORTG &= ~(1 << RTS0); }
static inline void hal_SetDTR0(void) { PORTG |= (1 << DTR0); }
static inline void hal_ClrDTR0(void) { PORTG &= ~(1 << DTR0); }
static inline void hal_PutRTS0(U8 val) { if (val) hal_SetRTS(); else hal_ClrRTS(); }
static inline void hal_PutDTR0(U8 val) { if (val) hal_SetDTR(); else hal_ClrDTR(); }
static inline U8 hal_GetCTS0(void) { return (PINE & (1 << CTS0)) != 0; }
static inline U8 hal_GetDCD0(void) { return (PINB & (1 << DCD0)) != 0; }
static inline U8 hal_GetDSR0(void) { return (PINB & (1 << DSR0)) != 0; }
static inline U8 hal_GetRI0(void) { return (PINB & (1 << RI0)) != 0; } .... А уже потом где надо, эти функции с осмысленными названиями назначать структурам: Код typedef struct tagFLOW_CONTROL { U8 enabled; // flow control enabled (check CTS before transmitting)
// acquiring signals cbs void (*On_DCD_Up)(struct tagFLOW_CONTROL *pCtrl); void (*On_CTS_Up)(struct tagFLOW_CONTROL *pCtrl); void (*On_DSR_Up)(struct tagFLOW_CONTROL *pCtrl); void (*On_RI_Up)(struct tagFLOW_CONTROL *pCtrl);
// losing signals cbs void (*On_DCD_Down)(struct tagFLOW_CONTROL *pCtrl); void (*On_CTS_Down)(struct tagFLOW_CONTROL *pCtrl); void (*On_DSR_Down)(struct tagFLOW_CONTROL *pCtrl); void (*On_RI_Down)(struct tagFLOW_CONTROL *pCtrl); void (*set_rts_cb)(U8 val); void (*set_dtr_cb)(U8 val); U8 (*get_cts_cb)(void); U8 (*get_dsr_cb)(void); U8 (*get_dcd_cb)(void); U8 (*get_ri_cb)(void); } TFLOW_CONTROL, *PFLOW_CONTROL;
...
#if (UART1_FULL_RS232) uart_con.u1_rs232_control.set_dtr_cb = hal_PutDTR0; uart_con.u1_rs232_control.set_rts_cb = hal_PutRTS0; uart_con.u1_rs232_control.get_cts_cb = hal_GetCTS0; uart_con.u1_rs232_control.get_dsr_cb = hal_GetDSR0; uart_con.u1_rs232_control.get_dcd_cb = hal_GetDCD0; uart_con.u1_rs232_control.get_ri_cb = hal_GetRI0;
uart_con.u1.pCtrl = &uart_con.u1_rs232_control; Kernel_SetTask( u1_DispatchRemoteFlowCtrlEvents, 5, TASK_PERIODIC); #endif Зачем нужны всякие макросы и прочая фигня для работы с портами то?
|
|
|
|
|
Jun 14 2009, 21:28
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(zltigo @ Jun 15 2009, 00:16)  А вместо декларируемого HAL для "объекта" получена просто заумная работа с отдельными битам  . HAL у меня не декларирует непосредственно объекты (объекты описываются уже в соответствующих им файлах). HAL у меня отделяет программу от МК. (Двухступенчатый HAL получается). В примере выше, TFLOW_CONTROL описан не в HAL, а в uart.h, т.к. это объект связанный с UART'ом. Если мне нужно включить реле1 то я предпочту написать hal_RelayOn(); если зажечь зеленый светодиод, а не красный и не желтый. hal_GreenLedOn(); вместо SET_BIT( PORT_HZx, PIN_HZx); CLR_BIT( PORT_HZy, PIN_HZy); или других извратов. В свою очередь, это дает возможность, легко управлять временем. Например отключить реле __через 2 секунды__ после включения, я могу сразу же при включении реле: hal_RelayOn(); Kernel_SetCb( hal_RelayOff, 2000, SEMA_NULL); Ну и полностью забыть о GPIO портах как о классе, вне HAL. Цитата Вы не одиноки , а заумные HAL пишут с неменьшим "успехом" и на макросах. на макросах такая конструкция hal_RelayOn(); Kernel_SetCb( hal_RelayOff, 2000, SEMA_NULL); непрокатит.
|
|
|
|
|
Jun 14 2009, 22:00
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(defunct @ Jun 15 2009, 00:28)  если зажечь зеленый светодиод, а не красный и не желтый.
hal_GreenLedOn();
вместо
SET_BIT( PORT_HZx, PIN_HZx); CLR_BIT( PORT_HZy, PIN_HZy); Ровным счетом никаких отличий  Вы написали "десяток функций" для дергания пином с разными именами, кто-то напишет десяток макросов с разными именами, кто-то опишет десяток дефайнов для макросов а-ля Волков.. На самом деле из всех этих вариантов самый правильный скорее всего будет тот, кто банально содержит минимум разных букв. Зачастую меня более всего устраивает и такое самое простое и незатейливое: Код #define P0B_SPI0_FSEL0 BIT22 #define P0B_SPI0_FSEL1 BIT31 #define IOSET_SPI0 IO0SET #define SPI0_SEL_MASK (P0B_SPI0_FSEL1|P0B_SPI0_FSEL0) .... IOSET_SPI0 = SPI0_SEL_MASK; И даже для тех-же светодиодов уровень абстакции может, и я считаю- должен, быть заметно выше, нежели ON/OFF void led_mode( Led_e led, Led_mode_e mode ); led_mode( LED_RED, LM_FLASH_1 ); Задается какой светодиод и десяток режимов миганий. Несклько десятков строк в отдельном файле посященном светодиодам. В файле без всяких слишком многоэтажных наворотов пишется, все , что нужно. Такой HAL, я понимаю.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 14 2009, 22:13
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(singlskv @ Jun 15 2009, 00:54)  простите, а кто Вас заставляет давать в качестве параметра именно функцию, почему не передавать просто идентификатор пина ? ну а если уж нужна разная обработка для разных пинов то можно и ссылку передавать и маску пина. Вы читали о чем я пишу? Я пишу что, я считаю, надо забыть о портах, номерах пинов, и т.п. чтобы спалось спокойно. Kernel у меня работает с функциями и с задачами а не с идентификаторами пинов. Любое __действие__ в общем виде всегда можно описать функцией. Номером пина либо еще какой-то фигней, любое действие не опишешь. Точно также как в примере с реле я работаю и с более сложными процессами: modem_Dial(); Kernel_SetCb( modem_Dial, 60000, SEMA_NULL); // повторный дозвон через минуту если не удалось дозвониться. Цитата(zltigo @ Jun 15 2009, 01:00)  Ровным счетом никаких отличий  Ну как же никаких... Вы можете поставить макрос в очередь задачь? А инлайн функцию - запросто, компилер поймет что от него хотят. Там где можно заинлайнит, там где нужно вызовет по адресу.
|
|
|
|
|
Jun 14 2009, 22:14
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(defunct @ Jun 15 2009, 02:03)  Вы читали о чем я пишу? Я пишу что надо забыть о портах, номерах пинов, и т.п. чтобы спалось спокойно. Наверное пока не уловил, поэтому и переспрашиваю...  Цитата Kernel у меня работает с функциями и с задачами а не с идентификаторами пинов. А может Вашему кернелу уже работать с объектами а не с отдельными сущностями ? Цитата Точно также как в примере с реле я работаю и с более сложными процессами: modem_Dial(); Kernel_SetCb( modem_Dial, 60000, SEMA_NULL); // повторный дозвон через минуту если не удалось дозвониться. совсем не уловил почему countdown счетчик для пина должен принципиально отличаться от таково же для модема ?
|
|
|
|
|
Jun 14 2009, 22:25
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(zltigo @ Jun 15 2009, 01:00)  Зачастую меня более всего устраивает и такое самое простое и незатейливое: Код #define P0B_SPI0_FSEL0 BIT22 #define P0B_SPI0_FSEL1 BIT31 #define IOSET_SPI0 IO0SET #define SPI0_SEL_MASK (P0B_SPI0_FSEL1|P0B_SPI0_FSEL0) .... IOSET_SPI0 = SPI0_SEL_MASK; А если проц поменялся? У меня это просто: hal_SPI0_Prepare(); Цитата(singlskv @ Jun 15 2009, 01:14)  А может Вашему кернелу уже работать с объектами а не с отдельными сущностями ? Вы о чем? Какие отдельные сущности? Kernel работает с ___функциями____ которые описывают ___любые___ действия любых объектов. Цитата совсем не уловил почему countdown счетчик для пина должен принципиально отличаться от таково же для модема ? Блин... дак ничем он и не отличается.
|
|
|
|
|
Jun 14 2009, 22:30
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(defunct @ Jun 15 2009, 02:25)  Блин... дак ничем он и не отличается.  Ну а если ничем не отличается, то легко реализуем с помощью макросов... и очень даже эфективненько... Ну положите в конце концов адрес функции обработчика при инициализации... зачем его каждый раз передавать ?
|
|
|
|
|
Jun 14 2009, 22:37
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(singlskv @ Jun 15 2009, 01:30)  Ну а если ничем не отличается, то легко реализуем с помощью макросов... и очень даже эфективненько... Что реализуемо с помощью макросов? Изобразите свой полет мысли, а то получается разговор слепого с глухим. Цитата Ну положите в конце концов адрес функции обработчика при инициализации... куда положить? Цитата зачем его каждый раз передавать ? Чтобы можно было зарегистрировать сколько угодно и каких угодно колбеков вестимо, с разными таймаутами и разными условиями запуска.
|
|
|
|
|
Jun 15 2009, 05:37
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(defunct @ Jun 15 2009, 01:13)  Вы можете поставить макрос в очередь задачь? А инлайн функцию - запросто, компилер поймет что от него хотят. Там где можно заинлайнит, там где нужно вызовет по адресу. В моем понимании макрос работы с портами - это действие, которое должно быть выполнено сейчас же. Ногодрыганье в самом чистом виде, без малейшей возможности компилятору сделать шаг в сторону  "Прокладка" для портирования. Если предусматривается какая-то более сложная логика, то это не совсем порт, а, скажем объект какой-то типа звукового сигнала со своими параметрами, или моргающего светодиода, как в примере zltigo. Для обслуживания такого "объекта" прописывается свой сервис в каком-нить бэкграунде. Его параметры устанавливаются типа так: void Beep (unsigned int ms, char beeps_qty), после чего "приложение" забывает о существовании этого объекта. Типичная организация системы без ОС. В Вашем варианте смешаны в кучу и быстрые действия и медленные, в результате быстрые могут оказаться не такими быстрыми, как иногда требуется.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jun 15 2009, 06:31
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Цитата(ReAl @ Jun 14 2009, 23:46)  где "корень всех зол" в виде макросов отсутствует? 1. Я нигде не утверждал, что макрос - страшное, ужасное зло. Бывают случаи, когда только они и работают. 2. "Букварный пример" он на то и пример, чтобы просто показать "подводные камни" макропрограммирования. 3. Все очень быстро в пылу дисскуссии забывают изначальный вопрос автора топика. 4. Любую программу можно написать десятком разных способов. Не спроста Кнут назвал свои книги "Искусство программирования". 5. Примеры с разложенными по строкам if .. else и тернарный оператор ? в 99% случае компилятором генерируются в одинаковый машинный код. Тут, как говорится, на вкус и цвет... 6. В большинстве случаев (есть и исключения) книги по программированию написаны людьми лично принимавшими участие в больших и огромных проектах и не знакомиться с их практическим опытом просто не разумно.
|
|
|
|
|
Jun 15 2009, 06:46
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(Dog Pawlowa @ Jun 15 2009, 08:37)  В Вашем варианте смешаны в кучу и быстрые действия и медленные, в результате быстрые могут оказаться не такими быстрыми, как иногда требуется. Если нужно совсем быстро опишу эти быстрые действия в том же HAL как еще одну inline функцию.. делов то.. Вы просто м.б. не представляете насколько это здорово, когда не только программа портируется без изменений с одного проца на другой, но и драйверы периферии портируются тоже практически без изменений (либо с очень небольшим числом таковых). Цитата Если предусматривается какая-то более сложная логика, то это не совсем порт, А кому нужен совсем "порт" в чистом виде то? (ну кроме студентов которые проходят лабораторки по портам). Надо выполнить действие. выполнить быстро. Тут inline функция работает ничуть не медленнее макроса, плюс к этому качеству она обладает еще и свойством обычной функции, и является частью стандарта языка. А что такое макрос? не подумайте что у меня есть какие-то предубеждения к макросам, я их тоже пользую ;> но не для портов, а например так: Код /*************************************** * Read access to RTL reg page * * ---> Addr 0x00..0x10 (including DMA) * * <--- returns register value * ***************************************/ #define nic_ReadReg( addr )\ (*(V8 *)(NIC_BASE + (addr)))
/*************************************** * Write access to RTL reg page * * ---> Addr 0x00..0x10 (including DMA) * * ---> value, data to be stored * * <--- returns: nothing * ***************************************/ #define nic_WriteReg(addr, val)\ (*(V8 *)(NIC_BASE + (addr)) = (val)) Когда точно уверен, что мне никогда не понадобится свойство функции от этого действия.
|
|
|
|
|
Jun 15 2009, 07:05
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(defunct @ Jun 15 2009, 01:25)  А если проц поменялся? У меня это просто: hal_SPI0_Prepare(); Ничего не мешает и подниматься на более высокие уровни абстракции HAL - пример со сведодиодом я лично приводил. В этом случае задача абстрагироваться от смены прцессора не ставилась, причина более чем проста - SPI все несколько разные и нагрузка у меня на них большая,посему совсем не хочется все SPI стричь под одну гребенку, дабы все выглядели в угоду HAL одинаково. Причем, как правило, равняясь по слабейшему, они будут выглядеть одинаково уродливо  . Даже на более высоком уровне абстракции "драйвер" не всегда несколько контроллеров хорошо стригутся под одну гребенку. Много чего обычно приходится придумвать для эффективной работы не вообще, например, "SPI" (про разные MAC, CAN,... вообще молчу) а "конкретного SPI" и на фоне этих работ, меня, честно говоря, совсем не волнуют "пролемы" HAL для одинокого пина  .
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 15 2009, 08:03
|

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

|
Цитата(sergeeff @ Jun 15 2009, 09:31)  2. "Букварный пример" он на то и пример, чтобы просто показать "подводные камни" макропрограммирования. Не спорю. Но с тем же успехом можно Вашу inline-функцию, просто модифицирующую свой собственный аргумент (независимо от того, как в данной системе представлены порты) использовать как пример "подводного камня" при использовании функций. Cобственно, что-то похожее и показывают в разговорах о передаче по ссылке и по значению. Ошибки, на мой взгляд, одного уровня, нормальный человек их может сделать только в начале обучения либо поздно вечером в пылу спора Годится как урок "как не надо делать", а не как аргумент за то, чтобы не использовать.Цитата(sergeeff @ Jun 15 2009, 09:31)  5. Примеры с разложенными по строкам if .. else и тернарный оператор ? в 99% случае компилятором генерируются в одинаковый машинный код. Тут, как говорится, на вкус и цвет... А я об эффективности кода и не говорил. Это иллюстрация к "упрощённый язык для объяснения школьнику" и "общение профессионалов". Многострочный вариант читается так: Цитата если флаг установлен, то такому-то элементу такого-то массива такой-то структуры присвоить а если же он сброшен, то такому-то элементу такого-то массива такой-то структуры присвоить b а, одной и той же структуры! а, одного и того же массива! а, и индекс одинаковый! щас... да, точно, всё до буковки одинаково. значит так, такому-то элементу такого-то массива такой-то структуры в зависимости от флага присвоить a или b тогда как тернарная операция сразу приводит понимание текста к последней строке. Конечно, только для человека, знающего язык достаточно хорошо. Так значит тут - "на вкус и цвет", а макросы - снижают читаемость и сопровождаемость текста?
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Jun 15 2009, 08:24
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(Dog Pawlowa @ Jun 14 2009, 13:49)  Описываю весь доступ к портам через макросы в одном h-файле и не парюсь. В прочих файлах НИКАКОГО упоминания о портах, только макросы с осмысленными названиями. Просто для понимания. Существенно упрощает портирование. К сожалению, есть проблема инлайнить функции, определенные в других модулях, теоретически можно тоже через #include, но это уж точно на изврат похоже. Поступаю также. Один в один. Как раз для переносимости очень удобно. Чётко знаешь что этот файл придётся переписать. Никакой неразберихи в файлах проекта у меня не возникает, так как там уже используются "осмысленные" макросы. Типа LED_ON или RG_STB. Для одного проекта (проца) может быть LED_ON единицей, для другого нулём. Это не имеет значение. Так как правится макрос, и он по макросу LED_ON загорается. (Естественно я упрощаю). Можно былобы ожидать, что этот файл большим будет, но на самом деле - совсем пустяковый. Всё сведено в одно место, сразу видны все биты и порты, видна их инициализация. Короче очень удобно. Если разработчик работает в коллективе, то должны быть определены какие то общие правила оформления проекта. Они должны постоянно корректироваться. Разработчики должны их придерживаться. Если груповой проект, то должен составляться план поекта и какие-то доп правила оформления (к типовым правилам).
|
|
|
|
|
Jun 15 2009, 08:33
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Цитата(ReAl @ Jun 15 2009, 11:03)  Так значит тут - "на вкус и цвет", а макросы - снижают читаемость и сопровождаемость текста? Макросы - это препроцессор, т.е. "до компилятора". Варианты if... и ? - компилятор. Вы лично часто изучаете листинг препроцессора? Уверен - почти никогда. Значит вы просто полагаетесь на то, что вы со своим многолетним опытом, ошибок при написании макросов не допускаете и препроцессор все сделал именно так, вы себе это представляете. А если ошибка есть, она трудноуловима (при одних данных есть, при других - нет, а еще хуже при одних типах данных - есть, при других - нет). Вам что больше по душе, чтобы компилятор вам хотя бы подсказывал про подобные потенциальные проблемы, или молча, по своему усмотрению чего-то там понаделал, а вы потом, "по вторичным половым признакам" аномального поведения программы это все вылавливали?
|
|
|
|
|
Jun 15 2009, 10:43
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(SasaVitebsk @ Jun 15 2009, 11:24)  Всё сведено в одно место, сразу видны все биты и порты, видна их инициализация.... ...и взаимосвязь со взаимоисключениями. Причем, этот файл на самом деле и внутри сруктурирован - те-же биты, хоть и для светодиодов поименованы и соответсвенно ниже по файлу, т.е. уже уровнем выше  используются только эти имена. Все это хозяйство компактно, лаконично и достаточно легко изучается в том числе и глазами.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 17 2009, 08:57
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(zltigo @ Jun 15 2009, 13:43)  ...и взаимосвязь со взаимоисключениями. Причем, этот файл на самом деле и внутри сруктурирован - те-же биты, хоть и для светодиодов поименованы и соответсвенно ниже по файлу, т.е. уже уровнем выше  используются только эти имена. Все это хозяйство компактно, лаконично и достаточно легко изучается в том числе и глазами. Именно так. Единственно, что я струкурирую по портам. Типа беру бит, обзываю его и объявляю макросы работы с ним с учётом специфики. Это даёт возможность не пропустить какой-либо бит. Так же комментирую этот бит если надо. С точки зрения программиста, часто схема просто не нужна. Точнее её он структурно представляет, а управление ей он читает именно в этом файле. При возвращении к проекту, чаще всего заглядываю именно в этот файл, для того чтобы вспомнить весь проект. Кроме того с помощью условной компиляции, либо сменой данного файла, вы можете версию платы менять. Например в версии 1а сменили ноги при переразводке.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|