|
|
  |
port definition for IAR C++, компилятор выдает предупреждения |
|
|
|
May 27 2006, 14:31
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Всем доброго времени суток!
Для написания программ для AVR всегда пользовал язык С, хотя С++ знаю, но как то применял для МК, на Си было попроще. Сейчас встала необходимость применять С++ ...В принципе, все компилируется и работает, но линкер сыпет предупреждениями типа:
Warning[w35]: There is more than one definition for the struct/union type with tag '__C1'; class/struct/union field names do not match: UCSRA_Bit0 vs DDRC_Bit0 struct __C1 /* Elements: 8, Bytes: 1 */ { unsigned char UCSRA_Bit0 : 1 /* disp: 0 */; unsigned char UCSRA_Bit1 : 1 /* disp: 1 */; unsigned char UCSRA_Bit2 : 1 /* disp: 2 */; unsigned char UCSRA_Bit3 : 1 /* disp: 3 */; unsigned char UCSRA_Bit4 : 1 /* disp: 4 */; unsigned char UCSRA_Bit5 : 1 /* disp: 5 */; unsigned char UCSRA_Bit6 : 1 /* disp: 6 */; unsigned char UCSRA_Bit7 : 1 /* disp: 7 */; };
etc.
Я понимаю так, что определения бит одного порта, используемого мною, перекрывают определения бит другого порта, который я тоже использую в своей программе. Как избавиться от этих предупреждений? Я привык составлять прогрмму так, что бы не было никаких предупреждений)))...
Спасибо.
--------------------
|
|
|
|
|
May 27 2006, 14:48
|

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

|
приведен неполный код. То что вы привели по идее не должно быть причиной warning'a. Ну и почему бы не воспользоваться typedef struct..., определить структуру с разбивкой на биты B0..B7, и пользоваться этим типом там где это требуется. пример: Код typedef struct /* Elements: 8, Bytes: 1 */ { unsigned char B0 : 1, B1 : 1, B2 : 1, B3 : 1, B4 : 1, B5 : 1, B6 : 1, B7 : 1; } TMyStruct;
volatile static __no_init TMyStruct DDRA @ 0x1A; volatile static __no_init TMyStruct UCSRA @ 0x0B; ...
|
|
|
|
|
May 27 2006, 15:21
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(defunct @ May 27 2006, 22:48)  приведен неполный код. То что вы привели по идее не должно быть причиной warning'a.
Ну и почему бы не воспользоваться typedef struct..., определить структуру с разбивкой на биты B0..B7, и пользоваться этим типом там где это требуется. По поводу кода: я попытался переделать на С++ драйвер USART который я выложил в http://electronix.ru/forum/index.php?showtopic=10934# Он чуть вышего Вашего программного USART. Так вот, когда я переправил в глобальных опциях проекта CLIB на Normal DLIB (Full DLIB/ Custom DLIB), и откомпилировал проект, не написав еще ни единого класса, у меня пошли Warning-и. Так что код можете посмотреть. При CLIB ни каких предупреждений не было((( >Re:Ну и почему бы не воспользоваться typedef struct... Не хочется нагромождать код лишними конструкциями, так хуже воспринимается) К тому же я думаю есть более простой путь, может быть какой то хедер подключить? Попутно еще вопрос, пусть даже на примере моего драйвера - как мне встроить в класс (допустим USART-а) прерывания. Ведь в прерывание я не смогу передать параметр, а функции класса всегда получают хотя бы один параметр - указатель класса. Делать для этого в модуле глобальную переменную -указатель? Или есть еще каки нибудь методы?
--------------------
|
|
|
|
|
May 27 2006, 15:41
|

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

|
Цитата(prottoss @ May 27 2006, 18:21)  По поводу кода: я попытался переделать на С++ драйвер USART который я выложил в http://electronix.ru/forum/index.php?showtopic=10934... Так вот, когда я переправил в глобальных опциях проекта CLIB на Normal DLIB (Full DLIB/ Custom DLIB), и откомпилировал проект, не написав еще ни единого класса, у меня пошли Warning-и. Так что код можете посмотреть. При CLIB ни каких предупреждений не было((( Весьма странно. Откомпилировал Ваш проект как есть с Normal DLIB (embedded C++), единственный Warning: Warning[Pe951]: return type of function "main" must be "int" C:\ATMEL\IAR\Prottoss\main.c 16 Цитата Попутно еще вопрос, пусть даже на примере моего драйвера - как мне встроить в класс (допустим USART-а) прерывания. Ведь в прерывание я не смогу передать параметр, а функции класса всегда получают хотя бы один параметр - указатель класса. Делать для этого в модуле глобальную переменную -указатель? Или есть еще каки нибудь методы? Сделать метод класса обработчиком прерывания - нельзя. Но можно объявить экземпляр класса (вашего драйвера) так, чтобы он попадал в область видимости функции обработчика прерывания, т.о. внутри функции обработчка прерывания можно будет вызывать методы конкретного экземпляра этого класса.
|
|
|
|
|
May 27 2006, 16:21
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(Сергей Борщ @ May 28 2006, 00:05)  Как победить эти warnings не знаю, они рождаются линкером при использовании прилагающихся к пакету заголовочных файлов ioxxx.h. А что касается обработчика прерывания - его можно сделать статическим членом класса. Как победить Warning-и я уже разобрался, хотя может и не то сделал, но они исчезли))) Options->Linker->Diagnostic->No_Global_Type_Checking = ON >Re: А что касается обработчика прерывания - его можно сделать статическим членом класса Не можно его делать статическим членом класса - не будет доступа к НЕстатическим (читай - всем нужным мне) членам (переменным и функциям) этого класса. Кстати,другом тоже не получится, все равно придется передавать параметр-указатель класса. Стандартный путь - в модуле сделать глобальный указатель на класс. Кстати, таким макаром, я предвижу, можно будет и двумя USART поуправлять, если сделать две переменные. Хотя пока это только планы)
--------------------
|
|
|
|
|
May 27 2006, 17:35
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
реплика не в тему созданную мной, но дабы не занимать пространство форума продолжу сдесь задавать вопросы по Embedded C++ и моих траблах с ним) в итоге я содал класс: Код
/***************************************************************************** Описание класса USART ******************************************************************************/ class clUSART { /****************************************************************************/ protected: UINT RX_Flags; // флаги ошибок UCHAR RX_Count; // количество принятых байт в буфере UCHAR RX_WrIndex; // индекс для принимаемых в буфер данных UCHAR RX_RdIndex; // индекс для читаемых из буфера данных UCHAR RX_Buffer[USART_RX_BUFFER_SIZE];// кольцевой FIFO буфер приемника
public: void RX_Reset(void); // сброс буфера приемника BOOL RX_GetChar(UCHAR *dest); // получить байт из буфера приемника UCHAR RX_GetCount(void); // проверить, если принятые данные UCHAR RX_GetState(void); // получить состояние приемника
/****************************************************************************/ protected: UINT TX_Flags; // флаги ошибок UCHAR TX_Count; // количество отправляемых байт в буфере UCHAR TX_WrIndex; // индекс для принимаемых в буфер данных UCHAR TX_RdIndex; // индекс для читаемых из буфера данных UCHAR TX_Buffer[USART_TX_BUFFER_SIZE];// кольцевой FIFO буфер передатчика
public: void TX_Reset(void); // сброс буфера передатчика BOOL TX_PutChar(UCHAR srch); // отправить байт в буфер передатчика UCHAR TX_GetCount(void); // проверить, если данные для отправки UCHAR TX_GetState(void); // получить состояние передатчика
/****************************************************************************/ protected: UCHAR Timeout; // счетчик для подсчета таймаутов
public: BOOL IsFrameTimeout(void); // проверить таймаут кадра
/****************************************************************************/ protected:
/****************************************************************************/ public: clUSART(void); void UDR_Empty(void); void RX_Complete(void); void TX_Complete(void); void TIMER_Timeout(void); }; В модуле создал глобальную переменную, которую конструктор класса инициализирует адресом класса: Код
/***************************************************************************** Глобальные переменные ******************************************************************************/ clUSART *g_usart = NULL;
....
/***************************************************************************** Инциализация USART ******************************************************************************/ clUSART::clUSART(void) {
g_usart = this;
....
} А прерывания использовал так: Код
/***************************************************************************** Обработчик опустошения регистра данных передатчика USART UDR ******************************************************************************/ __interrupt void UDR_Empty(void) { g_usart->UDR_Empty(); }
void clUSART::UDR_Empty(void) {
.....
}
// и так все остальные прерывания В итоге когда я посмотрел листинг то опешил, каждое прерывание сопровождается массовым сохранением в стек регистров, в начале, и таким же массовым в конце, что не есть хорошо на больших скоростях обмена по USART. В принципе я знаю про такой эффект компилятора, но надеялся что когда я перейду на Си++, компилятор "поумнеет". Увы.. Может быть кто занет как решить проблему, или подскажет способ, как внедрить прерывание в класс?
--------------------
|
|
|
|
|
May 27 2006, 19:07
|

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

|
Цитата(prottoss @ May 27 2006, 20:35)  В итоге когда я посмотрел листинг то опешил, каждое прерывание сопровождается массовым сохранением в стек регистров, в начале, и таким же массовым в конце, что не есть хорошо на больших скоростях обмена по USART. В принципе я знаю про такой эффект компилятора, но надеялся что когда я перейду на Си++, компилятор "поумнеет". Увы.. Может быть кто занет как решить проблему, или подскажет способ, как внедрить прерывание в класс? Увы и ах, такое поведение характерно не только для AVR Embedded C++, поэтому драйвера обычно пишутся без использования возможностей ООП. Если посмотреть на это с другой стороны, то 32 байта стека и 128 циклов CPU не такая уж и большая цена за использование возможностей ООП. На 115200 с частотой следования байтов 11.52 Khz накладные расходы составят 13.3% от общей произодительности МК при частоте тактирования 11.059Mhz. Вполне терпимо.. Код /***************************************************************************** Глобальные переменные ******************************************************************************/ clUSART *g_usart = NULL; ....
/***************************************************************************** Обработчик опустошения регистра данных передатчика USART UDR ******************************************************************************/ __interrupt void UDR_Empty(void) { g_usart->UDR_Empty(); } Код у Вас небезопастный, а это плохо.. В обработчике прерывания, обязательно следовало бы добавить: if (g_usart != NULL) .... И наверное, коль Вы пишете класс, то вероятно для возможности обслуживания нескольких UART'ов одинаковыми средствами, поэтому глобальным должен быть не один объект, а список объектов, который логично формировать взависимости от, например, наличия аппаратных USART'ов МК (#ifdef UDR0, #ifdef UDR1 и т.п.).. PS: избежать накладных расходов, на мой взгляд, можно в случае если скомбинировать обработку прерываний средствами inline функций, и постобработку принятых данных в основном цикле программы методами классов. Только такая организация потребует строго определенной структуры программы, что сделает Ваш драйвер менее универсальным, хотя и более эффективным.
|
|
|
|
|
May 28 2006, 07:30
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(defunct @ May 28 2006, 03:07)  Увы и ах, такое поведение характерно не только для AVR Embedded C++, поэтому драйвера обычно пишутся без использования возможностей ООП. Если посмотреть на это с другой стороны, то 32 байта стека и 128 циклов CPU не такая уж и большая цена за использование возможностей ООП. На 115200 с частотой следования байтов 11.52 Khz накладные расходы составят 13.3% от общей произодительности МК при частоте тактирования 11.059Mhz. Вполне терпимо.. Согласен, по этому я оставил два варианта драйвера. Для одного УСАПП буду пользоваться Си, для двух или более) - Си++ Цитата(defunct @ May 28 2006, 03:07)  Код у Вас небезопастный, а это плохо.. Согласен, это были просто наброски) Цитата(defunct @ May 28 2006, 03:07)  PS: избежать накладных расходов, на мой взгляд, можно в случае если скомбинировать обработку прерываний средствами inline функций, и постобработку принятых данных в основном цикле программы методами классов. Только такая организация потребует строго определенной структуры программы, что сделает Ваш драйвер менее универсальным, хотя и более эффективным. Будем пробовать)
--------------------
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|