juvf 18 15 ноября, 2017 Опубликовано 15 ноября, 2017 · Жалоба Подскажите, что я делаю не так? так компилятор же говорит, чёрным по белому "argument of type "unsigned char __eeprom *" is incompatible with parameter of type "void const *"". прототип memcmp int memcmp ( const void * ptr1, const void * ptr2, size_t num ); 1) явно приводите всё к воиду*. 2) возможно, что char __eeprom* не сможет привестись к void*, нужно проверять, будет ли работать memcmp с (приведённым)епромом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
pittyalex 0 16 ноября, 2017 Опубликовано 16 ноября, 2017 · Жалоба так компилятор же говорит, чёрным по белому "argument of type "unsigned char __eeprom *" is incompatible with parameter of type "void const *"". прототип memcmp int memcmp ( const void * ptr1, const void * ptr2, size_t num ); 1) явно приводите всё к воиду*. 2) возможно, что char __eeprom* не сможет привестись к void*, нужно проверять, будет ли работать memcmp с (приведённым)епромом. В доках черным по белому написано, что еепром кастить нельзя. Не знаю почему, не могу понять. И что теперь делать? Странно, ведь адресное посьрансьво общее.... Самому чтоли теперь писать процедуру... Элеменьарно, конечно, но я не понимаю изза чего пртходится городить такой огород. Есть какие нибудь подсказки как правильно сравнить массив в еепроме с массивом в ОЗУ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 16 ноября, 2017 Опубликовано 16 ноября, 2017 · Жалоба Есть какие нибудь подсказки как правильно сравнить массив в еепроме с массивом в ОЗУ? Конечно есть. Не использовать __eeprom. Я вообще не понимаю, зачем эта штука нужна. У себя использую обычные указатели и делаю функции записи в EEPROM. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 18 16 ноября, 2017 Опубликовано 16 ноября, 2017 · Жалоба В доках черным по белому написано, что еепром кастить нельзя.В каких доках? Есть какие нибудь подсказки как правильно сравнить массив в еепроме с массивом в ОЗУ? ну если memcmp не взлетит, кто мешает написать свою функцию сравнения? там на пару строк коду. И что теперь делать?я попробовал memcmp - работает. Из-за чего баня загорелась? __eeprom uint8_t co[10] = "hello"; int main() { EEPROM_Unlock(); char asd[10] = "hello"; if( memcmp((void*)co, asd, 5) == 0) delayMs(1000);//сюда попадаю ... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 16 ноября, 2017 Опубликовано 16 ноября, 2017 · Жалоба На чтение EEPROM в STM8 ничем не отличается от обычной памяти. Причин чтобы не работало через приведение типов не видно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
pittyalex 0 16 ноября, 2017 Опубликовано 16 ноября, 2017 · Жалоба Господа, огромное спасибо за помощь. Почему сам не пробовал кастинг - думал что вроде как должно само преобразоваться, а потом доступа к компу не было и писал с телефона (поэтому прошу прощения за кучу очепяток). По сути, был вопрос про где чёрным по белому написано. Вот цитата из хелпа к IAR for stm8: Casting Casts between pointers have these characteristics: * Casting a value of an integer type to a pointer of a smaller type is performed by truncation * Casting a value of an integer type to a pointer of a larger type is performed by zero extension * Casting a pointer type to a smaller integer type is performed by truncation * Casting a pointer type to a larger integer type is performed by zero extension * Casting a data pointer to a function pointer and vice versa is illegal * Casting a function pointer to an integer type gives an undefined result * Casting from a smaller pointer to a larger pointer is performed by zero extension * Casting from a larger pointer to a smaller pointer is performed by truncation. * Casting _ _eeprom to another data pointer and vice versa is illegal Почему сам не писал сравнение и ковыряние в ЕЕПРОМ: да всё просто - раньше я так и делал, так у меня было сделано в предыдущих проектах, а теперь хотел воспользоватся стандартными инструментами С и IAR, но пока не получилось. Вообще, мне кажется на STM проще всего писать на АСМ, т.к. сравниваю код, что генерит компилятор и код, что напишу я в этом случае на ассемблере - раза в 1,5 более эффективно получается (иногда 10%, иногда в 2 раза и больше). Просто хотелось освоить именно чистый С... В) С# - писал, ASM - писал, С - не писал. В) Сейчас попробую с приведением типа, будет ли работать. Всё заработало в таком виде: if (memcmp((void*)ee_key_list[0], mf_key_list[i], sizeof(mf_key_list[0]) == 0)) Тогда не понял, а что в доках написано: * Casting _ _eeprom to another data pointer and vice versa is illegal И ещё раз не понял: если на входе процедуры указатель на безтиповый массив (фактически - на первый байт массива), плюс длина этого массива, используется побайтовое сравнение (а не поэлементное, т.к. в любом случае кастится к void, как я понял?? - прав ли я?), тогда почему бы автоматически любой массив не кастить к войду? Чего компилятор не понимает? Какое может быть другое поведение, кроме сравнения побайтно двух областей памяти начиная с двух указателей? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 16 ноября, 2017 Опубликовано 16 ноября, 2017 · Жалоба Вообще, мне кажется на STM проще всего писать на АСМ, т.к. сравниваю код, что генерит компилятор и код, что напишу я в этом случае на ассемблере - раза в 1,5 более эффективно получается (иногда 10%, иногда в 2 раза и больше). Глупости. Проще на Си, а не на ассемблере. На то он и Си. А то, что все существующие компиляторы для стм8 - отстой, давно известно. Тем не менее, ставить рекорды по размеру кода или времени выполнения нужно далеко не каждый день, поэтому польза от этих компиляторов безусловно есть. И ещё раз не понял: если на входе процедуры указатель на безтиповый массив (фактически - на первый байт массива), плюс длина этого массива, используется побайтовое сравнение (а не поэлементное, т.к. в любом случае кастится к void, как я понял?? - прав ли я?), тогда почему бы автоматически любой массив не кастить к войду? Чего компилятор не понимает? Какое может быть другое поведение, кроме сравнения побайтно двух областей памяти начиная с двух указателей? Кстати, указатель на войд имеет такое полезное свойство: указатель на любой другой тип данных приводится к нему и обратно автоматически и без предупреждений. Яр придумал __eeprom для удобства пользователя, наверное, но по недомыслию написал, что указатель приводить нельзя. Просто кто-то у них там не подумал как следует. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
pittyalex 0 16 ноября, 2017 Опубликовано 16 ноября, 2017 · Жалоба Глупости. Проще на Си, а не на ассемблере. На то он и Си. А то, что все существующие компиляторы для стм8 - отстой, давно известно. Тем не менее, ставить рекорды по размеру кода или времени выполнения нужно далеко не каждый день, поэтому польза от этих компиляторов безусловно есть. Кстати, указатель на войд имеет такое полезное свойство: указатель на любой другой тип данных приводится к нему и обратно автоматически и без предупреждений. Яр придумал __eeprom для удобства пользователя, наверное, но по недомыслию написал, что указатель приводить нельзя. Просто кто-то у них там не подумал как следует. Но ведь тем не менее работает. В)) И ещё, если оно так автоматически приводится, почему у меня без явного каста автоматически не привелось? Или может быть речь в мануале шла именно об автоматическом кастинге? А в ручную можно? Хз. Но по сути эта догадка совпадает с реальным положением дел: пока не было явного кастинга - приведения не было, с явным кастингом - всё заработало. Кстати, вопрос: а есть ли какая-то подсказка компилятору, что у меня массивы всегда размером меньше 256 байт, а то он не мудруствуя лукаво, чтобы посчитать индекс в двумерном массиве (размер которого априори не может превыстить 40 байт), ажно вызывает умножение 16х16, что явно избыточно в моём случае (надо посчитать 2 индекса, на это уходит куча времени и кода). Правда я ещё не включал оптимизацию, может оптимизация это всё уберёт. В любом случае, товарищи, большое спасибо за подсказку. Простейшая вещь, но когда мало знаком и не хватает знаний матчасти (программирование - лишь хобби), иногда на такие детские грабли наступаешь (детские, потому что короткие, и бьют не в лоб, а в ... на знаете сами что примерно на высоте 80 см находится у мужчины), что диву потом даёшься, как всё просто и элементарно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 16 ноября, 2017 Опубликовано 16 ноября, 2017 · Жалоба Кстати, вопрос: а есть ли какая-то подсказка компилятору, что у меня массивы всегда размером меньше 256 байт, а то он не мудруствуя лукаво, чтобы посчитать индекс в двумерном массиве (размер которого априори не может превыстить 40 байт), ажно вызывает умножение 16х16, что явно избыточно в моём случае (надо посчитать 2 индекса, на это уходит куча времени и кода). Правда я ещё не включал оптимизацию, может оптимизация это всё уберёт. Лучше бы код выложили. "Правильный" выбор типов выражений при вычислении индекса может уговорить компилятор считать более оптимально, а может и не уговорить. Умный компилятор, конечно, сам догадается. Но яр для стм8 точно не умный, как я уже упомянул выше. Хотя говорят, что яр для арма, к примеру, творит чудеса. Сам не так давно пытался заставить его использовать инструкцию MUL для умножения 8x8=16 без знака. Это почти невозможно. Не придумал ничего лучше, чем сделать функцию mul( a, b ) с ассемблерной вставкой. И да, это было необходимо, поскольку в моём случае код просто не успевал бы делать то, что нужно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 18 17 ноября, 2017 Опубликовано 17 ноября, 2017 · Жалоба Тогда не понял, а что в доках написано: * Casting _ _eeprom to another data pointer and vice versa is illegal Так это написано для недописанного __eeprom. Тема называется "Дописываем библиотеки для работы модификатора __eeprom". пока не было явного кастинга - приведения не было, с явным кастингом - всё заработало.это хз.... возможно что-то не до конца дописанно в библе с модификатором __еепром. А вообще... неявные преобразования - это зло в Си. В С++ их оставили, чтоб сишный код компилился, а вообще не рекомендуют и ввели static_cast<>, dynamic_cast<> и т.п. С++ компилятор даст ворнинг на неявное приведение типа. Избегайте неявных приведений типов, можно ногу отстрелить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 17 ноября, 2017 Опубликовано 17 ноября, 2017 · Жалоба Все эти кастинги работают пока вы указатель для чтения данных используете. Начнёте писать по нему и сразу огребёте. Для того компилятор и матерится, чтобы вы голову включили, прежде чем приведение типов сделать. это хз.... возможно что-то не до конца дописанно в библе с модификатором __еепром. Именно так. Читаем с первого сообщения темы :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
pittyalex 0 18 ноября, 2017 Опубликовано 18 ноября, 2017 (изменено) · Жалоба Лучше бы код выложили. "Правильный" выбор типов выражений при вычислении индекса может уговорить компилятор считать более оптимально, а может и не уговорить. Умный компилятор, конечно, сам догадается. Но яр для стм8 точно не умный, как я уже упомянул выше. Хотя говорят, что яр для арма, к примеру, творит чудеса. Сам не так давно пытался заставить его использовать инструкцию MUL для умножения 8x8=16 без знака. Это почти невозможно. Не придумал ничего лучше, чем сделать функцию mul( a, b ) с ассемблерной вставкой. И да, это было необходимо, поскольку в моём случае код просто не успевал бы делать то, что нужно. Вот кусок кода: if (memcmp((void*)ee_key_list[i+1], mf_key_list[i], sizeof(mf_key_list[0])) == 0) 008B3E AE000A LDW X, #?b10 008B41 BF00 LDW 0x00, X 008B43 CD8AC1 CALL ?mov_w1_w0 008B46 3F08 CLR ?b8 008B48 AE000A LDW X, #?b10 008B4B BF00 LDW 0x00, X 008B4D BE08 LDW X, ?b8 008B4F CD90B4 CALL ?mul16_x_x_w0 008B52 9093 LDW Y, X 008B54 72A90016 ADDW Y, #mf_key_list 008B58 CD8AAC CALL ?mov_w0_w1 008B5B CD8AC1 CALL ?mov_w1_w0 008B5E 3F08 CLR ?b8 008B60 AE000A LDW X, #?b10 008B63 BF00 LDW 0x00, X 008B65 BE08 LDW X, ?b8 008B67 CD90B4 CALL ?mul16_x_x_w0 008B6A 1C400A ADDW X, #0x400A 008B6D CD8AAC CALL ?mov_w0_w1[/b][/i] 008B70 CD9128 CALL memcmp 008B73 5D TNZW X 008B74 26B1 JRNE 0xB1 Всё что выделено - это всего лишь вычисление индекса в двух массивах, размер которых принципиально меньше 255. Учитывая, что индекс хранится в регичистре ?b9, а адрес ee_key_list[1] = 0x400A, Можно было бы записать: LDW X, #?b10 //3 LD A, ?b9 //2 MUL X, A //1 LDW Y, X //2 ADDW Y, #mf_key_list //4 ADDW X,#0x400A //3 CLR ?b8 //2 CALL memcmp //3 TNZW X //1 JRNE 0xB1 //2 И всё, и всего 1 вызов функции вместо 7, да и в целом короче 56 байт против 23 байт. Не считая вызова сторонних функций. Индекс массива объявлен как unsigned char i; Я понимаю, что компилятор не может догадаться, что размер массива меньше байта, поэтому индекс не может (не должен) быть больше размера массива, т.е. байта и нет необходимости выполнять 16 битное умножение, но как ему это подсказать, я не знаю. Изменено 18 ноября, 2017 пользователем pittyalex Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 18 18 ноября, 2017 Опубликовано 18 ноября, 2017 · Жалоба был код __eeprom __no_init uint16_t countStarts; //0,1 __eeprom __no_init uint16_t period; //2,3 адрес countStarts 0х1000, адрес period 0х1002 - всего занято 4 байта. добавил переменную namespace Eeprom { __eeprom __no_init uint16_t countStarts; //0,1 __eeprom __no_init uint16_t period; //2,3 __eeprom __no_init uint32_t asd; //2,3 } получилось адрес countStarts 0х1004, адрес period 0х1006 - всё съехало на 4 байта. С какого перепугу? вобщем ни как не могу переменные в еепром размещать так, как мне нужно, а ни как компилятору. Он постоянно меняет адреса переменных, от компиляции к компиляции. А без этого этот __eeprom не нужен. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 18 ноября, 2017 Опубликовано 18 ноября, 2017 · Жалоба получилось адрес countStarts 0х1004, адрес period 0х1006 - всё съехало на 4 байта. С какого перепугу? У STM8 есть отдельные функции для записи в eeprom одного байта или слова (4 байта). Запись 4 байт разом быстрее, но требует выравнивания. Вот компилятор и пытается перетасовывать переменные в памяти. Возможно не всегда удачно, так как взросление компиляторов по STM8 ещё не закончено. вобщем ни как не могу переменные в еепром размещать так, как мне нужно, а ни как компилятору. Он постоянно меняет адреса переменных, от компиляции к компиляции. А без этого этот __eeprom не нужен. Во-первых, зачем на ЯВУ знать адреса переменных? Мне вот обычно фиолетово как они расположены. Во-вторых, есть директивы, привязывающие переменные к фиксированным адресам, если уж это действительно надо, в чём есть большое сомнение. В-третьих, отхапайте весь объём EEPROM одним массивом или структурой и располагайте в каком угодно порядке данные. Но, повторюсь, ЯВУ для того и есть, чтобы не думать о такой фигне как расположение переменных в памяти. Это дело компилятора и линкера. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 18 ноября, 2017 Опубликовано 18 ноября, 2017 · Жалоба получилось адрес countStarts 0х1004, адрес period 0х1006 - всё съехало на 4 байта. С какого перепугу? вобщем ни как не могу переменные в еепром размещать так, как мне нужно, а ни как компилятору. Он постоянно меняет адреса переменных, от компиляции к компиляции. А без этого этот __eeprom не нужен. Он их по алфавиту сортирует. Сделайте одну структуру для всех переменных в eeprom, в структуре компилятор переставлять поля не станет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться