Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Cortex M3, M4 - разрядность переменных.
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Allregia
Какую разрядность переменных, лучше выбирать в случае когда "а пофиг" ?
Например флаг, который может быть 0 или1, максимум -1, или считающий до 10 счетчик, и тому подобное, когда можно и u8, и s8, и u32б и s32.
Памяти-то в Кортексах обычно более чем достаточно, и экономить нужно не всегда, но влияет-ли это на быстродействие программы?
Есть ли разница для локальных и глобальных переменных, и для volatile?

Спасибо.
ViKo
Есть. Задавайте всё int, если ОЗУ у вас с избытком. Иные типы потребуют дополнительных команд (или байтов в команде). Оценить эффективность использования сможете, рассматривая листинг программы.
jcxz
Цитата(Allregia @ Jul 11 2014, 17:47) *
Есть ли разница для локальных и глобальных переменных, и для volatile?

Для локальных переменных, аргументов/результатов функций, используйте всегда нативные типы данных - int/uint.
Даже в случае экономии ОЗУ.
По занимаемому ОЗУ не будет никакой разницы, но кол-во команд однозначно будет меньше.
Для хранения в static памяти, нет большой разницы, но всё-же нативные типы тоже в некоторых случаях требуют меньше команд (или команды короче), так что для одиночных переменных - лучше они.
Для массивов лучше элементы меньшей разрядности (и в целях быстродействия операций с ними - тоже лучше). Но это моё имхо, не уверен, но надеюсь на повсеместное наличие write-back caching в M3/M4. Так что здесь предпочтение: u8/s8/u16/s16.
Сергей Борщ
На любом совершенно процессоре подключить к программе заголовочный файл stdint.h и всегда использовать объявленные в нем типы: uintXX_t - для данных, которым важен точный размер переменной, uint_fastXX_t - для данных, при работе с которыми важна скорость. Из фундаментальных типов в программе использовать только char и только для переменных, хранящих текстовые символы.
ViKo
И еще stdbool.h, и использовать bool тип.
demiurg_spb
Цитата(ViKo @ Jul 12 2014, 11:06) *
И еще stdbool.h, и использовать bool тип.
Ну это как раз спорно.
Т.к. sizeof(bool) are implementation-defined и зачастую sizeof(bool)==sizeof(int), что для 8-ми битных контроллеров весьма печально.
Поэтому у меня наложено табу на stdbool.h в ембедед разработках.
А про uint_fast8_t Сергей дело говорит.
ViKo
Цитата(demiurg_spb @ Jul 12 2014, 11:41) *
Ну это как раз спорно.
Т.к. sizeof(bool) are implementation-defined и зачастую sizeof(bool)==sizeof(int), что для 8-ми битных контроллеров весьма печально.

Вижу, что в Keil для STM32 под bool выделяется байт. Да, пожалуй, неэффективно, ни по размеру ОЗУ, ни по коду. Но и целое слово выделять для логической переменной жалко. Тогда - битовые поля.
skripach
Разница конечно есть, но она ничтожна, нужно использовать тот тип данных который нужен. ИМХО простота и понятность программы важнее.
demiurg_spb
Цитата(ViKo @ Jul 12 2014, 13:03) *
Тогда - битовые поля.
И потом для обеспечения атомарного доступа обрамлять к ним доступ критическими секциями. Увольте.
Единственный костыль для кортексов - это битбанд доступ к этим битам в поле. Но эти извращения должны быть сильно оправданы.

Цитата(skripach @ Jul 12 2014, 13:42) *
Разница конечно есть, но она ничтожна, нужно использовать тот тип данных который нужен.
uint_fast8_t - наше всёsm.gif
ViKo
Цитата(demiurg_spb @ Jul 12 2014, 12:56) *
И потом для обеспечения атомарного доступа обрамлять к ним доступ критическими секциями. Увольте.
Единственный костыль для кортексов - это битбанд доступ к этим битам в поле. Но эти извращения должны быть сильно оправданы.

Не единственный. Еще есть команды эксклюзивного доступа. LDREX и т.д. И соответствующие им интринсики для компилятора __LDREX().

И утрамбовать поля в слова можно так, чтобы не поганить одно поле при доступе к другому.
Allregia
Цитата(demiurg_spb @ Jul 12 2014, 11:56)
1268117[/url]']
И потом для обеспечения атомарного доступа обрамлять к ним доступ критическими секциями. Увольте.
Единственный костыль для кортексов - это битбанд доступ к этим битам в поле. Но эти извращения должны быть сильно оправданы.

uint_fast8_t - наше всё sm.gif


Спасибо всем.Чем отличается uint_fast8_t от просто u8 ? Насколько я понимаю, и то и то - байт?
Хотя нет - фаст это инт, т.е. 32 бита.
Тогда непонятно - зачем фаст8, фаст16, фаст32, если все это инт?
ViKo
Цитата(Allregia @ Jul 12 2014, 13:42) *
Спасибо всем.Чем отличается uint_fast8_t от просто u8 ? Насколько я понимаю, и то и то - байт?

Первое - не байт, а самое быстрое использование байта, конкретно, в STM32 должно превратиться в int.
Allregia
Еще пара вопросов про плавающую точку:

1) как я понял, чтобы М4 использовал FPU, надо чтобы все переменные были только float, а если double - то FPU не задействуется?

2) На такую строчку:
Код
static float b0, b1;
...

  b0 = b0* 0.99765 + b1*0.0990460;


Keil дает ворнинг:
#1035-D: single-precision operand implicitly converted to double-precision

Откуда тут double берется, и будет ли это считаться через FPU или мимо?
ms1
Цитата(Allregia @ Jul 13 2014, 01:03) *
Откуда тут double берется, и будет ли это считаться через FPU или мимо?


У Вас константы типа double, соответственно переменные также приводятся к double и вычисления будут двойной точности и "FPU мимо".
Добавьте к константам суффикс F
jcxz
Цитата(ViKo @ Jul 12 2014, 16:49) *
Первое - не байт, а самое быстрое использование байта, конкретно, в STM32 должно превратиться в int.

Тогда сильно сомневаюсь, что заполнение массива uint_fast8_t в цикле будет быстрее, чем массива u8.
Скорее - наоборот. Так как по размеру/кол-ву команд - одинаково, но кэш обратной записи предпочтёт u8.
Да и на чтение - аналогично.
DASM
Дайте пожалуйста, ссылку, где вы усмотрели write-back cache (впрочем как и иные виды кеша) в M3 кортексах blush.gif
jcxz
Если Вы потрудитесь открыть например "Cortex-M3 Technical Reference Manual", то тоже сможете усмотреть.
Например в разделе Bus Interface\Write buffer:
CODE
The processor exports memory attributes on the System bus by the addition of a
sideband bus, MEMATTR.
Table 14-3 shows the relationship between MEMATTR[0] and HPROT[3:2].
Table 14-3 Memory attributes
MEMATTR[0] HPROT[3] HPROT[2] Description
0 0 0 Strongly ordered
0 0 1 Device
0 1 0 L1 cacheable, L2 not cacheable
1 0 0 Invalid
1 0 1 Invalid
1 1 0 Cache WT, allocate on read
0 1 1 Cache WB, allocate on read and write
1 1 1 Cache WB, allocate on read

Да и вообще в куче мест, если воспользуетесь поиском по "cache".
Например ещё в MPU.

PS: К тому-же кеш может быть не в ядре M3, а периферии конкретного МК, например в его External Memory Interface.

PPS: А интересно, уважаемый DASM, у вас не возникала мысль "зачем вообще нужны команды типа DMB/DSB если кеша нет"?
DASM
Уточню, есть ли он в однокристаллках all-in-one, типа STM32F405 . Внешние памяти ,как ни крути, вешают на более серьезное, А9 и выше

Цитата(jcxz @ Jul 13 2014, 08:55) *
PPS: А интересно, уважаемый DASM, у вас не возникала мысль "зачем вообще нужны команды типа DMB/DSB если кеша нет"?

Не возникло, наличие команды еще не означает наличие соответствующего железа. These ARM and 32-bit Thumb instructions are available in ARMv7 ( http://infocenter.arm.com/help/index.jsp?t...c/CIHGHHIE.html ), а про Кортексы М3 пишут, что у них вообще нет кеш-контроллера
Хотя с другой стороны про M3 написано "The processor implements the ARMv7E-M architecture profile." Короче непонятно мне.
jcxz
Вообще-то топик не про какой-то конкретный проц, а про M3/M4 вообще. И советы соответственно - касабельно всех M3/M4.
На шине эти сигналы есть и если в STM32F405 кеша нет - это только его личная беда.

И насчёт внешней памяти Вы ошибаетесь. Зачем тогда интерфейсы внешней памяти присутствуют в M3/M4-ядрах?
Например LPC1778/LPC1788, STM32F429....
DASM
Может и ошибаюсь.
ViKo
Цитата(jcxz @ Jul 13 2014, 09:04) *
Вообще-то топик не про какой-то конкретный проц, а про M3/M4 вообще. И советы соответственно - касабельно всех M3/M4.

В M3 и M4 кэша нет. Цитата из книги Ю:
PLD Pre-load data. This is a hint instruction typically use for cache memory to
accelerate data accesses. However, since there is no cache inside the
Cortex-M3 and Cortex-M4 processors, this instruction behaves as NOP.

Цитата(jcxz @ Jul 13 2014, 07:29) *
Тогда сильно сомневаюсь, что заполнение массива uint_fast8_t в цикле будет быстрее, чем массива u8.
Скорее - наоборот. Так как по размеру/кол-ву команд - одинаково, но кэш обратной записи предпочтёт u8.
Да и на чтение - аналогично.

Если просто заполнение, то байтами, сгруппированными по 4, заполнить будет почти в 4 раза быстрее, чем словами. Но если еще что-то делать с байтами, то вряд ли. Впрочем, для массивов важнее экономить память, чем скорость, так что и выбора-то в данном случае не может быть.
jcxz
Цитата(ViKo @ Jul 13 2014, 12:35) *
В M3 и M4 кэша нет. Цитата из книги Ю:

В ядре нету. Но может присутствовать в МК, построенных на этом ядре. А в ядре есть вся поддержка для этого.
DASM
Не очень понимаю смысл кеша, расположенного на внешней памяти. Или в ядре со сверхбыстрым доступом, или он не нужен вообще. Тогда уж покупать лицензию на М3 и городить СОЗУ для кеша. Но вроде речь про серийные камни.
adnega
Все поняли вопрос?
Цитата
Какую разрядность переменных, лучше выбирать в случае когда "а пофиг" ?

Т.е. ограничений ни по размеру, ни по быстродействию нет, ибо "пофиг".
Ограничения по быстродействию или по размеру тут не обсуждается.
Насколько я понял, ТС просит "default type", когда выбор не очевиден и не играет роли.
Осмелюсь предположить, что в данном случае самым сильным критерием будет переносимость (в рамках M3/M4).
Очевидно, переносимость между компиляторами, средами, библиотеками и т.п.
demiurg_spb
Цитата(DASM @ Jul 13 2014, 11:15) *
Не очень понимаю смысл кеша, расположенного на внешней памяти.
А как же разгонять медленный флешь? Ведь вся соль применения CM3-4 именно в исполнении кода из FLASH на скорости не уступающей RAM. А без разного рода кешей этого бы не было. DSB я использую в реальных проектах (в обработчиках некоторых прерываний) и без этой инструкции программа была бы не так лаконична и вообще бы не работала (проверено).

Цитата(adnega @ Jul 13 2014, 11:43) *
Все поняли вопрос?
Ну да. Я могу и в третий раз повторить ответ.
Тут ведь вопрос стоит слишком глобально. Если говорить о аргументах функции, возвращаемых ей значениях, отдельных счётчиках или флагах, то наиболее переносимым вариантом является uint_fast8_t. В остальных случаях надо смотреть по задаче.

Цитата(ViKo @ Jul 12 2014, 14:33) *
Не единственный. Еще есть команды эксклюзивного доступа. LDREX и т.д. И соответствующие им интринсики для компилятора __LDREX().
И утрамбовать поля в слова можно так, чтобы не поганить одно поле при доступе к другому.
Об этом я забыл. Да и по жизни не приходилось использовать.
A. Fig Lee
Цитата(adnega @ Jul 13 2014, 03:43) *
Все поняли вопрос?

Насколько я понял, ТС просит "default type", когда выбор не очевиден и не играет роли.

Вот именно.
В целом правильно uintXX_t, но где значения не имеет, int, надо полагать достаточен.
adnega
Цитата(A. Fig Lee @ Jul 13 2014, 17:09) *
int, надо полагать достаточен.

Я везде (а это получатся только M3/M4/M0) int и пишу.
Для остальных случаев пользуюсь "своими" BYTE, WORD и DWORD - соответственно 8, 16, 32 бита (без знака).
Но это не правило, т.к. я программист-одиночка и работаю на себя.
Что там компилятор наоптимизирует для меня на порядок менее важно, т.к. в критических случаях заставляю "молотить" периферию, а не софт.
A. Fig Lee
Цитата(adnega @ Jul 13 2014, 11:46) *
Я везде (а это получатся только M3/M4/M0) int и пишу.
Для остальных случаев пользуюсь "своими" BYTE, WORD и DWORD - соответственно 8, 16, 32 бита (без знака).
Но это не правило, т.к. я программист-одиночка и работаю на себя.
Что там компилятор наоптимизирует для меня на порядок менее важно, т.к. в критических случаях заставляю "молотить" периферию, а не софт.

То бишь "пишу непереносимые приложения" .. biggrin.gif
adnega
Цитата(A. Fig Lee @ Jul 13 2014, 21:42) *
То бишь "пишу непереносимые приложения" .. biggrin.gif

Это с какой стороны посмотреть...
В своих проектах копипасту практикую чуть более чем полностью. Все при этом переносится.
С хорошим чужим кодом не работал. Свой код тоже никому отдавать не собираюсь.
И... ранее я предупреждал, что
Цитата
это не правило

Может, не от хорошей жизни я не использую стандартные C-библиотеки (в т.ч. и stdint).
Сейчас, вроде, нет никаких оснований их не использовать,но как-то... страшно.
Все работает, а я тут трогать начну...
Allregia
Цитата(adnega @ Jul 13 2014, 09:43) *
Все поняли вопрос?

Т.е. ограничений ни по размеру, ни по быстродействию нет, ибо "пофиг".
Ограничения по быстродействию или по размеру тут не обсуждается.
Насколько я понял, ТС просит "default type", когда выбор не очевиден и не играет роли.
Осмелюсь предположить, что в данном случае самым сильным критерием будет переносимость (в рамках M3/M4).
Очевидно, переносимость между компиляторами, средами, библиотеками и т.п.

Нет, не совсем так.
Я наверное не очень ясно выразился.
Под "пофиг" - имелось ввиду две вещи:
1) переменная типа флага, или считающего до 10 счетчика. Ее можно разместить и в байте и в ворде и в инте.
2)что памяти в этих процах как правило, более чем достаточно, и экономить ее используя именно байт - смысла нет, если это не дает каких-то других преимуществ.
А вот быстродействие как раз очень даже интересовало.
В общем, я понял что за исключением каких-то специальных случаев, юнитов, структур и больших массивов - надо не морочить себе голову и использовать u32,s32,vu32,vs32.
А тем более для локальных переменных.
AHTOXA
Цитата(Allregia @ Jul 14 2014, 03:00) *
В общем, я понял что за исключением каких-то специальных случаев, юнитов, структур и больших массивов - надо не морочить себе голову и использовать u32,s32,vu32,vs32.

Вы поняли неправильно. Надо включить стандартный заголовок <stdint.h> и использовать:
- uint_fast8_t для перемннных, значение которых не превысит 0xFF,
- uint_fast16_t для перемннных, значение которых не превысит 0xFFFF,
- uint_fast32_t для остальных.
Если нужны переменные со знаком, то берите int_fastX_t.
В этом случае компилятор выберет для вас оптимальный по скорости размер переменной.

Понятно, что для 32-разрядных процессоров компилятор выберет 32-разрядные переменные. Но при смене платформы это может измениться. Мало ли, захочется вам перенести какой-нибудь алгоритм на AVR. И как там себя будут чувствовать 32-битные счётчики цикла от 0 до 10? sm.gif
andrewlekar
АНТОХА, +1.
Не используйте u32, s32 и подобную ересь.
Однако поддержу adnega, если пофиг на производительность и главное - читаемость кода, то используйте встроенные типа: int, char. Но используйте с оглядкой на переносимость, если может произойти переполнение, то размер указывайте явно: uint32_t, uint16_t.
Сергей Борщ
Цитата(andrewlekar @ Jul 14 2014, 09:40) *
то используйте встроенные типа: int, char.
"и забудьте о переносимости, ибо размер их на другой платформе может быть любым".

Правильно надо было написать: "Не используйте встроенные типы, кроме char (а его - только для хранения символов), используйте типы из stdint.h". Впрочем, я повторяюсь.
andrewlekar
Будет не меньше байта: для счётчиков, флагов хватит.

А long не меньше 2-х байт. Хватит для большинства прочих применений. Правда писать текста больше.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.