Массив во флеш памяти, const, ф-ция hal

Кто любит RISC в жизни, заходим, не стесняемся.
compote
Первый раз сказал Мяу!
Сообщения: 26
Зарегистрирован: Вт фев 04, 2020 12:28:50

Массив во флеш памяти, const, ф-ция hal

Сообщение compote »

Всем привет :))
Подскажите, пожалуйста, как решить проблему. Есть массив, неизменяемый дамп еепромки

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

static const uint8_t dump[256] = {0, 1, 2, ...}; 
и халовская ф-ция,

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

HAL_I2C_Mem_Write(..., uint8_t *pData, ...)
где pData указатель на неконстантный буфер с данными. При компиляции выходит предупреждение
warning: passing argument 3 of 'AT24C02_Write' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
Компилятор ругается на несоответствие. Если сделать привидение типов ..., (uint8_t *)dump, ... то проблема уходит. Но тогда возникает другая, мы сами говорим, что массив изменяемый, и данные в константном массиве могут быть переписаны.

Массив определен константным, чтобы размещение было во flash памяти, и действительно, среда показывает, что массив размещен в секции .rodata. По поводу static не знаю, нужен или нет, в листинге дизассемблера код что с ним, что без него один и тот же. Таких массивов 4 штуки по 256 байт. Они и в ОЗУ нормально размещаются, памяти хватает, но все же как правильно выйти из ситуации, чтобы и массивы разместить во флеше и можно было использовать функции HALa.

Спасибо!
Реклама
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Массив во флеш памяти, const, ф-ция hal

Сообщение Reflector »

[uquote="compote",url="/forum/viewtopic.php?p=3996824#p3996824"]Если сделать привидение типов ..., (uint8_t *)dump, ... то проблема уходит. Но тогда возникает другая, мы сами говорим, что массив изменяемый, и данные в константном массиве могут быть переписаны.[/uquote]
Чтобы данные были переписаны функция по крайней мере должна пытаться их переписывать, а она из массива только читает, так что приводи тип и не жалуйся или напиши свою функцию которая будет принимать константный указатель :)
Реклама
compote
Первый раз сказал Мяу!
Сообщения: 26
Зарегистрирован: Вт фев 04, 2020 12:28:50

Re: Массив во флеш памяти, const, ф-ция hal

Сообщение compote »

[uquote="Reflector",url="/forum/viewtopic.php?p=3996841#p3996841"]так что приводи тип и не жалуйся[/uquote]
Понял, можно не заморачиваться. Спасибо!
Про static еще не подскажете, нужен ли он при объявлении и инициализации массива или нет при размещении во флеш? static const dump[256] = {...};
Не понимаю, какую роль он выполняет в данном случае. На Электрониксе была тема https://electronix.ru/forum/index.php?a ... c&id=79620
там товарищ пишет, что без static константа копируется сначала в стек, и только потом используется, что не совсем правильно.
Последний раз редактировалось compote Вс мар 14, 2021 13:46:01, всего редактировалось 1 раз.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Массив во флеш памяти, const, ф-ция hal

Сообщение VladislavS »

Для глобальной переменной static ограничивает область видимости единицей трансляции.

По ссылке речь о локальной переменной. Для неё static имеет другой смысл - делает её глобальной.

Как определить константу в С++. Речь про С++, но для понимания как эта кухня работает стоит ознакомиться.
Реклама
Эиком - электронные компоненты и радиодетали
compote
Первый раз сказал Мяу!
Сообщения: 26
Зарегистрирован: Вт фев 04, 2020 12:28:50

Re: Массив во флеш памяти, const, ф-ция hal

Сообщение compote »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3996895#p3996895"]Для глобальной переменной static ограничивает область видимости единицей трансляции.[/uquote]
Спасибо, вроде разобрался с этим вопросом.
У меня массивы с дампами вынесены в хидер и он подключен к мейну. Соответствено, объявляя в хидере массив со статик, мы ограничиваем его область видимости мейном, а в другом си файле, можно объявить массив с таким же именем и не будет никаких проблем с неопределенностью, правильно?

Спасибо за ссылку на видео, не встречал этот канал, обязательно посмотрю!
Реклама
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Массив во флеш памяти, const, ф-ция hal

Сообщение VladislavS »

[uquote="compote",url="/forum/viewtopic.php?p=3997047#p3997047"]а в другом си файле, можно объявить массив с таким же именем и не будет никаких проблем с неопределенностью, правильно?[/uquote]Специально делать разные массивы с одинаковым именем? Ну это ССЗБ. :)
Реклама
compote
Первый раз сказал Мяу!
Сообщения: 26
Зарегистрирован: Вт фев 04, 2020 12:28:50

Re: Массив во флеш памяти, const, ф-ция hal

Сообщение compote »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3997059#p3997059"]Ну это ССЗБ. :)[/uquote]
Это так, для примера :lol:
Professor Chaos
Открыл глаза
Сообщения: 41
Зарегистрирован: Вс мар 21, 2021 11:06:04

Re: Массив во флеш памяти, const, ф-ция hal

Сообщение Professor Chaos »

[uquote="compote",url="/forum/viewtopic.php?p=3997047#p3997047"]У меня массивы с дампами вынесены в хидер и он подключен к мейну. Соответствено, объявляя в хидере массив со статик, мы ограничиваем его область видимости мейном, а в другом си файле, можно объявить массив с таким же именем и не будет никаких проблем с неопределенностью, правильно?[/uquote]
Не правильно. Никогда не делайте так. Завтра вы забудете про это и подключиьте директивой #include этот ваш хидер к ещё одному или нескольким файлам проекта. И что тогда будет?
Хидеры не предназначены для определений. В них должны быть только объявления. Применительно к вашему случаю, в хидере вы должны объявить ваши константные массивы с квалификатором extern. А определить их в отдельном си-файле, который включить в проект.

Файл dump.h

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

#ifndef DUMP_H
  #define DUMP_H
  #include <stdint.h>
  extern const uint8_t dump[];
#endif

Файл dump.c

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

#include "dump.h"
const uint8_t dump[8]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};

Теперь во сколько бы файлов проекта вы бы ни подключили свой dump.h, в памяти выделится место лишь под один массив const uint8_t dump[8].
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Массив во флеш памяти, const, ф-ция hal

Сообщение VladislavS »

[uquote="Professor Chaos",url="/forum/viewtopic.php?p=4001322#p4001322"]Хидеры не предназначены для определений. В них должны быть только объявления.[/uquote]Это верно только для Си. На С++ можно в заголовочном файле определить.

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

inline constexpr uint8_t dump[]={1,2,3,4,5,6,7,8,9,0};
И подключать куда хочешь. В бинарник данная сущность попадёт один раз.
Professor Chaos
Открыл глаза
Сообщения: 41
Зарегистрирован: Вс мар 21, 2021 11:06:04

Re: Массив во флеш памяти, const, ф-ция hal

Сообщение Professor Chaos »

[uquote="VladislavS",url="/forum/viewtopic.php?p=4001712#p4001712"]Это верно только для Си[/uquote]
Не совсем.
В Си встраиваемые функции (inline) должны быть определены в заголовочном файле. Иначе компилятор просто не сможет встроить их код в месте вызова. Он должен видеть "тело", чтобы встроить его. Одного прототипа в этом случае недостаточно.
Но в Си это, пожалуй, единственное исключение из общего правила: в хидере никаких определений, только объявления.
NStorm
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Re: Массив во флеш памяти, const, ф-ция hal

Сообщение NStorm »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3996895#p3996895"]По ссылке речь о локальной переменной. Для неё static имеет другой смысл - делает её глобальной.[/uquote]
Область видимости то не меняется. Просто значение локальной переменной сохраняется при повторном входе в функцию, в отличии от обычного использования, когда она каждый раз инициализируется заново.
С константой и нормальным компилятором по идее разницы для локальной (внутри функции) переменной не должно быть разницы в итоге.
Professor Chaos
Открыл глаза
Сообщения: 41
Зарегистрирован: Вс мар 21, 2021 11:06:04

Re: Массив во флеш памяти, const, ф-ция hal

Сообщение Professor Chaos »

[uquote="NStorm",url="/forum/viewtopic.php?p=4001767#p4001767"]Область видимости то не меняется. Просто значение локальной переменной сохраняется при повторном входе в функцию[/uquote]
Это следствие.
А причина в том, что:
1. Статическим локальным переменным выделяется фиксированный адрес в статической памяти, как и глобальным.
2. В отличии от глобальных переменных, область видимости их ограничивается тем блоком, где они объявлены.

Сохранение значений между вызовами функции - следствие п. 1.
static - квалификатор класса хранилища (хранения, памяти). Ко всем локальным переменным, для которых явно не указан класс хранения применяется квалификатор auto. Что влечет их размещение в стеке. Даже если они константные.

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

void foo(void){
  const char a=10; // создается в стеке

}

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

void foo(void){
  auto const char a=10; // создается в стеке

}

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

void foo(void){
  static const char a=10; // создается в статической памяти,
                                            // имеет постоянный адрес

}
Константность и класс памяти - разные вещи. Хочешь изменить класс памяти локальной переменной с умолчального auto - должен явно сказать это компилятору с помощью квалификатором static. Сам он этого не сделает, даже для константы.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Массив во флеш памяти, const, ф-ция hal

Сообщение VladislavS »

Что такое статическая память?
a797945
Мучитель микросхем
Сообщения: 446
Зарегистрирован: Вс ноя 01, 2015 09:15:16
Откуда: 69.Ржев

Re: Массив во флеш памяти, const, ф-ция hal

Сообщение a797945 »

за статическую память то же не догнал.

...применяется квалификатор auto. Что влечет их размещение в стеке. Даже если они константные...
и это не помещается в мои представления о стеке.

...void foo(void){
const char a=10; // создается в стеке...
10 - это менее 12-ти разрядов, мне представляется, что в данном случае она будет просто внутри инструкции, а не ячейкой в какой-либо памяти.
Professor Chaos
Открыл глаза
Сообщения: 41
Зарегистрирован: Вс мар 21, 2021 11:06:04

Re: Массив во флеш памяти, const, ф-ция hal

Сообщение Professor Chaos »

[uquote="VladislavS",url="/forum/viewtopic.php?p=4001845#p4001845"]Что такое статическая память?[/uquote]
Насколько это жаргон, а насколько общепринятая терминология, не могу судить. Но лично я вкладываю в это понятие такой смысл: это область памяти, которую выделяет компоновщик/линкер во время своей работы (компоновки/линковки) для хранения объектов программы с временем жизни, равным времени работы программы.
Применительно к данным, размещаемым там, это глобальные, а также локальные статические переменные и константы.
Такие данные:
- существуют все время работы программы;
- инициализируются до входа в main() явно заданными в программе инициализаторами или, если таковые отсутствуют, нулями;
- имеют постоянный адрес размещения в памяти на протяжении всего времени жизни.

Добавлено after 15 minutes 35 seconds:
[uquote="a797945",url="/forum/viewtopic.php?p=4002139#p4002139"]10 - это менее 12-ти разрядов, мне представляется, что в данном случае она будет просто внутри инструкции, а не ячейкой в какой-либо памяти.[/uquote]
Именно так может сделать компилятор. Но может и не сделать. Потому, что не обязан. Ожидать от него именно такого поведения, и строить на этом предположении какие-либо выводы нельзя.
Стандарт позволяет компиляторам очень вольно обходиться с квалификаторами auto и register, вплоть до их полного игнорирования. Эти моменты отданы на откуп конкретным реализациям компиляторов.
Один компилятор может выделить место в стеке. Второй встроить в код инструкции. Третий - поместить в регистр. И все будут формально правы.
Чтобы не зависеть от деталей реализации конкретного компилятора, следует явно определить класс хранилища и константность: static const.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Массив во флеш памяти, const, ф-ция hal

Сообщение VladislavS »

Спасибо за уточнение. В целом есть неточности, но смысл понятен. Глобальные данные, вообще говоря, могут быть и неинициализированными. Также могут быть оптимизированы компилятором и линкером.
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Массив во флеш памяти, const, ф-ция hal

Сообщение Dimon456 »

А такой вопрос:

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

void foo(void){
  static char a=10; // не важно где создается
                            // важно имеет постоянный адрес
}
Как узнать этот адрес? Что бы я мог обращаться к этой переменной из вне. Интересуюсь в целях уменьшения размера кода, особенно в прерываниях.
NStorm
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Re: Массив во флеш памяти, const, ф-ция hal

Сообщение NStorm »

Dimon456, тогда логично будет создать эту переменную как глобальную. Локальные переменные имеют смысл именно в ограничении области видимости. Никаких преимуществ в месте вы не получите, храня её как локальную. Но если хочется извращаться - то сделать на неё указатель и в функции присвоить ему значение &a.

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

char *a_ptr;

void foo(void){
  static char a=10; // не важно где создается
                            // важно имеет постоянный адрес
  a_ptr = &a;
}

...
  foo();
  if (a_ptr) ...
Добавлено after 3 minutes 27 seconds:
А, как вариант еще из функции вернуть указатель:

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

char * foo(void){
  static char a=10; // не важно где создается
                            // важно имеет постоянный адрес
  ...
  return &a;
}
  a_ptr = foo();
Всё-равно имхо лучше с глобалками работать, если их надо где-то еще использовать.
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Массив во флеш памяти, const, ф-ция hal

Сообщение Dimon456 »

Спрошу по другому,
вот это

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

volatile uint32_t n = 1023;
volatile uint32_t a=0;
	  
void foo_IRG(void){
  a += n; 
}

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

volatile uint32_t n = 1023;
	  
void foo_IRG(void){
  static uint32_t a=0;

  a += n; 
}
влияет на размер самой функции, вот и вопрос возникает - можно ли еще уменьшить размер функции если использовать так

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

void foo_IRG(void){
  static uint32_t a=0;
  static uint32_t n=1023; нужен адрес этой переменной -?
  a += n; 
}
a797945
Мучитель микросхем
Сообщения: 446
Зарегистрирован: Вс ноя 01, 2015 09:15:16
Откуда: 69.Ржев

Re: Массив во флеш памяти, const, ф-ция hal

Сообщение a797945 »

последний вариант должен хорошо сократить размер - до нуля ;)
сложить два числа и тут же забыть - компилятор такое может просто выкинуть
Ответить

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