Привет, я пишу немного модифицированный код для загрузчика для MCU. Модификация, которую я пытаюсь сделать, - это включить загрузчик даже для сброса сторожевого таймера.

Я использую этот прототип функции для определения адреса загрузчика и получаю сообщение об ошибке:

недопустимое преобразование из 'long int' в 'void (*) ()' [-fpermissive]

Мой код

#if defined ( __AVR_ATmega1284P__ )
    void (*boot_start)(void) = 0xF000;
#elif defined ( __AVR_ATmega2560__ ) 
    void (*boot_start)(void) = 0x1F000;
#endif

Где 0xF000 и 0x1F000 - это области памяти. Я не получаю эту ошибку, если мой код - `

void (*boot_start)(void) = 0x0000;

Почему ??

1
Srini Vardhan 24 Фев 2016 в 11:28

3 ответа

Лучший ответ

Компилятор распознает 0xF000 как int и отменяет присвоение этого значения указателю. Вы должны явно указать это:

void (*boot_start)(void) = (void (*)())0xF000;
3
Yuriy Orlov 24 Фев 2016 в 08:35

Ответ, который я получил с форума AVRFreak,

ИСПОЛЬЗУЙТЕ TYPEDEF,

typedef void (*fptr_t)(void);

fptr_t boot_start = (fptr_t)0xF000;

...
  boot_start();

В противном случае вы получаете предупреждение, потому что 0xF000 является длинным int для AVR. Слева от '=' был указатель на функцию. Итак, вы пытаетесь присвоить указателю целое число. C думает, что это, вероятно, ошибка (часто это так!), И предупреждает вас. Чтобы подавить это предупреждение, нужно сказать: «Нет, это число 0xF000 действительно является значением указателя». Вы делаете это с помощью приведения типов. Теперь вы можете сделать это (подождите):

void (*boot_start)(void) = (void(*)(void))0xF000;

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

Если бы тип функции был более сложным, это могло бы быть даже примерно так:

int (*boot_start)(char, long, int *) = (int (*)(char, long, int *))0xF000;

И это действительно начинает выглядеть очень глупо - не только очень вероятно, что вы допустили опечатку, это просто попытка запомнить синтаксис здесь - настоящая боль! Итак, вы используете typedef, чтобы определить интерфейс функции только один раз:

typedef int (*myfn_t)(char, long, int *);

myfn_t boot_start  = (myfn_t))0xF000;

И это становится легче набирать и легче управлять. Если позже вы добавите в функцию четвертый параметр char **, вы сделаете это только в одном месте - typedef.

Спасибо Си Лоусону и Юрию.

0
Srini Vardhan 26 Фев 2016 в 07:00

0x0000 - это просто другое имя для NULL и будет нормально компилироваться как значение указателя, но другие значения необходимо явно привести к правильному типу.

3
Jim Buck 24 Фев 2016 в 08:34