|
Шаблон (tamplete ) для работы с EEPROM |
|
|
|
Jul 29 2013, 06:42
|
Участник

Группа: Участник
Сообщений: 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
|
|
|
|
|
Jul 29 2013, 09:57
|
Участник

Группа: Участник
Сообщений: 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. Не понятно, можно пример, или объяснить.
|
|
|
|
|
Jul 29 2013, 10:52
|
Знающий
   
Группа: Свой
Сообщений: 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;
|
|
|
|
|
Jul 29 2013, 11:23
|
Знающий
   
Группа: Свой
Сообщений: 567
Регистрация: 7-07-07
Из: Донецк
Пользователь №: 28 954

|
Цитата(jcxz @ Jul 29 2013, 14:03)  А это зачем? Этого не надо. Мдя... а ведь точно не надо. Когда-то давно то-ли в описании линкера увидел, то-ли в примере каком, ну в общем оно появилось, да так и пошло из проекта в проект  . Вспомнил, мне надо было кусок памяти из датафлеш в эту секцию кидать, соответственно нужны были __section_begin/end. Вот так и остался этот некрокусок.
|
|
|
|
|
Jul 29 2013, 12:27
|
Участник

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

|
Цитата(=F8= @ Jul 29 2013, 15:23)  Мдя... а ведь точно не надо. Когда-то давно то-ли в описании линкера увидел, то-ли в примере каком, ну в общем оно появилось, да так и пошло из проекта в проект  . Вспомнил, мне надо было кусок памяти из датафлеш в эту секцию кидать, соответственно нужны были __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 возможен ?
|
|
|
|
|
Jul 29 2013, 13:43
|
Гуру
     
Группа: Свой
Сообщений: 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)); зачем шаблоны то? Для некоторых частых переменных делаю макросы.
|
|
|
|
|
Jul 29 2013, 13:48
|
Участник

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

|
Цитата(Golikov A. @ Jul 29 2013, 17:43)  я сделал файл EEPROM который пихает данные и читает данные из еепром. ... Просто хочется более рационального подхода и по больше использовать возможности C++. Кстати кто какие С++ возможности использует ? например class ? знаю как работает но не знаю как полезно применить.
Сообщение отредактировал IgorKossak - Aug 1 2013, 06:30
Причина редактирования: бездумное цитирование
|
|
|
|
|
Jul 29 2013, 14:50
|
Знающий
   
Группа: Свой
Сообщений: 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;
|
|
|
|
|
Jul 30 2013, 05:18
|
Участник

Группа: Участник
Сообщений: 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
Причина редактирования: бездумное цитирование
|
|
|
|
|
Jul 30 2013, 11:34
|
Участник

Группа: Участник
Сообщений: 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
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|