Прошивка скомпилировалась и слинковалась!
Компилятор: XC8 v1.37 (PRO mode) - бесплатная лицензия от Microchip на 60 дней
Среда разработки: MPLAB X IDE v3.25
Проблема была в том, что память в этом микроконтроллере разделена на 4 страницы, каждая страница 2К слова (если нужно перейти по адресу, находящемуся на другой странице, то необходима дополнительная команда смены страницы). Компилятор подготавливает так называемые psect (раздел памяти) в которых объединены функции. Если я правильно понимаю, то это такие своеобразные "чёрные ящики", которые компилятор отдаёт линковщику в виде объектных файлов, чтобы тот их разместил в памяти. Так как эти объектные файлы не могут находиться на стыке двух страниц, то есть пересекать их, то может возникнуть ситуация, когда памяти вроде бы хватает, но линковщик отказывается размещать "чёрные ящики", говоря, что максимальная не занятая область внутри страниц меньше, чем то, что необходимо разместить.
Следовательно чтобы решить данную проблему, необходимо разбить "чёрные ящики" на части. Я это сделал при помощи спецификатора __section(), который добавил у больших функций, чтобы компилятор подготовил для них отдельный psect и линковщик мог разместить их в памяти по своему желанию.
Да, при использовании данного метода, у меня съелось около 160 слов. Они были использованы компилятором для смены страниц при переходах.
Собственно вот пример:
Код
void __section("main") main (void) {
...
}
byte __section("settings") my_settings(byte mod){
...
}
Ну и позволю себе привести цитату из документации на компилятор:
Цитата
The __section() specifier may be used to indicate that an object should be located
in the named section (or psect, using the XC8 terminology). This is typically used when
the object has special and unique linking requirements which cannot be addressed by
existing compiler features.
Use the native keywords discussed in the Differences section to look up information on
the semantics of this specifier.
2.5.13.1 EXAMPLE
The following shows a variable which uses the __section keyword.
int __section("comSec") commonFlag;
2.5.13.2 DIFFERENCES
The 8-bit compilers have used the #pragma psect directive to redirect objects to a
new section, or psect. The operation of the __section() specifier is different to this
pragma in several ways, described below.
Unlike with the pragma, the new psect created with __section() does not inherit the
flags of the psect in which the object would normally have been allocated. This means
that the new psect can be linked in any memory area, including any data bank. The
compiler will also make no assumptions about the location of the object in the new section.
Objects redirected to new psects using the pragma must always be linked in the
same memory area, albeit at any address in that area.
The __section() specifier allows objects that are initialized to be placed in a different
psect. Initialization of the object will still be performed even in the new psect. This will
require the automatic allocation of an additional psect (whose name will be the same
as the new psect prefixed with the letter i), which will contain the initial values. The
pragma cannot be used with objects that are initialized.
Objects allocated a different psect with __section() will be cleared by the runtime
startup code, unlike objects which use the pragma.
You must reserve memory, and locate via a linker option, for any new psect created with
a __section() specifier in the current XC8 compiler implementation.
The 16- and 32-bit compilers have used the section attribute to indicate a different
destination section name. The __section() specifier works in a similar way to the
attribute.
Если кто то знает другое решение данной проблемы, прошу сообщить мне об этом.
Спасибо большое за помощь zltigo и остальным!