2015-07-29 3 views
1

У меня есть простая и быстрая проблема с C в компиляторе PIC24f16ka102 и xc16.Переменный адрес в пространстве eeprom как аргумент функции в C

Я хочу передать переменную ссылку на мою функцию. Переменный находится в ЭСППЗУ пространстве:

int __attribute__ ((space(eedata))) eeData; // Variable located in EEPROM,declared as a global variable. 

С этой последовательностью я могу сохранить некоторые данные в ЭСППЗУ:

unsigned int offset; 
// Set up NVMCON to erase one word of data EEPROM 
NVMCON = 0x4004; 
// Set up a pointer to the EEPROM location to be erased 
TBLPAG = __builtin_tblpage(&eeData2); // Initialize EE Data page pointer 
testDebug = TBLPAG; 

offset = __builtin_tbloffset(&eeData); // Initizlize lower word of address 
__builtin_tblwtl(offset, 0x9876); // Write EEPROM data to write latch 
asm volatile ("disi #5"); // Disable Interrupts For 5 Instructions 
__builtin_write_NVM(); // Issue Unlock Sequence & Start Write Cycle 
while(NVMCONbits.WR == 1); 

Таким образом, я пишу значение 0x9876 для первых 16 битых ППЗА. Но мне нужно, чтобы иметь его в качестве &eeData

Я хочу написать свою собственную функцию:

void eeprom_writeWord(unsigned int __attribute__ ((space(eedata))) addresOfMyEEpromVariable, unsigned int value) 
{ 
    unsigned int offset; 
// Set up NVMCON to erase one word of data EEPROM 
NVMCON = 0x4004; 
// Set up a pointer to the EEPROM location to be erased 
TBLPAG = __builtin_tblpage(&addresOfMyEEpromVariable); // Initialize EE Data page pointer 
offset = __builtin_tbloffset(&addresOfMyEEpromVariable); // Initizlize lower word of address 
__builtin_tblwtl(offset, value); // Write EEPROM data to write latch 
asm volatile ("disi #5"); // Disable Interrupts For 5 Instructions 
__builtin_write_NVM(); // Issue Unlock Sequence & Start Write Cycle 
while(NVMCONbits.WR == 1); 
} 

но Как передать свой адрес в качестве аргумента функции, так что моя функция будет видеть, что он по-прежнему адресу в эпром пространство? Это не может быть просто адрес, потому что если я получаю ошибку. Для функций __builtin необходим адрес с некоторым атрибутом, который является памятью eeprom.

Как передать адрес eeprom с атрибутом моей функции? Пожалуйста, помогите

редактировать:

Спасибо за совет, но я все еще получаю ту же ошибку:

error: Argument to __builtin_tbloffset() is not the address 
of an object in a code, psv, or eedata section; 

функции встроенные функции __builtin_tblpage нужен адрес памяти EEPROM, а не только адрес чего-то , Он работает хорошо, если я использую всю последовательность, но не в функции (я имею в виду последовательность в моем первом сообщении).

Теперь я попытался, как Вы сказали:

void eeprom_writeWord(unsigned int *addresOfMyEEpromVariable, unsigned int value) 
{ 
     //write word 
// Set up NVMCON to write one word of data EEPROM 
NVMCON = 0x4004; 
// Set up a pointer to the EEPROM location to be written 
TBLPAG = __builtin_tblpage(*addresOfMyEEpromVariable); 
unsigned int offset = __builtin_tbloffset(*addresOfMyEEpromVariable); 
// Write Data Value To Holding Latch 
__builtin_tblwtl(offset, 0x9999); 
// Disable Interrupts For 5 Instructions 
asm volatile ("disi #5"); 
// Issue Unlock Sequence & Start Write Cycle 
__builtin_write_NVM(); 
while(NVMCONbits.WR == 1); 
} 

или даже без знака '*':

void eeprom_writeWord(unsigned int *addresOfMyEEpromVariable, unsigned int value) 
{ 
     //write word 
// Set up NVMCON to write one word of data EEPROM 
NVMCON = 0x4004; 
// Set up a pointer to the EEPROM location to be written 
TBLPAG = __builtin_tblpage(addresOfMyEEpromVariable); 
unsigned int offset = __builtin_tbloffset(addresOfMyEEpromVariable); 
// Write Data Value To Holding Latch 
__builtin_tblwtl(offset, 0x9999); 
// Disable Interrupts For 5 Instructions 
asm volatile ("disi #5"); 
// Issue Unlock Sequence & Start Write Cycle 
__builtin_write_NVM(); 
while(NVMCONbits.WR == 1); 
} 

Результат все тот же. __builtin_tblpage и другие функции __builtin _ (...) - это функции, встроенные в компилятор xc16.

+0

Начните с форматирования кода! –

ответ

0

Рассмотрим этот прототип:

void eeprom_writeWord(unsigned int addresOfMyEEpromVariable, unsigned int value) 

атрибут, вероятно, не делать ничего здесь, опущены для удобства чтения. То, что вы делаете, не принимает адрес (который будет иметь тип unsigned int *), но само значение (простой unsigned int, это не волшебный указатель, просто вызвав его addressOfSomething;)), поэтому он просто копируется в вашу функцию.

Изменить его к следующему

void eeprom_writeWord(unsigned int *addresOfMyEEpromVariable, unsigned int value) 

И использовать как этот

eeprom_writeWord(&eeData, 0x9876); 

И, конечно же, не следует использовать оператор AddressOf & внутри функции больше ... Потому что сейчас вы уже есть указатель. Затем это сделает то, что вы ожидали.

Редактировать: Что касается вашего ответа, вы должны удалить это (потому что это не ответ) и вместо этого отредактировать исходный вопрос и поместить его туда.

Версия без звездочек является правильной. Не зная ваш компилятор, он может помощи, чтобы иметь атрибут в вашем прототипе функции, а также:

void eeprom_writeWord(
    unsigned int __attribute__ ((space(eedata))) *addresOfMyEEpromVariable, 
    unsigned int value) 

Просто говоря без звездочку там (маркировка аргумента как указатель), это, безусловно, не может работать.

+0

Спасибо за совет, но я все равно получаю ту же ошибку: – cwanish

+0

Пожалуйста, прочтите мое обновление здесь ... –

+0

Все еще не помогло. Если у вас есть какая-то другая идея, пожалуйста, дайте мне знать. Спасибо за ваши ответы. Спасибо большое :) – cwanish

1

Возможно, что встроенные процедуры могут обрабатывать жестко закодированные адреса (как в вашем первом примере - компилятор/компоновщик знает, где находится eeData), но не может иметь дело с адресами переменных.

Две вещи, которые вы можете попробовать:

(1) сделать eeprom_writeWord инлайн функцию (так что еще раз, компилятор может жестко закодировать адрес). Обратите внимание, что если это будет работать, оно все равно будет работать для «сложных» ситуаций, таких как адреса, хранящиеся в индексированных массивах.

(2) Посмотрите на код ассемблера, сгенерированный для встроенных подпрограмм в вашем рабочем образце, и перепишите их для чего вы хотите (используя C или встроенный ассемблер). Эти процедуры - это всего лишь несколько инструкций. например __builtin_tblpage просто снимает верхнюю часть адреса - что-то легко выполняется на C с маскировкой и/или сдвигами вправо.

Смежные вопросы