uC/OS II + Philips ARM + IAR 4.30 = камасутра Все вроде как собрал, запускаю - проц вылетает в аборт. Начинаю копать... Вылет происходит при выполнении команды LDMFD SP!, {R0-R12, LR, PC} из асмописанной автором части порта под АРМ - запуска первой в жизни задачи оси, первое переключение контекста.
Для справки: Команда заполняет указанные регистры (r0-r12, lr(r14), pc(r15)) значениями из стека с постдекрементом SP(r13).
Приведу анализ этого фрагмента кода:
LDMFD SP!,{R4} ; pop new task's spsr
MSR SPSR_cxsf,R4
LDMFD SP!,{R4} ; pop new task's CPSR
MSR CPSR_cxsf,R4
LDMFD SP!,{R0-R12,LR,PC} ; pop new task's r0-r12,lr & pc
Первая строчка - выбираем из "стека" в регистр r4 новое значение для spsr регистра, второй строчкой обновляем его. Но это не важно, самое интерересное впереди.
Выбираем новое значение CPSR (Current Program Status Register) в r4. Интереса ради посмотрим его значение? Легко - 0x00000013 - разрешены и IRQ и FIQ прерывания и, главное, режим Supervisor. Смотрим текущее значение - 0xX00000DF - режим System!. Обновляем CPSR - как и пологается хорошему мальчику, процессор при смене режима подменяет SP, LR, SPSR для нового режима - в результате SP указывает куда угодно, кроме как туда куда он указывал в предудущем режиме. И, естесственно, выбраное из этого "нового стека" значение PC мало похоже на то, которое ожидается. Ага, причина вылета ясна - не тот режим работы, но почему? Ведь при старте (и после сброса) проц в режиме Supervisor согласно документации. Почему это он вдруг переходит в режим System? Копаем с самого начала и находим в самом начале - cstartup:
bic r0,r0,#MODE_BITS ; Clear the mode bits
orr r0,r0,#SYS_MODE ; Set System mode bits
msr cpsr_c,r0 ; Change the mode
Ага, нашли. Но вот незадача - зачем ИАР меняет режим? И как правильней обойти эту проблему? Поставить свой cstartup в котором сохраняется режим Supervisor или заставить uC/OS работать в режиме System? Проверка показала что оба варианта работают... Какой правильный? Или может кто-нибудь подскажет третий, действительно верный вариант?