Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: IAR для MSP430
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
Zelepuk
если какие-то особенности компилятора, может pragma какие-ниубдь, позволяющие работать с переменными во flash так же лекго как с обычными переменными?

например могу ли я объявить как-то по хитрому переменную "x", чтобы потом легко её инкрементировать в коде

x++; //например
SSerge
Чтобы изменить содержимое флэши нужно скопировать страницу её в ОЗУ, там изменить, страницу стереть (стирается только страница целиком) и снова записать во флэш изменённые данные.
Ну и какая прагма тут может помочь?
Zelepuk
Спасибо.
Дело в том, что мне требуется хранить только одну переменную в ПЗУ.
просто читаю вот такое:

...есть атрибуты, назначение которых описано в документации. То, что там написано, примерно выглядит так: Атрибут section(".infomem") функции или глобальной переменной указывает на то, что функция или ПЕРЕМЕННАЯ должна располагаться в сегменте информационной памяти.


это немного путает.

Как же тогда расположить одну переменную в ПЗУ и обращатсья к ней?
KARLSON
Вы можете сделать переменную во флеш по любому адресу какому захотите. Но изменить эту переменную просто проинициализировав не получиться. Нужны пароли к изменению флешь памяти. Почитайте раздел флеш память в Руководство пользователя MSP430x2xx Глава 7 стр 265.
Сергей Борщ
QUOTE (Zelepuk @ Nov 19 2011, 15:55) *
ПЕРЕМЕННАЯ должна располагаться в сегменте информационной памяти.
Переменая может быть и константной. Для переменных во флеше это подразумевается.
Zelepuk
Цитата(Сергей Борщ @ Nov 19 2011, 23:45) *
Переменая может быть и константной. Для переменных во флеше это подразумевается.


плохо((( надо чтобы она могла менятся в программе) rolleyes.gif
smile3046.gif
dxp
Цитата(Zelepuk @ Nov 20 2011, 05:00) *
плохо((( надо чтобы она могла менятся в программе) rolleyes.gif
smile3046.gif

Что это за константа такая, что может меняться в программе. Тогда это не константа.
Zelepuk
Цитата(dxp @ Nov 20 2011, 12:33) *
Что это за константа такая, что может меняться в программе. Тогда это не константа.

неправильно выразился... переменная конечно)

нашёл заветный код:

CODE

struct info_mem_s
{
union
{
struct nv_parms_s s;
int8_t x[128];
} seg_a;

struct nv_parms_s
{
int16_t variable;
}

void flash_write_int16(int16_t *ptr, int16_t value)
{
_DINT();
FCTL3 = FWKEY; /* Lock = 0 */
FCTL1 = FWKEY | WRT;
*((int16_t *) ptr) = value; /* Program the flash */
}


затем пишу во флешь так в функции main():

CODE

flash_write_int16((int *) &(nv_parms.seg_a.s.variable), (int16_t)1000);


я думаю вопрос с записью решён.

Как теперь можно прочитать эту переменную из флеши?
=DS=
Цитата(Zelepuk @ Nov 20 2011, 15:00) *
flash_write_int16((int *) &(nv_parms.seg_a.s.variable), (int16_t)1000);

я думаю вопрос с записью решён.

Как теперь можно прочитать эту переменную из флеши?

Прочитать-то просто: int x = nv_parms.seg_a.s.variable;
Но Вы, кажется, не понимаете, как работает флеш. Записать значение по любому адресу в ней можно без проблем, но только один раз и в чистую (все биты равны единице). При попытке повторной записи туда же другого значения старое не затрется - те биты, что были ранее сброшены в ноль, так и останутся. Нужно снова проинициализировать (стереть) память перед записью нового значения, а сделать это можно только со всей страницей целиком, а не с отдельным байтом.
Zelepuk
спасибо, но как же быть тогда?
може тогда перед перезаписью байта во флеши копировать содержимое страницы в RAM, затем переписывать содержимое байта и затем снова переписывать всю страницу во флеши?

Подскажите решение...
=DS=
Цитата(Zelepuk @ Nov 21 2011, 10:18) *
може тогда перед перезаписью байта во флеши копировать .......

Так обычно и делают. Альтернатива (если настроек мало и меняются они часто) - писать их блоками друг за другом в чистую страницу, для работы использовать последний блок, а когда страница заполнится, стирать и начинать сначала. Чуть сложнее, но помогает сэкономить ресуры флеши (она ограничена по числу перезаписей).
Zelepuk
нашёл интересный код по теме поста:

CODE
// ***********************************************************************
// This routine makes the flash looks like EEPROM. It will erase and
// replace just one word
// This routine copies will erase SEGA and then image SEGB to SEGA
// It will then erase SEGB and copy from SEGA back to SEGB all 128 bytes
// except the one to be replaced.
// ***********************************************************************
void flash_replace16(int16_t *ptr, int16_t word)
{
int *read_ptr;
int *write_ptr;
int w;

//Optimise the case where the new and old values are the same
if (*ptr == word)
return;
flash_clr((int *) FSEG_A);

_DINT();
//Set to write mode to prepare for copy
FCTL3 = FWKEY; /* Lock = 0 */
FCTL1 = FWKEY | WRT;

//Copy block B to A
read_ptr = (int *) FSEG_B;
write_ptr = (int *) FSEG_A;
for (w = 0; w < 64; w++)
*write_ptr++ = *read_ptr++;
flash_clr((int *) FSEG_B);

//Set to write mode to prepare for copy
FCTL3 = FWKEY; /* Lock = 0 */
FCTL1 = FWKEY | WRT;

//Copy block A to B, slipping in the new value at the right location
read_ptr = (int *) FSEG_A;
write_ptr = (int *) FSEG_B;
for (w = 0; w < 64; w++, read_ptr++, write_ptr++)
{
if (write_ptr == ptr)
*write_ptr = word;
else
*write_ptr = *read_ptr;
}
flash_secure();
_EINT();
}


как я понял, эта функция то, что мне нужно
Прошу прокоментировать
=DS=
А что тут комментировать? Стандартная процедура, о которой говорили выше - сохранить где-то содержимое страницы, стереть ее и записать повторно, за исключением модифицируемой переменной. Просто тут для временного хранения используется другая страница флеши. Имеет ли это смысл? Трудно сказать, разве что катастрофически припрет со свободной RАМ. Все остальное в минусе - временные затраты, энергия, ресурс флеши. Чтобы выбрать оптимальный для Вас вариант, надо знать гораздо больше о количестве сохраняемых переменных, частоте их изменения, и куче других параметров.
Zelepuk
спасибо за ответы, я разбираю код для MSP430
так вот есть такая конструкция
CODE
#define __infomem___ Pragma("location=\"INFO\"")

__infomem__ const struct info_mem_s nv_parms


и затем

CODE
flash_write_int16((int *) &(nv_parms.seg_a.s.variable), nv_parms.seg_a.s.variable & ~(1 << 2));


получается: обявили константу во флеши и затем записали на её место что-то...
верно?
не совсем понятно как потом прочитать то что записали через flash_write_int16()

smile3046.gif
MrYuran
Цитата(Zelepuk @ Nov 21 2011, 16:31) *
не совсем понятно как потом прочитать то что записали через flash_write_int16()

Берете адрес ваших данных и читаете без всяких чудес.
Zelepuk
Цитата(=DS= @ Nov 20 2011, 22:46) *
Прочитать-то просто: int x = nv_parms.seg_a.s.variable;
Но Вы, кажется, не понимаете, как работает флеш. Записать значение по любому адресу в ней можно без проблем, но только один раз и в чистую (все биты равны единице). При попытке повторной записи туда же другого значения старое не затрется - те биты, что были ранее сброшены в ноль, так и останутся. Нужно снова проинициализировать (стереть) память перед записью нового значения, а сделать это можно только со всей страницей целиком, а не с отдельным байтом.


пытаюсь после манипуляций описаных выше (в частности flash_write_int16()) прочитать записанное значение

int x = nv_parms.seg_a.s.variable;
вывожу 'x' на дисплей: нули((

P.S. дисплей выводит правильно
=DS=
CODE
#define __infomem___ Pragma("location=\"INFO\"")

Подмена на __infomem___ прагмы "location="INFO"" . Просто для удобства чтения и модификации. Но тут могут быть зарыты грабли. В частности, этот текст может быть несовместим с вышеописанной процедурой. Надо смотреть распределение флеш памяти для конкретного кристалла. Секция INFO включает в себя сегменты A, B (C, D в зависимости от кристалла)

CODE
__infomem__ const struct info_mem_s nv_parms

Разместить стуктуру nv_parms типа info_mem_s в памяти в секции INFO. Здесь надо проверить, как расположены в памяти входящие в INFO сегменты INFOA, INFOB (C, D). Компилятор расположит структуру nv_parms в начале секции INFO, а в серии 2хх там расположена секция D, например, в то время как flash_replace16 подразумевает, что данные хранятся в секции В. Можно не париться и прямо указать Pragma("location=\"INFOB\"")

CODE
flash_write_int16((int *) &(nv_parms.seg_a.s.variable), nv_parms.seg_a.s.variable & ~(1 << 2));


>>получается: обявили константу во флеши и затем записали на её место что-то...верно?
Не совсем так. Скорее жестко привязали имя и местоположение структуры к определенному адресу памяти. Делают так, потому что TI специально выделяют зону флеш-памяти именно для этих целей. У нее уменьшен размер страницы и увеличено количество возможных перезаписей по сравнению с основной страницей


JTAG есть? Давайте ВЕСЬ код, относящися к теме, тип кристалла.
Zelepuk
Спасибо за подсказки. Всё заработало. Кристалл F47187
непонятно только почему не работает конструкция

CODE
void flash_write_int16(int16_t *ptr, int16_t value)
{
_DINT();
FCTL3 = FWKEY; /* Lock = 0 */
FCTL1 = FWKEY | WRT;
*((int16_t *) ptr) = value; /* Program the flash */
}


когда применяю её вместо flash_replace16()
=DS=
Цитата(Zelepuk @ Nov 21 2011, 20:48) *
Спасибо за подсказки. Всё заработало. Кристалл F47187
непонятно только почему не работает конструкция

CODE
void flash_write_int16(int16_t *ptr, int16_t value)
}


когда применяю её вместо flash_replace16()

Возможно, потому что вы оставили флеш в режиме записи?
По завершении записи надо дать команды
FCTL1 = FWKEY;
FCTL3 = FWKEY | LOCK;

Еще одна вещь, о которой не надо забывать - если собака работает, перед записью во флеш ее надо отключать, а то взбрыкнуть может капитально.

Zelepuk
Цитата(=DS= @ Nov 21 2011, 15:22) *
А что тут комментировать? Стандартная процедура, о которой говорили выше - сохранить где-то содержимое страницы, стереть ее и записать повторно, за исключением модифицируемой переменной. Просто тут для временного хранения используется другая страница флеши. Имеет ли это смысл? Трудно сказать, разве что катастрофически припрет со свободной RАМ. Все остальное в минусе - временные затраты, энергия, ресурс флеши. Чтобы выбрать оптимальный для Вас вариант, надо знать гораздо больше о количестве сохраняемых переменных, частоте их изменения, и куче других параметров.


если предположить что таких переменных для хранения не более десяти. Частота изменения около 15 минут.

-наверное лучше написать функцию которая сразу меняет 10 переменных во флеши, чтобы как-то сбереч ресурс флеши?
-при перезаписи каждые 15 минут и количестве циклов флеши 100 000(как у MSP430) получается имеем всего 25000 часов такой работы, после чего флешь загнётся...

наверное лучше на какую-то внешнюю ПЗУ перейти.
=DS=
Цитата(Zelepuk @ Nov 23 2011, 00:35) *
-при перезаписи каждые 15 минут и количестве циклов флеши 100 000(как у MSP430) получается имеем всего 25000 часов такой работы, после
наверное лучше на какую-то внешнюю ПЗУ перейти.

Не так все плохо. Там 255 ячеек памяти в инфо области, прежде чем ее стирать можно заполнить 25 - 10 блоками настроек в завистимости от их типа, что уже дает 250000-500000 часов работы, а если вы еще заранее знаете, что часть из них будет меняться очень редко, то можно их сгруппироать и выиграть еще больше.
Или поставить кондер побольше по питанию и держать быстро меняющиеся настройки в ОЗУ, а во флеш их писать при пропадании питания.
Zelepuk
Цитата(=DS= @ Nov 23 2011, 03:53) *
Не так все плохо. Там 255 ячеек памяти в инфо области, прежде чем ее стирать можно заполнить 25 - 10 блоками настроек в завистимости от их типа, что уже дает 250000-500000 часов работы...


можно по подробнее об этом?
Дмитрий К.
QUOTE (Zelepuk @ Nov 23 2011, 08:58) *
можно по подробнее об этом?

имеется ввиду такая последовательность:
- стереть страницу
- записать данные (10 байт) со смещением 0x00 (начало страницы),
- через 15 мин записать данные (10 байт) со смещением 0x0A,
- через 15 мин записать данные (10 байт) со смещением 0x14,
- ... так 50 раз
- страница заполнилась, стирание всей страницы

это для обычной страницы по 512 байт (не INFO),
для INFO размер 64 байта
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.