Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Раздельная инициализация константного массива
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
ArtemKAD
Похоже у меня прогрессирует склероз. sad.gif
Не могу вспомнить и найти как можно инициализировать конкретные ячейки массива в флаш-памяти.
Т.е. не забивать все сразу
__root __flash const char __flash *in_name_table[] = { DoorSw, DriverSw, HoodSw, TrunkSw};

А сперва объявить
__root __flash const char __flash *in_name_table[4];

а потом указать содержимое каждой конкретной ячейки по ее номеру.

in_name_table[0]=DoorSw;
in_name_table[1]=DriverSw;
in_name_table[2]=HoodSw;
in_name_table[3]=TrunkSw;



Как собственно заставить IAR понять что я от него хочу?
Непомнящий Евгений
__flash char a1 = 1;
__flash char a2 = 2;
__flash char a3 = 3;
__flash char a4 = 4;

char __flash * a = &a1;
a[0] + a[1] + a[2] - a[3];
prottoss
Так не возможно.
В первом случае Вы объявляете константную переменную
Во втором случае Вы пытаетесь инициализировать константную переменную
ArtemKAD
Цитата
__flash char a1 = 1;
__flash char a2 = 2;
__flash char a3 = 3;
__flash char a4 = 4;

char __flash * a = &a1;


А где гарантия того, что компилятор а1 - а4 расположит рядом и в указанном порядке? Кроме того, суть была в использовании индекса который потом будет еще неоднократно использоваться. А тут индекса как такового нет. Т.е. опять порядок определяется глазами на экране вместо числа.

Цитата
Так не возможно.
В первом случае Вы объявляете константную переменную
Во втором случае Вы пытаетесь инициализировать константную переменную

Я знаю, что конкретно так нельзя. Но ведь должен быть способ указать какое должно быть скомпилировано значение в конкретной (определенной номером ячейки) ячейке флеш-массива.
SSerge
Конкретные ячейки инициализировать можно таким способом
Код
__root __flash const char __flash *in_name_table[] =  { [2]=HoodSw, [3]=TrunkSw, [0]=DoorSw, [1]=DriverSw};

но только одновременно с объявлением переменной, потом указать уже не получится, нет таких средств.
prottoss
Цитата(ArtemKAD @ Aug 8 2012, 17:16) *
Я знаю, что конкретно так нельзя. Но ведь должен быть способ указать какое должно быть скомпилировано значение в конкретной (определенной номером ячейки) ячейке флеш-массива.
Да. Этот способ вы сами указали в первом посте.
Мне все таки не понятна Ваша идея: зачем сначала объявлять массив констант, а за тем присваивать им значения. Всегда считал, что это принципиально невозможно.

Цитата(SSerge @ Aug 8 2012, 18:52) *
Конкретные ячейки инициализировать можно таким способом
Это та же палка, только в другой руке.
ArtemKAD
Цитата(SSerge @ Aug 8 2012, 15:52) *
Конкретные ячейки инициализировать можно таким способом
Код
__root __flash const char __flash *in_name_table[] =  { [2]=HoodSw, [3]=TrunkSw, [0]=DoorSw, [1]=DriverSw};

но только одновременно с объявлением переменной, потом указать уже не получится, нет таких средств.


О, большое спасибо! Это хоть и не совсем то что я хотел, но с этим уже можно работать.
prottoss
Цитата(ArtemKAD @ Aug 8 2012, 19:48) *
О, большое спасибо!

Рад за Вас. На самом деле криво объявлять
Код
__root __flash const char __flash *in_name_table[] =  { DoorSw, DriverSw, HoodSw, TrunkSw};

На много лучше
Код
__root __flash const char __flash *in_name_table[] =  { [2]=HoodSw, [3]=TrunkSw, [0]=DoorSw, [1]=DriverSw};
IgorKossak
Только я здесь вижу лишний __flash?
ArtemKAD
Цитата
Мне все таки не понятна Ваша идея: зачем сначала объявлять массив констант, а за тем присваивать им значения.


К примеру - задача создания простейшего диспетчера задач. Есть два массива - один массив во флеш с указателями на задачи, а второй массив в ОЗУ с байтом-состояния каждой задачи. Первый массив надо заполнить указателями (константы), а со вторым надо работать(переменные). По сути для управления задачей надо знать индекс ее данных в массиве. Так вот хочется этот индекс объявить один раз и не беспокоиться дальше о соответствии этого индекса содержимому массива.

Цитата
Только я здесь вижу лишний __flash?

В флеше константный массив указателей на константные строки в флеше.
_Артём_
Цитата(ArtemKAD @ Aug 8 2012, 17:15) *
Первый массив надо заполнить указателями (константы),

Стоит ли массив городить - элемент используется 1 раз при запуске задачи и дальше не нужен.
ArtemKAD
Цитата(prottoss @ Aug 8 2012, 16:52) *
На много лучше
Код
__root __flash const char __flash *in_name_table[] =  { [2]=HoodSw, [3]=TrunkSw, [0]=DoorSw, [1]=DriverSw};


Если заметить 2,3,0,1 на #define - объявленные константы, для меня этот вариант становится действительно намного лучше.

Цитата
элемент используется 1 раз при запуске задачи и дальше не нужен.


Элемент используется КАЖДЫЙ раз при запуске задачи. А задача запускается каждый раз, когда диспетчер доходит до активного байта статуса задачи во втором массиве.
_Артём_
Цитата(ArtemKAD @ Aug 8 2012, 17:38) *
Элемент используется КАЖДЫЙ раз при запуске задачи.

Согласен.

Цитата(ArtemKAD @ Aug 8 2012, 17:38) *
А задача запускается каждый раз, когда диспетчер доходит до активного байта статуса задачи во втором массиве.

Получается что задача запускается всегда сначала? Адрес-то константный.
Зачем такое может понадобится?
prottoss
Цитата(ArtemKAD @ Aug 8 2012, 20:38) *
Если заметить 2,3,0,1 на #define - объявленные константы, для меня этот вариант становится действительно намного лучше.


Код
#define OOPS_1    DoorSw
#define OOPS_2    DriverSw
#define OOPS_3    HoodSw
#define OOPS_4    TrunkSw

__flash char DoorSw[1];
__flash char DriverSw[1];
__flash char HoodSw[1];
__flash char TrunkSw[1];


__root __flash const char __flash *in_name_table[] = { DoorSw, DriverSw, HoodSw, TrunkSw};
__root __flash const char __flash *oops[] = { OOPS_1, OOPS_2, OOPS_3, OOPS_4};

ИЧО?
ArtemKAD
Цитата
Получается что задача запускается всегда сначала? Адрес-то константный.
Зачем такое может понадобится?

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

Как по мне то, что диспетчер не вырывает задачу "на самом интересном месте" даже плюс - с общими ресурсами (переменными) проблем меньше т.к. точно знаешь, что во время работы этой задачи никакая другая не влезет.
_Артём_
Цитата(ArtemKAD @ Aug 8 2012, 18:09) *
Да вроде обычная кооперативная многозадачность. Адрес константный (как к примеру у любого обработчика прерываний) , но данные(в частности статические) - нет.

Да, понятно: адрес задачи-функции не меняется, внутри её switch или ещё что.
Я как-то забыл, что многозадачность кооперативная бывает.
ArtemKAD
Цитата(prottoss @ Aug 8 2012, 17:53) *
Код
....

ИЧО?

Так, действительно ничо...
А так:
Код
#define OOPS_1    0
#define OOPS_2    1
#define OOPS_3    2
#define OOPS_4    3

  #define STATE_OFF    0
  #define STATE_SLEEP    1
  #define STATE_RUN    2

__flash char DoorSw[1];
__flash char DriverSw[1];
__flash char HoodSw[1];
__flash char TrunkSw[1];



__root __flash const char __flash *oops[] = {
[OOPS_1]=DoorSw,
[OOPS_2]=DriverSw,
[OOPS_3]=HoodSw,
[OOPS_4]=TrunkSw

};

char state[] = {
[OOPS_1]=STATE_OFF,
[OOPS_2]=STATE_RUN,
[OOPS_3]=STATE_RUN,
[OOPS_4]=STATE_SLEEP
};

//....

RunTask (OOPS_2);   // запуск задачи (который на самом деле только меняет один элемент в массиве state[])

?
prottoss
Цитата(ArtemKAD @ Aug 8 2012, 21:30) *
Так, действительно ничо...
Просто замечательно, только через полгода выстрел в голову. Может это лично для меня. Если Вас устраивает, то похоже что проблема топика решена
ReAl
Цитата(ArtemKAD @ Aug 8 2012, 17:15) *
В флеше константный массив указателей на константные строки в флеше.
В таком случае для const по стандарту C должно бы быть
Код
const TYPE * const ARRAY[];
По логике __flash должен быть рядом с const


Цитата(prottoss @ Aug 8 2012, 18:36) *
Просто замечательно, только через полгода выстрел в голову.
Чтобы не настолько в голову, можно как-то так

Код
// task_list.h
TASK(OOPS_1, DoorSw,   STATE_OFF)
TASK(OOPS_4, TrunkSw,  STATE_SLEEP)
TASK(OOPS_2, DriverSw, STATE_RUN)
TASK(OOPS_3, HoodSw,   STATE_RUN)

Код
// task_tables.c

#define TASK(number, var, state) [number] = var ,
__flash const char * __flash const oops[] = {
#include "task_list.h"
};
#undef TASK

#define TASK(number, var, state) [number] = state ,
char state[] = {
#include "task_list.h"
};
#undef TASK
ArtemKAD
Цитата
Чтобы не настолько в голову, можно как-то так

beer.gif
ArtemKAD
ЗЫ. Кстати, для обламывания головы можно добавить такой кусок
Код
#define TASK(number, fun, state) const char ht_##fun = number;
#include "task_list.h"
#undef TASK

Который позволяет не объявлять заранее дескрипторы задач OOPS_1,OOPS_2,OOPS_3,..., а сделать его из имени функции добавив перед ним ht_ .

Т.е. после такого:

Код
// task_list.h
TASK(1, DoorSw,   STATE_OFF)
TASK(4, TrunkSw,  STATE_SLEEP)
TASK(2, DriverSw, STATE_RUN)
TASK(3, HoodSw,   STATE_RUN)


появятся константы ht_DoorSw, ht_TrunkSw, ht_DriverSw, ht_HoodSw со значениями равными соответствующим индексам в массивах ...
jcxz
Цитата(SSerge @ Aug 8 2012, 18:52) *
Конкретные ячейки инициализировать можно таким способом
Код
__root __flash const char __flash *in_name_table[] =  { [2]=HoodSw, [3]=TrunkSw, [0]=DoorSw, [1]=DriverSw};

Очень интересный способ. Надо взять на заметку. Давно искал что-то подобное.
Применение?
Часто бывает нужно например иметь массив структур-описателей каких-то объектов и иметь возможность в каких-то случаях работать со всем этим массивом (в цикле к примеру) или работать с отдельными элементами (но проименованными через enum).
Приходилось писать что типа:
struct {...} static const m[] = {{...}, {...}, {...}, {...}, {...}};
enum {OBJ_A, OBJ_B, OBJ_C, OBJ_D, OBJ_E};
Причём - enum бывает нужно в хидере расположить, а массив - в cpp.
Получается что видимой явной связи между m[] и enum нет и в дальнейшем при добавлении/удалении элементов m[] можно легко забыть отредактировать enum, да и отсчитывать номер элемента тож неудобно.
Так что - спасибо за инфу, возьму на заметку. sm.gif
SSerge
Цитата(jcxz @ Aug 11 2012, 00:01) *
Очень интересный способ. Надо взять на заметку. Давно искал что-то подобное.

Ну, дык, стандарт С99, раздел 6.7.8 Initialization.
а это один из примеров из этого раздела:
struct { int a[3], b; } w[] = { [0].a = {1}, [1].a[0] = 2 };

update
Кстати о enum. Для любителей головоломок (и плюсов) тот же пример можно переписать и так:
Код
struct sss{
  enum {one=1, two};
  int a[3], b;
} w[] = {[0].a = {sss::one}, [1].a[0] = sss::two };

всё в одном флаконе sm.gif
_Артём_
Цитата(SSerge @ Aug 10 2012, 23:46) *
Ну, дык, стандарт С99, раздел 6.7.8 Initialization.
а это один из примеров из этого раздела:
struct { int a[3], b; } w[] = { [0].a = {1}, [1].a[0] = 2 };

всё в одном флаконе sm.gif

Что-то у меня этот интересный пример не компилируется (GCC C++)

Даже такое не хочет:
Код
unsigned char B[3]={
    [0]=2,
    [1]=10,
    [2]=47
};

.
Про головоломки и не говорю.
ReAl
В С++, увы, этого нет :-( и прочие смайлики, утирающие слёзы.
Что-то там в C++11 вроде сделали, «типа даже лучше, но не совсем то», но у меня gcc 4.5.x, 4.6.x, они пример SSerge не берут.

Чистый С с 1999 года.
_Артём_
Цитата(ReAl @ Aug 11 2012, 10:34) *
В С++, увы, этого нет :-( и прочие смайлики, утирающие слёзы.

А ИАР-овский Си++ такое понимает...
GetSmart
Спасибо начитанным людям. Подсказали как в константу-массив юнионов на этапе компиляции положить не первый элемент юниона. Например когда объявляются float и long по одному и тому же адресу поля.

А заодно любопытно, такой или похожий синтаксис - индексирование (пропуская имя переменной) сразу с квадратных скобок или точки с именем поля
Код
struct { int a[3], b; } w[] = { [0].a = {1}, [1].a[0] = 2 };

ещё где-то встречается?

Upd.
Цитата(ReAl @ Aug 11 2012, 12:34) *
В С++, увы, этого нет :-( и прочие смайлики, утирающие слёзы.
Что-то там в C++11 вроде сделали, «типа даже лучше, но не совсем то», но у меня gcc 4.5.x, 4.6.x, они пример SSerge не берут.

Почему такого в С++ нет, с чем-то конфликтует?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.