Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 09.10.2009, 15:48   #1
valeologiya
Пользователь
 
Регистрация: 07.07.2009
Сообщений: 37
По умолчанию Запись во flash память

Здравствуйте! Передо мной стоит задача сохранения и чтения из ППЗУ структуры. В структуре есть как целочисленные поля, так и с плавающей точкой. Организация flash побайтовая; проц, ОЗУ - 32 разряда. Писать и читать можно только по одному байту, что и делают функции wr_byteEPROM и rd_byteEPROM

G - указатель на структуру. Размер 284 байт.
Код:
aa = (char*) (G);

			for(i=0; i<280; i++)
			{
		   	   	wr_byteEPROM(0xA8005 + (ChainsEPROM)*284 + i, (*(aa+i)) & 0xFF);
			}
Код:
                       bb = (char *) G + ChainsEPROM;
				
				for(i=0; i<280; i++)
				{
					*(bb+i) = rd_byteEPROM(0xA8005 + ChainsEPROM*284 + i);
				}
После записи первой структуры, она читалась как надо, но не читались поля с плавающей точкой. Затем остальные писались как-то криво. И первая уже считывалась криво. Залез на умные сайты и вычитал что структура может занимать в памяти не сумму байт с учетом выравнивания, а как захочет компилятор... и пр.

Сказав, ок. Надо так надо, решил писать каждую переменную в отдельности. Написал кучу строчечек и функции:

Для целочисленных
Код:
wr_wordEPROM(int addr, long data, int n)
{
	int i;

	for(i=0; i<n; i++)
		wr_byteEPROM(addr+i, (data>>(i*8))&0xFF);
}

long rd_wordEPROM(int addr, int n)
{
	long a = 0;
	char *b = (void*) &a;
	int i;
	for ( i=0;i<n;i++)
	{
		a |= (0xFF&(rd_byteEPROM(addr+i)))<<(i*8);
	}
	return a;
}
работает

Для плавающих пробовал кучу вариантов, последним был:
Код:
wr_fwordEPROM(int addr1, float data)
{

 /*	int i;
  	long *a1 = (void*)(&data);

		for(i=0; i<4; i++)
			wr_byteEPROM(addr+i, ((*a1)>>(i*8))&0xFF);   */
 	long a1;
	long* b = (void*) (&data);
	a1 = *b;
   	memcpy(&data, &a1, 4);
	wr_wordEPROM(addr1, a1, 4);
}
На этом этапе я запортачил себе прошивку, лежащую на этой же флешке, но в других секторах. Сказал #$% что я нубяра полный и не умею кодить.

Теперь вопрос.
1) Как сохранить double/float на flash? Писать можем только побайтово.
2) Можно ли сохранить структуру легким движением руки, как было в первой попытке.
valeologiya вне форума Ответить с цитированием
Старый 09.10.2009, 17:15   #2
ds.Dante
Старожил
 
Аватар для ds.Dante
 
Регистрация: 06.08.2009
Сообщений: 2,992
По умолчанию

Вместо 284 используй "sizeof T", где T - сама структура. Только не факт, что ты после этого не испортишь прошивку. :)

Совет: вместо констант типа 0xA8005 используй константы типа
#define FLASH_DATA_START 0xA8005

Может, на решение наведет такой вариант: выделяешь под масив char столько памяти, сколько нужно на всё-про-всё, и копируешь туда данные так, как они должны копироваться на флеш.

Последний раз редактировалось ds.Dante; 09.10.2009 в 17:20.
ds.Dante вне форума Ответить с цитированием
Старый 09.10.2009, 17:20   #3
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Цитата:
Сообщение от valeologiya
Залез на умные сайты и вычитал что структура может занимать в памяти не сумму байт с учетом выравнивания, а как захочет компилятор... и пр.
Что это за умные сайты такие? о_О Не как захочет, а в соответствии с выравниванием какое укажет пользователь. Для микрософт С это, параметр /Zp<число>. (В свойствах проекта, C/C++ => Создание кода => Выравнивание членов структур), по умолчанию 4.

Последний раз редактировалось netrino; 09.10.2009 в 17:22.
netrino вне форума Ответить с цитированием
Старый 09.10.2009, 17:34   #4
ds.Dante
Старожил
 
Аватар для ds.Dante
 
Регистрация: 06.08.2009
Сообщений: 2,992
По умолчанию

Цитата:
Сообщение от netrino Посмотреть сообщение
Для микрософт С это, параметр /Zp<число>. (В свойствах проекта, C/C++ => Создание кода => Выравнивание членов структур), по умолчанию 4.
Если верить MSDN, можно задавать 1, 2, 4, 8 или 16.

А можно задать этот параметр прямо в коде?
ds.Dante вне форума Ответить с цитированием
Старый 09.10.2009, 17:45   #5
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Цитата:
Сообщение от ds.Dante
А можно задать этот параметр прямо в коде?
Судя по этой странице - можно )

p.s. 2Данте спс за плюс = )

Последний раз редактировалось netrino; 09.10.2009 в 17:50.
netrino вне форума Ответить с цитированием
Старый 09.10.2009, 17:53   #6
valeologiya
Пользователь
 
Регистрация: 07.07.2009
Сообщений: 37
По умолчанию

Цитата:
Сообщение от ds.Dante Посмотреть сообщение
Вместо 284 используй "sizeof T", где T - сама структура.
С sizeof вообще прикол. Он выдает размер не в байтах, а в словах. Выравнивание у меня по 4 байта. Это я уже проверил.
Но всеравно в память под структуру данные записываются не по порядку, а как, понять не могу. Мониторил оперативку - ересь. Там приколы типа в целочисленном поле long лежит 5, а в следующем 6532, так 5 лежит в одном байте, а 0х19 и 0х84 в следующих. Не знаю, может это и мои глюки...
Во. Нашел что за компиль. G21K C Compiler Попробую на него доки покопать

и все же, есть идеи как float сохранить?

Последний раз редактировалось valeologiya; 09.10.2009 в 17:57.
valeologiya вне форума Ответить с цитированием
Старый 09.10.2009, 18:06   #7
ds.Dante
Старожил
 
Аватар для ds.Dante
 
Регистрация: 06.08.2009
Сообщений: 2,992
По умолчанию

Цитата:
Сообщение от valeologiya Посмотреть сообщение
в целочисленном поле long лежит 5, а в следующем 6532, так 5 лежит в одном байте, а 0х19 и 0х84 в следующих.
Может, 0x00, 0x05? Учти еще, что иногда байты записываются в обратном порядке (сначала младший, потом старший).

Цитата:
Сообщение от netrino Посмотреть сообщение
Судя по этой странице - можно )
У меня микрософт.ком уже неделю как не пашет. Можно чуть поподробнее?

Цитата:
Сообщение от netrino Посмотреть сообщение
p.s. 2Данте спс за плюс = )
Теперь у нас поровну. :)

Последний раз редактировалось ds.Dante; 09.10.2009 в 18:09.
ds.Dante вне форума Ответить с цитированием
Старый 09.10.2009, 18:25   #8
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Цитата:
Сообщение от ds.Dante
Можно чуть поподробнее?
Если вкратце, то можно задавать выравнивание данных двумя путями: с помощью директив препроцессора и с помощью __declspec.
Код:
__declspec(align(4)) struct Structure { // вместо 4 можно любую степень двойки до 8192
	long long int d;
	long int b;
	int c;
	char a;
};
Однако этот способ у меня почему-то не всегда работает, надо будет почитать об этом подробнее. Конкретнее он не работает на уменьшение размера выравнивания, то есть в данном случае всё равно структура будет выровнена до 24 байт.
Код:
#pragma pack(push) // Сохраняем текущее значение выравнивания
#pragma pack(1) // Задаём своё
struct Structure {
	long long int d;
	long int b;
	int c;
	char a;
};
#pragma pack(pop) // восстанавливаем предыдущее
Этот способ работает всегда
netrino вне форума Ответить с цитированием
Старый 09.10.2009, 18:37   #9
ds.Dante
Старожил
 
Аватар для ds.Dante
 
Регистрация: 06.08.2009
Сообщений: 2,992
По умолчанию

Цитата:
Сообщение от netrino Посмотреть сообщение
Код:
#pragma pack(push) // Сохраняем текущее значение выравнивания
#pragma pack(pop) // восстанавливаем предыдущее
Ого! У меня здоровые пробелы в знании языка.
ds.Dante вне форума Ответить с цитированием
Старый 09.10.2009, 19:14   #10
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Цитата:
Сообщение от valeologiya
Для плавающих пробовал кучу вариантов, последним был:
Код:
wr_fwordEPROM(int addr1, float data)
{

 /*	int i;
  	long *a1 = (void*)(&data);

		for(i=0; i<4; i++)
			wr_byteEPROM(addr+i, ((*a1)>>(i*8))&0xFF);   */
 	long a1;
	long* b = (void*) (&data);
	a1 = *b;
   	memcpy(&data, &a1, 4);
	wr_wordEPROM(addr1, a1, 4);
}
Если я правильно понял, то wr_byteEPROM(addr+i, ((*a1)>>(i*8))&0xFF); принимает в качестве первого параметра адрес куда писать, и в качестве второго что писать, так? Тогда зачем эти шаманства с указателями на long и побитовыми операциями? Почему бы не объявить указатель на data типа char? Ведь он равен одному байт(по крайней мере на большинстве машин )
Код:
int wr_fwordEPROM(int addr, float data)
{
	int i;
	char* p = (void*)(&data);

	for(i = 0; i < sizeof(float); i++)
		wr_byteEPROM(addr+i, p[i]);

	return i;
}
netrino вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Оперативная память Warhead BOX Компьютерное железо 6 31.08.2009 10:45
Память Ghennadiy Общие вопросы Delphi 9 25.08.2009 09:23
Динамическая память!!! Doholyan Паскаль, Turbo Pascal, PascalABC.NET 12 30.06.2009 17:11
оперативная память Pr1meEX Помощь студентам 3 16.06.2009 23:28
динамическая память aka_faith Общие вопросы C/C++ 47 12.06.2009 12:35