Перейти к содержанию
    

"vet" твой ответ добавил мне уверенности и синтаксическую ошибку я нашёл. Пасибо тебе в очередной раз. Правда синтаксически верная программа не всегда работает. :)

 

У меня в структуре стоял массив. Поэтому синтаксически правильно было передавать &KomG->Pict[0].

 

Подскажите если есть массив указателей на многомерные массивы.

const void __flash *symbol[maxfonts] = {&fnt0_6x8,&fnt1_8x8,&fnt2_10x10,&fnt3_11x13};

 

Приведу для примера объявление одного из массивов.

const byte __flash fnt0_6x8[224][8] = {

 

Я при работе с элементами использую арифметику. Т.е. высчитываю адрес. Ну например:

id = *(((byte*)symbol[tekfonts])+(Znak*Fonts[tekfonts][2])+iy);

 

А может можно компилятору просто указать элемент типа [][]

Наверное тогда указатель нужно привести к типу "конкретный масив".

 

И ещё один вопрос:

Как мне найти начало свободной памяти для динамических данных? Я по аналогии с Паскалем пробовал сделать так

 

TekAdrActive = malloc(SizeFree); //Выделить память

 

пишет что malloc типа void

Изменено пользователем SasaVitebsk

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И ещё один вопрос:

Как мне найти начало свободной памяти для динамических данных? Я по аналогии с Паскалем пробовал сделать так

А зачем находить начало? Просто выделяйте память под структуру..

  MYSTRUCT *mystruct;
  mystruct = malloc( sizeof( MYSTRUCT) );

 

если вас интересует численное значение адреса, его можно получить например так:

  int i;
  i = (int)malloc( 0 );

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Чувствую, что я скоро всем надоем, и отвечать мне никто не будет. :)

Но у меня уже есть прогресс! Я написал большую часть проги и откомпиллил её без ошибок!!! :)

 

Вот такой вот вопрос:

Есть объявление функции. В качестве параметра 32 битное число. Я хочу использовать его побайтно.

Могу я сделать так?

 

union uint32_u {

uint32_t dw;

uint8_t bt[4];

};

 

в вызове использовать типа: uint32_u addr;

 

а при обращении использовать unsigned long int addr.

 

Или как поступить в данном случае. Как обратится к байтам длинного числа не пребегая к операциям типа ">> 8 ...."

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Могу я сделать так?

 

union uint32_u {

uint32_t dw;

uint8_t bt[4];

};

можете, но для задания размера массива лучше использовать sizeof напр. так:

 

union uint32_u{
   long Num;
   char Arr[sizeof(long)];  
};

 

Или как поступить в данном случае. Как обратится к байтам длинного числа не пребегая к операциям типа ">> 8 ...."

uint32_u Addr;
Addr.Num = <some long number>;
for ( i = 0; i < sizeof(long); ++i)
     Addr.Arr[i] = ...;

Изменено пользователем defunct

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Есть объявление функции. В качестве параметра 32 битное число. Я хочу использовать его побайтно.

Могу я сделать так?

 

union uint32_u {

uint32_t dw;

uint8_t bt[4];

};

 

в вызове использовать типа: uint32_u addr;

 

а при обращении использовать unsigned long int addr.

 

Или как поступить в данном случае. Как обратится к байтам длинного числа не пребегая к операциям типа ">> 8 ...."

Можно, все будет работать. На AVR. Но способ этот непереносимый, т.е. нет гарантий, что этот код будет работать на другой платформе. Об этом всегда надо помнить.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Или как поступить в данном случае. Как обратится к байтам длинного числа не пребегая к операциям типа ">> 8 ...."

Кстати говоря, с большой долей вероятности при достаточном уровне оптимизации компилятор сам не будет использовать сдвиги, а просто возьмет нужный байт из регистра или из памяти. Во всяком случае, IAR так делает.

 

Вообще, очень полезно бывает смотреть на сгенерированный компилятором код, чтобы что-то там оптимизировать (если это хочется сделать). Пример:

 

unsigned char CRC(...)
{
    int crc;
    ...
    return crc ? 1 : 0;    // 0 - все в порядке, не ноль - ошибка
}

Дает совершенно правильный, но не слишком оптимальный для AVR код (на IAR). Вычисление кода возврата по return компилируется в 10 байтов.

 

Можно улучшить ситуацию, записав вот так:

 

    return (crc | (crc >> 8));    // 0 - все в порядке, не ноль - ошибка

При видимом усложнении кода получаем вместо 10-ти уже 6 байтов. Неплохо.

 

Но самое интересное будет, если переставить местами операнды и добавить лишние 0xff:

 

    return ((crc >> 8) | (crc & 0xff));    // 0 - все в порядке, не ноль - ошибка

Это компилируется всего в 4 байта, несмотря на увеличение количества операций.

 

Поэтому крайне рекомендуется при необходимости писать оптимально для конкретного процессора изучать генерируемый компилятором код. Иногда можно обнаружить совершенно неочевидные вещи.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

    return ((crc >> 8) | (crc & 0xff));    // 0 - все в порядке, не ноль - ошибка

Это компилируется всего в 4 байта, несмотря на увеличение количества операций.

 

Поэтому крайне рекомендуется при необходимости писать оптимально для конкретного процессора изучать генерируемый компилятором код. Иногда можно обнаружить совершенно неочевидные вещи.

на ассемблере для этой задачи (0- все в порядке, не 0 - ошибка crc16) требуется всего одна команда or al, ah (2 байта), поэтому при необходимости получить оптимальный код, неплохо бы изучить ассемблер конкретного процессора.. Вопрос, лишь в том оправдается ли затраченное время (немалое) на получение оптимального кода для конкретного процессора?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

    return ((crc >> 8) | (crc & 0xff));    // 0 - все в порядке, не ноль - ошибка

Это компилируется всего в 4 байта, несмотря на увеличение количества операций.

на ассемблере для этой задачи (0- все в порядке, не 0 - ошибка crc16) требуется всего одна команда or al, ah (2 байта), поэтому при необходимости получить оптимальный код, неплохо бы изучить ассемблер конкретного процессора.. Вопрос, лишь в том оправдается ли затраченное время (немалое) на получение оптимального кода для конкретного процессора?

 

Одна команда - это два байта. Вторые два байта - это, собственно, ret. Фрагмент листинга компилятора:

 

// 159

// 160 // returned 0 means CRC is OK

// 161 return ((crc >> 8) | (crc & 0xff));

OR R16, R17

 

Однозначно ассемблер надо знать, иначе смысла смотреть на генерируемый код нет никакого.

 

А насчет оправдания затрат - во первых, это надо сделать примерно раз и дальше использовать везде.

 

Во вторых, это дает результат, и не такой малый. Скажем, компилированная GCC ассемблерная часть USB драйвера от Objective Development получается на 166 байтов короче, чем она же, но скомпилированная IAR. А на написанном мной куске того же объема результат прямо противоположный, и при этом я не оптимизировал тот свой код вручную. Это - результат вполне определенной оптимизации исходника USB под GCC, о чем вполне определенно пишет автор в readme IAR порта (не уверен, появился ли тот порт на их сайте или еще нет, так как последняя версия лежит у меня, всё ход не дойдет ее дотестировать).

 

В третьих, всё подряд оптимизировать не имеет смысла. Но в ряде случаев это просто необходимо. Когда мой бут вылез за пределы 4-х кило на 200 байтов, мне пришлось приложить ряд усилий, чтобы вернуть его обратно. При этом ничем не было пожертвовано, и код не потерял читабельности. Правда, пришлось переписать часть кода Atmel, да и свой немного поправить. Зато всё осталось на C, и поддерживать его будет проще.

 

Я сам был поборником ассемблера, ибо в свое время общался больше чем с десятком-полутора разных вариантов. Но с некоторых пор мнение изменил. Проще поддерживать все же C код. А на ассемблер надо переносить только критически важные участки: ISR и т.п. Вот это реально будет экономить время на поддержке.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я вот тут подумал, чем надеяться на оптимизация компилятора не проще ли просто писать, то что требуется:

return crc != 0

Увы, нет. Сравните с предыдущим листингом:

//  160     // returned 0 means CRC is OK
//  161 //    return ((crc >> 8) | (crc & 0xff));
//  162     return crc != 0;
        OR    R16, R17
        BREQ    ??crcApplicationCheck_1
        LDI    R16, 1
        RJMP    ??crcApplicationCheck_2
??crcApplicationCheck_1:
        LDI    R16, 0
??crcApplicationCheck_2:

 

Логическая операция должна вернуть 0 или 1. А побитовая - что угодно, лишь бы не ноль.

 

Опять же, если не стоит задачи оптимизации, то писать надо то, что надо. Но иногда приходится извернуться, и это верно для любых компиляторов.

 

ЗЫ. В приведенном примере я сам поражен: и это - максимальная оптимизация в IAR??? Ведь LDI R16, 0 - совершенно излишняя команда в данном случае.

Изменено пользователем osnwt

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Увы, нет. Сравните с предыдущим листингом:

После того как написал пост - проверил, заметил, потому и удалил пост...

 

ЗЫ. В приведенном примере я сам поражен: и это - максимальная оптимизация в IAR??? Ведь LDI R16, 0 - совершенно излишняя команда в данном случае.

Да поразительно работает оптимизация..

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

После того как написал пост - проверил, заметил, потому и удалил пост...

А я думаю: что за глюки форума? В почте - вот оно, на сайте - нет ничего :) Потом уж догадался о природе вещей, но ответить Чемберлену-то нужно! (без обид - шутка - после бессонной ночи сборки очередного девайса сижу вот такой: :blink:).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Беседа была интересная. :) И я планирую проверить некоторые вещи в плане генерации.

Пока я ещё не завершил написание проекта. Обычно я сначала пишу всё, и только потом вылизываю.

И всётаки вопрос: Если применяешь с компиллер, то оптимизация описанным путём, - это же явная привязка к конкретному компилятору. И даже, вероятней всего, к его конкретной версии. :)

 

Второй вопрос. Зачем, конкретно Вы, используете два разных компилятора. Хотя бы коротко. :)

Третий. Насколько сложно программу написанную на IAR "заставить" компилится на GCC. Может у кого есть спец. ".h" файлы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если вопросы ко мне - попробую ответить.

 

Если применяешь с компиллер, то оптимизация описанным путём, - это же явная привязка к конкретному компилятору. И даже, вероятней всего, к его конкретной версии. :)

Верно, хотя это не привязка, так как таким образом оптимизированный код скомпилируется правильно и другим компилятором. Может, не столь же эффективно - но правильно. С другой стороны, то, что пишется под AVR, едва ли будет компилироваться десятками разных компиляторов под десятком платформ. С вероятностью процентов 95% этот код вообще не выйдет за пределы компьютера автора (авторов). Потому при сохранении общей наглядности кода на C такая оптимизация имеет право на жизнь, когда есть проблемы по быстродействию или объему. Мне для впихивания навороченного USB крипто-загрузчика в 4 килобайта бут-блока меги32 пришлось соптимизировать примерно 200 лишних байтов. Ясное дело, что не только таким способом - многое пришлось переписать по другому. Но результат был достигнут.

 

Причем, переписать неочевидным путем. Скажем, алгоритм дешифровки использует сравнение 4-х байтов, загружаемых через последовательные *p++ и сравниваемые с 4-мя байтами сигнатуры побайтно. Казалось бы - самое оптимальное, раз байты так извлекаются. НЕТ. Более оптимально оказалось сделать так (непортабельно из за выравнивания на других платформах, но это и не нужно): v = *(unsigned long *)p; p += 4; а потом сравнить v с unsigned long сигнатурой. Это дало приличную экономию, учитывая, что сигнатура в данном случае - константа.

 

Второй вопрос. Зачем, конкретно Вы, используете два разных компилятора. Хотя бы коротко. :)

Лично я не использую, я использую IAR. Однако, версия USB драйвера для AVR написана под GCC компилятор и ассемблер, и под них оптимизирована автором. Потому мне пришлось сравнить эти два компилятора, чтобы портировать все на IAR. Это оказалось весьма несложно - C код вообще не менялся, практически. Ассемблерный - тоже. Были символические нюансы по особенностям типа "PROGMEM меняется на __flash", и т.п. А также соглашения по вызову ассемблерных функций из C и оформлению процедур обработки прерываний.

 

И вот при всём этом при максимальных оптимизациях C-часть драйвера компилируется под IAR примерно в 750 байтов, а под GCC - 550. 200 байтов проигрывает IAR. Однако, алгоритм дешифровки, никак не оптимизированный, скомпилированный под IAR получился около 1000 байтов, а под GCC - 1400. Вот мы уже впереди.

 

Так что особенности того компилятора, под который пишем, знать всё же полезно. Однако, в худшем случае переносимый код скомпилируется и другим компилятором. А вот всякие ассемблерные вставки с разным их синтаксисом и особенностями распределения регистров уже совсем непереносимы. Для USB драйвера пришлось переписать пару процедур, вызываемых из C, именно из за другого соглашения по регистрам.

 

Третий. Насколько сложно программу написанную на IAR "заставить" компилится на GCC. Может у кого есть спец. ".h" файлы.

Если программа написана "правильно", то очень просто. Особенности относятся, как правило, к расширениям языка для поддержки FLASH, SFR, и т.п. Для примера приведу файл iarcompat.h из неопубликованной пока версии USB драйвера, который включается сишной и ассемблерной частями вместо "avr/*.h" файлов, используемых GCC. Остальные изменения не сильно принципиальны. Главное - это по всем спорным вопросам расширений писать макро, которые можно потом просто переопределить.

 

/* Name: iarcompat.h
* Project: AVR USB driver
* Author: Christian Starkjohann
* Creation Date: 2006-03-01
* Tabsize: 4
* Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH
* License: Proprietary, free under certain conditions. See Documentation.
* This Revision: $Id$
*/

/*
General Description:
This header is included when we compile with the IAR C-compiler and assembler.
It defines macros for cross compatibility between gcc and IAR-cc.

Thanks to Oleg Semyonov for his help with the IAR tools port!
*/

#ifndef __iarcompat_h_INCLUDED__
#define __iarcompat_h_INCLUDED__

#if defined __IAR_SYSTEMS_ICC__ || defined __IAR_SYSTEMS_ASM__

/* Enable bit definitions */
#ifndef ENABLE_BIT_DEFINITIONS
#   define ENABLE_BIT_DEFINITIONS    1
#endif

/* Include IAR headers */
#include <ioavr.h>
#ifndef __IAR_SYSTEMS_ASM__
#   include <inavr.h>
#endif

#define __attribute__(arg)
#define IAR_SECTION(section)    @ section

#ifndef USB_BUFFER_SECTION
#   define  USB_BUFFER_SECTION  "TINY_Z"    /* if user has not selected a named section */
#endif

#ifdef __IAR_SYSTEMS_ASM__
#   define __ASSEMBLER__
#endif

#ifdef __HAS_ELPM__
#   define PROGMEM __farflash
#else
#   define PROGMEM __flash
#endif

#define PRG_RDB(addr)   (*(PROGMEM char *)(addr))

/* The following definitions are not needed by the driver, but may be of some
* help if you port a gcc based project to IAR.
*/
#define cli()       __disable_interrupt()
#define sei()       __enable_interrupt()
#define wdt_reset() __watchdog_reset()


#endif  /* defined __IAR_SYSTEMS_ICC__ || defined __IAR_SYSTEMS_ASM__ */
#endif  /* __iarcompat_h_INCLUDED__ */

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Третий. Насколько сложно программу написанную на IAR "заставить" компилится на GCC. Может у кого есть спец. ".h" файлы.

Немножко дополню.

Кроме указанных osnwt макросов, по другому объявляются прерывания, что легко обходиться с помощью #ifdef #else #endif.

С флэшью gcc обходиться не так непринужденно как IAR, т.е. хитрые

фокусы со всякими связанными списками во флэши, требуют некоторых

ухищрений.

Вообще желательно писать с Шилдтом на столе, не привязываясь к соблазнительным фичам конкретного компилятора, и тогда переносимость будет вполне приличная.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кроме указанных osnwt макросов, по другому объявляются прерывания, что легко обходиться с помощью #ifdef #else #endif.

Да. Я просто привел то, что реально использовалось в драйвере. А прерывание там находится в ассемблерной части, что тоже потребовало определенных #if-ов для корректного его описания.

 

С флэшью gcc обходиться не так непринужденно как IAR

Как пояснил Кристиан, gcc не рассчитывался на гарвардскую архитектуру процессора. Потому чтобы поддержать в нем AVR, пришлось сделать немалые хаки.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...