Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Работа с EEPROM STM8 в IAR
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Все остальные микроконтроллеры > STM8
Страницы: 1, 2
pittyalex
Господа, огромное спасибо за помощь. Почему сам не пробовал кастинг - думал что вроде как должно само преобразоваться, а потом доступа к компу не было и писал с телефона (поэтому прошу прощения за кучу очепяток).

По сути, был вопрос про где чёрным по белому написано. Вот цитата из хелпа к 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
Цитата(pittyalex @ Nov 16 2017, 21:11) *
Вообще, мне кажется на STM проще всего писать на АСМ, т.к. сравниваю код, что генерит компилятор и код, что напишу я в этом случае на ассемблере - раза в 1,5 более эффективно получается (иногда 10%, иногда в 2 раза и больше).

Глупости. Проще на Си, а не на ассемблере. На то он и Си. А то, что все существующие компиляторы для стм8 - отстой, давно известно. Тем не менее, ставить рекорды по размеру кода или времени выполнения нужно далеко не каждый день, поэтому польза от этих компиляторов безусловно есть.

Цитата(pittyalex @ Nov 16 2017, 21:11) *
И ещё раз не понял: если на входе процедуры указатель на безтиповый массив (фактически - на первый байт массива), плюс длина этого массива, используется побайтовое сравнение (а не поэлементное, т.к. в любом случае кастится к void, как я понял?? - прав ли я?), тогда почему бы автоматически любой массив не кастить к войду? Чего компилятор не понимает? Какое может быть другое поведение, кроме сравнения побайтно двух областей памяти начиная с двух указателей?

Кстати, указатель на войд имеет такое полезное свойство: указатель на любой другой тип данных приводится к нему и обратно автоматически и без предупреждений. Яр придумал __eeprom для удобства пользователя, наверное, но по недомыслию написал, что указатель приводить нельзя. Просто кто-то у них там не подумал как следует.
pittyalex
Цитата(scifi @ Nov 16 2017, 19:58) *
Глупости. Проще на Си, а не на ассемблере. На то он и Си. А то, что все существующие компиляторы для стм8 - отстой, давно известно. Тем не менее, ставить рекорды по размеру кода или времени выполнения нужно далеко не каждый день, поэтому польза от этих компиляторов безусловно есть.


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


Но ведь тем не менее работает. В))
И ещё, если оно так автоматически приводится, почему у меня без явного каста автоматически не привелось?
Или может быть речь в мануале шла именно об автоматическом кастинге? А в ручную можно? Хз. Но по сути эта догадка совпадает с реальным положением дел: пока не было явного кастинга - приведения не было, с явным кастингом - всё заработало.

Кстати, вопрос: а есть ли какая-то подсказка компилятору, что у меня массивы всегда размером меньше 256 байт, а то он не мудруствуя лукаво, чтобы посчитать индекс в двумерном массиве (размер которого априори не может превыстить 40 байт), ажно вызывает умножение 16х16, что явно избыточно в моём случае (надо посчитать 2 индекса, на это уходит куча времени и кода). Правда я ещё не включал оптимизацию, может оптимизация это всё уберёт.

В любом случае, товарищи, большое спасибо за подсказку. Простейшая вещь, но когда мало знаком и не хватает знаний матчасти (программирование - лишь хобби), иногда на такие детские грабли наступаешь (детские, потому что короткие, и бьют не в лоб, а в ... на знаете сами что примерно на высоте 80 см находится у мужчины), что диву потом даёшься, как всё просто и элементарно.
scifi
Цитата(pittyalex @ Nov 16 2017, 23:17) *
Кстати, вопрос: а есть ли какая-то подсказка компилятору, что у меня массивы всегда размером меньше 256 байт, а то он не мудруствуя лукаво, чтобы посчитать индекс в двумерном массиве (размер которого априори не может превыстить 40 байт), ажно вызывает умножение 16х16, что явно избыточно в моём случае (надо посчитать 2 индекса, на это уходит куча времени и кода). Правда я ещё не включал оптимизацию, может оптимизация это всё уберёт.

Лучше бы код выложили. "Правильный" выбор типов выражений при вычислении индекса может уговорить компилятор считать более оптимально, а может и не уговорить. Умный компилятор, конечно, сам догадается. Но яр для стм8 точно не умный, как я уже упомянул выше. Хотя говорят, что яр для арма, к примеру, творит чудеса. Сам не так давно пытался заставить его использовать инструкцию MUL для умножения 8x8=16 без знака. Это почти невозможно. Не придумал ничего лучше, чем сделать функцию mul( a, b ) с ассемблерной вставкой. И да, это было необходимо, поскольку в моём случае код просто не успевал бы делать то, что нужно.
juvf
Цитата(pittyalex @ Nov 16 2017, 23:11) *
Тогда не понял, а что в доках написано:
* Casting _ _eeprom to another data pointer and vice versa is illegal
Так это написано для недописанного __eeprom. Тема называется "Дописываем библиотеки для работы модификатора __eeprom".

Цитата
пока не было явного кастинга - приведения не было, с явным кастингом - всё заработало.
это хз.... возможно что-то не до конца дописанно в библе с модификатором __еепром.
А вообще... неявные преобразования - это зло в Си. В С++ их оставили, чтоб сишный код компилился, а вообще не рекомендуют и ввели static_cast<>, dynamic_cast<> и т.п. С++ компилятор даст ворнинг на неявное приведение типа. Избегайте неявных приведений типов, можно ногу отстрелить.
VladislavS
Все эти кастинги работают пока вы указатель для чтения данных используете. Начнёте писать по нему и сразу огребёте. Для того компилятор и матерится, чтобы вы голову включили, прежде чем приведение типов сделать.

Цитата(juvf @ Nov 17 2017, 06:00) *
это хз.... возможно что-то не до конца дописанно в библе с модификатором __еепром.

Именно так. Читаем с первого сообщения темы sm.gif
pittyalex
Цитата(scifi @ Nov 16 2017, 20:40) *
Лучше бы код выложили. "Правильный" выбор типов выражений при вычислении индекса может уговорить компилятор считать более оптимально, а может и не уговорить. Умный компилятор, конечно, сам догадается. Но яр для стм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 битное умножение, но как ему это подсказать, я не знаю.
juvf
был код

Код
__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
Цитата(juvf @ Nov 18 2017, 16:55) *
получилось адрес countStarts 0х1004, адрес period 0х1006 - всё съехало на 4 байта. С какого перепугу?

У STM8 есть отдельные функции для записи в eeprom одного байта или слова (4 байта). Запись 4 байт разом быстрее, но требует выравнивания. Вот компилятор и пытается перетасовывать переменные в памяти. Возможно не всегда удачно, так как взросление компиляторов по STM8 ещё не закончено.

Цитата(juvf @ Nov 18 2017, 16:55) *
вобщем ни как не могу переменные в еепром размещать так, как мне нужно, а ни как компилятору. Он постоянно меняет адреса переменных, от компиляции к компиляции.
А без этого этот __eeprom не нужен.

Во-первых, зачем на ЯВУ знать адреса переменных? Мне вот обычно фиолетово как они расположены.
Во-вторых, есть директивы, привязывающие переменные к фиксированным адресам, если уж это действительно надо, в чём есть большое сомнение.
В-третьих, отхапайте весь объём EEPROM одним массивом или структурой и располагайте в каком угодно порядке данные.

Но, повторюсь, ЯВУ для того и есть, чтобы не думать о такой фигне как расположение переменных в памяти. Это дело компилятора и линкера.
AHTOXA
Цитата(juvf @ Nov 18 2017, 18:55) *
получилось адрес countStarts 0х1004, адрес period 0х1006 - всё съехало на 4 байта. С какого перепугу?

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

Он их по алфавиту сортирует.
Сделайте одну структуру для всех переменных в eeprom, в структуре компилятор переставлять поля не станет.
juvf
Цитата(VladislavS @ Nov 18 2017, 22:10) *
Во-первых, зачем на ЯВУ знать адреса переменных? Мне вот обычно фиолетово как они расположены.
В еепром кофигурацию прибора (адрес свой, адрес сервера, всякие периоды, коефициенты и т.п.). Я вычитываю в ПК дамп памяти и в пк разбераю - что есть что, также дамп из пк записываю в мк. Нужно знать, где и что.

Цитата
Во-вторых, есть директивы, привязывающие переменные к фиксированным адресам

#pragma location = 0x100C
не сработала эта деректива с __еепром

Цитата
Сделайте одну структуру для всех переменных в eeprom, в структуре компилятор переставлять поля не станет.
Да, так и придется делать. Спасибо
scifi
Цитата(pittyalex @ Nov 18 2017, 12:27) *
но как ему это подсказать, я не знаю.

Вернее, возможно ли это в принципе. Скорее всего нет, конечно. Я бы не стал тратить на это время. Если реально поджимает, программирование на ассмблере куда реалистичнее. Всё-таки основное свойство компилятора - выдавать корректный код, и яр для стм8 с этим справляется. Выдавать более оптимальный код - это следующая задача, и руки у них до этого не дошли, очевидно. Кстати, яр для Coldfire может отлично оптимизировать, но при этом иногда выдаёт нерабочикй код (md5, к примеру) laughing.gif
pittyalex
Цитата(juvf @ Nov 19 2017, 07:47) *
В еепром кофигурацию прибора (адрес свой, адрес сервера, всякие периоды, коефициенты и т.п.). Я вычитываю в ПК дамп памяти и в пк разбераю - что есть что, также дамп из пк записываю в мк. Нужно знать, где и что.


#pragma location = 0x100C
не сработала эта деректива с __еепром

Да, так и придется делать. Спасибо


Попробовал сделать по стандартной схеме:

__eeprom __no_init uint16_t countStarts @0x4030; //0,1
__eeprom __no_init uint16_t period@ 0x4040; //2,3


И всё заработало.
А у вас что за камень, где еепром с адреса 0х1000??? Может поэтму у вас компилятор отказался выполнять такую директиву? Стандартно у СТМ8 адрес 0х1000 попадает в RAM, а еепром начинается с 0х4000, флеш с 0х8000, так что я так и не понял, куда это вы хотели писать... на всех стм8 вроде как область памяти 0х1000 не задействована (ну нет у них 4кБ ОЗУ, или я не помню, может в самых старших моделях).
razrab83
У меня @0x4030 - такой "стандартный" способ не работает, не знаю почему

Код
__eeprom __no_init uint16_t countStarts @0x1004;

ошибка компилятора
Цитата
Error[Li005]: no definition for "countStarts" [referenced from C:\Users\stm8\stm8L_sh\Debug\Obj\main.o]


Камень stm8l051. см рис. Без явного указания адреса компилятор сам делает мэп в область 0х1000
Код
"P6-P8":                                   0x19
.eeprom.noinit      uninit   0x001000    0x10  varInEeprom.o [1]
  .eeprom.noinit      uninit   0x001010     0x2  varInEeprom.o [1]
scifi
Цитата(pittyalex @ Nov 19 2017, 20:56) *
Попробовал сделать по стандартной схеме:

__eeprom __no_init uint16_t countStarts @0x4030; //0,1
__eeprom __no_init uint16_t period@ 0x4040; //2,3

И всё заработало.

Не понимаю я, зачем нужны все эти выкрутасы.
CODE
struct eeprom_layout
{
int i;
float f;
char str[16];
};

struct eeprom_layout volatile* const eeprom = (void volatile*)0x4000;

void f(void)
{
int j = eeprom->i;
jcxz
Цитата(pittyalex @ Nov 18 2017, 11:27) *
Я понимаю, что компилятор не может догадаться, что размер массива меньше байта, поэтому индекс не может (не должен) быть больше размера массива, т.е. байта и нет необходимости выполнять 16 битное умножение, но как ему это подсказать, я не знаю.

А какой версией IAR это скомпилено?
Предполагаю что старой (v2.xx) и без оптимизации.
У меня подобный код (с кучей 16-битных операций) генерит старый v2.20 и с выключенной оптимизацией.
Со включенной оптимизацией уже гораздо лучше. А новый IAR (3.с чем-то) генерит гораздо лучше.
juvf
Цитата
struct eeprom_layout volatile* const eeprom = (void volatile*)0x4000;
-это даже не компиляется. ))

Цитата(scifi @ Nov 20 2017, 11:38) *
Не понимаю я, зачем нужны все эти выкрутасы.
за тем, что еппром != озу. ваш код будет работать с переменной в ОЗУ. А 0х4000 (или 0х1000) - это епром.

scifi
Цитата(juvf @ Nov 20 2017, 14:20) *
-это даже не компиляется. ))

Сочувствую. У меня компиляется.

Цитата(juvf @ Nov 20 2017, 14:20) *
за тем, что еппром != озу. ваш код будет работать с переменной в ОЗУ. А 0х4000 (или 0х1000) - это епром.

Снова сочувствую, у меня работает. Прежде чем будет новая порция негатива, уточню, что для записи в EEPROM использую специально для этого сделанные функции. Зачем их прятать за оператором присваивания, снова не пойму.
VladislavS
Цитата(scifi @ Nov 20 2017, 15:02) *
Зачем их прятать за оператором присваивания, снова не пойму.

Затем же за чем придумали языки высокого уровня.
juvf
Цитата(scifi @ Nov 20 2017, 17:02) *
Прежде чем будет новая порция негатива
где вы видите негатив?

Цитата
, уточню, что для записи в EEPROM использую специально для этого сделанные функции. Зачем их прятать за оператором присваивания, снова не пойму.

ах да, сорри, проглядел ваш const.

Речь идет о том, как разместить переменные по заданному адресу в флеше с модификатором __eeprom, вы взамен переменных предлагаете константные переменные . Что к чему?
scifi
Цитата(juvf @ Nov 21 2017, 12:16) *
ах да, сорри, проглядел ваш const.

Речь идет о том, как разместить переменные по заданному адресу в флеше с модификатором __eeprom, вы взамен переменных предлагаете константные переменные . Что к чему?

Вы много чего ещё проглядели.
juvf
Цитата(scifi @ Nov 21 2017, 16:19) *
Вы много чего ещё проглядели.

Это вы проглядели о чем речь и не в тему постите
pittyalex
Цитата(jcxz @ Nov 20 2017, 10:20) *
А какой версией IAR это скомпилено?
Предполагаю что старой (v2.xx) и без оптимизации.
У меня подобный код (с кучей 16-битных операций) генерит старый v2.20 и с выключенной оптимизацией.
Со включенной оптимизацией уже гораздо лучше. А новый IAR (3.с чем-то) генерит гораздо лучше.

С выключенной оптимизацией и самая последняя версия.
jcxz
Цитата(pittyalex @ Nov 22 2017, 23:36) *
С выключенной оптимизацией и самая последняя версия.

Хм... Включать не пробовали? laughing.gif
pittyalex
Цитата(jcxz @ Nov 23 2017, 08:48) *
Хм... Включать не пробовали? laughing.gif

Нет, после включения оптимизации иногда код понять совершенно не возможно, да и не всегда потом, говорят, работает. Пока места хватает и производительности, не вижу смысла включать. В) ХОтя если будет время, надо будет на том же самом месте эксперимент поставить. Спасибо за "наводку".
jcxz
Цитата(pittyalex @ Nov 23 2017, 21:28) *
Нет, после включения оптимизации иногда код понять совершенно не возможно, да и не всегда потом, говорят, работает. Пока места хватает и производительности, не вижу смысла включать. В) ХОтя если будет время, надо будет на том же самом месте эксперимент поставить. Спасибо за "наводку".

Периодически включать оптимизацию полезно даже при написании/отладке: вылезают скрытые баги (сам на днях ещё раз убедился).
И если при включении полной оптимизации код перестаёт работать, это в 99% говорит не о багах оптимизатора, а о багах программы.
Если как Вы говорите "после включения оптимизации иногда код понять совершенно не возможно", то это говорит о том, что оптимизирует он хорошо rolleyes.gif
scifi
Цитата(pittyalex @ Nov 23 2017, 22:28) *
Нет, после включения оптимизации иногда код понять совершенно не возможно

А зачем его понимать? Привыкайте не заглядывать в дизассемблер - сон станет спокойнее и глубже, уровень стресса понизится, производительность труда повысится, волосы станут мягче и шелковистей biggrin.gif
juvf
Цитата(scifi @ Nov 24 2017, 13:03) *
А зачем его понимать? Привыкайте не заглядывать в дизассемблер - сон станет спокойнее и глубже, уровень стресса понизится, производительность труда повысится, волосы станут мягче и шелковистей biggrin.gif

Троль!!! ))
pittyalex
Цитата(scifi @ Nov 24 2017, 08:03) *
А зачем его понимать? Привыкайте не заглядывать в дизассемблер - сон станет спокойнее и глубже, уровень стресса понизится, производительность труда повысится, волосы станут мягче и шелковистей biggrin.gif

А слышали такое слово - отладка? Хотя согласен, необходимость залезть глубоко-глубоко бывает редко... но метко в)
scifi
Цитата(pittyalex @ Nov 24 2017, 23:45) *
А слышали такое слово - отладка? Хотя согласен, необходимость залезть глубоко-глубоко бывает редко... но метко в)

Хотите интересных историй? Их есть у нас. GCC и опция -flto. Это когда код из разных исходников смешивается в жуткий винегрет. Таки да, отладчик и дизассемблер помогли определить, что нужно было добавить задержку там, где надо. Без этой оптимизации задержка получалась из-за неоптимальности сгенерированного кода.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.