Страница 1 из 2
Массив во флеш памяти, const, ф-ция hal
Добавлено: Сб мар 13, 2021 22:29:29
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.
Спасибо!
Re: Массив во флеш памяти, const, ф-ция hal
Добавлено: Сб мар 13, 2021 23:03:45
Reflector
[uquote="compote",url="/forum/viewtopic.php?p=3996824#p3996824"]Если сделать привидение типов ..., (uint8_t *)dump, ... то проблема уходит. Но тогда возникает другая, мы сами говорим, что массив изменяемый, и данные в константном массиве могут быть переписаны.[/uquote]
Чтобы данные были переписаны функция по крайней мере должна пытаться их переписывать, а она из массива только читает, так что приводи тип и не жалуйся или напиши свою функцию которая будет принимать константный указатель

Re: Массив во флеш памяти, const, ф-ция hal
Добавлено: Сб мар 13, 2021 23:28:31
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 константа копируется сначала в стек, и только потом используется, что не совсем правильно.
Re: Массив во флеш памяти, const, ф-ция hal
Добавлено: Вс мар 14, 2021 03:29:20
VladislavS
Для глобальной переменной static ограничивает область видимости единицей трансляции.
По ссылке речь о локальной переменной. Для неё static имеет другой смысл - делает её глобальной.
Как определить константу в С++. Речь про С++, но для понимания как эта кухня работает стоит ознакомиться.
Re: Массив во флеш памяти, const, ф-ция hal
Добавлено: Вс мар 14, 2021 14:07:35
compote
[uquote="VladislavS",url="/forum/viewtopic.php?p=3996895#p3996895"]Для глобальной переменной static ограничивает область видимости единицей трансляции.[/uquote]
Спасибо, вроде разобрался с этим вопросом.
У меня массивы с дампами вынесены в хидер и он подключен к мейну. Соответствено, объявляя в хидере массив со статик, мы ограничиваем его область видимости мейном, а в другом си файле, можно объявить массив с таким же именем и не будет никаких проблем с неопределенностью, правильно?
Спасибо за ссылку на видео, не встречал этот канал, обязательно посмотрю!
Re: Массив во флеш памяти, const, ф-ция hal
Добавлено: Вс мар 14, 2021 14:47:37
VladislavS
[uquote="compote",url="/forum/viewtopic.php?p=3997047#p3997047"]а в другом си файле, можно объявить массив с таким же именем и не будет никаких проблем с неопределенностью, правильно?[/uquote]Специально делать разные массивы с одинаковым именем? Ну это
ССЗБ.

Re: Массив во флеш памяти, const, ф-ция hal
Добавлено: Вс мар 14, 2021 15:04:01
compote
[uquote="VladislavS",url="/forum/viewtopic.php?p=3997059#p3997059"]Ну это
ССЗБ.

[/uquote]
Это так, для примера

Re: Массив во флеш памяти, const, ф-ция hal
Добавлено: Вс мар 21, 2021 11:33:26
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].
Re: Массив во флеш памяти, const, ф-ция hal
Добавлено: Вс мар 21, 2021 21:27:22
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};
И подключать куда хочешь. В бинарник данная сущность попадёт один раз.
Re: Массив во флеш памяти, const, ф-ция hal
Добавлено: Вс мар 21, 2021 21:52:43
Professor Chaos
[uquote="VladislavS",url="/forum/viewtopic.php?p=4001712#p4001712"]Это верно только для Си[/uquote]
Не совсем.
В Си встраиваемые функции (inline) должны быть определены в заголовочном файле. Иначе компилятор просто не сможет встроить их код в месте вызова. Он должен видеть "тело", чтобы встроить его. Одного прототипа в этом случае недостаточно.
Но в Си это, пожалуй, единственное исключение из общего правила: в хидере никаких определений, только объявления.
Re: Массив во флеш памяти, const, ф-ция hal
Добавлено: Вс мар 21, 2021 23:06:29
NStorm
[uquote="VladislavS",url="/forum/viewtopic.php?p=3996895#p3996895"]По ссылке речь о локальной переменной. Для неё static имеет другой смысл - делает её глобальной.[/uquote]
Область видимости то не меняется. Просто значение локальной переменной сохраняется при повторном входе в функцию, в отличии от обычного использования, когда она каждый раз инициализируется заново.
С константой и нормальным компилятором по идее разницы для локальной (внутри функции) переменной не должно быть разницы в итоге.
Re: Массив во флеш памяти, const, ф-ция hal
Добавлено: Пн мар 22, 2021 06:57:13
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. Сам он этого не сделает, даже для константы.
Re: Массив во флеш памяти, const, ф-ция hal
Добавлено: Пн мар 22, 2021 07:04:45
VladislavS
Что такое статическая память?
Re: Массив во флеш памяти, const, ф-ция hal
Добавлено: Пн мар 22, 2021 18:11:50
a797945
за статическую память то же не догнал.
...применяется квалификатор auto. Что влечет их размещение в стеке. Даже если они константные...
и это не помещается в мои представления о стеке.
...void foo(void){
const char a=10; // создается в стеке...
10 - это менее 12-ти разрядов, мне представляется, что в данном случае она будет просто внутри инструкции, а не ячейкой в какой-либо памяти.
Re: Массив во флеш памяти, const, ф-ция hal
Добавлено: Пн мар 22, 2021 20:06:56
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.
Re: Массив во флеш памяти, const, ф-ция hal
Добавлено: Пн мар 22, 2021 20:17:47
VladislavS
Спасибо за уточнение. В целом есть неточности, но смысл понятен. Глобальные данные, вообще говоря, могут быть и неинициализированными. Также могут быть оптимизированы компилятором и линкером.
Re: Массив во флеш памяти, const, ф-ция hal
Добавлено: Вт мар 23, 2021 15:02:28
Dimon456
А такой вопрос:
Код: Выделить всё
void foo(void){
static char a=10; // не важно где создается
// важно имеет постоянный адрес
}
Как узнать этот адрес? Что бы я мог обращаться к этой переменной из вне. Интересуюсь в целях уменьшения размера кода, особенно в прерываниях.
Re: Массив во флеш памяти, const, ф-ция hal
Добавлено: Вт мар 23, 2021 16:17:32
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();
Всё-равно имхо лучше с глобалками работать, если их надо где-то еще использовать.
Re: Массив во флеш памяти, const, ф-ция hal
Добавлено: Вт мар 23, 2021 18:17:48
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;
}
Re: Массив во флеш памяти, const, ф-ция hal
Добавлено: Вт мар 23, 2021 18:48:19
a797945
последний вариант должен хорошо сократить размер - до нуля

сложить два числа и тут же забыть - компилятор такое может просто выкинуть