Цитата(733259 @ Dec 17 2008, 06:01)

правильнее __attribute__((signal,used)). К тому же вариант singlskv не универсален - переключаются векторы INT0, INT1, а если они нужны?
Следовательно, как компромисс, можно просто заюзать все неиспользуемые вектора.
Есть у меня еще в стадии тестирования субвекторизация. Допустим, у нас есть функция, при должном внимании к построению которой можно добиться, что она состоит из набора независимых блоков, между которыми компилятор не будет осуществлять операции по сохранению используемых регистров
Код
void foo(void)
{
{
block 1
}
//........
{
block N
}
}
Сделаем необходимый инструментарий
Код
typedef uint16_t pc_type; // пока обошел указатели стороной
uint8_t wherePC(void* pcreg) __attribute__((naked));
void setPC(pc_type newPC) __attribute__((naked));
/*Обертка для субвекторов*/
#define SubVector(t_name) if(wherePC(&t_name))
WherePC заточено таким образом, чтобы возвращать 0 при вызове, а в параметре - адрес, с которого ее вызывали, исключая обработку возвращаемого значения.
Код
void setPC(pc_type newPC)
{
asm volatile("ijmp" : : "z" (newPC));
}
uint8_t wherePC(void* pcreg)
{
asm volatile (
"pop r25" "\n\t"
"pop r24" "\n\t"
"adiw r24,2" "\n\t"
"st Z, r24" "\n\t"
"std Z+1,r25" "\n\t"
"movw r30,r24" "\n\t"
"sbiw r30,2" "\n\t"
"clr r24" "\n\t"
"ijmp" "\n\t"
::"z" (pcreg));
}
Используя SubVector(имя_переменной_указателя_на_блок)
Код
void foo(void)
{
static pc_type sv[3];
static uint8_t work = 0;
if(work)
{// код, использующий косв. переход на sv[n]
set_PC(sv[1]);
}
else
{
SubVector(sv[0])
{
block 1
}
SubVector(sv[1])
{
block 2
}
SubVector(sv[2])
{
block 3
}
work = 1;
}
return;
}
В итоге при первом вызове получаем адреса блоков кода в переменных sv[], но сами блоки не выполняем, по аналогии с setjmp, а при последующих вызовах - переходим в кратчайшие сроки к независимому блоку. В данном контексте это должно обеспечить выигрыш по сравнению со switch()
Просьба потестить эти примитивы и высказать мнения о применимости. Заранее спасибо.