|
|
  |
Привязка структур к аппаратуре |
|
|
|
Feb 19 2008, 16:09
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Обычный С. В системе есть несколько идентичных узлов (управление температурой, двигатели), описываемых структурами переменных. Стоит задача сокращения текста программы. Вариантов три - макросы, функции и их комбинации. Вначале сделал вариант с макросами, и он работает Код #define MOTOR_SERVICE(OBJ, MOT) \ if (!OBJ##.time) \ { PWM##MOT=PWM_TOP+1; HIGH_MODE##MOT; \ OBJ##.state=moSTOPPED; \ } \ else { if (OBJ##.speed==0) \ { PWM##MOT=PWM_TOP+1; HIGH_MODE##MOT; \ ну и так далее... В этом макросе параметры - имя структуры и номер, который служит для обращения к нужным портам через другие макросы. Но у макросов есть недостатки: - трудность отладки (в отладчике IAR в этом случае нет привязки к строкам кода С) - трудности привязки ошибки компиляции к месту в макросе - ну и размер кода, конечно. Хотелось бы использовать функции с параметром указателя на структуру, причем чтобы и работа с портами легко укладывалась в этот стройный подход. Вопрос - как это сделать красиво, если там разные входы, выходы, и собственно сами регистры. Добавить с структуру указатели на функции? Добавить в параметры функции индекс, который использовать для выбора функций работы с портами из массива, как в примере макроса? Может, что-то еще?
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Feb 19 2008, 20:17
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555

|
Цитата(Dog Pawlowa @ Feb 19 2008, 19:09)  Хотелось бы использовать функции с параметром указателя на структуру, причем чтобы и работа с портами легко укладывалась в этот стройный подход. С указателем на порт в общем случае IMHO не получится - во первых таймеры разные и могут быть биты в разных местах, доступ к порту через указатель часто не оптимален. Хотя если указатель на PWM регистр можно его рассматривать как указатель на volatile (главное если 16 бит по байтам писать в нужном порядке). Но доступ к GPIO особенно на уровне бит будет кривой совсем. Я реализовывал как и у вас через макросы! и ## Цитата(prottoss @ Feb 19 2008, 19:32)  Перейти на С++ Есть и такой вариант использовать template главное что бы компилер не глючил!
|
|
|
|
|
Feb 19 2008, 20:56
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(KRS @ Feb 19 2008, 23:17)  С указателем на порт в общем случае IMHO не получится - во первых таймеры разные и могут быть биты в разных местах, доступ к порту через указатель часто не оптимален. Хотя если указатель на PWM регистр можно его рассматривать как указатель на volatile (главное если 16 бит по байтам писать в нужном порядке). Но доступ к GPIO особенно на уровне бит будет кривой совсем. ИМХО, все это зависит от конкретного проца и от конкретной задачи, Если речь об управляющих регистрах, и биты попутаны местами то там и макросы не очень..., а если речь о регулярных регистрах(там где задается значение в 16ричном виде), там вариантов масса, например массивы адресов регистров и к примеру масок для них. Только все равно, по хорошему, для таких вариантов нужно четко определять volatile доступ к таким адресам, и проще всего это сделать через макросы. Вобщем, ИМХО, нужно видеть задачу что бы сказать как будет выгоднее.
|
|
|
|
|
Feb 19 2008, 21:18
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555

|
Есть еще вариант использовать #pragma inline=forced примерно так Код #pragma inline=forced void Action(unsigned num,val) { counter[num]=val; ..... if (num==0) PORTA|=1; else if (num==1) PORTA|=2; else if (num==2) PORTB|=4; pos[num] =.... if (stop[num]) { if (num==0) PORTA&=~1; else if (num==1) PORTA&=~2; else if (num==2) PORTB&=~4; } } т.е. там где доступ к регистрам переферии использовать тупо перебор if elseif... т.к. функция всегда инлайн все if оптимизатор уберет и код будет оптимален
|
|
|
|
|
Feb 19 2008, 21:41
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(KRS @ Feb 20 2008, 00:18)  Есть еще вариант использовать ....... т.е. там где доступ к регистрам переферии использовать тупо перебор if elseif... т.к. функция всегда инлайн все if оптимизатор уберет и код будет оптимален Такой вариант получается очень процессорозависимым, те при переходе на новый проц придется пересмотреть все функции в которых это встречается. Хотя я например использую оба варианта, и спец быстрые функции для доступа к конкретным портам/битам когда нужно очень быстро, и абстрактные массивы из пар (адрес порта, маска) когда нужно много и переносимость значит чуть больше чем скорость...
|
|
|
|
|
Feb 20 2008, 07:11
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(KRS @ Feb 20 2008, 01:18)  Есть еще вариант использовать #pragma inline=forced примерно так Да, ночью мне вместо таблицы Менделеева и бутылки водки inline приснился  Как средство восстановления быстродействия, поскольку мои мысли крутятся вокруг использования массива указателей на функции: Код void SetPosSpeed1(void) { OCR1AL=PWM_TOP - last_speed1 - (last_speed1>>1); } void SetPosSpeed2(void) { OCR1BL=PWM_TOP - last_speed2 - (last_speed2>>1); } PROCEDURE SetPosSpeed[2]= { SetPosSpeed1, SetPosSpeed2};
void MoService( char i) { mo_type * mop=tm[i-1]; // pointer to structure ... SetPosSpeed[i](); // call hardware support function by index of "object" ... } Только я не уверен, что IAR проглотит inline для функции, вызываемой по индексу из массива. Не будет получаться - попробую Ваш вариант. Я помню, у меня были проблемы с индивидуальным inline и какими-то общими установками проекта в IAR, я даже писал про это здесь, на форуме. Цитата(singlskv @ Feb 20 2008, 01:41)  Такой вариант получается очень процессорозависимым, те при переходе на новый проц придется пересмотреть все функции в которых это встречается. Это часть фактически описывает подключение оборудования к конкретным ножкам конкретного контроллера, тут и невозможно сделать процессорно-независимо.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Feb 20 2008, 09:47
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(KRS @ Feb 20 2008, 11:23)  Проверил, вроде все работает. Главное - не забыть включить оптимизацию , иначе inline игнорируется. И это хорошо, потому что иначе трудно отладиться - в окне дизассемблера при полной оптимизации привязка к строкам исходного текста отсутствует. Итого - достоинство по сравнению с макросами - более читаемый текст, - управление кодом с помощью оптимизации. Спасибо.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|