prottoss 0 27 мая, 2006 Опубликовано 27 мая, 2006 · Жалоба Всем доброго времени суток! Для написания программ для 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. Я понимаю так, что определения бит одного порта, используемого мною, перекрывают определения бит другого порта, который я тоже использую в своей программе. Как избавиться от этих предупреждений? Я привык составлять прогрмму так, что бы не было никаких предупреждений)))... Спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
defunct 0 27 мая, 2006 Опубликовано 27 мая, 2006 · Жалоба приведен неполный код. То что вы привели по идее не должно быть причиной 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; ... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 27 мая, 2006 Опубликовано 27 мая, 2006 · Жалоба приведен неполный код. То что вы привели по идее не должно быть причиной 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-а) прерывания. Ведь в прерывание я не смогу передать параметр, а функции класса всегда получают хотя бы один параметр - указатель класса. Делать для этого в модуле глобальную переменную -указатель? Или есть еще каки нибудь методы? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
defunct 0 27 мая, 2006 Опубликовано 27 мая, 2006 · Жалоба По поводу кода: я попытался переделать на С++ драйвер 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-а) прерывания. Ведь в прерывание я не смогу передать параметр, а функции класса всегда получают хотя бы один параметр - указатель класса. Делать для этого в модуле глобальную переменную -указатель? Или есть еще каки нибудь методы? Сделать метод класса обработчиком прерывания - нельзя. Но можно объявить экземпляр класса (вашего драйвера) так, чтобы он попадал в область видимости функции обработчика прерывания, т.о. внутри функции обработчка прерывания можно будет вызывать методы конкретного экземпляра этого класса. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 27 мая, 2006 Опубликовано 27 мая, 2006 · Жалоба Весьма странно. Откомпилировал Ваш проект как есть с Normal DLIB (embedded C++), единственный Warning: Warning[Pe951]: return type of function "main" must be "int" C:\ATMEL\IAR\Prottoss\main.c 16 Хм...Значит буду щелкать галочками, что то где-то не включил-выключил... Сделать метод класса обработчиком прерывания - нельзя. Но можно объявить класс-драйвер так, чтобы он попадал в область видимости функции обработчика прерывания, т.о. внутри функции обработчка прерывания можно будет вызывать методы конкретного экземпляра этого класса. Да я тоже подумал, что можно сделать другом класса функцию прерывания Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 27 мая, 2006 Опубликовано 27 мая, 2006 · Жалоба Как победить эти warnings не знаю, они рождаются линкером при использовании прилагающихся к пакету заголовочных файлов ioxxx.h. А что касается обработчика прерывания - его можно сделать статическим членом класса. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 27 мая, 2006 Опубликовано 27 мая, 2006 · Жалоба Как победить эти warnings не знаю, они рождаются линкером при использовании прилагающихся к пакету заголовочных файлов ioxxx.h. А что касается обработчика прерывания - его можно сделать статическим членом класса. Как победить Warning-и я уже разобрался, хотя может и не то сделал, но они исчезли))) Options->Linker->Diagnostic->No_Global_Type_Checking = ON >Re: А что касается обработчика прерывания - его можно сделать статическим членом класса Не можно его делать статическим членом класса - не будет доступа к НЕстатическим (читай - всем нужным мне) членам (переменным и функциям) этого класса. Кстати,другом тоже не получится, все равно придется передавать параметр-указатель класса. Стандартный путь - в модуле сделать глобальный указатель на класс. Кстати, таким макаром, я предвижу, можно будет и двумя USART поуправлять, если сделать две переменные. Хотя пока это только планы) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sensor_ua 0 27 мая, 2006 Опубликовано 27 мая, 2006 · Жалоба Это должно быть то же, что #include <ioavr.h> Если оно где-то подключается (а лучше, ИМХО, именно его и подключать, а не ioxxx.h), то дважды включается нужный ioxxx.h, а там нет #if !defined _ioxxx_h_ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 27 мая, 2006 Опубликовано 27 мая, 2006 · Жалоба реплика не в тему созданную мной, но дабы не занимать пространство форума продолжу сдесь задавать вопросы по 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. В принципе я знаю про такой эффект компилятора, но надеялся что когда я перейду на Си++, компилятор "поумнеет". Увы.. Может быть кто занет как решить проблему, или подскажет способ, как внедрить прерывание в класс? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
defunct 0 27 мая, 2006 Опубликовано 27 мая, 2006 · Жалоба В итоге когда я посмотрел листинг то опешил, каждое прерывание сопровождается массовым сохранением в стек регистров, в начале, и таким же массовым в конце, что не есть хорошо на больших скоростях обмена по 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 функций, и постобработку принятых данных в основном цикле программы методами классов. Только такая организация потребует строго определенной структуры программы, что сделает Ваш драйвер менее универсальным, хотя и более эффективным. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 28 мая, 2006 Опубликовано 28 мая, 2006 · Жалоба Увы и ах, такое поведение характерно не только для AVR Embedded C++, поэтому драйвера обычно пишутся без использования возможностей ООП. Если посмотреть на это с другой стороны, то 32 байта стека и 128 циклов CPU не такая уж и большая цена за использование возможностей ООП. На 115200 с частотой следования байтов 11.52 Khz накладные расходы составят 13.3% от общей произодительности МК при частоте тактирования 11.059Mhz. Вполне терпимо.. Согласен, по этому я оставил два варианта драйвера. Для одного УСАПП буду пользоваться Си, для двух или более) - Си++ Код у Вас небезопастный, а это плохо.. Согласен, это были просто наброски) PS: избежать накладных расходов, на мой взгляд, можно в случае если скомбинировать обработку прерываний средствами inline функций, и постобработку принятых данных в основном цикле программы методами классов. Только такая организация потребует строго определенной структуры программы, что сделает Ваш драйвер менее универсальным, хотя и более эффективным. Будем пробовать) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться