testerplus (01.10.2008 19:53, просмотров: 169) ответил MBedder на Вообще-то условно пропускать ulnk/return - дело ответственное, нужно обеспечить обязательное исполнение таковых где-либо после пропуска. И сам факт непропуска по btsc выглядит подозрительно - покажи-ка лучше весь код
Код огромадный. Я портировал кооперативную RTOS под MCC30. При отключенной оптимизации в каждую функцию в начало и в конец самим MCC30 вставлялись lnk и ulnk, соотв. И я, поторопившись и приняв это как должное, передавал управление планировщику с учетом этой особенности комплятора (могу расписать механизм подробнее). А выяснилось, что эти lnk и ulnk так безусловно и везде вставляются только при отключенной оптимизации. При включенной же - они появляются только там, где нужно, т.е. не везде.
В результате появились сбои стека.
Сейчас я переделываю так, чтобы работало в любом случае. При инициализации системы выясняю, есть ли lnk в функциях передачи управления планировщику и выставляю для каждой свой бит (всего 5 таких функций).
Попадая в такую функцию из задачи, я достаю адрес возврата и сохраняю его в блок управления задачей. Так вот, если MCC30 вставил в начало этой функции lnk, то мне, чтобы достать адрес возврата, нужно выполнить ulnk. Каждый раз читать память на предмет наличия lnk в начале функции - долго, поэтому заведены 5 битовых переменных. По ним я и смотрю, нужет unlk или нет, для чего и использовал инструкцию btsc.
При включенной оптимизации получалось так, что в функцию передачи управления планировщику можно было попасть с нулевым W14, здесь и происходил ресет.
Вот одна из таких функций; она короткая, но отдельно от программы не очень понятная:
/************************************************************************/
/* Возврат в планировщик без сохранения адреса возврата */
/************************************************************************/
void _OS_SchedRetPointNoSave (void)
{
asm volatile(" btsc _OS_Flags, #11 "); // bOSSchedRPNS_LNK
asm volatile(" ulnk ");
//--------------------------------------------------------
asm volatile(" mov __OS_CurTask, w0 ");
asm volatile(" pop.d w2 "); // Вытаскиваем адрес вызвавшей задачи
//--------------------------------------------------------
asm volatile("OS_RETURN_SAVE_STACK: ");
asm volatile(" mov w15, w4 "); // Сохраняем указатель стека
asm volatile(" mov [w0 + #4], w15 ");
asm volatile(" mov w4, [w0 + #4] ");
asm volatile(" btsc _OS_state, #7 "); // bLNK
asm volatile(" pop w14 ");
asm volatile(" return ");
}
Первая проверка теперь заменена на:
asm volatile(" btss _OS_Flags, #11 "); // bOSSchedRPNS_LNK
asm volatile(" bra OS_RPSN_SKIP_ULNK ");
asm volatile(" ulnk ");
asm volatile("OS_RPSN_SKIP_ULNK: ");
Ресеты прекратились.