ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Воскресенье
19 мая
133284 Топик полностью
testerplus (01.10.2008 19:53, просмотров: 153) ответил 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: "); Ресеты прекратились.