Первый фрагмент кода инициализирует все стеки для различных задач.
Сначала сохраняем ПК как адрес функции задачи (первая инструкция):
*(multistack) = (int) taskpnt[++i];
затем он сохраняет регистр состояния с включенным GIE (необходим для правильной функции переключения задач):
*(multistack-1) = GIE;
Эти два будут автоматически восстановлены reti, когда прерывание планировщика закончится.
Также сохраняется новый указатель стека для задачи (включая пространство для сохранения реестров):
taskstackpnt[i] = (int) multistack-26;
Второй фрагмент - это само прерывание планировщика.
ПК и SR автоматически сохраняются во время вызова прерывания.В коде прерывания реестр сохраняется для текущей задачи:
asm ("push R15\n push R14\n push R13\n push R12\n"
"push R11\n push R10\n push R9\n push R8\n"
"push R7\n push R6\n push R5\n push R4");
, затем программа сохраняет указатель стека для текущей задачи:
taskstackpnt[taskrun] = __get_SP_register();
и получает индекс указателя стека следующей задачи.:
if (++taskrun == tasks) taskrun = 0;
затем восстановите новый указатель стека задач:
__set_SP_register(taskstackpnt[taskrun]);
и извлеките реестры, сохраненные в стеке:
asm ("pop R4\n pop R5\n pop R6\n pop R7\n"
"pop R8\n pop R9\n pop R10\n pop R11\n"
"pop R12\n pop R13\n pop R14\n pop R15");
ПК и SR дляновое задание восстанавливается с помощью reti прерывания.
Новое задание готово к работе!