реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Шаблон (tamplete ) для работы с EEPROM
paravozru
сообщение Jul 29 2013, 06:42
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 15
Регистрация: 2-07-12
Пользователь №: 72 586



Возникла проблема при работе с EEPROM на STM32L-Discovery
Как можно создать адресацию EEPROM в заголовочном файле. Вот грабли на которые я наткнулся: в заголовочном файле .h сначала объявил указатели и им присвоил адреса вот примерно так
1.Мысля:
uint16_t *ModBusAddr = (uint16_t *)0x08080000;
в каком то .с файле вызов функции чтения EEPROM
uint16_t ReadEEPROM(uint16_t *addr) { // функция чтения EEPROM принимающая адрес указателя, и возвращающая uint16_t
uint16_t *ptr;
uint16_t result;
ptr = (uint16_t *)(addr);
result = *ptr;
return result;
}
Вот грабли №1: Keil выдал ошибку что множественное объявление «ModBusAddr » , оказывается можно только объявить переменные в .h но присвоить значения можно только в .с файлах.

2. Мысля
Решил адресацию EEPROM через #define
#define ModBusAddr 0
в таком случае функция чтения EEPROM приняла вид
uint16_t ReadEEPROM(uint16_t addr) { // функция чтения EEPROM принимающая позицию в памяти , и возвращающая uint16_t
uint16_t *ptr;
uint16_t result;
ptr = (uint16_t *)(eepromADR + addr ); // где #define eepromADDR 0x08080000 - начало EEPROM в STM32L-discovery
result = *ptr;
return result;
}
вот грабли №2: Да все работает, но во первых придется рассчитать каждый short, int, переменную в адресном пространстве EEPROM и задавать последовательность 0,1,2,3,4 и т п
Например для
#define ModBusAddr 0 //так в голове держу 0x08080000 , выделю два байта для этой переменной
#define ModBusFunc 2 // так в голове держу 0x08080002 выделю два байта для этой переменной
и т д.
Вот еще проблема функция uint16_t ReadEEPROM(uint16_t addr) имеет тип uint16 что принимаемый что возвращаемый, как быть если я хочу выделить для одной переменной например только байт, для другой два байта, а с float что делать ?

Тоже подумал и решил так создам Шаблон функции которая будет принимать различные типы данных и в зависимости от этого читать определенное количество байт с EEPROM/

template<typemane eeType>

eeType ReadEEPROM(eeType addr) {
eeType *ptr;
eeType result;
ptr = (eeType *)(addrEEPROM + adrr);
result = *ptr;
return result;
}

Проошу помощи, каким образом Вы распределяете память и как описаны функции чтения и записи c различными типами данных с EEPROM.

Забыл указать, при создании шаблона Keil выдал ошибку "this declaration has no storage class or type specifier"

Сообщение отредактировал paravozru - Jul 29 2013, 06:46
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 29 2013, 08:46
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



1. При объявлении переменной, задаёте ей альтернативный сегмент. Для IAR:
static __no_init int var[N] @ ".eeprom";
или
static const int var[N] @ ".eeprom";
2. В командном файле линкёра компонуете ваш сегмент (.eeprom) в нужные адреса EEPROM.
Go to the top of the page
 
+Quote Post
=F8=
сообщение Jul 29 2013, 09:01
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 567
Регистрация: 7-07-07
Из: Донецк
Пользователь №: 28 954



А теперь подставьте вместо eeType к примеру char и что вы получите?

char ReadEEPROM(char addr) {
char *ptr;
char result;
ptr = (int *)(addrEEPROM + adrr);
result = *ptr;
return result;
}
Вас не смущает что адрес задается как char?

Тут есть 3 варианта:
1. C выравниванием.
template<typemane eeType>
eeType ReadEEPROM(addr_t addr){
return(*((eeType *)(addrEEPROM + addr)));
}

2.Если все хранится без выравнивания

template<typemane eeType>
eeType ReadEEPROM(addr_t addr){
eeType res;
memcpy(&res, addrEEPROM + addr, sizeof(eeType));
return res;
}

3 Тоже с выравниванием. Мне этот вариант не нравится в силу нелогичности.
template<typemane eeType>
eeType ReadEEPROM(eeType *addr){
return(*((eeType *)addrEEPROM + addr));
}
Go to the top of the page
 
+Quote Post
paravozru
сообщение Jul 29 2013, 09:57
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 15
Регистрация: 2-07-12
Пользователь №: 72 586



Цитата(jcxz @ Jul 29 2013, 12:46) *
1. При объявлении переменной, задаёте ей альтернативный сегмент. Для IAR:
static __no_init int var[N] @ ".eeprom";
или
static const int var[N] @ ".eeprom";
2. В командном файле линкёра компонуете ваш сегмент (.eeprom) в нужные адреса EEPROM.

Не понятно, можно пример, или объяснить.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 29 2013, 09:59
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Так я же привёл пример. wacko.gif
Go to the top of the page
 
+Quote Post
=F8=
сообщение Jul 29 2013, 10:52
Сообщение #6


Знающий
****

Группа: Свой
Сообщений: 567
Регистрация: 7-07-07
Из: Донецк
Пользователь №: 28 954



Цитата(paravozru @ Jul 29 2013, 12:57) *
Не понятно, можно пример, или объяснить.


в .icf
define symbol __region_SEGMENT_NAME_start__= 0xXXXXXXXX;
define symbol __region_SEGMENT_NAME_end__ = 0xXXXXXXXX;
define region SEGMENT_NAME_region= mem:[from __region_SEGMENT_NAME_start__ to __region_SEGMENT_NAME_end__];
place in SEGMENT_NAME_region { section SEGMENT_NAME };

в .с
#pragma segment="SEGMENT_NAME"

#pragma location="SEGMENT_NAME"
int a;
или
int b @ "SEGMENT_NAME";

а еще лучше

struct eeprom_t{
Сюда добавляем все, что хотим хранит в еепром
};
и затем
#pragma location="SEGMENT_NAME"
struct eeprom_t eeprom;
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 29 2013, 11:03
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(=F8= @ Jul 29 2013, 16:52) *
в .с
#pragma segment="SEGMENT_NAME"

А это зачем? Этого не надо.
Go to the top of the page
 
+Quote Post
=F8=
сообщение Jul 29 2013, 11:23
Сообщение #8


Знающий
****

Группа: Свой
Сообщений: 567
Регистрация: 7-07-07
Из: Донецк
Пользователь №: 28 954



Цитата(jcxz @ Jul 29 2013, 14:03) *
А это зачем? Этого не надо.

Мдя... а ведь точно не надо. Когда-то давно то-ли в описании линкера увидел, то-ли в примере каком, ну в общем оно появилось, да так и пошло из проекта в проект sm.gif.
Вспомнил, мне надо было кусок памяти из датафлеш в эту секцию кидать, соответственно нужны были __section_begin/end. Вот так и остался этот некрокусок.
Go to the top of the page
 
+Quote Post
paravozru
сообщение Jul 29 2013, 12:27
Сообщение #9


Участник
*

Группа: Участник
Сообщений: 15
Регистрация: 2-07-12
Пользователь №: 72 586



Цитата(=F8= @ Jul 29 2013, 15:23) *
Мдя... а ведь точно не надо. Когда-то давно то-ли в описании линкера увидел, то-ли в примере каком, ну в общем оно появилось, да так и пошло из проекта в проект sm.gif.
Вспомнил, мне надо было кусок памяти из датафлеш в эту секцию кидать, соответственно нужны были __section_begin/end. Вот так и остался этот некрокусок.

Вот по поводу примера "=F8=" я сталкивался что переменные хранят как struct:, но все равно переменной uint8_t выделяется 2 байта в памяти. Я и думал возможность применения универсальной функции "template" для оптимизации пространства EEPROM, что бы каждому типу переменной выделялся соответствующий размер. И кстати функция чтения и записи в данном примере оперирует только с uint16_t
Вот пример действующий :
struct eeprom { // Структура разнотипных данных
vu16 MyModBusAdr; //0
vu16 MyHartAdr; //2
vu16 MyCanAdr; //4
vu8 IPadr[4]; //6
vu8 Result[4]; //8
}

uint8_t SetEEPROMData (uint16_t address, uint16_t Value) { функция записи в struct eeprom
тело функции;
}

Ох спасибо, начинает доходить, к сож с подобным образом хранения данных в EEPROM я не встречался, ( по опыту разбора чужих прошивок), я постараюсь разобраться. И способ c template возможен ?
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jul 29 2013, 13:43
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



я сделал файл EEPROM который пихает данные и читает данные из еепром.

функции у него

Код
read_data(void * var, unsigned adr,  unsigned len);
write_data(void * var, unsigned adr,  unsigned len);

и все... Дальше дефайнами размечаю память

Код
#define BASE_ADDR 0x0000
#define VAR1_ADDR BASE_ADDR
#define VAR2_ADDR (BASE_ADDR + sizeof(Var1))


или просто напрямую без sizeof в уме высчитываю и все...


запись-чтение
Код
read_data((void *)&var1, VAR1_ADDR, sizeof(var1));
write_data((void *)&var2, VAR2_ADDR, sizeof(var2));



зачем шаблоны то? Для некоторых частых переменных делаю макросы.



Go to the top of the page
 
+Quote Post
paravozru
сообщение Jul 29 2013, 13:48
Сообщение #11


Участник
*

Группа: Участник
Сообщений: 15
Регистрация: 2-07-12
Пользователь №: 72 586



Цитата(Golikov A. @ Jul 29 2013, 17:43) *
я сделал файл EEPROM который пихает данные и читает данные из еепром.
...

Просто хочется более рационального подхода и по больше использовать возможности C++. Кстати кто какие С++ возможности использует ? например class ? знаю как работает но не знаю как полезно применить.

Сообщение отредактировал IgorKossak - Aug 1 2013, 06:30
Причина редактирования: бездумное цитирование
Go to the top of the page
 
+Quote Post
=F8=
сообщение Jul 29 2013, 14:50
Сообщение #12


Знающий
****

Группа: Свой
Сообщений: 567
Регистрация: 7-07-07
Из: Донецк
Пользователь №: 28 954



Цитата(paravozru @ Jul 29 2013, 15:27) *
но все равно переменной uint8_t выделяется 2 байта в памяти.

Если беспокоит плотность упаковки то

#pragma pack(1)
struct eetrom_t{
...........
};
#pragma pack()

В этом случае все будет паковаться байт к байту. В этом случае работать с переменными можно только напрямую т.е. eeprom.var = xx или xx = eeprom.var. Но не int *p = &eeprom.var; *p = 10;
Go to the top of the page
 
+Quote Post
paravozru
сообщение Jul 30 2013, 05:18
Сообщение #13


Участник
*

Группа: Участник
Сообщений: 15
Регистрация: 2-07-12
Пользователь №: 72 586



Цитата(=F8= @ Jul 29 2013, 12:01) *
А теперь подставьте вместо eeType к примеру char и что вы получите?...

Да вот проблема Keil ругается на template <typename eeType> "this declaration has no storage class or type specifier". не могу заставить работать, хотя в Visual Studio без пролбем.

На сколько я понимаю __no_init, segment, location, pack это директивы препроцессора ? Огромное спасибо всем по поводу советов размещения переменных в EEPROM.

Сообщение отредактировал IgorKossak - Aug 1 2013, 06:30
Причина редактирования: бездумное цитирование
Go to the top of the page
 
+Quote Post
paravozru
сообщение Jul 30 2013, 11:34
Сообщение #14


Участник
*

Группа: Участник
Сообщений: 15
Регистрация: 2-07-12
Пользователь №: 72 586



в .icf
define symbol __region_EEPROM_start__= 0x08080000; // __region_EEPROM_start__= начало EEPROM таак можно записать ? и что значит symbol ?
define symbol __region_EEPROM_end__ = 0x08080FFFF; // допустим так
define region SEGMENT_NAME_region= mem:[from __region_EEPROM_start__= to __region_EEPROM_end__]; // что значит эта запись region
place in SEGMENT_NAME_region { section SEGMENT_NAME };

в .с
#pragma segment="SEGMENT_NAME"

#pragma location="SEGMENT_NAME"
int a;
или
int b @ "SEGMENT_NAME";

а еще лучше

struct eeprom_t{
Сюда добавляем все, что хотим хранит в еепром
};
и затем
#pragma location="SEGMENT_NAME" // а что указывается тут ?! адрес куда размещается struct ? .
struct eeprom_t eeprom;[/quote]
Объясните плиз, если честно не знакомо такое объявление и где можно прочитать о таком способе ?

Сообщение отредактировал paravozru - Jul 30 2013, 11:35
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Jul 30 2013, 11:41
Сообщение #15


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(paravozru @ Jul 30 2013, 14:34) *
#pragma location="SEGMENT_NAME" // а что указывается тут ?! адрес куда размещается struct ? .

Имя секции, в которой будет размещена структура.
Секция либо одна из предопределенных, либо размеченная самостоятельно.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th June 2025 - 21:36
Рейтинг@Mail.ru


Страница сгенерированна за 0.01503 секунд с 7
ELECTRONIX ©2004-2016