Omnicake 0 17 мая, 2014 Опубликовано 17 мая, 2014 · Жалоба Здравствуйте. Обнаружил в своем проекте ошибку, и никак не могу понять, в чем причина. Сначала опишу то, где это возникает: Я делаю простейший переключатель задач, используя Keil Uvision и процессор STM32. Диспетчер срабатывает от прерывания таймера и в зависимости от статуса и значения «количества шагов» либо выходит из прерывания на нужную задачу, либо переключается на следующую. Реализовано это таким образом: 1. Массив указателей на задачи. TaskPointer DCD TaskTableStart TaskTableStart DCD ddd1 DCD ddd2 DCD ddd3 DCD ddd4 TaskTableEnd END Где ddd – указатель на задачу, вида: ddd1={1,1,4,0,(int*)task1,(int*)task1,(int*)Stack_task1,(int*)Stack_task1}; Первое число это статус, второе количество шагов, также есть указатели на метки задачи и метку стэка задачи. В стэк, для того чтобы из прерывания корректно выходило в задачу, изначально дописываю такие числа: int Stack_task1[512]={0xfffffff9,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,(int*)task1,(int*)task1,0x21000000}; Структура полностью повторяет то, что делает Cortex-M3 при срабатывании прерывания (0 поставил на месте регистров R1-R4,R12 так как их состояние при первом запуске неважно) При входе в прерывание диспетчер вызывается так Systick_Handler { PUSH {LR} BL scheduler POP {pc} } Вызов задачи делаю так: LDR r0, =TaskPointer LDR r0, [r0] LDR r0, [r0] MOV r1, r0 LDR SP, [r1,#24] BX LR Тем самым после BX LR идет выход из диспетчера на команду POP {pc} и срабатывает выход из прерывания на задачу по метке записанной в стэке. Смену указателей на задачу делаю прибавлением 4 битов к текущему адресу и записью в TaskTableStart. Тем самым перед следующим срабатыванием диспетчера указатель заменяется. Задачи task1, task2, task3, task4 абсолютно идентичны (отличаются только метками) . И вот тут возникает проблема со стэками этих задач. При первом срабатывании диспетчер подгружает указатель и стэк для первой задачи и запускает ее, выходя из прерывания и потом вновь приходит на прерывание. Вид стэка задачи при первом заходе на прерывание и втором (после выполнения команды PUSH {LR} приведены на рисунках. Как видно все отработало нормально и число 0xfffffff9 осталось на месте. Однако при переключении на вторую задачу и выполнение тех же самых действий получается вот так: Причем если выбрать адрес за 4 бита до метки до число 0xfffffff9, используемое для выхода из прерывания окажется там. Однако так как я вызываю стэк по метке при выполнении команды POP {pc} туда грузится там самая 0x00000001 и уводит в ошибку. Причем самое интересное, если поменять порядок указателей например на TaskTableStart DCD ddd1 DCD ddd3 DCD ddd2 DCD ddd4 То сработает первая задача, переключится на третью, третья переключится на вторую и та опять выдаст ошибку. Понять такую ненависть программы к двойке я не могу, потому спрашиваю здесь. Почему в случае с первой задачей стэк по метке оказался без изменений, а во втором случилась такая беда? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
A. Fig Lee 0 17 мая, 2014 Опубликовано 17 мая, 2014 · Жалоба Проще всего наверное, скачать CoOX, там простенькая ассемблерная программка переключения и сравнить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 17 мая, 2014 Опубликовано 17 мая, 2014 · Жалоба да уже обсуждали, ноги растут оттуда, откуда не надо качать какос и другой ОС.... Теперь вопрос, что есть за 4 бита до? Имелось ввиду за 4 байта? То есть у первой задачи стэк сохраняется куда надо, а у второй смещено на 1 слово 4 байтное в памяти? А если стэки именно на это слово? Может там есть какое дурное правильно на выравнивание адресов? Указатель стэка на последние НЕ пустое слово в обоих задачах? Может в какой-то ошиблись? я вот сейчас поглядел документацию.... LDR r0, =TaskPointer LDR r0, [r0] LDR r0, [r0] MOV r1, r0 LDR SP, [r1,#24] BX LR это выглядит странно, в r0 пихаете метку TaskPointer (адрес я так понимаю) в r0 пихаете данные по адресу r0, то есть фактически адрес TaskPointer зачем опять LDR r0, [r0] ? и почему это все в итоге пихается в указатель стэка, и даже если каким то образом вы получили указатель стэка, почему оно пихается смещено на 24, когда после прерывания стэк увеличивается на 32? ну и как то странно выглядят данные в стэке, здесь http://infocenter.arm.com/help/index.jsp?t...a/BABIJDIC.html другая последовательность... ну и константа у вас F9, то есть работа с основным стэком.... думаю из за неправильного смещения в стэке после первой задачи вы возвращаетесь сдвинуто, и запуск второй задачи выбирает криво... все таки я бы разделил стэки и Маин стэк использовал для нужд ОС, а задачам раздал бы программ стэки. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Omnicake 0 17 мая, 2014 Опубликовано 17 мая, 2014 (изменено) · Жалоба Второй LDR r0, [r0] грузит метку TaskTableStart ее адрес смещен на 4 байта относительно TaskPointer и используется как активный указатель плюс его адрес потом записывается по достижению конца списка. По поводу возвращения из 1 задачи я уже написал: я поставил последовательность - 1,3,4,2 задача. Они все отработали нормально до 2ой. Меня смущает, что все указатели и описания задач при этом абсолютно одинаковы и отличаются лишь номером. А на 24 смещено, из за того что в ddd1 со смещением на 24 байта лежит указатель на стэк задачи, которым я командой LDR sp, [r1,#24] подменяю текущий. Изменено 17 мая, 2014 пользователем Omnicake Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 192 17 мая, 2014 Опубликовано 17 мая, 2014 · Жалоба А если стэки именно на это слово? Может там есть какое дурное правильно на выравнивание адресов? Указатель стэка на последние НЕ пустое слово в обоих задачах? Может в какой-то ошиблись? Я думаю ТС-у и невдомёк, что Cortex-M3 может опционально выравнивать стек на 8 при выполнении стекинга (при прерывании). А всё потому, что "не читатель, а писатель..." :smile3046: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 17 мая, 2014 Опубликовано 17 мая, 2014 · Жалоба вот оно как.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться