Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум разработчиков электроники ELECTRONIX.ru _ STM8 _ Работа с EEPROM STM8 в IAR

Автор: VladislavS Jul 21 2017, 20:54

Привет, любители STM!

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

CODE
int __eeprom_wait_for_last_operation(void)
{
if(FLASH_IAPSR_bit.WR_PG_DIS) return 0;
while(!FLASH_IAPSR_bit.HVOFF);
return 1;
}

void __eeprom_program_byte(uint8_t __near * dst, uint8_t v)
{
*dst = v;
}

void __eeprom_program_long(uint8_t __near * dst, uint32_t v)
{
FLASH_CR2_bit.WPRG = 1;
*(dst++) = *((uint8_t*)(&v));
*(dst++) = *((uint8_t*)(&v) + 1);
*(dst++) = *((uint8_t*)(&v) + 2);
*dst = *((uint8_t*)(&v) + 3);
}

Ну и не забывать разблокировать запись.
CODE

void EEPROM_Unlock(void)
{
FLASH_DUKR = FLASH_RASS_KEY2;
FLASH_DUKR = FLASH_RASS_KEY1;
}

void EEPROM_Lock(void)
{
FLASH_IAPSR_bit.DUL=0;
}


А дальше как обычно определяем неинициализированные и инициализированные переменные с модификатором __eeprom и компилятор сам всё сделает.
CODE
__no_init __eeprom uint8_t x;
#pragma data_alignment=4
__no_init __eeprom uint32_t y;
__no_init __eeprom uint8_t z;
__eeprom uint8_t test[10]={ 1,2,3,4,5,6,7,8,9,10 };

int main()
{
EEPROM_Unlock();
x=test[5];
z=x+1;
y=0x12345678;
EEPROM_Lock();
for(;;);
}


И даже при отладке IAR сам прошивает инициализированные __eeprom переменные вместе с кодом. Удобно.

Следует обратить внимание на следующие вещи:
- почему-то компилятор смело при оптимизации выкидывает переменные с модификатором __eeprom. Мне кажется они должны быть по умолчанию volatile как и SFR, но нет. Ну нет, так нет. В приложенном проекте пришлось обтыкать их volatile.
- STM8 32-битные переменные шьёт за один присест, но для этого они должны быть выровнены по 4. Приходится компилятору напоминать о выравнивании.
- что-то мне с ходу не удалось получить два раздельных HEX с кодом и eeprom, но у меня опыт с STM8 аж один день sm.gif Только сегодня STM8L-Discovery получил. Может кто научит?

Прикладываю проект для дискавери (STM8L152C6), может кому пригодится.
 STM8_IAR_EEPROM.rar ( 27.42 килобайт ) : 68

Автор: jcxz Jul 31 2017, 09:22

Цитата(VladislavS @ Jul 21 2017, 23:54) *
Следует обратить внимание на следующие вещи:
- почему-то компилятор смело при оптимизации выкидывает переменные с модификатором __eeprom. Мне кажется они должны быть по умолчанию volatile как и SFR, но нет. Ну нет, так нет. В приложенном проекте пришлось обтыкать их volatile.

Выкидывает вероятно потому, что у Вас в коде к ним нет обращений? И выкидывает тогда не компилятор, а компоновщик (по этой причине). И правильно делает.
"Обтыкивать" в этом случае (если они нужны, но обращений почему-то нет) нужно не volatile, а добавлять префикс __root (см. доку на IAR).
Хотя - может подумать - почему переменная описана, а обращений к ней нет? Может что-то в консерватории структуре программы неправильно построено? laughing.gif

PS: И почему у Вас инициализированные данные
__eeprom uint8_t test[10]={ 1,2,3,4,5,6,7,8,9,10 };
без модификатора const? Предполагается, что при каждом старте устройства, эти данные должны переписываться в EEPROM заново??? wacko.gif

Автор: VladislavS Jul 31 2017, 11:01

Цитата(jcxz @ Jul 31 2017, 12:22) *
Выкидывает вероятно потому, что у Вас в коде к ним нет обращений?

Как это нет? main() смотрим внимательнее.

Цитата(jcxz @ Jul 31 2017, 12:22) *
"Обтыкивать" в этом случае (если они нужны, но обращений почему-то нет) нужно не volatile, а добавлять префикс __root (см. доку на IAR).

Причём тут __root ? Обращения есть, модификатор __eeprom стоит, этого должно быть достаточно для запрета выкидывать операции с этими переменными.


Цитата(jcxz @ Jul 31 2017, 12:22) *
PS: И почему у Вас инициализированные данные
__eeprom uint8_t test[10]={ 1,2,3,4,5,6,7,8,9,10 };
без модификатора const?

А с какой стати они const? Мои переменные, захочу - изменю. EEPROM для того и нужен. Почему вы мне это решили запретить?
В принципе, процессор позволяет и во flash писать, так что, чисто теоретически, можно было бы неконстантную переменную и во flash разместить, главное с компилятором "договориться".

Цитата(jcxz @ Jul 31 2017, 12:22) *
Предполагается, что при каждом старте устройства, эти данные должны переписываться в EEPROM заново??? wacko.gif

Формально да, должен. Но если почитать докуентацию, то там будет следующее:
Цитата
.eeprom.data
Description Holds static and global initialized and zero-initialized __eeprom variables. Eeprom
data is persistent, so this section should not be included in any initialize by copy
linker directive.

То есть, компилятор генерит сегмент данных для eeprom. Что с ним делать дальше решает пользователь.
При отладке в железке или симуляторе отладчик автоматически каждый раз загружает его в eeprom - тут всё чисто.
В случае релиза мы его прошиваем ручками один раз при программировании чипа. При следующих стартах гарантии что там будет прежнее значение нет. Формально - отступление от стандарта, а реально лишь особенность, привнесённая модификатором __eeprom. Это ни хорошо, ни плохо, а так есть и удобно!


Автор: jcxz Jul 31 2017, 11:25

Цитата(VladislavS @ Jul 31 2017, 14:01) *
Как это нет? main() смотрим внимательнее.
Причём тут __root ? Обращения есть, модификатор __eeprom стоит, этого должно быть достаточно для запрета выкидывать операции с этими переменными.

И что там в main()? Смотрим внимательнее. wink.gif
Какие-то присваивания, каких-то переменных, которые потом больше нигде не используются, не передаются ни в какие функции и не присваиваются никаким volatile переменным?
Вот это и называется "переменная не используется", по этой причине компилятор/линкер имеет полное право её выкинуть.
Компилятор всё сделал правильно, а Вам стоит повышать свой уровень в написании ПО wink.gif

Цитата(VladislavS @ Jul 31 2017, 14:01) *
А с какой стати они const? Мои переменные, захочу - изменю. EEPROM для того и нужен. Почему вы мне это решили запретить?

Я Вам ничего не запрещаю, я просто читаю что у Вас там написано. А написано у Вас инструкция компилятору, что нужно разместить test в модифицируемой памяти и при старте ПО startup-код должен проинициализировать её указанным значением. Вот именно это компилятор и будет делать.
Возможно Вы именно этого и хотели. Но возможно что и нет, ибо это - одна из распространённых ошибок начинающих при описании инициализированных переменных в ОЗУ laughing.gif
Здесь как бы неясно - возможно, что в IAR ключевое слово __eeprom включает в себя неявно и префикс const, но трудно сказать.

Цитата(VladislavS @ Jul 31 2017, 14:01) *
можно было бы неконстантную переменную и во flash разместить, главное с компилятором "договориться".

"неконстантная переменная" - это нонсенс. Может быть или переменная или константа. Тут как ни договаривайся - компилятор мзду не берёт biggrin.gif

Цитата(VladislavS @ Jul 31 2017, 14:01) *
Формально да, должен. Но если почитать докуентацию, то там будет следующее:

Вполне возможно, что префикс __eeprom неявно включает в себя const. Но не факт.

Автор: VladislavS Jul 31 2017, 12:31

Цитата(jcxz @ Jul 31 2017, 14:25) *
Вот это и называется "переменная не используется", по этой причине компилятор/линкер имеет полное право её выкинуть.

Как это не используется? Она хранится в EEPROM после выключения питания! И компилятор об этом знает, я же ему об этом и указал посредством __eeprom. Я считаю это достаточным, разработчики компилятора нет. Это лишь условность, которая определена для модификатора __eeprom и я просто обратил на неё внимание, чтобы новички не попались.

Цитата(jcxz @ Jul 31 2017, 14:25) *
А написано у Вас инструкция компилятору, что нужно разместить test в модифицируемой памяти и при старте ПО startup-код должен проинициализировать её указанным значением. Вот именно это компилятор и будет делать.

Нет, не будет. Будет делать то что написано в документации, а что там написано - смотрите предыдущий пост.

Цитата(jcxz @ Jul 31 2017, 14:25) *
Возможно Вы именно этого и хотели. Но возможно что и нет,

Предлагаю подумать над вопросом почему у меня в примере инициализированные и неинициализированные переменные разной размерности и выравнивания применены.

Цитата(jcxz @ Jul 31 2017, 14:25) *
ибо это - одна из распространённых ошибок начинающих при описании инициализированных переменных в ОЗУ laughing.gif
Здесь как бы неясно - возможно, что в IAR ключевое слово __eeprom включает в себя неявно и префикс const, но трудно сказать.

Ошибка - делать умозаключение не прочитав документацию.

Цитата(jcxz @ Jul 31 2017, 14:25) *
"неконстантная переменная" - это нонсенс. Может быть или переменная или константа. Тут как ни договаривайся - компилятор мзду не берёт biggrin.gif

Или, сюрприз, http://electronix.ru/redirect.php?https://www.google.ru/search?client=opera&q=константная+переменная&sourceid=opera&ie=UTF-8&oe=UTF-8. Под "неконстантной переменной" я, возможно коряво, имел в виду, что данная переменная не относится к классу "константных переменных". Ну да, получается, что этот массив обычная переменная, только с модификатором __eeprom, который намекает компилятору что с ней надо как-то по особенному работать.

Цитата(jcxz @ Jul 31 2017, 14:25) *
Вполне возможно, что префикс __eeprom неявно включает в себя const. Но не факт.

А может почитать документацию, а не гадать?

jcxz, ну всё же, почему вы хотите EEPROM сделать const насильно? Он для того и придуман чтобы в него писать. Во так, например:

Хотелось бы посмотреть как вы будете писать в константную переменную и что вам на это компилятор скажет.

Автор: VladislavS Jul 31 2017, 14:26

Цитата(jcxz @ Jul 31 2017, 14:25) *
Тут как ни договаривайся - компилятор мзду не берёт biggrin.gif


Ну это как предложить sm.gif Следите за руками.
Размещаем переменную во FLASH. Хотите неинициализированную, хотите инициализированную, не важно.
И записываем в неё.



Упс! Компилятор даже не пискнул! Но это так, чисто поржать. sm.gif

Автор: jcxz Jul 31 2017, 15:10

Цитата(VladislavS @ Jul 31 2017, 15:31) *
Как это не используется? Она хранится в EEPROM после выключения питания! И компилятор об этом знает, я же ему об этом и указал посредством __eeprom. Я считаю это достаточным, разработчики компилятора нет. Это лишь условность, которая определена для модификатора __eeprom и я просто обратил на неё внимание, чтобы новички не попались.

Попробуйте создать константу во флешь. И присвоить её значение какой-то переменной, которая потом не используется.
Корректный оптимизирующий компилятор её не поместит в выходной образ.
Шок! да?? Ведь если следовать Вашей логике как он мог её удалить - ведь оно там хранится (переменная в ОЗУ или константа во flash - не важно).
Странно почему это разработчики компиляторов считают по другому, не находите? Может надо пересмотреть своё видение мира?
И с __eeprom всё то же самое.

Цитата(VladislavS @ Jul 31 2017, 15:31) *
Ошибка - делать умозаключение не прочитав документацию.

Странные умозаключения Вы оттуда почерпнули. И то что они противоречат логике работы оптимизирующего компилятора, Вас похоже даже не насторожило - они все дураки, я один умный biggrin.gif

Цитата(VladislavS @ Jul 31 2017, 15:31) *
Ну да, получается, что этот массив обычная переменная, только с модификатором __eeprom, который намекает компилятору что с ней надо как-то по особенному работать.

Вот, до Вас уже всё таки доходит истина! rolleyes.gif
То, как Вы описали test - это именно переменная, а не константа. Наличие данных справа от неё говорит, что она инициализированная. А инициализацией переменных в си занимается стартап-код, который выполняется при старте ПО. Вот он и должен будет при старте устройства, записать в эту переменную указанное значение.
Как уж он это будет делать - другое дело, он может например перед записью сравнить имеющиеся по этому адресу данные, и если они равны записываемым - ничего не делать.

Цитата(VladislavS @ Jul 31 2017, 15:31) *
А может почитать документацию, а не гадать?

Документацию на что? На язык си? Да, пожалуй Вам стоит её почитать laughing.gif

Цитата(VladislavS @ Jul 31 2017, 15:31) *
jcxz, ну всё же, почему вы хотите EEPROM сделать const насильно? Он для того и придуман чтобы в него писать. Во так, например:

Я ничего не хочу. Я всего лишь написал, что то как описан был Ваш массив, как бы намекает что там должно быть ключевое слово const скорей всего.
А если там реально нет этого слова, то я написал что будет делать компилятор в этом случае.

Цитата(VladislavS @ Jul 31 2017, 15:31) *
Хотелось бы посмотреть как вы будете писать в константную переменную и что вам на это компилятор скажет.

Такого бреда я делать не буду. Ибо "константная переменная" - это Ваше изобретение. Вы сами то разве не понимаете бредовость этого термина??? wacko.gif

Автор: VladislavS Jul 31 2017, 16:34

Цитата(jcxz @ Jul 31 2017, 18:10) *
А если там реально нет этого слова, то я написал что будет делать компилятор в этом случае.

И попали пальцем в небо, потому что делать этого он не будет. Почему, читайте документацию на компилятор, я уже давал цитату.

Цитата(jcxz @ Jul 31 2017, 18:10) *
Ибо "константная переменная" - это Ваше изобретение.

Рекомендую ознакомиться с трудами Бьёрна Страуструпа. Можете даже оспорить их, а я пасс, пожалуй, понаблюдаю со стороны.

PS: я тут файлик внизу оставлю, не вздумайте его читать!
 24._Constant_varyables.pdf ( 180.95 килобайт ) : 142

Автор: juvf Aug 1 2017, 11:38

2VladislavS

Цитата(jcxz @ Jul 31 2017, 14:22) *
Предполагается, что при каждом старте устройства, эти данные должны переписываться в EEPROM заново??? wacko.gif

вопрос остался. у меня тоже этот вопрос возник и не нашел(не придумал) на него ответ


и ещё вопрос.... на сколько модификатор __eeprom съедает меньше флеша, чем spl?

Автор: jcxz Aug 1 2017, 13:08

Цитата(juvf @ Aug 1 2017, 14:38) *
вопрос остался. у меня тоже этот вопрос возник и не нашел(не придумал) на него ответ

Товарищ противоречит сам себе, но даже этого не замечает. rolleyes.gif
При описании переменных, которые не должны ничем инициализироваться (даже нулями) он объявляет переменную как:
__no_init __eeprom uint8_t z;
что уже как бы намекает, что если её объявить без __no_init, то стартап-код её должен обнулить (как для обычных RAM-переменных) записью в EEPROM,
но при этом объявляет массив с начальным значением в __eeprom и упорно твердит что он не будет переписываться в EEPROM при каждом рестарте устройства.
Значит - где-то обманывает laughing.gif

Цитата(juvf @ Aug 1 2017, 14:38) *
и ещё вопрос.... на сколько модификатор __eeprom съедает меньше флеша, чем spl?

Ну так если:
__eeprom char const x[N] = {...};
то флеша ==0, только EEPROM.
А если:
__eeprom char x[N] = {...};
то как минимум N байт во флешь для хранения инициализационных данных {...} и ещё сколько-то байт на хранение процедуры записи EEPROM.

Автор: VladislavS Aug 1 2017, 14:09

Цитата(juvf @ Aug 1 2017, 14:38) *
вопрос остался. у меня тоже этот вопрос возник и не нашел(не придумал) на него ответ

Инициализированные переменные с модификатором __eeprom не будут переписываться при каждом старте программы.
jcxz не слушайте, он неадекватен. Про сегменты EEPROM в документации IAR очень хорошо всё написано.
Смотрите, в конфигурационном файле линкера это всё отлично видно
CODE
/////////////////////////////////////////////////////////////////
// Example ILINK command file for
// STM8 IAR C/C++ Compiler and Assembler.
//
// Copyright 2017 IAR Systems AB.
//
/////////////////////////////////////////////////////////////////

define memory with size = 16M;

define region TinyData = [from 0x00 to 0xFF];

define region NearData = [from 0x0000 to 0x07FF];

define region Eeprom = [from 0x1000 to 0x13FF];

define region BootROM = [from 0x6000 to 0x67FF];

define region NearFuncCode = [from 0x8000 to 0xFFFF];

define region FarFuncCode = [from 0x8000 to 0xFFFF];

define region HugeFuncCode = [from 0x8000 to 0xFFFF];


/////////////////////////////////////////////////////////////////

define block CSTACK with size = _CSTACK_SIZE {};

define block HEAP with size = _HEAP_SIZE {};

define block INTVEC with size = 0x80 { ro section .intvec };

// Initialization
initialize by copy { rw section .far.bss,
rw section .far.data,
rw section .far_func.textrw,
rw section .huge.bss,
rw section .huge.data,
rw section .huge_func.textrw,
rw section .iar.dynexit,
rw section .near.bss,
rw section .near.data,
rw section .near_func.textrw,
rw section .tiny.bss,
rw section .tiny.data,
ro section .tiny.rodata };

initialize by copy with packing = none {section __DLIB_PERTHREAD };

do not initialize { rw section .eeprom.noinit,
rw section .far.noinit,
rw section .huge.noinit,
rw section .near.noinit,
rw section .tiny.noinit,
rw section .vregs };

// Placement
place at start of TinyData { rw section .vregs };
place in TinyData { rw section .tiny.bss,
rw section .tiny.data,
rw section .tiny.noinit,
rw section .tiny.rodata };

place at end of NearData { block CSTACK };
place in NearData { block HEAP,
rw section __DLIB_PERTHREAD,
rw section .far.bss,
rw section .far.data,
rw section .far.noinit,
rw section .far_func.textrw,
rw section .huge.bss,
rw section .huge.data,
rw section .huge.noinit,
rw section .huge_func.textrw,
rw section .iar.dynexit,
rw section .near.bss,
rw section .near.data,
rw section .near.noinit,
rw section .near_func.textrw };

place at start of NearFuncCode { block INTVEC };
place in NearFuncCode { ro section __DLIB_PERTHREAD_init,
ro section .far.data_init,
ro section .far_func.textrw_init,
ro section .huge.data_init,
ro section .huge_func.textrw_init,
ro section .iar.init_table,
ro section .init_array,
ro section .near.data_init,
ro section .near.rodata,
ro section .near_func.text,
ro section .near_func.textrw_init,
ro section .tiny.data_init,
ro section .tiny.rodata_init };

place in FarFuncCode { ro section .far.rodata,
ro section .far_func.text };

place in HugeFuncCode { ro section .huge.rodata,
ro section .huge_func.text };

place in Eeprom { section .eeprom.noinit };

place in Eeprom { section .eeprom.data };

place in Eeprom { section .eeprom.rodata };

/////////////////////////////////////////////////////////////////


Цитата(juvf @ Aug 1 2017, 14:38) *
и ещё вопрос.... на сколько модификатор __eeprom съедает меньше флеша, чем spl?

Библиотеки IAR для работы с EEPROM какие-то монстроидные. Прикладываю .map с моего примера. Вроде как 199 байт занимает.
 st8test.zip ( 2.45 килобайт ) : 48


Автор: jcxz Aug 1 2017, 15:23

Цитата(VladislavS @ Aug 1 2017, 17:09) *
Смотрите, в конфигурационном файле линкера это всё отлично видно

Товарищ одыкватный, в какую из приведённых в Вашей портянке секций компоновщика попадает ваше творение строкой ниже ?:
__eeprom uint8_t test[10]={ 1,2,3,4,5,6,7,8,9,10 };
и почему?

Автор: DS Aug 1 2017, 16:02


Прекратите хамить собеседнику. При повторении будет предупреждение.


Автор: VladislavS Aug 1 2017, 16:11

Инициализированные переменные с модификатором __eeprom попадут в секцию .eeprom.data и будут размещены линкером в региона Eeprom. И всё это согласно "IAR C/C++ Development Guide Compiling and Linking for the STMicroelectronics STM8 Microcontroller Family" страница 372.

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

К сообщению приложил HEX с прошивкой, полученной из этого проекта. Найдите там во FLASH последовательность 1,2,3,4,5,6,7,8,9,10 которой по вашему при старте должен инициализироваться массив.

Страуструпа то переспорили?

 stm8_eeprom.zip ( 824 байт ) : 36





Автор: Эдди Aug 1 2017, 16:19

Подтверждаю, никаких const писать не надо. http://electronix.ru/redirect.php?https://github.com/eddyem/STM8_samples/blob/master/1-wire/onewire.c, ничего при старте не копируется.

Автор: VladislavS Aug 1 2017, 16:34

Цитата(Эдди @ Aug 1 2017, 19:19) *
Подтверждаю, никаких const писать не надо.

Ну не надо так категорично. const применять надо там где надо, а где не надо - не надо sm.gif
Представьте себе ситуацию, когда программа не влезла во FLASH. Можно попробовать разместить какие-нибудь данные (строки, например) в константных переменных EEPROM. У stm8 доступ на чтение из EEPROM происходит без накладных расходов.

Цитата(Эдди @ Aug 1 2017, 19:19) *
ничего при старте не копируется.

Естественно, и об этом даже написано в документации. Ещё бы её читал кто...

Я вот подумал, у STM8 общее адресное пространство для RAM, FLASH и EEPROM. Из FLASH и RAM код выполняться может, а что мешает его из EEPROM выполнять? Надо попробовать будет sm.gif

Автор: juvf Aug 1 2017, 17:29

Цитата(VladislavS @ Aug 1 2017, 19:09) *
Библиотеки IAR для работы с EEPROM какие-то монстроидные. Прикладываю .map с моего примера. Вроде как 199 байт занимает.
у меня занял stm8s_flash.o 319 ro code и 63 ro data. В библах ассертов куча... всяких условий. если тесно, нужно их переписывать.

Автор: Эдди Aug 1 2017, 19:00

Цитата(VladislavS @ Aug 1 2017, 19:34) *
а что мешает его из EEPROM выполнять?

А смысл? Еепрома же с гулькин нос! Что туда влезет-то? Вот какие-нибудь инициализационные константы вполне можно хранить (в том исходнике, на который я ссылку приводил, я храню в еепроме пары ID-номер для датчиков DS18x20).
Цитата(juvf @ Aug 1 2017, 20:29) *
В библах ассертов куча... всяких условий. если тесно, нужно их переписывать.

Зачем вы вообще этими яровскими штуками пользуетесь? SPL еще припомните...
STM8 же прост как 5 копеек! Бери себе, да пиши безо всяких "библиотек". Я для начала где-то минимальный заголовочный файл содрал (правда, он был для L-серий, а название его я так и не сменил — так и болтается теперь с буквой l, хотя я для l-ек ничего не писал никогда), а потом по мере необходимости пополнял его макросами.
В отличие от ARM'ов этим 8-биткам даже файл-стартап не нужен! Тупо сишные файлы сразу пишешь, потом make && make flash — вуаля!

Автор: juvf Aug 1 2017, 19:48

Цитата(Эдди @ Aug 2 2017, 00:00) *
Зачем вы вообще этими яровскими штуками пользуетесь? SPL еще припомните...
я его и имею в виду. библы - это SPL и есть. в библах куча ассертов
Цитата
STM8 же прост как 5 копеек! Бери себе, да пиши безо всяких "библиотек".
С библиотеками быстрее и безопаснее.... берёшь спл... вызываешь UART_Init().... где указываешь в аргументах все настройки,.... махом подыматеся уарт.... без задро очень частых и длительных возвратно-поступательных движений с даташитом,.... Да, UART_Init() универсальный и тяжелый.... если хватает места - забыть про него, пусть живет. Если всё таки не влез, то я заметил, что UART_Init изменяет всего 3 регистра. Для верности чиркнул зрачком по исходнику UART_Init(), и заменил вызов UART_Init() на 3 строчки кода. вот и весь инит, вот и помощь от спл.

ps да ещё и без спл легче себе в ногу стрельнуть.


Цитата(Эдди @ Aug 2 2017, 00:00) *
В отличие от ARM'ов этим 8-биткам даже файл-стартап не нужен! Тупо сишные файлы сразу пишешь, потом make && make flash — вуаля!
Мне не нравится "обвес".... т.е. всякие стартапы, cppinit-ы и т.п. 1400 байт флеша отьели.

dlstm8mmn.a: [4]
cexit.o 10
char.o 26
cppinit.o 210 2 11
cstartup.o 34
dc_util.o 44
exit.o 4
far.o 10
far_util.o 56
init.o 30
init_small.o 70
interrupt.o 4 128
long.o 284
long_util.o 38
low_level_init.o 3
memcpy.o 32
short.o 62
strlen.o 13
unhandled_exception.o 3
vreg_util.o 331
vregs.o 16
------------------------------------------------
Total: 1264 130 27

если вы пишете без стартапа, .... то у вас тоже нет cppinit.o, vreg_util.o, interrupt.o и т.п.?

Автор: VladislavS Aug 1 2017, 20:38

Цитата(Эдди @ Aug 1 2017, 22:00) *
А смысл? Еепрома же с гулькин нос!

Из любопытства, ради любви к искусству, по приколу - выбирайте sm.gif

Цитата(Эдди @ Aug 1 2017, 22:00) *
Зачем вы вообще этими яровскими штуками пользуетесь?

Реализация __eeprom реально удобно сделана, особенно в AVR версии. Грех не пользоваться.
Мне ещё нравится функция low_level_init() - там все железки проинитил и выходишь на main с мыслями об алгоритмах.
Да вроде и нет больше прямо таки фишек...

Цитата(juvf @ Aug 1 2017, 22:48) *
ps да ещё и без спл легче себе в ногу стрельнуть.

Куда обидней стрельнуть в ногу из SPL...

Цитата(juvf @ Aug 1 2017, 22:48) *
Мне не нравится "обвес".... т.е. всякие стартапы, cppinit-ы и т.п. 1400 байт флеша отьели.

Ну вы же их использовали в программе. Хотите ручками всё это написать? И не факт что короче выйдет.

Цитата(juvf @ Aug 1 2017, 22:48) *
если вы пишете без стартапа, .... то у вас тоже нет cppinit.o, vreg_util.o, interrupt.o и т.п.?

Скорее всего имелось в виду не совсем без стартапа, а с библиотечным стартапом по умолчанию. Окружение для С/C++ программы кто-то же должен создать. На ARM-е зоопарк чипов и в 99% случаев стартап надо свой для используемого чипа вставлять. В STM8 или AVR этого не надо делать.

Можно, конечно и отказаться от стандартного стартапа, но это уже какой-то недо-С и тем более не С++ получится.

Автор: Эдди Aug 2 2017, 05:30

Да, под стартапом я имел в виду ассемблерный файл, который занимается инициализацией регистров и первичным заполнением памяти. Для STM8 этого не нужно.
А структуру файлов, которая у меня используется, наглядно можно в исходниках просмотреть. В отличие от некоторых, я не скрываю свои исходники — зачем, если есть хорошая лицензия GPL?

По поводу инициализации периферии: один раз потратил 2 часа на даташит — написал сниппет для USART/I2C/etc. По мере необходимости количество сниппетов расширяется. А т.к. у меня всегда 57600 скорость USART'а, я просто этот код вставляю! Можно вообще собрать все сниппеты в заголовочный файл (как макросы или static inline) и вызывать из кода. Будет как будто бы в "блиблиотеках", зато без лишних телодвижений.
И если gcc вполне справляется с оптимизацией, так, что можно даже на цепепе писать, то sdcc еще до него оочень далеко. И малейшая гадость вполне войдет в результирующий код (sdcc даже неиспользуемые функции выкидывать не умеет).

Насчет SPL очень правильно было сказано: с помощью этой дряни значительно легче себе в ногу стрельнуть.
Ну и просто уродливо выглядят все эти инициализации структур перед вызовом функции. Похоже, все-таки, хоть инженеры у STM грамотные, программисты — безнадежные идиоты: то SPL родят, то HAL… Нет бы сразу сниппетов "на голых регистрах" побольше написать, в которых наглядно можно было бы подводные камни errat'ы увидеть!

Автор: juvf Aug 2 2017, 07:15

Цитата
Ну и просто уродливо выглядят все эти инициализации структур перед вызовом функции.

может это в стм32? так там нету спл (уже нету). а в спл для стм8 нет инициализации структур перед вызовом функции. По крайней мере в gpio, uart, exti, tim, spi....
вот например инит уарт
Код
      UART1_Init(19200,
                 UART1_WORDLENGTH_8D,
                 UART1_STOPBITS_1,
                 UART1_PARITY_NO,
                 UART1_SYNCMODE_CLOCK_DISABLE,
                 UART1_MODE_TXRX_ENABLE);

не знаю как тут себе можно в ногу стрельнуть? только если вам нужно скорость 19200, а вы напишете 19400.
а вот как выглядит оптимизированная установка скорости без спл, скорость 19200 при такте в 4 МГц.
Код
    UART1->BRR2 = 8;
    UART1->BRR1 = 6;
А вот тут самострел на лицо, к гадалке не ходи.


Цитата
Похоже, все-таки, хоть инженеры у STM грамотные, программисты — безнадежные идиоты: то SPL родят, то HAL…
а у остальных как? TI? Atmel? Там теже спл.... теже уродливые структуры. Вообще, проинитить GPIO в арме без спл... напрямую в регистры - это дрянь ещё та.... всякие клоки, альтфунк, моде, пулапы..... *застрелиться*. С спл/хал - хоть и уродливые структуры, но всё таки уже полегче... не нужно лазить по всему даташиту и изучать все регистры, достаточно изучить уродливую структуру.

Цитата
Нет бы сразу сниппетов "на голых регистрах" побольше написать, в которых наглядно можно было бы подводные камни errat'ы увидеть!
что за снипеты? можно пример, например для уарта в стм8?


ps чтоб не открывать новой темы, спрошу тут любителей стм8.... в даташите есть такое

Program memory: 8 Kbyte Flash memory; data
retention 20 years at 55 °C after 100 cycles

Ни кого не пугает всего 20 лет хранения?

Автор: Obam Aug 2 2017, 07:50

Кто-нибудь, покажите устройство, реально отслужившее 20 лет (; (напомню, 1997г выпуска)

Везде так: SAM3S1A (щас на столе) - типовое 30 тыс циклов W/E и мин 10 лет хранит; AT91SAM7S256 - 10 тыс циклов W/E и те же 10 лет хранения; для AT90S8535 приглючивается хранение 25 лет.

Автор: Эдди Aug 2 2017, 08:19

Цитата(juvf @ Aug 2 2017, 10:15) *
вот например инит уарт

Мало того, что уродливо, так еще вызывается левая функция, когда уарт инициализуется тремя-четырьмя строчками!
Цитата
не знаю как тут себе можно в ногу стрельнуть?

Когда понадобится что-то эдакое, а окажется, что в SPL это либо не реализовано, либо, что еще хуже, реализовано криво (жаловался уже на что-то подобное народ).
Цитата
А вот тут самострел налицо

Если правильно задокументировать, все будет отлично.
Цитата
а у остальных как? TI? Atmel? Там теже спл.... теже уродливые структуры.

Не надо тут! Почти любой МК можно по-человечески запрограммировать. Даже абдурину: достаточно стереть к чертовой бабушке загрузчик и программировать его как обычный авр. Ну или как обычный авр, но заливать через загрузчик. Пользоваться абдуриновскими библиотеками — это уж вообще треш!
Цитата
Вообще, проинитить GPIO в арме без спл... напрямую в регистры - это дрянь ещё та...

После облома с opencm3 я решил переходить абсолютно полностью на nolib решение: сниппеты — наше все! Вот как с STM32F042 закончу более-менее, вернусь к F103. Без библиотек элегантно получается, не тормозит и читается лучше. А даташит с RM — их в любом случае подробно читать придется. Хоть с библиотеками, хоть без них. Так зачем мучиться, и читать помимо даташита с RM еще и исходники кривых библиотек?
Цитата
что за снипеты? можно пример, например для уарта в стм8?

Кусочки кода. Я их вообще как готовые к загрузке штуки оформляю. См. у меня на гитхабе.
Цитата
Ни кого не пугает всего 20 лет хранения?

Нет. Это STM8S003, которые мегадешевые. Их во всяких халявных китайских приборчиках используют, которые все равно выкинешь раньше, чем через 20 лет.
Кстати, я когда двум этим мелкосхемам ресурс флеша исчерпал (одну аж раз на 250 хватило!), прикупил девборды на STM8S103 — практически один-в-один, но флеш намного дольше убивается. На них отлаживал, а потом 003 прошивал. Из баксовых "вольтметров" на 003 можно вполне приличный термометр с датчиком Tsic506 сделать, или экранчик по I2C (правда, криворукие китайцы даже "вольтметр" с внешним АЦП спаяли так, что аппаратный I2C у них использовать нельзя — этими ногами дисплей дергают, идиоты!).

Цитата(Obam @ Aug 2 2017, 10:50) *
для AT90S8535 приглючивается хранение 25 лет.

Вот, кстати, подозреваю, что из-за этого, а не каких-то "наведенных грозой зарядов" (а грозы-то и не было) у нас сдох этот самый МК в приборе почти 20-летней давности. И пришлось мне http://electronix.ru/redirect.php?http://eddy-em.livejournal.com/143241.html.

Автор: juvf Aug 2 2017, 09:10

Цитата(Obam @ Aug 2 2017, 12:50) *
Кто-нибудь, покажите устройство, реально отслужившее 20 лет (; (напомню, 1997г выпуска)
радиостанция, весы, автомобиль, станок, часы, свитч, модем... или например счетчик электроэнергии.... есть счетчики которые уже по 50 лет прослужили и ещё столько же прослужат. Или вы счетчик эл энергии меняете раз в 10-20 лет?

ps глянул другие... у атмеги 20 лет, у стм32 30 лет..... не айс.....

Цитата(Эдди @ Aug 2 2017, 13:19) *
Мало того, что уродливо, так еще вызывается левая функция, когда уарт инициализуется тремя-четырьмя строчками!
УРОДЛИВО!!! Это вы называете УРОДЛИВО!? Ту даже коменты в коде не нужны. Весь инит уарта в одну строчку. вызовом одной функции. вам всё равно свою функцию писать... а если в коде в нескольких местах инит уарта? а если динамически менять режим работы?....

тогда позвольте ваш, не уродливый, инит в студию?

Цитата
Когда понадобится что-то эдакое, а окажется, что в SPL это либо не реализовано
когда понадобиться что-то этакое, а в спл этого нет, то вы НИКОГДА с помощью спл не стрельните себе в ногу, ибо потому что там этого нет. Вы что-то эдакое будете реализовавыть сами, без спл.... и вот тут если и будет выстрел, то уж не из кода спл, а из вашего.


Цитата
Цитата
а у остальных как? TI? Atmel? Там теже спл.... теже уродливые структуры.


Не надо тут! Почти любой МК можно по-человечески запрограммировать.
Вы о чем.... вы обвиняете стм программистов
Цитата
Похоже, все-таки, хоть инженеры у STM грамотные, программисты — безнадежные идиоты: то SPL родят, то HAL…
и "даете им совет " или как вы бы сделали на месте программистов у ST
Цитата
Нет бы сразу сниппетов "на голых регистрах" побольше написать
Так вот в рамках контектста этих высказываний вопрос: А программисты у TI тоже идиоты? А программисты у Atmela тоже идиоты? А программисты у других компаний тоже идиоты? Программисты TI тишут теже грамоздкие спл. Да, я согласен, любой МК можно закодить без спл... коротко и быстро.... но вопрос не об этом....

Цитата
А даташит с RM — их в любом случае подробно читать придется. Хоть с библиотеками, хоть без них. Так зачем мучиться, и читать помимо даташита с RM еще и исходники кривых библиотек?
Дело в том, что не придется. Понимаете... библа и абдурино скрывает даташит. заглянул в мануал на библу, вызвал UART1_Init() и забыл про уарт. работает как часы. не нужно досконально изучать даташит и РМ. Скорость вхождения в новый МК на порядок быстрее. Как пример абдурино.... многие юзеры сего чуда вообще не знают что такое даташит и РМ. Инит уарта - Serial.begin(19200) - ВСЁ! Уровень вхождения в программирование МК нулевой.

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


Цитата
Если правильно задокументировать, все будет отлично.
ээээ.... не понятно.... что тут документировать?... ещё раз... вот код для скорости 19200 при 4 МГц.

UART1->BRR2 = 8;
UART1->BRR1 = 6;
тут легче ошибиться, чем с спл.

Тут нужно открыть рм... покурить его... понять как рассчитать регистры... как это всё привязано к клокам... посчитать... и прописать 8 и 6 в нужной последовательности (в обратной не работает). вот допустим вы ошиблись в расчетах, или не правильно поняли даташит и получили 7 и 6 - это и есть выстрел в ногу.
вот пример ошибочного кода.
UART1->BRR2 = 7;
UART1->BRR1 = 6;

задокументируйте его ПРАВИЛЬНО, чтобы всё было отлично!


Автор: Эдди Aug 2 2017, 09:11

Вот можно подумать, обычные USB-флешки гарантируют больше ~10 лет! Какая разница? Сдохнет через 30 лет — туда и дорога! Железяки такого типа нужно хотя бы раз в 10-15 лет обновлять, чтобы не было как у нас (см. выше).

Автор: Obam Aug 2 2017, 09:17

Цитата(juvf @ Aug 2 2017, 12:28) *
радиостанция, весы, автомобиль, станок, часы, свитч, модем... или например счетчик электроэнергии.... есть счетчики которые уже по 50 лет прослужили и ещё столько же прослужат. Или вы счетчик эл энергии меняете раз в 10-20 лет?

ps глянул другие... у атмеги 20 лет, у стм32 30 лет..... не айс.....

"Курьер" у меня '01-го, не 20-лет.
В часах "флэш"? Для чего?
В '11 был заменён эл.счётчик '74-го, ни в нём, ни в новом никакой "флэши" нет. Аргумент - не аргумент (;

Автор: Эдди Aug 2 2017, 09:20

Цитата(juvf @ Aug 2 2017, 12:10) *
вам всё равно свою функцию писать...

И что? У меня не будет 100500 ассертов и кучи вычислений для такой элементарщины. Три-четыре присвоения — и все!
Цитата
а если в коде в нескольких местах инит уарта?

Больше, чем количество уартов, их все равно быть не может. ctrl+c → ctrl+v решают ☺ Всяко меньше кода на выходе будет.
Цитата
а если динамически менять режим работы?

Кому это может понадобиться?
Цитата
тогда позвольте ваш, не уродливый, инит в студию?

На гитхабе лежит, я ж говорю.
Цитата
когда понадобиться что-то этакое, а в спл этого нет, то вы НИКОГДА с помощью спл не стрельните себе в ногу, ибо потому что там этого нет.

Спасибо, посмеялся. Ну и на кой тогда вы эти спл используете?
Цитата
А программисты у TI тоже идиоты? А программисты у Atmela тоже идиоты? А программисты у других компаний тоже идиоты? Программисты TI тишут теже грамоздкие спл.

Индусу заплатили, он пишет. Какая ему разница, что смысла в этой писанине нет?
Цитата
библа и абдурино скрывает даташит

И поэтому с ними работать еще сложней: нужно не только даташит читать, но и исходники долбаных библиотек/абдурин!
Цитата
Скорость вхождения в новый МК на порядок быстрее

Это хорошо только если задача — помигать светодиодиком, когда СМС придет. И делается эта железяка в одном-единственном экземпляре.
Цитата
многие юзеры сего чуда вообще не знают что такое даташит и РМ

И им наплевать, что для мигания светодиодом код 4кБ занимает! И что SPI/I2C/etc у них тупым ногодрыгом реализуются. И что для простой задачи, где при правильном подходе хватило бы 8кБ флеша за глаза, им требуется минимум 32. И т.д., и т.п.
Я вообще ничего хорошего в этом не вижу. Вон, компьютеры тоже когда-то были приличными железяками, для работы на них нужно было быть инженером. А сейчас любая блондинко сидит, мышкой тыкает. В итоге скатились чуть ли не в каменный век! Народ уже вообще не считает, что нужно учиться — компьютер же все сделает!
Та же самая мастдайка развилась именно благодаря тезису "каждой кухарке — по компутеру!". Иначе никто бы эту неюзабельную дрянь не покупал!
Цитата
А вообще вы тоже даташит скрываете своими снипетами. вы изучаете даташит, пишете снипеты (это ни что иное как та же библа), а потом не заглядывая в даташит пользуетесь своими снипетами.

По коду моего сниппета все видно, а по коду вызова библиотечной функции — нет.
Цитата
ээээ.... не понятно.... что тут документировать?... ещё раз... вот код для скорости 19200 при 4 МГц.

Написать, например, в комментариях, откуда эти числа взялись.

Автор: jcxz Aug 2 2017, 09:53

Цитата(juvf @ Aug 1 2017, 22:48) *
Мне не нравится "обвес".... т.е. всякие стартапы, cppinit-ы и т.п. 1400 байт флеша отьели.
dlstm8mmn.a: [4]
...
vregs.o 16
------------------------------------------------
Total: 1264 130 27
если вы пишете без стартапа, .... то у вас тоже нет cppinit.o, vreg_util.o, interrupt.o и т.п.?

Вообще-то здесь не только стартап. Даже лучше сказать - не столько.
Здесь вообще-то присутствует то, что Вы сами попросили у компилятора в своей программе laughing.gif
Например "long.o" - откажитесь от использования многоразрядных чисел в программе и не будет его.
"cppinit.o" - откажитесь от статических инициализированных классов/структур с конструкторами - и не будет его.
Уберите из программы все статические объекты инициализированные не нулями - и тоже не будет каких-то секций или будут меньше.
То же самое "strlen.o", "memcpy.o" и пр.
Есть конечно ещё модель работы компилятора IAR, который зачем-то вместо использования стекового фрейма для локальных переменных (что стандартно) использует виртуальные регистры.
Из-за этого есть "vreg_util.o" и "vregs.o". Но они тоже могут быть меньше.

Цитата(Obam @ Aug 2 2017, 12:17) *
В '11 был заменён эл.счётчик '74-го, ни в нём, ни в новом никакой "флэши" нет. Аргумент - не аргумент (;

Но там есть FRAM? biggrin.gif

Цитата(juvf @ Aug 2 2017, 12:10) *
ээээ.... не понятно.... что тут документировать?... ещё раз... вот код для скорости 19200 при 4 МГц.
UART1->BRR2 = 8;
UART1->BRR1 = 6;

Такому коду место на помойке. "Без библиотек" совсем не означает что нужно писать такое.
Почему нельзя написать "без библиотек" и при этом вполне прилично? Как-то так:
Код
void UARTinit(UART_RATE rate)
{
  static u8 const tr[UART_RATE_n][2] = {
    RATE_DIV(9600), RATE_DIV(19200), RATE_DIV(38400), RATE_DIV(57600),
    RATE_DIV(115200), RATE_DIV(230400), RATE_DIV(460800)};
  u8 const *s;
...
  UART.BRR[1] = *(s = &tr[rate][0]);
  UART.BRR[0] = s[1];

Автор: Obam Aug 2 2017, 09:58

Там нет FRAM, счётчик обычный, рабоче-крестьянский без блэк-джека. Механический.

Автор: jcxz Aug 2 2017, 10:01

Цитата(Obam @ Aug 2 2017, 12:58) *
Там нет FRAM, счётчик обычный, рабоче-крестьянский без блэк-джека. Механический.

Поставленный недавно?? Не думал что их ещё ставят. Может где-о в деревне? rolleyes.gif
У нас в доме ещё несколько лет назад все счётчики заменили на электронные. Централизованно.

Автор: juvf Aug 2 2017, 10:03

Цитата(Obam @ Aug 2 2017, 14:17) *
В '11 был заменён эл.счётчик '74-го, ни в нём, ни в новом никакой "флэши" нет. Аргумент - не аргумент (;
При чем тут это. ещй раз... был вопрос
" покажите устройство, реально отслужившее 20 лет" - я показал.

не было вопроса "покажите устройство с флеш памятью, реально отслужившее 20 лет"

Вот эл. счетчик.... какогонить года 60-го выпуска... его в сталинские дома поставили и он до сих пор работает. Теперь 21-ый век.... разрабатываем новый, современный эл. счетчик. сунули туда микропроцессор. а он всего на 20 лет. А почему? а потому что там флеш 20 лет..... ((( Просто новые устройства делают, взамен старым. Везде суют МК. Старые устройства работают по 20 лет. и дольше.... Новые устройства, должны быть не хуже старых.


Автор: Obam Aug 2 2017, 10:47

Цитата(juvf @ Aug 2 2017, 14:03) *
При чем тут это. ещй раз... был вопрос
" покажите устройство, реально отслужившее 20 лет" - я показал.

не было вопроса "покажите устройство с флеш памятью, реально отслужившее 20 лет"

Вот эл. счетчик.... какогонить года 60-го выпуска... его в сталинские дома поставили и он до сих пор работает. Теперь 21-ый век.... разрабатываем новый, современный эл. счетчик. сунули туда микропроцессор. а он всего на 20 лет. А почему? а потому что там флеш 20 лет..... ((( Просто новые устройства делают, взамен старым. Везде суют МК. Старые устройства работают по 20 лет. и дольше.... Новые устройства, должны быть не хуже старых.

Ну ёлы-палы, ну "флэш" же обсуждали и её "срок" годности. Технологии и 30-ти лет нету (Атмел же первыми сделали контроллер с "флэшом" в '94 - я не путаю?).

Автор: juvf Aug 2 2017, 11:12

Цитата(Эдди @ Aug 2 2017, 14:20) *
Кому это может понадобиться?
в смысле кому? работала железка на скорости 19200, теперь нужно перестроить на 9600. Полно таких устройств.

Цитата
Индусу заплатили, он пишет. Какая ему разница, что смысла в этой писанине нет?
Ещё раз... при чем тут индус? вы говорите, что программисты у ST - иниоты. Именно у СТ!!! Можно подумать в других компаниях другой подход. Я и спрашиваю, а программисты не СТ? Программисты ТИ и Атмела - так какой подход? тьретий раз спрашиваю - нет ответа на конкретный вопрос, один флуд.

Цитата
По коду моего сниппета все видно, а по коду вызова библиотечной функции — нет.

пока что кода вашего снипета вообще не видно ))
а по коду библиотечной функции ВАМ не понятно как настраивается уарт???
Код
      UART1_Init(19200,
                 UART1_WORDLENGTH_8D,
                 UART1_STOPBITS_1,
                 UART1_PARITY_NO,
                 UART1_SYNCMODE_CLOCK_DISABLE,
                 UART1_MODE_TXRX_ENABLE);
вам не понятно какой битрейт? сколько стоп, паритетность, длинна 8 бит? ВАМ реально не понятно это из этого кода..... тогда смысла с вами дальнейшей дискуссии нет. И всё остальное, что вы пишете, простите, но просто бред.
Такой код не понятен либо глупцу, либо это троллинг. При этом вы явно не хотите скопипастить в студию свой снипер инита, ссылаясь на гит ( и при этом даже не соизволите дать ссылку на гит).

Цитата(jcxz @ Aug 2 2017, 14:53) *
"cppinit.o" - откажитесь от статических инициализированных классов/структур с конструкторами - и не будет его.
Уберите из программы все статические объекты инициализированные не нулями - и тоже не будет каких-то секций или будут меньше.

Ну уже float убрал.... исчезло float.o. Когда станет не в моготу, уберу с++..... "и ещё ещё ещё ещё чего-нибудь". )) спс за совет.

Цитата(jcxz @ Aug 2 2017, 14:53) *
Такому коду место на помойке. "Без библиотек" совсем не означает что нужно писать такое.
Почему нельзя написать "без библиотек" и при этом вполне прилично? Как-то так:
Потому что ваш "приличный" код всё же больше помойного. Опять же, интересно посмотреть на реализацию RATE_DIV(19200)?

Автор: jcxz Aug 2 2017, 13:08

Цитата(juvf @ Aug 2 2017, 14:12) *
Потому что ваш "приличный" код всё же больше помойного. Опять же, интересно посмотреть на реализацию RATE_DIV(19200)?

В помойном нет выбора скорости, в моём есть - поэтому и больше. Если без выбора скорости - то ровно столько же.
RATE_DIV - это просто макрос:
Код
#define RATE_DIV_TRA(div) {div & 15 | div >> 8 & 0xF0, div >> 4 & 255}
#define RATE_DIV_TST(div) \
  RATE_DIV_TRA(assert_static(div >= 16 && div < 65536) * div)
#define RATE_DIV(rate) RATE_DIV_TST(SYSCLK_MH * 2 / (rate) + 1 >> 1)

где: SYSCLK_MH - тактовая частота МК.

Автор: Эдди Aug 2 2017, 16:08

Цитата(juvf @ Aug 2 2017, 14:12) *
При этом вы явно не хотите скопипастить в студию свой снипер инита, ссылаясь на гит ( и при этом даже не соизволите дать ссылку на гит).

Для особо слепых: ссылка у меня в подписи.
http://electronix.ru/redirect.php?https://github.com/eddyem/STM8_samples/blob/master/stepper_independent_bin/main.c#L258:
Код
    // Configure UART
    // 9 bit, no parity, 1 stop (UART_CR3 = 0 - reset value)
    // 57600 on 16MHz: BRR1=0x11, BRR2=0x06
    UART2_BRR1 = 0x11; UART2_BRR2 = 0x06;
    UART2_CR1  = UART_CR1_M; // M = 1 -- 9bits
UART2_CR2 = UART_CR2_REN | UART_CR2_RIEN; // Allow RX, generate ints on rx

Автор: juvf Aug 2 2017, 17:08

Цитата(Эдди @ Aug 2 2017, 21:08) *
Код
    UART2_BRR1 = 0x11; UART2_BRR2 = 0x06;

Это и есть снипер? Так я такой код и заюзал, чтоб сэкономить флешь. По мнению некоторых - это помойный код. ))) Это во первых, во вторых - что такое выстрел в ногу? Это например когда руками посчитал что-то и и в расчетах ошибся. Допусим нужны 0х11 и 0х6 в регистрах брр1 и брр2, а вы ошиблись и насчитали 4 и 8. Пишете свой "не уродливый", понятный код.... аля..
Код
// Configure UART
    // 9 bit, no parity, 1 stop (UART_CR3 = 0 - reset value)
    // 57600 on 16MHz: BRR1=0x4, BRR2=0x08
    UART2_BRR1 = 0x04; UART2_BRR2 = 0x08;
    UART2_CR1  = UART_CR1_M; // M = 1 -- 9bits
UART2_CR2 = UART_CR2_REN | UART_CR2_RIEN; // Allow RX, generate ints on rx

Вот вам и выстрел себе в ногу. И ни какая хорошая документация кода вас от выстрела не спасет. А с спл сложнее ошибиться.

И в третих.... я не знаю, что за камень вы используете, но в stm8s такой код не взлетит.... судя по инклуде в вашем коде, это какойто stm8l*, открыл на вскидку RM0031 для stm8l051, стр 532
Цитата
The Baud Counters will be updated with the new value of the Baud Registers after a write to BRR1. Hence the Baud Register value should not be changed during a transaction. The
BRR2 should be programmed before BRR1
Вот он вам, чистой воды самострел, без всяких спл. ))))

Цитата
один раз потратил 2 часа на даташит — написал сниппет для USART..... А даташит с RM — их в любом случае подробно читать придется.....
ну ну.... я вижу как вы их подробно читаете. wink.gif

Автор: VladislavS Aug 2 2017, 18:04

А я бы как-то так написал:

Код
#define F_CPU 16000000.0
#define BaudRate 57600.0
#define Divider ((uint16_t)(F_CPU/BaudRate + 0.5))
  
  USART1_BRR2 = (Divider&0x0F) | ((Divider>>8)&0xF0);
  USART1_BRR1 = (Divider>>4);

Если надо много скоростей, то много делителей бы просчитал на этапе компиляции.

А как сделано в SPL это "сон разума"
Мало того что 32-битные деления в рантайме, так ещё и резельтат без округления к ближайшем целому будет.
Код
/* Clear the LSB mantissa of USARTDIV */
  USARTx->BRR1 &= (uint8_t)(~USART_BRR1_DIVM);
  /* Clear the MSB mantissa of USARTDIV */
  USARTx->BRR2 &= (uint8_t)(~USART_BRR2_DIVM);
  /* Clear the Fraction bits of USARTDIV */
  USARTx->BRR2 &= (uint8_t)(~USART_BRR2_DIVF);
  BaudRate_Mantissa  = (uint32_t)(CLK_GetClockFreq() / BaudRate );
  /* Set the fraction of USARTDIV */
  USARTx->BRR2 = (uint8_t)((BaudRate_Mantissa >> (uint8_t)8) & (uint8_t)0xF0);
  /* Set the MSB mantissa of USARTDIV */
  USARTx->BRR2 |= (uint8_t)(BaudRate_Mantissa & (uint8_t)0x0F);
  /* Set the LSB mantissa of USARTDIV */
  USARTx->BRR1 = (uint8_t)(BaudRate_Mantissa >> (uint8_t)4);


Мой код 0x11 и 0x06 запишет, а индусский скорее всего 0x11 и 0x05. Проверять лень, на глаз вроде так.

Автор: juvf Aug 2 2017, 18:53

Цитата(VladislavS @ Aug 2 2017, 23:04) *
А я бы как-то так написал:
кошерный код.... и даже float.o не подтянулся. Спасибо

Автор: jcxz Aug 2 2017, 21:04

Цитата(juvf @ Aug 2 2017, 21:53) *
кошерный код.... и даже float.o не подтянулся. Спасибо

Мой лучше cool.gif

Автор: Эдди Aug 2 2017, 22:40

Цитата(juvf @ Aug 2 2017, 20:08) *
И в третих.... я не знаю, что за камень вы используете, но в stm8s такой код не взлетит....

Очень даже взлетит. Работает на STM8S003, S103 и S105. Не работало бы — полез бы глубже читать мануал.
А название инклюда у меня так исторически сложилось — рыбу утянул с L-серии, потом туда потихоньку дописывал нужные дефайны.
Понятно, почему это работало: 6 как-то не сильно много для LSB, а MSB пустой. Иначе не взлетело бы. Надо будет сниппеты в соответствие с RM привести, а то копирую этот кусок из одного в другое место, без учета требований последовательности записи регистров...

В любом случае мой подход правильней SPL. А еще правильней у VladislavS.

Автор: VladislavS Aug 3 2017, 09:56

Для того чтобы изменить скорость USART надо записать две правильных константы в два регистра в правильной последовательности. Как вы это сделаете - смесь вкусовщины с бесовщиной. Я стараюсь делать чтобы код максимально близко был похож на описание в документации. Так проще потом что-то менять и косяки отлавливать.

Автор: juvf Aug 3 2017, 15:35

Цитата(VladislavS @ Jul 22 2017, 01:54) *
А дальше как обычно определяем неинициализированные и инициализированные переменные с модификатором __eeprom и компилятор сам всё сделает.
а как uint16_t в епром разместить/писать?

Автор: VladislavS Aug 3 2017, 16:48

Цитата(juvf @ Aug 3 2017, 18:35) *
а как uint16_t в епром разместить/писать?


Весь смысл IAR-вских библиотек - сделать работу с EEPROM прозрачной. Не важно какого типа переменная, модификатор __eeprom размещает её в EEPROM и дальше забота компилятора куда её размещать, как читать и писать.
Код
__eeprom uint16_t x;
x=0x1234;



Автор: pittyalex Nov 14 2017, 21:22

Господа, товарищи, здравствуйте.
Помогите разобраться можно (и нужно) с отсылкой к даташитам или мануалам, но желательно конкретное место.
Проблема: пытаюсь сравнить массив в памяти с таким же массивом в еепром (по сути адресное пространство одинаковое) с помощью библиотечной процедуры memcmp, но компилятор ругается:

Error[Pe167]: argument of type "unsigned char __eeprom *" is incompatible with parameter of type "void const *" C:\DISTRIBUTIVES\!Develop\STM\STM8\Projects\S003F3\IAR-Robot\stm8_rc522-master\main.c 81

Объявление массивов:
__near unsigned char mf_key_list[4][10] = { {0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0}};

__eeprom unsigned char ee_key_list[4][10] = { {0x04, 0x44, 0x2C, 0x12, 0x05, 0x33, 0x82,0,0,0}, //MasterKey
{0,0,0,0,0,0,0,0,0,0}, //Key for first reader
{0,0,0,0,0,0,0,0,0,0}, //Key for second reader
{0,0,0,0,0,0,0,0,0,0}}; //Key for third reader

Сравнение:
if (memcmp(ee_key_list[0], mf_key_list[i], sizeof(mf_key_list[0]) == 0))
{

};

Подскажите, что я делаю не так?

Автор: juvf Nov 15 2017, 03:48

Цитата(pittyalex @ Nov 15 2017, 02:22) *
Подскажите, что я делаю не так?

так компилятор же говорит, чёрным по белому "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 Nov 16 2017, 12:30

Цитата(juvf @ Nov 15 2017, 04:48) *
так компилятор же говорит, чёрным по белому "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 Nov 16 2017, 12:46

Цитата(pittyalex @ Nov 16 2017, 15:30) *
Есть какие нибудь подсказки как правильно сравнить массив в еепроме с массивом в ОЗУ?

Конечно есть. Не использовать __eeprom. Я вообще не понимаю, зачем эта штука нужна. У себя использую обычные указатели и делаю функции записи в EEPROM.

Автор: juvf Nov 16 2017, 13:30

Цитата(pittyalex @ Nov 16 2017, 17:30) *
В доках черным по белому написано, что еепром кастить нельзя.
В каких доках?


Цитата
Есть какие нибудь подсказки как правильно сравнить массив в еепроме с массивом в ОЗУ?
ну если 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 Nov 16 2017, 17:14

На чтение EEPROM в STM8 ничем не отличается от обычной памяти. Причин чтобы не работало через приведение типов не видно.

Автор: pittyalex Nov 16 2017, 18:11

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

По сути, был вопрос про где чёрным по белому написано. Вот цитата из хелпа к 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 Nov 16 2017, 19:58

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

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

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

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

Автор: pittyalex Nov 16 2017, 20:17

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


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


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

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

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

Автор: scifi Nov 16 2017, 20:40

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

Лучше бы код выложили. "Правильный" выбор типов выражений при вычислении индекса может уговорить компилятор считать более оптимально, а может и не уговорить. Умный компилятор, конечно, сам догадается. Но яр для стм8 точно не умный, как я уже упомянул выше. Хотя говорят, что яр для арма, к примеру, творит чудеса. Сам не так давно пытался заставить его использовать инструкцию MUL для умножения 8x8=16 без знака. Это почти невозможно. Не придумал ничего лучше, чем сделать функцию mul( a, b ) с ассемблерной вставкой. И да, это было необходимо, поскольку в моём случае код просто не успевал бы делать то, что нужно.

Автор: juvf Nov 17 2017, 03:00

Цитата(pittyalex @ Nov 16 2017, 23:11) *
Тогда не понял, а что в доках написано:
* Casting _ _eeprom to another data pointer and vice versa is illegal
Так это написано для недописанного __eeprom. Тема называется "Дописываем библиотеки для работы модификатора __eeprom".

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

Автор: VladislavS Nov 17 2017, 04:19

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

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

Именно так. Читаем с первого сообщения темы sm.gif

Автор: pittyalex Nov 18 2017, 09:27

Цитата(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 Nov 18 2017, 13:55

был код

Код
__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 Nov 18 2017, 17:10

Цитата(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 Nov 18 2017, 20:20

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

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

Он их по алфавиту сортирует.
Сделайте одну структуру для всех переменных в eeprom, в структуре компилятор переставлять поля не станет.

Автор: juvf Nov 19 2017, 07:47

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

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

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

Цитата
Сделайте одну структуру для всех переменных в eeprom, в структуре компилятор переставлять поля не станет.
Да, так и придется делать. Спасибо

Автор: scifi Nov 19 2017, 13:27

Цитата(pittyalex @ Nov 18 2017, 12:27) *
но как ему это подсказать, я не знаю.

Вернее, возможно ли это в принципе. Скорее всего нет, конечно. Я бы не стал тратить на это время. Если реально поджимает, программирование на ассмблере куда реалистичнее. Всё-таки основное свойство компилятора - выдавать корректный код, и яр для стм8 с этим справляется. Выдавать более оптимальный код - это следующая задача, и руки у них до этого не дошли, очевидно. Кстати, яр для Coldfire может отлично оптимизировать, но при этом иногда выдаёт нерабочикй код (md5, к примеру) laughing.gif

Автор: pittyalex Nov 19 2017, 17:56

Цитата(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 Nov 20 2017, 04:37

У меня @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 Nov 20 2017, 06:38

Цитата(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 Nov 20 2017, 10:20

Цитата(pittyalex @ Nov 18 2017, 11:27) *
Я понимаю, что компилятор не может догадаться, что размер массива меньше байта, поэтому индекс не может (не должен) быть больше размера массива, т.е. байта и нет необходимости выполнять 16 битное умножение, но как ему это подсказать, я не знаю.

А какой версией IAR это скомпилено?
Предполагаю что старой (v2.xx) и без оптимизации.
У меня подобный код (с кучей 16-битных операций) генерит старый v2.20 и с выключенной оптимизацией.
Со включенной оптимизацией уже гораздо лучше. А новый IAR (3.с чем-то) генерит гораздо лучше.

Автор: juvf Nov 20 2017, 11:20

Цитата
struct eeprom_layout volatile* const eeprom = (void volatile*)0x4000;
-это даже не компиляется. ))

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


Автор: scifi Nov 20 2017, 12:02

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

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

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

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

Автор: VladislavS Nov 21 2017, 04:16

Цитата(scifi @ Nov 20 2017, 15:02) *
Зачем их прятать за оператором присваивания, снова не пойму.

Затем же за чем придумали языки высокого уровня.

Автор: juvf Nov 21 2017, 09:16

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

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

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

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

Автор: scifi Nov 21 2017, 11:19

Цитата(juvf @ Nov 21 2017, 12:16) *
ах да, сорри, проглядел ваш const.

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

Вы много чего ещё проглядели.

Автор: juvf Nov 21 2017, 11:21

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

Это вы проглядели о чем речь и не в тему постите

Автор: pittyalex Nov 22 2017, 21:36

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

С выключенной оптимизацией и самая последняя версия.

Автор: jcxz Nov 23 2017, 08:48

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

Хм... Включать не пробовали? laughing.gif

Автор: pittyalex Nov 23 2017, 19:28

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

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

Автор: jcxz Nov 23 2017, 23:13

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

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

Автор: scifi Nov 24 2017, 08:03

Цитата(pittyalex @ Nov 23 2017, 22:28) *
Нет, после включения оптимизации иногда код понять совершенно не возможно

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

Автор: juvf Nov 24 2017, 08:26

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

Троль!!! ))

Автор: pittyalex Nov 24 2017, 20:45

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

А слышали такое слово - отладка? Хотя согласен, необходимость залезть глубоко-глубоко бывает редко... но метко в)

Автор: scifi Nov 24 2017, 21:03

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

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

Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)