Omnicake 0 12 мая, 2014 Опубликовано 12 мая, 2014 (изменено) · Жалоба Видимо действительно у меня нет понимания. Я решаю, извините за каламбур, задачу переключения задач в ассемблере. Для этого хотелось использовать прерывание от системного таймера, так как там вполне ясный и понятный режим срабатывания (время прошло - сработало прерывание - задача сменилась). Про PendSV мне удалось найти только информацию о том, что он пригодится при переключении задач. Но то как его вызывать, как он срабатывает и что делает - нет. Каким образом тогда построить стэк, чтобы при записи числа EXC он правильно подцеплялся? Изменено 12 мая, 2014 пользователем Omnicake Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 12 мая, 2014 Опубликовано 12 мая, 2014 · Жалоба Видимо действительно у меня нет понимания. Я решаю, извините за каламбур, задачу переключения задач в ассемблере. Для этого хотелось использовать прерывание от системного таймера, так как там вполне ясный и понятный режим срабатывания (время прошло - сработало прерывание - задача сменилась). Про PendSV мне удалось найти только информацию о том, что он пригодится при переключении задач. Но то как его вызывать, как он срабатывает и что делает - нет. Каким образом тогда построить стэк, чтобы при записи числа EXC он правильно подцеплялся? Понимаю тягу к ассемблеру Cortex-M, но считаю, что это всего лишь инструмент. Для переключения контекста не обязательно писать на Си или Асм - нужно разобраться в архитектуре. SysTick это всего лишь таймер, одинаковый для всех производителей микроконтроллеров на ядре Cortex-M. Для переключения задач Вам нужно либо в задаче вызавать системную функцию, в которой произойдет переключение. Либо переключить задачу по прерыванию. В том числе от таймера. В том числе от таймера SysTick. Можно переключать задачи в SysTick, но в случае, если SysTick у Вас с самым низким приоритетом - это гарантирует, что Вы точно знаете положение стекового кадра main. Можно использовать два стека, что в какой-то степени решит проблему вложенных прерываний. Но когда Вы сделаете такой переключатель задач по таймеру, вряд ли легко сможете переключать задачи где-либо еще. Задачи в некоторый случаях (где есть ассинхронная пауза) будут "тупить" до момента сработки таймера SysTick. Если в конце SysTick взводить PendSv (ровно как и в функциях ядра), то переключение будет: - гарантированно происходить после каждого срабатывания SysTick; - в функциях ядра; - гарантированно происходить до момента передачи управления в main. Идеально. Что при таком подходе Вам не нравится? На Асме красиво реализуется. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 12 мая, 2014 Опубликовано 12 мая, 2014 · Жалоба 1. PendSv - это просто особое прерывание, приоритет которого можно поставить минимальным, это позволит вам быть уверенным что в него вы попали из задачи а не из другого прерывания. В вашем случае PendSV и Прерывания таймера не различимы, задайте таймеру минимальный приоритет, и будет почти тоже самое. То есть во взрослых системах PendSV вызывается во многих случаях, те только через заданное время после прошлого вызова, у вас же только так. 2. LDR sp, [r1,#24];Загрузил стэк программы MOVW R2,#0x00d0; в котором по адресу 0x200000d0 MOVT R2,#0x2000; положил число 0xFFFFFFF9 LDR pc, [r2]; Загрузил его в PC чет я не понимаю:)... Видать я как то непонятно пишу... Попробую еще раз. если вы находитесь в hendlre режиме, как только вы в счетчик команд запишите 0xFFFFFFF9, обращаю внимание именно в счетчик команд, ни в стэк, ни в память, а именно в него. То процессор запустить процедуру выхода из hendler режима в thread режим (он не перейдет по указанному адресу, а запустить процедуру). В ходе этой процедуры процессор из стэка восстановит значения счетчика команд куда ему надо идти. При этом процессор будет использовать главный стэк в случае если на конце 9, и стэк программ если на конце D. В стэке к моменту записи магического числа должно лежать правильной последовательности PC, LR, r0-r3, и чего-то там еще, то есть полный набор сохраняемых данных для входа в прерывание. забудьте про регистр LR - он строго говоря вам не нужен, без вложенных прерываний, и без надобности вернуться в старую задачу он в целом нафиг не сдался... вам надо подменить указатель стека на стэк той задачи в какую вы идете, в стеке этой задачи должна лежать правильная структура, и записать магическое число. После этого проц сам из указаного стека выберет значение счетчика команд и пойдет по задаче. В следующем прерывании, процессор сам сохранит счетчик команд на каком моменте он остановился. И когда опять дойдет до вызова этой задачи, счетчик команд будет восстановлен из стэка. То есть в начале работы вам надо сделать задачи со своими локальными стэками положить в них структуру которая кладется когда вызовиться прерывание из этой задача, в место где хранится РС положить начало вашей задачи. далее в прерывании вам надо, сохранять PSP задачи из которой пришли, далее РSP устанавливать на стэк нвоой задачи, и записывать магическое число. Все! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
1113 5 12 мая, 2014 Опубликовано 12 мая, 2014 · Жалоба Про PendSV мне удалось найти только информацию о том, что он пригодится при переключении задач. Но то как его вызывать, как он срабатывает и что делает - нет.как систик, только вызывается не аппаратно а програмно там и тогда когда вам надо. этот эксепшен используют из мэйна для запуска операционки, то есть для входа в первую задачу. ну а все последующие переключения задач - в систик. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Omnicake 0 13 мая, 2014 Опубликовано 13 мая, 2014 · Жалоба вам надо сделать задачи со своими локальными стэками положить в них структуру которая кладется когда вызовиться прерывание из этой задача, в место где хранится РС положить начало вашей задачи. Локальные стэки я задал, в каждой задаче у меня прописано Stack_task1[512]. LDR sp, [r1,#24] как раз и грузить адрес метки Stack_task1. А по поводу если вы находитесь в hendlre режиме, как только вы в счетчик команд запишите 0xFFFFFFF9, обращаю внимание именно в счетчик команд, ни в стэк, ни в память, а именно в него. Может я чего-то не увидел, но напрямую через команду MOV в PC на Cortex M3 вроде бы писать нельзя, компилятор мне выдает ошибку. Да и в инструкции написано, что грузятся значения в PC только через LDR или POP, а для этого нужно магическое число куда-то положить (я и положил его в стэк задачи). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 13 мая, 2014 Опубликовано 13 мая, 2014 · Жалоба обращаемся к первоисточнику http://infocenter.arm.com/help/index.jsp?t...9125006491.html 1. есть мнение что LDR sp - изменит не PSP а MSP, вернее через sp вы вообще меняете 13 регистр, который по сути есть только отображение указателя стэка. А надо менять именно psp или msp 2. положили ли вы в стэк задач http://infocenter.arm.com/help/index.jsp?t...a/Babefdjc.html структуру как на рисуночке с указателями и прочей байдой, где в РС лежит первая команда задачи? А указатель показывает на последнюю непустую ячейку 3. Exception return occurs when the processor is in Handler mode and executes one of the following instructions attempts to set the PC to an EXC_RETURN value: an LDM or POP instruction that loads the PC an LDR instruction with PC as the destination a BX instruction using any register. EXC_RETURN - это магическое число. Причем 0xFFFFFFF9 - это возврат через MSP, а 0xFFFFFFFD это возврат через PSP Третий пункт вы вроде бы выполнили правильно (хотя я воспользовался бы командой BX, наверное), значит остается вопросы к 1, 2 пунктам.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Omnicake 0 13 мая, 2014 Опубликовано 13 мая, 2014 · Жалоба 1. Ну у меня и отображается активным MSP все это время, и до прерывания и внутри него. Командой LDR я меняю указатель на метку Stack_task1 - массив из 512 чисел, который я взял за стэк задачи. 2. Как корректно класть туда эту структуру? Заранее прописывать ее в массив в самой задаче или загонять через PUSH необходимые регистры? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 121 13 мая, 2014 Опубликовано 13 мая, 2014 · Жалоба в симуляторе я могу свободно просматривать память и пошагово следить за программой. После входа в прерывание у меня лежит LR возврата на main,Начните с чтения документации. В момент входа в обработчик исключения адрес возврата вместе с содержимым некоторых регистров кладется на стек. В LR заносится магическое число. Если вы наблюдаете в LR адрес возврата - выкиньте свой симулятор. Или вы попадаете в исключение каким-то нестандартным методом, вроде прямого вызова функции? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Omnicake 0 13 мая, 2014 Опубликовано 13 мая, 2014 · Жалоба В LR заносится магическое число. Если вы наблюдаете в LR адрес возврата - выкиньте свой симулятор. Или вы попадаете в исключение каким-то нестандартным методом, вроде прямого вызова функции? Тут возможно я недостаточно подробно описал, при входе в прерывание там действительно лежит число EXC_RETURN но затем, из за того что в обработчике у меня стоит вызов другой программы (а именно переключателя задач), он уходит на ту программу, помещая в LR адрес возврата. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 121 13 мая, 2014 Опубликовано 13 мая, 2014 · Жалоба он уходит на ту программу, помещая в LR адрес возврата.Так сохраните старое значение LR куда-нибудь. Например, на стек. И потом со стека восстанавливайте сразу в PC командой POP. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Omnicake 0 13 мая, 2014 Опубликовано 13 мая, 2014 · Жалоба Видимо это Keil uVision и делает: после того как я добавил ассемблерные вставки в main, написанный на C, он создал автоматически файл main.s и там функция SysTick_Handler { scheduler(); } Выглядит вот так SysTick_Handler PUSH {r4,lr} BL systick POP {r4,pc} Однако из-за того, что из systick я прыгаю на другую программу, POP {r4,pc} пропускается. Значит, судя по всему, нужно делать это внутри шедулера. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
1113 5 13 мая, 2014 Опубликовано 13 мая, 2014 · Жалоба Omnicake, ваше желание разобраться похвально, но такими темпами вы будете делать это ещё полгода. предлагаю вам почитать о coocox os. она написана очень просто, имеет документацию на русском, процедуры переключения контекста написаны на ассемблере, что позволит вам за несколько дней разобраться в сути вопроса. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Omnicake 0 13 мая, 2014 Опубликовано 13 мая, 2014 · Жалоба Хорошо. Спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 121 13 мая, 2014 Опубликовано 13 мая, 2014 · Жалоба Однако из-за того, что из systick я прыгаю на другую программу, POP {r4,pc} пропускается.Так вы вернитесь из "другой подпрограммы". Или, если не собираетесь возвращаться, переходите на SysTick не по BL, а по B. И в LR останется магическое число. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Omnicake 0 13 мая, 2014 Опубликовано 13 мая, 2014 · Жалоба Починил, правда, для меня, это шаманством осталось. Я говорил выше, что компилятор создает файл main.s вместо main.c, а так как внутри него я не мог ничего редактировать (он создан компилятором) я решил просто скопировать его и заменить им файл main.c, после этого когда я запустил в шедулере этот код: LDR r0, =TaskPointer LDR r0, [r0] LDR r0, [r0] MOV r1, r0 LDR sp, [r1,#24] BX lr При этом стэк для задачи я задал вручную вот так: int Stack_task1[512]={0x00000000,0xfffffff9,0x00000007,0xe000e000,0x200021e8,0x200021e8,0x200021 c4,0x08000211,0x08000212,0x21000000}; поместив в него нужные метки и то самое число. С этим стэком я уже запускал до этого (на main.c) и ничего не работало, однако тут удалось: после BX LR он вышел из шедулера на хэндлер, выполнил POP {pc} и прыгнул на задачу. Метод скорее всего "напролом" но от него уже можно плясать. Спасибо всем за советы и помощь, буду работать дальше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться