STM32 новичку в ARM что к чему

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 354
Зарегистрирован: Чт июл 24, 2014 23:09:23
Откуда: Киев

Сообщение hosturik »

Подскажите как более правильно писать volatile перед типом переменной
Переписываю чужой проект, меняю его структуру, избавляюсь от глобальных переменных.
И столкнулся с одним моментом, который не совсем понятен и в гугле не знаю как правильно найти интересующий вопрос.
Есть два варианта, оба работают, но хотелось бы выбрать более правильный.

В первом варианте я пишу volatile перед названием структуры,
во втором пишу volatile перед типом каждой переменной в самой структуре
Абстрактный пример кода набросал, который передает суть

Код: Выделить всё

// Вариант 1
// file *.h
typedef struct
{
  uint16_t current_temperature;
  uint16_t round_temperature;
  uint16_t voltage;
  uint16_t power;
} parameter_st;

void func(volatile parameter_st *param);

// file *.c
volatile parameter_st parameter = {10, 20, 30, 40};

void func(volatile parameter_st *param)
{
	if(param->voltage > 1000) param->power = 80;
	else param->power = 0;
	
	if(param->voltage < 0xFFFF) param->voltage++;
	else param->voltage = 0;
}
void ***_IRQHandler(void) 
{
	func(&parameter);
}



// Вариант 2
// file *.h
typedef struct
{
  volatile uint16_t current_temperature;
  volatile uint16_t round_temperature;
  volatile uint16_t voltage;
  volatile uint16_t power;
} parameter_st;

void func(parameter_st *param);

// file *.c
parameter_st parameter = {10, 20, 30, 40};

void func(parameter_st *param)
{
	if(param->voltage > 1000) param->power = 80;
	else param->power = 0;
	
	if(param->voltage < 0xFFFF) param->voltage++;
	else param->voltage = 0;
}

void ***_IRQHandler(void) 
{
	func(&parameter);
}
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

hosturik, а нет никакого "как правильно", есть как надо вам в вашей программе. Что вы хотите от этой структуры?
1. Все структуры данного типа будут volatile как, например, регистры периферии в CMSIS.
2. Только конкретный экземпляр структуры будет volatile и возможно обычное её применение.
Нам то откуда знать? Ваша программа, вам и решать.
Реклама
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 354
Зарегистрирован: Чт июл 24, 2014 23:09:23
Откуда: Киев

Сообщение hosturik »

VladislavS, Поскольку почти все элементы структуры будут изменятся в прерывании, важно чтобы программа работала правильно.
Структуры в моем случае нужны чтобы не плодить глобальные переменные. Я создаю переменную типа структуры в одном сишном файле и все нужные функции вызываю в нем, передавая в них указатель на структуру.
Итог - с более чем 30 глобальных переменных, их не стало вообще. И код стал намного чище. Под глобальными имею ввиду когда в хедере пишется extern uint8_t val; а в си файле то же самое но без extern.
И эта переменная будет видна везде где подключается этот хедер.
Такой стиль написания мне не понравился решил все переписать, чтобы было красиво.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18793
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

typedef volatile struct {} my_struct_type; определит тип my_struct_type, который будет соответствовать вашей структуре с префиксом volatile.
все экземпляры структур этого типа будут исключены из оптимизации компилятора, т.е. доступ к ним и всем их полям будет, как к volatile-переменным.
можно создавать указатели на этот тип (в параметрах функций, например) и т.п.

но если вам вдруг потребуется создать, например, локальный экземпляр такой структуры (не-volatile то есть), типа для этого не найдется. вам об этом говорили.

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

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

hosturik, вы практически пришли к первому постулату ООП - инкапсуляция. Если ещё вспомнить, что в С++ struct и class это практически одно и то же, то можете смело перемещать функции в структуры, обзывать их методами и вместо структур создавать объекты.
Реклама
Первый раз сказал Мяу!
Сообщения: 21
Зарегистрирован: Сб янв 24, 2015 21:07:59

Сообщение horoc »

Пытаюсь освоить stm32f100. Что значат эти цифры?
Program Size: Code=612 RO-data=304 RW-data=0 ZI-data=1632
На пустом проекте реально занято 1632 байт озу? Может я, по не знанию, что то не то подключил? Или это не ОЗУ?
Вложения
keil.png
(51.3 КБ) 435 скачиваний
Реклама
Опытный кот
Аватара пользователя
Сообщения: 819
Зарегистрирован: Вт окт 23, 2012 13:17:25
Откуда: Прокопьевск

Сообщение Oxford »

1. Data ZI: нулевые инициализированные данные

2. Data RO - это константы.
Общий объем RAM память = Data RW + Data ZI
Общий размер FLASH память = Code + Data RO + Data RW

3. Некоторые константы (Data RO) генерируются компилятором / компоновщиком и также могут быть добавлены из библиотек. Таким образом, они будут существовать независимо от того, что ваша программа явно не определяет какие-либо константы.
Инженер R@D

Telegram чат: https://t.me/radiowolf или в поиске приложения @radiowolf. Личка:@cncoxford
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="horoc",url="/forum/viewtopic.php?p=3612406#p3612406"]На пустом проекте реально занято 1632 байт озу?[/uquote]Про стек и кучу не забываем.

[uquote="horoc",url="/forum/viewtopic.php?p=3612406#p3612406"]Может я, по не знанию, что то не то подключил? Или это не ОЗУ?[/uquote]Ответы на все вопросы есть в .map файле. Не ленитесь в него заглядывать.
Первый раз сказал Мяу!
Сообщения: 21
Зарегистрирован: Сб янв 24, 2015 21:07:59

Сообщение horoc »

Спасибо! Разобрался, оказывается на стек и кучу ушло.

Код: Выделить всё

      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name
        64         26        236          0       1536        804   startup_stm32f10x_ld.o
Stack_Size      EQU     0x00000400
Heap_Size       EQU     0x00000200
Еще один вопрос, на stm32 предпочтительно надо использовать 32 битные переменные? Это увеличит скорость по сравнению с переменными 8 и 16 бит? Хочу перенести проект с меги на стм, переделал так, что бы функции возвращали 32 битные значения, все локальные переменные тоже 32 бита. Но вот глобальные переменные, отъедающие ОЗУ, жаба душит объявлять 32 битными.
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Что вы потом будете делать с сэкономленной памятью? Солить?

Преждевременная оптимизация — корень всех (или большинства) проблем в программировании. (с) Дональд Кнут.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18793
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

VladislavS писал(а):Солить?
бинго!!! :))) :beer:
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Первый раз сказал Мяу!
Сообщения: 21
Зарегистрирован: Сб янв 24, 2015 21:07:59

Сообщение horoc »

Я большей части спрашивал, в каких переменных работать в STM32. Понизит ли скорость работы с 8битными переменными, например в цикле for(uint8_t j=0;j<50;++j) или же здесь предпочтительно писать uint32_t j. Просто по коду, иногда с uint8_t компилируются меньше по размеру, отсюда сомнения что uint32_t всегда правильно. Сейчас у меня 4к оперативы, в текущем проекте RO-data=17610 RW-data=424 ZI-data=3816 И я засуетился :)))
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="horoc",url="/forum/viewtopic.php?p=3612599#p3612599"]переделал так, что бы функции возвращали 32 битные значения, все локальные переменные тоже 32 бита.[/uquote]В этом нет необходимости. Определяйте типы данных так, чтобы они соответствовали тому что описывают. За разрядностью процессора пусть компилятор следит. Тогда и не будет "мук переноса".

Добавлено after 10 minutes 26 seconds:
[uquote="horoc",url="/forum/viewtopic.php?p=3612837#p3612837"]Я большей части спрашивал, в каких переменных работать в STM32.[/uquote]В тех, которые нужны для логики работы программы.

[uquote="horoc",url="/forum/viewtopic.php?p=3612837#p3612837"]Понизит ли скорость работы с 8битными переменными, например в цикле for(uint8_t j=0;j<50;++j) или же здесь предпочтительно писать uint32_t j.[/uquote]В данном случае на тип переменной счётчика фиолетово, это будет регистр процессора.

Код: Выделить всё

//  for(uint8_t j=0;j<50;++j) __no_operation();
        MOVS     R0,#+50
??main_1:
        Nop      
        SUBS     R0,R0,#+1
        BNE      ??main_1
[uquote="horoc",url="/forum/viewtopic.php?p=3612837#p3612837"]в текущем проекте RO-data=17610 RW-data=424 ZI-data=3816 И я засуетился :)))[/uquote]Надо смотреть что больше всего жрёт память, там и ужиматься. Каких-нибудь буферов наделали, вот память и уходит. Или строковые константы без const определены и в ОЗУ копируются. Вот где надо искать, а на переменных экономить - последнее дело.

PS: 512 байт под кучу и 1024 байт под стек тоже кучеряво так.
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Сообщение СКАЗОЧНИК »

А кто и где выделяет место под стек и кучу? Почему вообще куча? Разве не можно сделать часть ОЗУ под стек, а остальное ОЗУ уже куча и есть?
Станислав
Собутыльник Кота
Аватара пользователя
Сообщения: 2723
Зарегистрирован: Пт сен 07, 2018 20:20:02
Откуда: деревня в Тульской губернии

Сообщение ПростоНуб »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3612794#p3612794"]Преждевременная оптимизация[/uquote]
Наступили мне на больной мозоль. Очень оригинально некоторые программеры эту фразу воспринимают. Да, оптимизировать программу на этапе проектирования преждевременно, так же, как в БД создавать к таблице индексы до того, как стало известно, как и сколь часто из нее будут извлекаться данные. Но уже при написании SQL запроса, выбирающего данные из этой таблицы для отчета, есть прямой смысл озаботиться созданием индекса, если подходящего нет. Потому что, как обычно, отчет замечательно работает на нескольких тысячах записей в таблице и умирает на нескольких миллионах.
А заниматься оптимизацией уже за свой счет, после рекламации заказчика - удовольствие ниже среднего.

Так что запоздалая оптимизация не меньше зло, чем преждевременная.
Друг Кота
Аватара пользователя
Сообщения: 4906
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

СКАЗОЧНИК писал(а):Разве не можно сделать часть ОЗУ под стек, а остальное ОЗУ уже куча и есть?
Нельзя. Ну вот, представьте, стек растёт от одного конца ОЗУ к другому. А всё остальное - куча. И тут в куче выделяется один байт, где-то близко к стеку. Всё - стек больше расти не может, упрётся в этот байт. Хотя памяти, казалось бы, свободной ещё много.
Контактная информация:
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Сообщение СКАЗОЧНИК »

Где-то видел картинку, на ней была обозначена область ОЗУ, в конце самом стек, а куча лишь часть памяти, которая располагалось перед стеком. Так же тоже стеку некуда расти...
Станислав
Друг Кота
Аватара пользователя
Сообщения: 4906
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Да, но в этом случае хотя бы понятно, до каких пор позволено расти стеку. А в случае динамической отдачи под кучу той же памяти, что и стеку, перекрытие их может произойти в любой случайный момент.
Контактная информация:
afz
Опытный кот
Аватара пользователя
Сообщения: 744
Зарегистрирован: Сб дек 22, 2012 08:17:42
Откуда: Караганда, Казахстан

Сообщение afz »

Оно-то, конечно, так, только вот аппаратуры контроля переполнения стека у STM32 нет, о переполнении стека мы можем узнать только тогда, когда его кто-то испортит. И то не всегда сразу, иногда такие чудеса творятся, что ой! Обсуждалось уже не один раз.

Теоретически, конечно, если стек расположить в самом начале ОЗУ, то его переполнение вызовет однозначно идентифицируемый Hard Fault, но ни одна из систем программирования STM32 так не делает.
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Друг Кота
Сообщения: 6457
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

[uquote="horoc",url="/forum/viewtopic.php?p=3612837#p3612837"]Я большей части спрашивал, в каких переменных работать в STM32. Понизит ли скорость работы с 8битными переменными, например в цикле for(uint8_t j=0;j<50;++j) или же здесь предпочтительно писать uint32_t j.[/uquote]
Я обычно

Код: Выделить всё

for(int i = 0; i < 50; i++)
пишу. На результирующем коде это никак не сказывается, а писанины меньше. :-)
Ответить

Вернуться в «ARM»