WinAvr в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Ответить
Первый раз сказал Мяу!
Сообщения: 22
Зарегистрирован: Сб дек 26, 2015 22:28:05

Сообщение Andrey3885 »

Alexeyslav писал(а):Компилятор не настолько умный чтобы рассматривать все возможные ветви условий, тем более ваша переменная могла быть изменена где-то в коде по пути от инициализации до условия. Да и условие могло быть и посложнее.
Компиляторы такие ситуации не разруливают настолько глубоко, этим занимаются отдельные статические анализаторы кода.
Если хотите чтобы начальное значение Х было равно 5 то так и сделайте. Такая инициализация значением переменной X как у вас сомнительна в плане надёжности, хоть алгоритм и очевиден с первого взгляда. Но не всегда будет так.
В даном примере я с Вами согласен, но в реальном проэкте у меня задача немного сложнее. Вместо X мне нада прочесть с памяти программ значения структур меню. Переменная status - переменная флагов, которая получает своё значение от функции управления Console(), и в другом месте функции не изменяется. В момент входа в функцию func() в переменной флагов устанавливается флаг (в примере бит 1) "флаг изменения уровня" и производится чтение параметров 0-го (корневого) уровня меню. В цикле производится перемищение по пунктам меню текущего уровня (без повторной чтения параметров уровня меню). И только когда возвращается функцией Console() значение с установленным "флагом изменения уровня" производится цтение параметров нового уровня. До этого подобные алгоритмы делал на ассемблере и для того чтобы не дублировать код при начальной инициализации и переходах между уровнями, использовалась установка "флага изменения уровня" при входе в меню. Но в отличии от ассемблера, Си сам выполняет оптимизацию, и на начальных этапах освоения особенностей програмирования на Си, предупреждения подобного рода вызывают сомнения в надёжности такого кода. На ассемблере подобный метод вопросов в плане надёжности не вызывает, и уже проверен в разных устройствах. А вот с Си пытаюсь разобраться, что я делаю не так...
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

В отличие от сообщений об ошибках, сообщения-предупреждения служат для привлечения внимания программиста к "подозрительным" местам.
Если вы не имеете аналогичных сообщений в ассемблере, то не потому, что ваш алгоритм безупречен, а потому, что ассемблер не имеет такой функции - обращать внимание на подозрительные места (да и определить такое место в ассемблере - задача та еще и для человека).
Предупреждения вообще можно отключить - будет вам полный аналог поведения ассемблера, и вы сможете спокойно спать.
А можно включить "параноидальный" режим предупреждений, и тогда сами авторы языка Керниган с Ричи вряд ли сумели бы написать код без варнингов :)))

Поэтому увидели варнинг - просмотрите код: если на самом деле компилятор прав - устраняйте проблему, если он "перебдел" - живите спокойно. Как правило, всегда можно устранить варнинг правкой кода, но не всегда это дает реально полезный эффект, если не считать за пользу спокойствие компилятора.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Первый раз сказал Мяу!
Сообщения: 22
Зарегистрирован: Сб дек 26, 2015 22:28:05

Сообщение Andrey3885 »

ARV писал(а):В отличие от сообщений об ошибках, сообщения-предупреждения служат для привлечения внимания программиста к "подозрительным" местам.
Если вы не имеете аналогичных сообщений в ассемблере, то не потому, что ваш алгоритм безупречен, а потому, что ассемблер не имеет такой функции - обращать внимание на подозрительные места (да и определить такое место в ассемблере - задача та еще и для человека).
Предупреждения вообще можно отключить - будет вам полный аналог поведения ассемблера, и вы сможете спокойно спать.
А можно включить "параноидальный" режим предупреждений, и тогда сами авторы языка Керниган с Ричи вряд ли сумели бы написать код без варнингов :)))

Поэтому увидели варнинг - просмотрите код: если на самом деле компилятор прав - устраняйте проблему, если он "перебдел" - живите спокойно. Как правило, всегда можно устранить варнинг правкой кода, но не всегда это дает реально полезный эффект, если не считать за пользу спокойствие компилятора.
Спасибо за разъяснение, именно в этом и был вопрос. При написании кода на ассемблере пытаешся сделать код максимально компактным и оптимальным с точки зрения расхода "тактов", но вот при попытке подобного подхода в Си иногда стал получать такие предупреждения.
Первый раз сказал Мяу!
Сообщения: 22
Зарегистрирован: Сб дек 26, 2015 22:28:05

Сообщение Andrey3885 »

Форумчане, прошу совет: надо передать в функцию указатель на значение типа char, при том что параметром функции является указатель на тип int. Реализовал с помощью буфера int, копирую туда значение, вызываю функцию, после чего востанавливаю значение с буфера. Какой подход будет более коректным не изменяя тип значения char?
Реклама
Эиком - электронные компоненты и радиодетали
Встал на лапы
Сообщения: 134
Зарегистрирован: Вс авг 01, 2010 16:05:25

Сообщение TICLIR »

Помогите со структурой

Код: Выделить всё

struct teme {

unsigned int ch;
unsigned int vin;
unsigned int mih;
volatile unsigned int eig;
} vremu={10,23,45,0};

void chitaem( time *vremu){ // error: expected ')' before '*' token
vremu.eig=vremu.vin+12;
}
Вот нашёл в своих старых записях, решил применить да что то не выходит пишет ошибку, но раньше компилировалось, кажется.
Помогите связать функцию и структуру?
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Что такое time и в чём отличие от teme?
Потом, vremu - указатель, поэтому доступ к элементам - либо через (*vremu).ch, либо через vremu->ch.
Поэтому так:

Код: Выделить всё

struct time {
    unsigned int ch;
    unsigned int vin;
    unsigned int mih;
    volatile unsigned int eig;
} vremu = {10,23,45,0};

void chitaem(struct time *vremu) {
    vremu->eig = vremu->vin + 12;
}
либо так:

Код: Выделить всё

typedef struct {
    unsigned int ch;
    unsigned int vin;
    unsigned int mih;
    volatile unsigned int eig;
} time;

time vremu = {10,23,45,0};

void chitaem(time *vremu) {
    vremu->eig = vremu->vin + 12;
}
Контактная информация:
Реклама
Встал на лапы
Сообщения: 134
Зарегистрирован: Вс авг 01, 2010 16:05:25

Сообщение TICLIR »

Спасибо, это просто набор букв, в котором закралась ошибочка.
А как теперь вызывать эту функцию?
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Как обычно, по имени, передавая в аргументах адрес структуры, в которой надо eig = vin + 12 проделать.
Контактная информация:
Встал на лапы
Сообщения: 134
Зарегистрирован: Вс авг 01, 2010 16:05:25

Сообщение TICLIR »

Т.е.

Код: Выделить всё

 chitaem(&vremu);
Нет как то это всё мудрёно, я наверно пойду другим путём

Код: Выделить всё

void chitaem (unsigned int* eig,unsigned int* vin){
*eig=*vin+12;
}
Это просто пример.
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Вообще, если это vremu (что за странное название, кстати?) одно, то ничто не мешает эту функцию вообще без параметров сделать.
Ну а если не одно - то красивее получается так:

Код: Выделить всё

typedef struct {
    unsigned int ch;
    unsigned int vin;
    unsigned int mih;
    volatile unsigned int eig;
} time;

time vrem0 = {10,23,45,0};
time vrem1 = {11,24,25,0};
time vrem2 = {12,42,12,0};

void chitaem(time *vr) {
    vr->eig = vr->vin + 12;
}

...
chitaem(&vrem0);
...
chitaem(&vrem1);
...
chitaem(&vrem2);
...
Плюс, если vremu (врему это время?) должно как-то со временем работать, то unsigned int для элементов структуры - это слишком, достатоно и обчного char. Всё-таки на 8бит контроллерах это существенно.

И да, интересно всё же - что скрывается под этими странными именами переменных, странно звучащими в русской транскрипции "врему", "вин", "мих", "еиг"? Просто я, например, когда пишу код, стараюсь какие-то осмысленные имена переменным давать, а тут даже близко непонятно, что это. Интригует, знаете ли.
Контактная информация:
Встал на лапы
Сообщения: 134
Зарегистрирован: Вс авг 01, 2010 16:05:25

Сообщение TICLIR »

Да я не могу придумать, какие то подходящие приблизительно по смыслу, ударил по клавиатуре пальцами что получилось то и ладно.
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Ага, а потом
TICLIR писал(а):нашёл в своих старых записях, решил применить да что то не выходит
:)
Контактная информация:
OKF
Это не хвост, это антенна
Сообщения: 1430
Зарегистрирован: Вт июн 07, 2011 08:03:18

Сообщение OKF »

Вопрос к ARV. хотя, и не только.))
Нужна быстрая реакция на прерывание. И хотелось что бы вся задача крутилась в прерывании.
Но, т.к. в задаче имеются функции, будет увеличен и пролог, что крайне нежелательно.
Собственно вопрос. Возможно ли что бы прологом/эпилогом были оформлены уже сами функции?
Т.е., что бы этот огромный пролог располагался не с самого начала обработчика?
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

Зачем крутить задачу в прерывании? Они не для этого предназначены а для быстрой реакции на внешние события.
Друг Кота
Аватара пользователя
Сообщения: 8007
Зарегистрирован: Вс ноя 14, 2010 19:24:26
Откуда: Лукалэнд

Сообщение hybroid »

Взаимоисключающие параграфы. Быстрой реакции на прерывания при раздутом прерывании не будет. Если только при условии разрешения вложенных прерываний.... и потом разгребать непонятно как работающий индусский код.
В прерывании надо быстро, как пуля, среагировать и вылететь из него. Остальное, что нужно доделать - в основном коде. Если успользуются функции в прерывании - инлайнить их в прерывание.
OKF
Это не хвост, это антенна
Сообщения: 1430
Зарегистрирован: Вт июн 07, 2011 08:03:18

Сообщение OKF »

Согласен, не красиво. Но хотелось бы ещё чего то полезного поделать...
А тогда не получается быстро обрабатывать данные получаемые в прерывании...((
Друг Кота
Аватара пользователя
Сообщения: 8007
Зарегистрирован: Вс ноя 14, 2010 19:24:26
Откуда: Лукалэнд

Сообщение hybroid »

А их там надо быстро обрабатывать? Обычно данные надо быстро получить, а разгребать можно потом. Не часто требуется на лету обрабатывать.
В общем, мало исходных данных. Точнее, их совсем нет. Что за данные, что с ними делать..
OKF
Это не хвост, это антенна
Сообщения: 1430
Зарегистрирован: Вт июн 07, 2011 08:03:18

Сообщение OKF »

А нет ли возможности принудительно запретить формирование пролога?
Т.е., что бы функции брали на себя эту заботу. Либо "не светить" функции в ISR, что аналогично?
Инлайн, как я понимаю, не гарантирует инлайн на 100%?
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич

Сообщение Alexeyslav »

И разрушить работу всей программы?
Компилятор лучше знает что туда добавлять и если у него не будет повода туда что-то добавлять(код на ассемблере, например), то ничего и не создаст.
Посмотрите дизассемблированный листинг, может там ничего такого и нет страшного.

Инлайнить функции в обработчик прерывания имеет смысл только для очень коротких функций, дальше 20...50 ассемблерных команд функции уже нет смысла инлайнить - выигрыш минимальный а цена слишком большая по сравнению с эффектом.
Контактная информация:
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

OKF писал(а):Вопрос к ARV. хотя, и не только.))
Нужна быстрая реакция на прерывание. И хотелось что бы вся задача крутилась в прерывании.
Но, т.к. в задаче имеются функции, будет увеличен и пролог, что крайне нежелательно.
Собственно вопрос. Возможно ли что бы прологом/эпилогом были оформлены уже сами функции?
Т.е., что бы этот огромный пролог располагался не с самого начала обработчика?
OKF писал(а):А нет ли возможности принудительно запретить формирование пролога?
Т.е., что бы функции брали на себя эту заботу. Либо "не светить" функции в ISR, что аналогично?
Инлайн, как я понимаю, не гарантирует инлайн на 100%?
если хотите, используйте "голый" обработчик прерываний

Код: Выделить всё

ISR(TIMER0_OVF_vect, ISR_NAKED)
в этом случае компилятор не будет генерировать ни пролог, ни эпилог функции обработчика - делайте, что хотите

если надо, чтобы функция ГАРАНТИРОВАННО инлайнилась, используйте атрибут always_inline

Код: Выделить всё

inline void my_func(void) __attribute__((always_inline)){
//}
учтите, я ответил на ваши вопросы, но что вы там при помощи этих советов накодите, будет целиком на вашей совести

P.S. кстати, static-функции достаточно неплохо инлайнятся автоматически при включении оптимизиции, особенно, если вызываются из одного места :)))
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Ответить

Вернуться в «AVR»