fk0, легенда (08.02.2013 18:12 - 20:23, просмотров: 4194)
PIC18 и callbacks (вообще любые функции вызываемые по указателю) для MCU с объёмом FLASH > 64КБайт вызывают проблемы (hitech-C 9.51pl2 с опцией --cp=16) известного плана: адрес функции шире собственно указателя и старшие биты обрезаются. С опцией --cp=24 эта проблема уходит, но приходят массово множество других, лучше сразу забыть. Остаётся такие функции вручную класть в сегмент lowtext. Проблема в том, что в итоге практически вся программа окажется в lowtext (на ту же область претендует и const, что совсем печально). Ибо #pragma psect text=lowtext действует на весь модуль в целом. В других компиляторах, более приличных, в таких случях используют промежуточную функции (вида jmp real_function), размещаемые в нижнем участке памяти. Можно поступить также:
#ifndef CONCAT
#define CONCAT(x, y) _CONCAT(x, y)
#define _CONCAT(x, y) x##y
#endif
#ifndef STRINGIFY
#define __STRINGIFY(str) #str
#define STRINGIFY(str) __STRINGIFY(str)
#endif
/* non static on PIC18 */
#define NSTATIC /* на других платформах NSTATIC=static */
/* для callback функций */
// ,global,reloc=2,class=LOWCODE
// asm(STRINGIFY(CONCAT(CONCAT(__end_of_,name),:)));
#define CB_GLOBAL global
#define CB_LOCAL local
#define CB_FUNC(cb_type, type, name, args) \
static type CONCAT(_,name) args; /* real function */ \
/* NO STATIC! */ type name args; /* proxy function */ \
asm("psect lowtext"); \
asm(STRINGIFY(cb_type) " " STRINGIFY(CONCAT(_,name))); \
asm("local " STRINGIFY(CONCAT(__,name))); /* make real function local */ \
asm("global " STRINGIFY(CONCAT(?__,name))); \
asm("dw " STRINGIFY(CONCAT(?__,name))); \
asm(STRINGIFY(CONCAT(CONCAT(_,name),:))); \
asm("goto " STRINGIFY(CONCAT(__,name))); \
asm("fncall " STRINGIFY(CONCAT(_,name)) "," STRINGIFY(CONCAT(__,name))); \
/* eliminate "unused function" error */ \
static const char CONCAT(__void_,__LINE__) = (unsigned long)CONCAT(_,name)&0; \
static type CONCAT(_,name) args /* real function */
Декларация (в месте определения функции) такая (пример):
CB_FUNC(CB_LOCAL, NSTATIC int, flash_writer, (char *buf, unsigned size))
{
...
return 0;
}
Для глобальных функций используется CB_GLOBAL и без NSTATIC. Принцип работы упомянут в тексте выше.
[ZX]