Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Работа с EEPROM STM8 в IAR
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Все остальные микроконтроллеры > STM8
Страницы: 1, 2
VladislavS
Привет, любители 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), может кому пригодится.
Нажмите для просмотра прикрепленного файла
jcxz
Цитата(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
Цитата(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
Цитата(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
Цитата(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

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

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

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

jcxz, ну всё же, почему вы хотите EEPROM сделать const насильно? Он для того и придуман чтобы в него писать. Во так, например:
Нажмите для просмотра прикрепленного файла
Хотелось бы посмотреть как вы будете писать в константную переменную и что вам на это компилятор скажет.
VladislavS
Цитата(jcxz @ Jul 31 2017, 14:25) *
Тут как ни договаривайся - компилятор мзду не берёт biggrin.gif


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

Нажмите для просмотра прикрепленного файла

Упс! Компилятор даже не пискнул! Но это так, чисто поржать. sm.gif
jcxz
Цитата(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
Цитата(jcxz @ Jul 31 2017, 18:10) *
А если там реально нет этого слова, то я написал что будет делать компилятор в этом случае.

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

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

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

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

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


и ещё вопрос.... на сколько модификатор __eeprom съедает меньше флеша, чем spl?
jcxz
Цитата(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
Цитата(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 байт занимает.
Нажмите для просмотра прикрепленного файла
jcxz
Цитата(VladislavS @ Aug 1 2017, 17:09) *
Смотрите, в конфигурационном файле линкера это всё отлично видно

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

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

VladislavS
Инициализированные переменные с модификатором __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 которой по вашему при старте должен инициализироваться массив.

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

Нажмите для просмотра прикрепленного файла



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

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

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

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

может это в стм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
Кто-нибудь, покажите устройство, реально отслужившее 20 лет (; (напомню, 1997г выпуска)

Везде так: SAM3S1A (щас на столе) - типовое 30 тыс циклов W/E и мин 10 лет хранит; AT91SAM7S256 - 10 тыс циклов W/E и те же 10 лет хранения; для AT90S8535 приглючивается хранение 25 лет.
Эдди
Цитата(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-летней давности. И пришлось мне стать золотарем.
juvf
Цитата(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;

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

Эдди
Вот можно подумать, обычные USB-флешки гарантируют больше ~10 лет! Какая разница? Сдохнет через 30 лет — туда и дорога! Железяки такого типа нужно хотя бы раз в 10-15 лет обновлять, чтобы не было как у нас (см. выше).
Obam
Цитата(juvf @ Aug 2 2017, 12:28) *
радиостанция, весы, автомобиль, станок, часы, свитч, модем... или например счетчик электроэнергии.... есть счетчики которые уже по 50 лет прослужили и ещё столько же прослужат. Или вы счетчик эл энергии меняете раз в 10-20 лет?

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

"Курьер" у меня '01-го, не 20-лет.
В часах "флэш"? Для чего?
В '11 был заменён эл.счётчик '74-го, ни в нём, ни в новом никакой "флэши" нет. Аргумент - не аргумент (;
Эдди
Цитата(juvf @ Aug 2 2017, 12:10) *
вам всё равно свою функцию писать...

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

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

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

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

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

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

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

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

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

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

Написать, например, в комментариях, откуда эти числа взялись.
jcxz
Цитата(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
Там нет FRAM, счётчик обычный, рабоче-крестьянский без блэк-джека. Механический.
jcxz
Цитата(Obam @ Aug 2 2017, 12:58) *
Там нет FRAM, счётчик обычный, рабоче-крестьянский без блэк-джека. Механический.

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

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

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

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

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

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

Ну ёлы-палы, ну "флэш" же обсуждали и её "срок" годности. Технологии и 30-ти лет нету (Атмел же первыми сделали контроллер с "флэшом" в '94 - я не путаю?).
juvf
Цитата(Эдди @ 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
Цитата(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 - тактовая частота МК.
Эдди
Цитата(juvf @ Aug 2 2017, 14:12) *
При этом вы явно не хотите скопипастить в студию свой снипер инита, ссылаясь на гит ( и при этом даже не соизволите дать ссылку на гит).

Для особо слепых: ссылка у меня в подписи.
Вот, например:
Код
    // 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, 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
А я бы как-то так написал:
Код
#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
Цитата(VladislavS @ Aug 2 2017, 23:04) *
А я бы как-то так написал:
кошерный код.... и даже float.o не подтянулся. Спасибо
jcxz
Цитата(juvf @ Aug 2 2017, 21:53) *
кошерный код.... и даже float.o не подтянулся. Спасибо

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

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

В любом случае мой подход правильней SPL. А еще правильней у VladislavS.
VladislavS
Для того чтобы изменить скорость USART надо записать две правильных константы в два регистра в правильной последовательности. Как вы это сделаете - смесь вкусовщины с бесовщиной. Я стараюсь делать чтобы код максимально близко был похож на описание в документации. Так проще потом что-то менять и косяки отлавливать.
juvf
Цитата(VladislavS @ Jul 22 2017, 01:54) *
А дальше как обычно определяем неинициализированные и инициализированные переменные с модификатором __eeprom и компилятор сам всё сделает.
а как uint16_t в епром разместить/писать?
VladislavS
Цитата(juvf @ Aug 3 2017, 18:35) *
а как uint16_t в епром разместить/писать?


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


pittyalex
Господа, товарищи, здравствуйте.
Помогите разобраться можно (и нужно) с отсылкой к даташитам или мануалам, но желательно конкретное место.
Проблема: пытаюсь сравнить массив в памяти с таким же массивом в еепром (по сути адресное пространство одинаковое) с помощью библиотечной процедуры 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
Цитата(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
Цитата(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
Цитата(pittyalex @ Nov 16 2017, 15:30) *
Есть какие нибудь подсказки как правильно сравнить массив в еепроме с массивом в ОЗУ?

Конечно есть. Не использовать __eeprom. Я вообще не понимаю, зачем эта штука нужна. У себя использую обычные указатели и делаю функции записи в EEPROM.
juvf
Цитата(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
На чтение EEPROM в STM8 ничем не отличается от обычной памяти. Причин чтобы не работало через приведение типов не видно.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.