|
Keil Оптимизатор |
|
|
3 страниц
1 2 3 >
|
 |
Ответов
(1 - 33)
|
Jan 16 2012, 18:43
|
Местный
  
Группа: Участник
Сообщений: 218
Регистрация: 24-06-10
Пользователь №: 58 127

|
Цитата(scifi @ Jan 16 2012, 22:08)  А почему это проблема? Если выбрасывает, значит они не нужны. Вот пример кода. Заполняем массив Buf_RS485 и отправляем его в UART. Первый байт в массиве определяет его длинну. Первые 2 строки после case00: копируют некие данные известной длинны. Поэтому в следующей строке эта длинна и записывается. Далее, если есть Cnt_sob, то туда еще кучка всего вписывается и другая длинна перезаписывается. Таким образом отправляется либо короткий, либо более длинный пакет. Так вот 3 строку оптимизатор игнорирует и пакет отправляется с неверной длинной! Код vu8 Buf_RS485[256]; // Глобальная
void sw_get(void) { u32 i, j, k, u;
switch(GetSet) {
case 0x00: Pool=1; RX_RS485=1; memcpy((char*)Buf_RS485+1,Mac_mas_bcd,4); memcpy((char*)Buf_RS485+5,Mac_sl_bcd,4); u=9; Buf_RS485[0]=u-1;
if(Cnt_sob) { j=EE_rd_byte(UK_WRS); if(j>=Cnt_sob) k=j-Cnt_sob; else k=KOL_BUF-(Cnt_sob-j); k=k*LEN_SOB+BAZA_S; i=0; EE_rd_nbyte(k,Buf_tmp,64); Buf_tmp[64]=0; k=strlen((char*)Buf_tmp); k=k-6; Buf_RS485[u++]=k|0x40; for(i=0; i<12; i=i+2,u++) Buf_RS485[u]=((Buf_tmp[i]-0x30)<<4)|((Buf_tmp[i+1]-0x30)&0xF); for(i=0; i<(k-6); i++) Buf_RS485[u++]=Buf_tmp[i+12]; Buf_RS485[0]=u-1; }
SEND_RS485; return; ......... }
Сообщение отредактировал IgorKossak - Jan 17 2012, 08:12
Причина редактирования: [code]
|
|
|
|
|
Jan 16 2012, 19:07
|
Местный
  
Группа: Участник
Сообщений: 218
Регистрация: 24-06-10
Пользователь №: 58 127

|
Цитата(Genadi Zawidowski @ Jan 16 2012, 22:57)  Несовсем понятно о какой строчке идёт речь. Можекте пометить её в исходнике? Угу. Пометил. Вот эта имелась ввиду: Buf_RS485[0]=u-1;
Сообщение отредактировал vlad_new - Jan 16 2012, 19:09
|
|
|
|
|
Jan 16 2012, 19:51
|
Местный
  
Группа: Участник
Сообщений: 218
Регистрация: 24-06-10
Пользователь №: 58 127

|
Цитата(scifi @ Jan 16 2012, 23:34)  Этот код какой-то кривой. Например, переменная 'char Buf_RS485;' используется как массив. Что это? Неточно запостили? Будьте любезны постить реальный код. Кто знает, что Вы там ещё переиначили? И лучше с отступами, а также обрамлять тегами (code)(/code). Вы подозреваете баг в компиляторе, а я подозреваю баг в программе. Чаще бывает второе. Уже подправил. Реальный код слишком длинный. К тому же похожие проблеммы с оптимизатором не редки. И как правило когда индекс =0, или он const. Иногда помагало обозвать переменную индекса массива как static. Но вот в этом куске бубны с танцами не помогли.
Сообщение отредактировал vlad_new - Jan 16 2012, 19:52
|
|
|
|
|
Jan 16 2012, 20:03
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(vlad_new @ Jan 16 2012, 23:51)  Уже подправил. Реальный код слишком длинный. К тому же похожие проблеммы с оптимизатором не редки. И как правило когда индекс =0, или он const. Иногда помагало обозвать переменную индекса массива как static. Но вот в этом куске бубны с танцами не помогли. Это глюки в программе с вероятностью 99%. Поскольку реальный код видеть нет возможности, то больше сказать нечего. Даже если бы был реальный код, было бы слишком трудно в нём разобраться, так как написан он (если судить по показанному отрывку) не самым лучшим образом, мягко говоря. Update: Забыл добавить. О глюках судят по результатам выполнения программы. Например, если содержимое пакета данных на проводе отличается от ожидаемого. Если Вы смотрите на содержимое переменных в отладчике и видите неожиданные значения - не факт, что это глюк. На высоких уровнях оптимизации бывает так, что данные отладчика весьма слабо коррелируют с исходным кодом. И вообще отлаживать удобнее на самом низком уровне оптимизации.
|
|
|
|
|
Jan 16 2012, 20:12
|
Местный
  
Группа: Участник
Сообщений: 218
Регистрация: 24-06-10
Пользователь №: 58 127

|
Цитата(scifi @ Jan 17 2012, 00:03)  Это глюки в программе с вероятностью 99%. Поскольку реальный код видеть нет возможности, то больше сказать нечего. Даже если бы был реальный код, было бы слишком трудно в нём разобраться, так как написан он (если судить по показанному отрывку) не самым лучшим образом, мягко говоря. Да отступы почему то здесь не выходят, хотя в режиме редактирования я их вижу. А на счет глюков в программе: ну так она же работает если без оптимизатора или Buf_RS485 описать как vu8 ( volatile unsigned char ), но тогда в сотнях местах приходится вписывать явное преобразование типов. memcopy((char*)Buf_RS485,.... ) Updete: Да я в таких случиях смотрю код ассемблера. А о веревке: Так и есть другое устройство принимает пакет с ошибочной длинной.
Сообщение отредактировал vlad_new - Jan 16 2012, 20:18
|
|
|
|
|
Jan 16 2012, 20:17
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763

|
Цитата(vlad_new @ Jan 16 2012, 22:12)  Да отступы почему то здесь не выходят, хотя в режиме редактирования я их вижу. Потому что Вы не оформили свой код в теги [сode] [/сode] Если бы оформили - все бы отсупало: Код с начала с отступом 8 пробелов
|
|
|
|
|
Jan 16 2012, 20:20
|
Местный
  
Группа: Участник
Сообщений: 218
Регистрация: 24-06-10
Пользователь №: 58 127

|
Цитата(Allregia @ Jan 17 2012, 00:17)  Потому что Вы не оформили свой код в теги [сode] [/сode] Если бы оформили - все бы отсупало: Код с начала с отступом 8 пробелов Не знал что так надо. Век живи век учись. Ща попробую.
|
|
|
|
|
Jan 16 2012, 20:24
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(vlad_new @ Jan 17 2012, 00:12)  А на счет глюков в программе: ну так она же работает если без оптимизатора или Buf_RS485 описать как vu8 ( volatile unsigned char ), но тогда в сотнях местах приходится вписывать явное преобразование типов. memcopy((char*)Buf_RS485,.... ) Подобные симптомы свидетельствуют отнюдь не в пользу версии о правильности программы, а совсем даже наоборот. Цитата(scifi @ Jan 17 2012, 00:20)  Зачем вообще включаете оптимизацию? Если работает - не трогайте. Не открывайте ящик Пандоры. Есть большой класс ошибок, чувствительных к уровню оптимизации. Они Вам нужны? Странный совет. Правильнее было бы не выключать оптимизацию, дабы по мере написания программы выгребать содержимое ящика.
|
|
|
|
|
Jan 16 2012, 20:30
|
Местный
  
Группа: Участник
Сообщений: 218
Регистрация: 24-06-10
Пользователь №: 58 127

|
Цитата(aaarrr @ Jan 17 2012, 00:20)  Подобные симптомы свидетельствуют отнюдь не в пользу версии о правильности программы, а совсем даже наоборот. Естественно. Внешний массив и обязан быть volatile, тем более что он используется в прерываниях. Ну так я и спрашивал как бы сделать так, чтоб в стандартные библиотеки передовать тип volatile без явного преобразования типа повсеместно. Может через какой нибудь typedef переопределить типы параметров в библиотеке. А может еще какие то другие есть решения.
|
|
|
|
|
Jan 16 2012, 20:32
|
Местный
  
Группа: Участник
Сообщений: 218
Регистрация: 24-06-10
Пользователь №: 58 127

|
Цитата(aaarrr @ Jan 17 2012, 00:24)  Подобные симптомы свидетельствуют отнюдь не в пользу версии о правильности программы, а совсем даже наоборот.
Странный совет. Правильнее было бы не выключать оптимизацию, дабы по мере написания программы выгребать содержимое ящика. В KEIL-е без оптимизатора на код смотреть противно. Да и скорость почти 2 раза ниже.
|
|
|
|
|
Jan 16 2012, 20:36
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(vlad_new @ Jan 17 2012, 00:30)  Естественно. Внешний массив и обязан быть volatile, тем более что он используется в прерываниях. Ну так я и спрашивал как бы сделать так, чтоб в стандартные библиотеки передовать тип volatile без явного преобразования типа повсеместно. Может через какой нибудь typedef переопределить типы параметров в библиотеке. А может еще какие то другие есть решения. Можно тупо объявить указатель на этот массив и использовать его в вызовах библиотечных функций: Код char* const nv_Buf_RS485 = (char*)Buf_RS485; Но вообще такие проблемы не возникают, если изначально построить программу вменяемым образом. Цитата(vlad_new @ Jan 17 2012, 00:32)  В KEIL-е без оптимизатора на код смотреть противно. Да и скорость почти 2 раза ниже. Лучше не начинайте. А то я начну рассказывать, какие эмоции вызывает Ваш код :-)
|
|
|
|
|
Jan 16 2012, 20:51
|
Местный
  
Группа: Участник
Сообщений: 218
Регистрация: 24-06-10
Пользователь №: 58 127

|
Цитата(scifi @ Jan 17 2012, 00:36)  Можно тупо объявить указатель на этот массив и использовать его в вызовах библиотечных функций: Код char* const nv_Buf_RS485 = (char*)Buf_RS485; Но вообще такие проблемы не возникают, если изначально построить программу вменяемым образом. Лучше не начинайте. А то я начну рассказывать, какие эмоции вызывает Ваш код :-) Думал я про указатель. Иногда так и делаю. Код нормальный с точки зрения 8 битных процессоров, где указатель является очень сложной конструкцией и работает через библиотеки жутко медленно. ARM-наоборот. Ему только указатели и подавай. Да я собственно и не претендовал на программиста. На перелопачивание СРМа и MS-DOSа меня в свое время хватало, а Андроид писать и не собираюсь. Но в любом случае, как я Вас понял, пороблемма снимается изменением стиля работы с буферами. Типа заводим буфер и сразу на него указатель. А про индексы на всегда збываем.  PS: Подредактировано.
Сообщение отредактировал vlad_new - Jan 16 2012, 21:09
|
|
|
|
|
Jan 16 2012, 21:08
|
Местный
  
Группа: Участник
Сообщений: 218
Регистрация: 24-06-10
Пользователь №: 58 127

|
Цитата(scifi @ Jan 17 2012, 01:05)  Да, забыл. Можно просто макрос. Ну и я переврал немного с указателем: не нужно его делать const, иначе он ничем не лучше volatile - требует приведения типа. Вот только хотел спросить про const  Я подредактировал предыдущее сообщение. Сенкю.
|
|
|
|
|
Jan 16 2012, 21:23
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(vlad_new @ Jan 17 2012, 00:51)  Но в любом случае, как я Вас понял, пороблемма снимается изменением стиля работы с буферами. Типа заводим буфер и сразу на него указатель. А про индексы на всегда збываем.  Позволите позанудствовать немного? Если преобразование типов действительно необходимо, то лучше выполнить его в момент вызова, а не заводить левый указатель. Если таких преобразований требуются сотни, значит программу надо переписать. С указателем можно тоже работать с использованием индекса.
|
|
|
|
|
Jan 16 2012, 21:35
|
Местный
  
Группа: Участник
Сообщений: 218
Регистрация: 24-06-10
Пользователь №: 58 127

|
Цитата(aaarrr @ Jan 17 2012, 01:23)  Позволите позанудствовать немного?
Если преобразование типов действительно необходимо, то лучше выполнить его в момент вызова, а не заводить левый указатель. Если таких преобразований требуются сотни, значит программу надо переписать. С указателем можно тоже работать с использованием индекса. Хороший совет тем, кто перелез с 8 битников на ARMы, а таких сейчас очень много. К стате почему эту строчку оптемизатор отбрасывает - понятно. Поскольку Buf_RS485[0] нигде далее не используется, она, типа, и не нужна! А то что это нужно прерыванию компелятор в упор не видит. А зря. Вот и приходится либо где нибудь влепить холостую дурь типа k=Buf_RS485[0]; либо терять скорость на куче volatile. Но вопрос то стоял не почему оптимизатор в Keil-е дурной  , а как в библиотеке подмену на volatile сделать. Хотя может это и не возможно, поскольку библиотека уже оптимизирована на регистровые операции и заставить библиотечные ф-ции сбрасывать регистровые переменные в ОЗУ вряд ли возможно. А может я и ошибаюсь. Собственно я это и хотел выяснить.
Сообщение отредактировал vlad_new - Jan 16 2012, 23:38
|
|
|
|
|
Jan 17 2012, 06:16
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Опять всё по кругу... Цитата(vlad_new @ Jan 17 2012, 01:35)  К стате почему эту строчку оптемизатор отбрасывает - понятно. Поскольку Buf_RS485[0] нигде далее не используется, она, типа, и не нужна! Абсолютно верно. Цитата(vlad_new @ Jan 17 2012, 01:35)  А то что это нужно прерыванию компелятор в упор не видит. А зря. Компилятор вообще много чего не видит и не должен видеть. Вы как будто пытаетесь ему приписать роль этакого телепата-волшебника, угадывающего намерения программиста. А программист на что? Цитата(vlad_new @ Jan 17 2012, 01:35)  Вот и приходится либо где нибудь влепить холостую дурь типа k=Buf_RS485[0]; либо терять скорость на куче volatile. Лепить холостую дурь не надо. А вот одно из применений volatile - для переменных, используемых как в основном потоке, так и в прерывании. Действительно, каждый доступ к volatile потенциально замедляет программу. Поэтому число таких доступов уменьшают до минимального необходимого уровня. Есть как минимум несколько способов это сделать. Цитата(vlad_new @ Jan 17 2012, 01:35)  Но вопрос то стоял не почему оптимизатор в Keil-е дурной  , а как в библиотеке подмену на volatile сделать. Хотя может это и не возможно, поскольку библиотека уже оптимизирована на регистровые операции и заставить библиотечные ф-ции сбрасывать регистровые переменные в ОЗУ вряд ли возможно. Вопрос ставится некорректно. Стандартная библиотека описана в стандарте языка Си. То, что Вы предлагаете, по сути меняет семантику библиотечных функций, то есть это будет уже не стандартная библиотека. Ну и флаг Вам в руки: напишите свою библиотеку и используйте её. Цитата(vlad_new @ Jan 17 2012, 01:35)  А может я и ошибаюсь. Собственно я это и хотел выяснить. Вы ошибаетесь :-) Налицо все признаки ужасно структурированной программы. Отсюда и лезут все эти косяки. По неопытности бывает, конечно. У меня в начале тоже программы были не фонтан.
|
|
|
|
|
Jan 17 2012, 17:07
|
Местный
  
Группа: Свой
Сообщений: 352
Регистрация: 13-08-11
Из: Воронеж
Пользователь №: 66 710

|
Продолжу от лица неопытных новичков Можно было бы конечно продублировать все библиотечные функции своими аналогами, внутри которых заводятся локальные переменные нужных типов, им присваиваются значения параметров и с ними вызываются библиотечные функции. Но мне кажется, это несколько коряво, хотя как лучше - не знаю. Простейший пример из практики - преобразование числа в строку. Мне было проще написать эту функцию самому, чем копаться в библиотеках. Она принимает аргумент типа int. А мне надо вызывать её и с int и с char. Два решения лежат на поверхности: 1 - написать дубль этой же функции, но принимающий char 2 - заводить лишнюю переменную int куда присваивать нужный char, и с ним вызывать функцию Оба решения мне не нравятся. Но как сделать красивее - не придумал. Использование указателя не только не помогло, но и таит ошибку при исполнении.
|
|
|
|
|
Jan 17 2012, 17:22
|
Местный
  
Группа: Свой
Сообщений: 352
Регистрация: 13-08-11
Из: Воронеж
Пользователь №: 66 710

|
Хороший вопрос!  Я сначала написал, а потом начал что-то вспоминать про "неявное преобразование типов" и т.п. Будете смеяться, но не помню, почему я был вынужден так изголяться... Или там передавался наоборот указатель на int... ЗЫ щас попробую найти код и посмотреть  Точно, принимаю указатель  Чтобы переменная изменялась а не передалась по значению и все. Код //-----------------------------------------------------------------------------------------------
char count_of_order(unsigned int *n, unsigned int order) { char res = 0;
while (*n >= order) { *n = *n - order; res++; }
return res; } //-----------------------------------------------------------------------------------------------
char *int_to_string(char *s, unsigned int n) { char *begin = s; char digit;
if((digit = count_of_order(&n, 10000)) || s!=begin) *s++ = '0' + digit; if((digit = count_of_order(&n, 1000)) || s!=begin) *s++ = '0' + digit; if((digit = count_of_order(&n, 100)) || s!=begin) *s++ = '0' + digit; if((digit = count_of_order(&n, 10)) || s!=begin) *s++ = '0' + digit;
*s++ = '0' + n;
return s; } //----------------------------------------------------------------------------------------------- а в другом месте нужен вызов с указателем на char Код //-----------------------------------------------------------------------------------------------
char *GPS_end_of_string(char *begin, char *end) { char *d; char chek_summ = 0; unsigned int int_chek_summ;
for(d=begin+1; d<end; d++) chek_summ = chek_summ^*d; int_chek_summ = chek_summ;
*d++ = GPS_char_multiply; *d++ = '0' + count_of_order(&int_chek_summ, 16); *d++ = '0' + int_chek_summ; *d++ = GPS_char_enter; *d++ = GPS_char_return; *d++ = 0;
return d; } //----------------------------------------------------------------------------------------------- ЗЫ вышеприведенный код содержит ошибку - это не финальная редакция, я её потом исправил - тут неправильно пишутся буквы 16-ричной строки числа, поскольку A, B и т.д. идут не сразу после "9" в таблице символов  Но на принципиальном вопросе это не отражается, а его напомню кратко - нам надо передавать не числовое значение переменной в функцию, а указатель на неё, чтобы функция в процессе своего выполнения изменяла этот параметр. А при передаче указателя на char в указатель на int он обрастет ещё соседним байтом и будет ошибка.
Сообщение отредактировал _Ivana - Jan 17 2012, 17:43
|
|
|
|
|
Jan 17 2012, 18:25
|
Местный
  
Группа: Свой
Сообщений: 352
Регистрация: 13-08-11
Из: Воронеж
Пользователь №: 66 710

|
Цитата Зачем, нет ЗАЧЕМ делить на 16 последовательным вычитанием? Можно просто написать n >> 4.  Точно! Спасибо за науку. Буду задавать больше глупых вопросов - подозреваю, что узнаю и не такое. Например, если длина кольцевого буфера равна степени 2, то инкремент его индексов делается тоже как-то проще, без прямой проверки на превышение. Но стоит поиграться размером буфера в дефайнах - и всё поломается Цитата С указателями - да, никакой автоматики не предусмотрено. Вот и я пока думаю, что либо передача переменных по значению, зато с преобразованием типов, либо по ссылке - но без преобразования...
|
|
|
|
|
Jan 19 2012, 09:26
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
Цитата(vlad_new @ Jan 19 2012, 05:04)  Я тут попробывал интерсный тип указателя к библиотекам подставлять. (void*) - свободный тип называется. Тогда все автоматом преобразуется как надо. А как надо? volatile он не отменит - все равно преобразовывать придется Цитата А что нельзя было сразу в библиотеках такой интересный тип использовать? Где надо там используется. В memcpy например Цитата Бит он и в африке бит, как его не переобзави. void - это не бит! void* вообще разименовать нельзя, не преобразовав сначала во что то осмысленное
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|