#function #memory #pointers #embedded
#функция #память #указатели #встроенный
Вопрос:
Я хотел бы попросить совета. Я работаю с небольшим встроенным uP.
Я хотел бы назначить свои различные функции структуре myfunctions. Как это сделать правильно? Затем я хочу поместить эту myfunctions (структуру указателей функций) на определенный адрес памяти (например, 0x1000). Какова наилучшая процедура для достижения этой цели?
typedef void (*fptr)(void);
typedef struct FCN_IMAGE
{
fptr fcn1;
fptr fcn2;
fptr fcn3;
} FUNC_T;
FUNC_T myfunctions;
На самом деле это должна быть своего рода таблица переходов.
Во-вторых, я хочу прочитать указатели на эту функцию из другой программы — непосредственно из указанного местоположения адреса (например, 0x1000).
Это означает, что первый код должен назначить структуру указателей на функции определенной ячейке памяти, а другой независимый код должен считывать эту таблицу из определенной памяти. Взаимосвязь между этими двумя программами должна быть
#define FCN_BASE_ADDRESS (0x1000)
Есть идеи, каков наилучший способ добиться этого?
PS Это будет выполняться на встроенном процессоре, а не на ПК.
Комментарии:
1. Я думаю, что это будет функцией вашего компоновщика.
2. частично вы правы, но должно быть достижимо поместить указатель функции в определенную ячейку памяти, чтобы компоновщик не участвовал.
3. Например, я не уверен, правильно ли это:
4. unsigned int volatile * fcn_base = (unsigned short *) FCN_BASE_ADDRESS *fcn_base = ;
5. FUNC_T * myfunctions; *порт = myfunctions->fcn1;
Ответ №1:
Поиск объектов в определенных местоположениях обычно проще всего выполняется с помощью специфичного для компилятора расширения; стандартного метода, определенного языком, не существует. Также может быть возможно найти глобальный объект в определенном месте, изменив сценарий компоновщика, но это будет зависеть от вашей конкретной цепочки инструментов
Какой компилятор / цепочку инструментов вы используете? Обратитесь к его документации.
Комментарии:
1. Я использую инструмент Freescale CodeWarrior, мне кажется, есть только один способ с помощью самого компоновщика. Так что все еще изучаю это…
2. @Pepe: «Codewarior» — это имя, которое Freescale использует для средств разработки (IDE) для всех их архитектур, оно ничего не говорит мне о том, какой компилятор вы используете. Однако я не уверен, что вы правы, посмотрите в документации, например, » Модификатор адреса глобальной переменной (@address) «.
3. @Pepe, Клиффорд ответил на ваш вопрос. Я использую Freescale Codewarrior, и
typename varname @address
формат — это способ делать то, что вы хотите.
Ответ №2:
Возможно, вам поможет следующее:
// assign my various functions to myfunctions struct
myfunctions.fcn1 = amp;YourFunction1;
myfunctions.fcn2 = amp;YourFunction2;
myfunctions.fcn3 = amp;YourFunction3;
// assign the struct of function pointers to specific memory location
memcpy((void*)FCN_BASE_ADDRESS, amp;myfunctions, sizeof(myfunctions));
// read this table from specific memory
memcpy(amp;myfunctions, (void*)FCN_BASE_ADDRESS, sizeof(myfunctions));
Это основано на моем предположении о том, что вы на самом деле хотите сделать.
Комментарии:
1. Я просто попробую. Код компилируется, как предложено, но не работает и не дает результатов. По конкретному адресу нет myfunctions . Возможно, memcpy не работает над этим (просто догадываюсь из-за указателя функции)…
2. @Pepe: memcpy — это memcpy; если это не сработало для вас, значит, вы неправильно поняли или неправильно применили решение. Это будет работать, если
FCN_BASE_ADDRESS
это не ROM. Однако существует более простой способ; еслиFCN_BASE_ADDRESS
имеет тип ‘FUNC_T *`, то к функциям можно получить доступ напрямуюFCN_BASE_ADDRESS->fcn1()
, например, через без второго memcpy() .
Ответ №3:
Это лучший способ решить эту проблему переносимым способом:
typedef void (*fptr)(void);
#define FCN_BASE_ADDRESS ((volatile fptr*)0x1000)
/* Make myfunctions an array, not a struct.
Structs can have padding and aren't portable.
It doesn't look like you need a struct in this case.
*/
fptr myfunctions [N] =
{
fptr fcn1;
fptr fcn2;
fptr fcn3;
};
memcpy(amp;FCN_BASE_ADDRESS, myfunctions, sizeof(myfunctions));
Хотя, если вы используете Codewarrior, вы, вероятно, могли бы использовать #pragma для их размещения там, где вы хотите. Вот пример, предполагающий, что они хранятся в оперативной памяти для чтения / записи и 32-разрядной адресной шине.
// .prm file
SECTIONS
MEM_FCN_BASE_ADDRESS = READ_WRITE 0x2000 TO 0x200C;
END
PLACEMENT
FCN_BASE_ADDRESS INTO MEM_FCN_BASE_ADDRESS;
END
// .c file
#pragma DATA_SEG FCN_BASE_ADDRESS
fptr myfunctions[N] = ...;
#pragma DATA_SEG DEFAULT
Если они должны храниться в ROM / flash, например, в векторной таблице, то это должно быть сделано по-другому с разделами READ_ONLY, #pragma CONST_SEG и const fptr
. (Обратите внимание, что ключевое слово const в C ведет себя иррациональным образом в сочетании с указателями typedef:ed. В этом случае я считаю, что это даст постоянный указатель на непостоянную функцию, и, следовательно, она должна оказаться в NVM по желанию.)