Указатель функции на определенную память

#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 по желанию.)