Сергей Борщ 143 17 мая, 2006 Опубликовано 17 мая, 2006 · Жалоба Послушал советы, кое-чего поправил. Сделал targets для AT91SAM7S64(RAM/Flash) и LPC2119(RAM/FLASH). В качестве стека прерываний теперь используется стек main(), процесс Idle как обычный со своим стеком. Исходники самой ОС взял от последней версии 2.04а. Надеюсь, возможность попробовать порт на LPC увеличит активность отзывов/советов. Вопрос с симулятором остается открытым. По моим понятиям все же он некорректно отрабатывает LDMFD LR, {R0-LR}^. Попробую выяснить этот вопрос в отдельной ветке. scmRTOS_ARM.zip Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 17 мая, 2006 Опубликовано 17 мая, 2006 (изменено) · Жалоба Странно, но почему-то в моем макете с AT91SAM7S64 при отладке через MT-Link перегрузки CPSR не происходит. Могу попробовать на LPC2119, но не думаю что будет большая разница. Совсем забыл. Перезагрузка CPSR происходит только когда процессор находится не в USER или SYSTEM режиме. Потому что в этих режимах регистра SPSR вообще нет. Команда как бы некорректная, хотя процессор не падает. И ещё. Прочитать (загрузить в CPSR) можно только SPSR текущего режима. Запись в SPSR - аналогично. Даже если в команде явно будет указан регистр SPSR из другого режима. Непонятно только, зачем ассемблер разрешает так писать. У вас вообще по какому событию происходит переключение? А для чего или кого вообще пишите? Изменено 17 мая, 2006 пользователем GetSmart Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 17 мая, 2006 Опубликовано 17 мая, 2006 (изменено) · Жалоба Странно, но почему-то в моем макете с AT91SAM7S64 при отладке через MT-Link перегрузки CPSR не происходит. Могу попробовать на LPC2119, но не думаю что будет большая разница. Совсем забыл. Перезагрузка CPSR происходит только когда процессор находится не в USER или SYSTEM режиме. Все это понятно. На это я с самого начала нарвался :-) У меня эта команда выполнятеся в IRQ_mode. Но все же я настаиваю, что восстановление CPSR происходит только в одном варианте команды: когда стоит крыжик (^) И в списке регистров есть R15(PC). При этом восстанавливаются регистры в банке соотв. режима исключений. Если же в команде стоит крыжик и R15 в списке нет, то восстанавливаются регистры user(system) банка и CSPR не восстанавливается. Или другими словами: если в списке LDM есть R15, то крыжик означает восстановление CSPR, если R15 нет - то крыжик означает восстановление в _user регистры. Детализируя: LDMxx {R13-R15}^ восстанавливает R13_mode, R14_mode, PC, SPSR_mode->CPSR LDMxx {R13-R14}^ восстанавливает R13_user, R14_user Именно так происходит в железе (LPC2119 тоже проверил). Можете проверить. Симулятор же отрабатывает эту команду иначе. Я не вижу ничего незаконного в этой команде поэтому продолжаю считать что в этом случае симулятор явно ошибается. Даже если в команде явно будет указан регистр SPSR из другого режима. Непонятно только, зачем ассемблер разрешает так писать. Ассемблер не позволяет их указывать. Это в описании ядра они имеют такие обозначения. У вас вообще по какому событию происходит переключение?Планировщик взводит бит программного прерывания в контроллере прерываний. А для чего или кого вообще пишите? Для себя :-) Готовлю почву для новых проектов. FreeRTOS не понравилась чрезмерными требованиями к ОЗУ и кривизной написания. scmRTOS использовал в одном проекте на MSP430, понравилась. Из кристаллов под рукой есть макетки с SAM7 и LPC, есть еще ADuС, но на нем пока только пример из иара запускал. Ближайшие 2 проекта будут на ADuC и LPC. Изменено 17 мая, 2006 пользователем Сергей Борщ Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 17 мая, 2006 Опубликовано 17 мая, 2006 · Жалоба Смотрите, что я нарыл: (цитата из книжки) Бит S используется для управления (обновления, по-моему) флагами условий. Если этот бит установлен, флаги условий изменяются в соответствии с результатом выполнения команды. Если этот бит сброшен, состояние флагов условий не меняется. Однако, если при установленном бите S в качестве регистра результата указан R15 производится копирование содержимого SPSR текущего режима в регистр CPSR. Эта возможность используется для восстановления РС и переключения в исходный режим в конце обработки исключительных ситуаций. Не пытайтесь выполнить такую команду в режиме User (System забыли!), поскольку в этом режиме отсутствует регистр SPSR и соответственно результат выполнения этой команды невозможно предсказать. ___________________________ Я так понял, что бит S и есть эта галочка (^). В командах она означает обновление арифметических флагов в CPSR после выполнения команды, если результат не в R15. Если же в R15, то обновится весь CPSR значением из SPSR. __________________________ Проверил в отладчике IAR 4.20 Команда с битом S типа SUBS R15,R0,R0 перегружает R15 и SPSR копирует в CPSR. А команда SUBS R1,R0,R0 обновляет только арифметические флаги в CPSR. Команда LDRxx Rx,{R0}^ вообще не меняет регистр CPSR. Тем более, что арифметической операции и нет. Команда LDRxx Rx,{...,R15}^ копирует SPSR в регистр CPSR. Всё это я проделывал находясь в IRQ режиме, а в SPSR был SYSTEM. В командах STMxx эта галочка (^) вообще ни на что не влияет, даже если указан R15. Хотя, может и нет. Надо это ещё проверить. ___________________________ А нафига вы её решили использовать без регистра R15 ? Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 17 мая, 2006 Опубликовано 17 мая, 2006 · Жалоба Касательно файла Target_LPC2xxx.h "#define CONTEXT_SWITCH_INT VIC_SW" - Использовать отдельное прерывание (VIC_SW) не обязательно, если у вас так же прерывать задачу может таймер. Для этого я принудительно вызывал прерывание от таймера такой командой: VICSoftInt = (1 << VIC_TIMER1) Внутри обработчика прерывания таймера не забудьте сбросить этот бит, а то зависнет. Если же таймер не переключает задачи, то всё нормально. Так писать не нужно: "VICIntEnable |= (1<<CONTEXT_SWITCH_INT);" Через этот регистр можно только устанавливать биты, но не сбрасывать. Поэтому пишите так: VICIntEnable = (1<<CONTEXT_SWITCH_INT); А эта конструкция вообще убьёт всю систему: "#define BlockContextSwitchMacro() do { \ VICIntEnable &= ~(1<<CONTEXT_SWITCH_INT); \ } while (0) // disable context switching interrupt " Для сброса бита разрешения конкретного прерывания есть другой регистр. Надо так: VICIntEnClear = (1<<CONTEXT_SWITCH_INT); Кстати, зачем пишите "do {...} while (0)" ??? Для чего timer 0, match 0 используете? Поосторожней пользуйтесь битовым доступом к регистрам. Иногда из регистров читается не то, что хочется. Для справки, все свободные биты из 32 источников прерываний можно использовать для своих нужд через регистр VICSoftInt. Специально для этого сделан VIC_SW, но и остальные действуют аналогично. Я проверял. В одной проге аж 4 независимых софт-прерывания зафигачил. Кстати, у меня прерывание, переключающее задачи (которое я приводил) сделано так, что прерывания запрещены очень короткий момент и даже для 100 КГц прерываний ни одного не потеряется! Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 17 мая, 2006 Опубликовано 17 мая, 2006 · Жалоба Но все же я настаиваю, что восстановление CPSR происходит только в одном варианте команды: когда стоит крыжик (^) И в списке регистров есть R15(PC). При этом восстанавливаются регистры в банке соотв. режима исключений. Если же в команде стоит крыжик и R15 в списке нет, то восстанавливаются регистры user(system) банка и CSPR не восстанавливается. Или другими словами: если в списке LDM есть R15, то крыжик означает восстановление CSPR, если R15 нет - то крыжик означает восстановление в _user регистры. Детализируя: LDMxx {R13-R15}^ восстанавливает R13_mode, R14_mode, PC, SPSR_mode->CPSR LDMxx {R13-R14}^ восстанавливает R13_user, R14_user Именно так происходит в железе (LPC2119 тоже проверил). Можете проверить. Симулятор же отрабатывает эту команду иначе. Я не вижу ничего незаконного в этой команде поэтому продолжаю считать что в этом случае симулятор явно ошибается. Думаю вы правы. Однако у меня симулятор всё как надо сделал. Оказывается в командах LDM и STM когда указан ^ и нет R15 сохраняются и восстанавливаются регистры User/System. Можно даже не переключаться специально в эти режимы. А я и не знал! Команды "LDMFD LR, {R0-LR}^ ; NOP ; ADD LR, LR, #15*4" можно упростить до "LDMFD LR!, {R0-LR}^". У меня в отладчике нормально прошло. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 18 мая, 2006 Опубликовано 18 мая, 2006 · Жалоба Думаю вы правы. Однако у меня симулятор всё как надо сделал. Оказывается в командах LDM и STM когда указан ^ и нет R15 сохраняются и восстанавливаются регистры User/System. Можно даже не переключаться специально в эти режимы. А я и не знал! Ну вот хоть какая-то польза :-) Команды "LDMFD LR, {R0-LR}^ ; NOP ; ADD LR, LR, #15*4" можно упростить до "LDMFD LR!, {R0-LR}^". У меня в отладчике нормально прошло. Нет, нельзя. Если идет ^ и в качестве опроного используется банкируемый регистр то нельзя писать в него обратно и в следующем такте обращаться к нему тоже нельзя. Вот цитата из того же ARM DDI 0029E:R15 not in list and S bit set (User bank transfer) For both LDM and STM instructions, the User bank registers are transferred rather than the register bank corresponding to the current mode. This is useful for saving the user state on process switches. Base write-back should not be used when this mechanism is employed. When the instruction is LDM, care must be taken not to read from a banked register during the following cycle (inserting a dummy instruction such as MOV R0, R0 after the LDM will ensure safety). Да, вот из старого сообщения: А команды сохранения и восстановления контекста как бы парные (точнее префиксы stmDB и ldmIA). У вас они почему-то одни и те же. На самом деле это одни и те же команды, разработчики зачем-то дали этим командам по два имени " to support stacks or for other purposes." Так что STMDB == STMFD, LDMIA == LDMFD Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 18 мая, 2006 Опубликовано 18 мая, 2006 · Жалоба Не сочтите за 'наезд' - работа несомненно полезная! Однако не могу не отметить, что основная прадигма отлично реализованная в scmRTOS на типичном ARM смотрится уже не так привлекательно, как на AVR с полукилобайтом-килобайтом памяти. FreeRTOS не понравилась чрезмерными требованиями к ОЗУ и кривизной написания. В частности по этой причине не смог пройти спокойно мимо вышеотцитированого :-(. "Кривизну", в виду неопределенности формулировки, оставим в покое (хотя можем и побеседовать - тут есть подходящие ветки ) а по RAM.. Cобрал Ваш демо проект с тремя светодиодиками: Module CODE DATA CONST ------ ---- ---- ----- (Rel) (Rel) (Abs) (Rel) ?CMAIN 108 ?CSTARTUP 56 ?EnI_t 20 ?RESET + common 60 ?_EXIT 12 ?__dbg_break 2 ?__exit 18 ?cppinit 70 ?exit 14 ?segment_init 84 OS_Kernel 300 40 + shared 32 8 12 OS_Services 16 OS_Target_cpp 272 108 + shared 8 main 478 940 220 scmRTOS_Asm 132 + common 28 N/A (command line) 768 N/A (alignment) 10 ---------- ----- ----- --- -- Total: 1 624 1 856 236 12 + common 60 И под FreeRTOS такой-же: Module CODE DATA CONST ------ ---- ---- ----- (Rel) (Rel) (Abs) (Rel) ?CMAIN 80 ?CSTARTUP 476 ?DiI_t 32 ?EnI_t 16 ?RESET + common 64 ?_EXIT 12 ?__exit 2 ?exit 14 ?segment_init 84 ?strncpy 44 croutine + shared 12 heap 244 24 leds 76 8 + shared 4 list 174 ll_init 4 main 186 8 16 port 376 4 40 16 portasm 340 tasks 902 168 8 N/A (command line) 530 N/A (alignment) 10 ---------- ----- --- -- -- Total: 3 072 726 60 52 + common 64 Собственно разница по декларированному критическому ресурсу (RAM занимаемому ядром) отнюдь не впечатляет: scmRTOS = 0x148 байт FreeRTOS = 0x1AC Итого - 100(dec) байт. Не слишком большая плата за несколько отличающюся базовую функциональность и (личное мнение) за большую способность к доработкам. Причем, при "необходимости" можно убрать еще по 8 байт на задачу во FreeRTOS :-) Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 18 мая, 2006 Опубликовано 18 мая, 2006 · Жалоба Смотрите, что я нарыл: (цитата из книжки) ___________________________ Я так понял, что бит S и есть эта галочка (^). В командах она означает обновление арифметических флагов в CPSR после выполнения команды, если результат не в R15. Если же в R15, то обновится весь CPSR значением из SPSR. __________________________ Я пользуюсь оригинальной англоязычной документацией, но в данном случае в ней написано то же самое. Проверил в отладчике IAR 4.20 Команда LDRxx Rx,{R0}^ вообще не меняет регистр CPSR. Тем более, что арифметической операции и нет. В данном контексте (R15 нет) ^ означает доступ к user-банку. Но поскольку R0 небанкируемый, то в этом конкретном варианте наличие ^ не играет роли. Команда LDRxx Rx,{...,R15}^ копирует SPSR в регистр CPSR. Всё это я проделывал находясь в IRQ режиме, а в SPSR был SYSTEM. Вот тут появляется тонкость, которая не позволила мне восстановить весь контекст одной командой: если в списке есть R15, то ^ означает копирование SPSR в CPSR а не восстановление user-банка. Т.е. значения со стека попадут вместо необходимого мне SP_user, LR_user в SP_irq, LR_irq. Это ответ на А нафига вы её решили использовать без регистра R15 ? В командах STMxx эта галочка (^) вообще ни на что не влияет, даже если указан R15. Хотя, может и нет. Надо это ещё проверить. Влияет. В STM если есть галочка будут сохранены регистры user mode. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 18 мая, 2006 Опубликовано 18 мая, 2006 · Жалоба FreeRTOS не понравилась чрезмерными требованиями к ОЗУ и кривизной написания. В частности по этой причине не смог пройти спокойно мимо вышеотцитированого :-(. "Кривизну", в виду неопределенности формулировки, оставим в покое (хотя можем и побеседовать - тут есть подходящие ветки ) Объясню очень просто: указатели на любой объект передаются как void* что легко позволяет мне передать вместо указателя на семафор указатель на процесс или очередь. Зачем же в "языке высогага уровня Ц" был придуман контроль типов на этапе компиляции? Далее это же void * передается в другие функции место указателя соответствующего типа, а чтобы компилятор не выдавал предупреждения вместо элементарного создания локальной переменной нужного типа и приведения типа signed portBASE_TYPE xQueueSend( xQueueHandle xQueue, const void *pvItemToQueue, portTickType xTicksToWait ) { xQueuePtr pxQueue = xQueue; в описании предлагается задавить предупреждения этого типа в опциях компилятора. Причем предупреждения возникают при компиляции кода самой ОС. Что же это как не кривизна? а по RAM..46 байт на битовый семафор мне показалось расточительно. Они его реализуют как очередь из одного элемента нулевого размера. Да и на очередь 46 байт ОЗУ накладных "жаба душит". Cобрал Ваш демо проект с тремя светодиодиками: Собственно разница по декларированному критическому ресурсу (RAM занимаемому ядром) отнюдь не впечатляет: scmRTOS = 0x148 байт FreeRTOS = 0x1AC Итого - 100(dec) байт. Не слишком большая плата за несколько отличающюся базовую функциональность и (личное мнение) за большую способность к доработкам. Причем, при "необходимости" можно убрать еще по 8 байт на задачу во FreeRTOS :-) Я не отрицаю большого потенциала в FreeRTOS. Однако в моем примере из базовой функциональности был только один сервис Sleep(). Оно и понятно - надо было отладить переключатель контекста. Более серьезный пример идет в исходнике scmRTOS с сайта автора. Там есть и семафоры и очереди. Если есть желание - можем сравнить. Еще раз - я не хоче наступить на горло FreeRTOS, просто мне она субъективно не понравилась. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 18 мая, 2006 Опубликовано 18 мая, 2006 · Жалоба Касательно файла Target_LPC2xxx.h "#define CONTEXT_SWITCH_INT VIC_SW" - Использовать отдельное прерывание (VIC_SW) не обязательно, если у вас так же прерывать задачу может таймер. Для этого я принудительно вызывал прерывание от таймера такой командой: VICSoftInt = (1 << VIC_TIMER1) Внутри обработчика прерывания таймера не забудьте сбросить этот бит, а то зависнет. Если же таймер не переключает задачи, то всё нормально. Основной механизм - вытесняющая многозадачность. Таймер может вызвать переключение если истек тайм-аут какого-либо процесса. Так писать не нужно: "VICIntEnable |= (1<<CONTEXT_SWITCH_INT);" Через этот регистр можно только устанавливать биты, но не сбрасывать. Поэтому пишите так: VICIntEnable = (1<<CONTEXT_SWITCH_INT); А эта конструкция вообще убьёт всю систему: "#define BlockContextSwitchMacro() do { \ VICIntEnable &= ~(1<<CONTEXT_SWITCH_INT); \ } while (0) // disable context switching interrupt " Для сброса бита разрешения конкретного прерывания есть другой регистр. Надо так: VICIntEnClear = (1<<CONTEXT_SWITCH_INT); Каюсь, здесь я промухал. Посыпаю голову окурками :-) Кстати, зачем пишите "do {...} while (0)" ??? Это долгая история. Сначала увидел такую конструкцию в исходниках линукса и тоже был озадачен. Задал вопрос на сахаре и ReAl мне наглядно объяснил, что поскольку в макрос может быть добавлена еще одна команда то его лучше сразу заключить в {}, но макрос с {} нельзя использовать в лоб в конструкции if(cond) Macro(); else ....; а если добавить do while(0) то смысл не изменится но ограничений уже не будет. Для чего timer 0, match 0 используете?Системное время, ОС по нему считает тайм-ауты. Для справки, все свободные биты из 32 источников прерываний можно использовать для своих нужд через регистр VICSoftInt. Специально для этого сделан VIC_SW, но и остальные действуют аналогично. Я проверял. Угу, мне об этом говорили. Я, наивный, подумал что в атмеловском SAM7 так же. И тут же получил граблями в лоб - у атмела неиспользуемые биты не реализованы физически, т.е. "атакой, не атакуй...". С тех пор я слегка пуганый, и когда увидел в описании специально заточенный бит подумал "ВОТ!" и глубже решил не копать. Кстати, у меня прерывание, переключающее задачи (которое я приводил) сделано так, что прерывания запрещены очень короткий момент и даже для 100 КГц прерываний ни одного не потеряется! Я еще не измерял сколько у меня получилось время переключения - наверное сегодня выделю минутку. Вообще мы с автором scmRTOS обсуждали идею как сильно сократить время запрета прерываний, но пока это на уровне идеи - должно какое-то время повариться в мозгу. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 18 мая, 2006 Опубликовано 18 мая, 2006 · Жалоба Еще раз - я не хоче наступить на горло FreeRTOS, просто мне она субъективно не понравилась. Это пожалуй главное. Так бывает. Я тоже не в восторге от многого, но идеал при знании потрохов :-) недостижим, посему начал просто править "под себя" и под свой "вкус". А как "база" максимально устроила. Объясню очень просто: указатели на любой объект передаются как void* Ну такуж и на любой. Семафоры ака очередь это отдельная песня и при необходимости иметь оные несомненно буду встраивать 'семафористые' семафоры :-). Причем предупреждения возникают при компиляции кода самой ОС. Что же это как не кривизна? Это бардак :-(, такие места правлю, правда "легкой" c "наплевать на warnings" переносимости под разные компиляторы уже гарантировать нельзя. Более серьезный пример идет в исходнике scmRTOS с сайта автора. Там есть и семафоры и очереди. Если есть желание - можем сравнить. Нет, особого желания нет. Порядок "платы" ясен и меня совсем не смущают пару сот байт, особенно по отношению к размеру стеков (особенно при отсутствии даже простейших механизмов контроля обьема использования стека присутствующих в FreeRTOS) задач :-(. Кстати о стеках, на штатное (руками и так реализуется без напряга) нововведение FreeRTOS 4.x обратили внимание? Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 18 мая, 2006 Опубликовано 18 мая, 2006 · Жалоба Объясню очень просто: указатели на любой объект передаются как void* Ну такуж и на любой. Семафоры ака очередь это отдельная песня и при необходимости иметь оные несомненно буду встраивать 'семафористые' семафоры :-). typedef void * xQueueHandle; typedef xQueueHandle xSemaphoreHandle; typedef void * xTaskHandle; Собственно других открытых пользователю сервисов там вроде и нет. Более серьезный пример идет в исходнике scmRTOS с сайта автора. Там есть и семафоры и очереди. Если есть желание - можем сравнить. Нет, особого желания нет. Порядок "платы" ясен и меня совсем не смущают пару сот байт, особенно по отношению к размеру стеков (особенно при отсутствии даже простейших механизмов контроля обьема использования стека присутствующих в FreeRTOS) задач :-(. Надо будет этот вопрос изучить, спасибо за наводку. Кстати о стеках, на штатное (руками и так реализуется без напряга) нововведение FreeRTOS 4.x обратили внимание? Нет, я работал с 3.2.2, как проект сдал больше на FreeRTOS.org не заглядывал. Посмотрю обязательно, спасибо. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 18 мая, 2006 Опубликовано 18 мая, 2006 · Жалоба Команды "LDMFD LR, {R0-LR}^ ; NOP ; ADD LR, LR, #15*4" можно упростить до "LDMFD LR!, {R0-LR}^". У меня в отладчике нормально прошло. Нет, нельзя. Если идет ^ и в качестве опроного используется банкируемый регистр то нельзя писать в него обратно и в следующем такте обращаться к нему тоже нельзя. Вот цитата из того же ARM DDI 0029E: Если подумать, то обратная запись в этой команде происходит не в тот регистр, который восстанавливается из стека. Поэтому мне кажется, что всё должно нормально прокатить. А в документе просто не слишком подробно этот момент описан. Он в некотором смысле уникальный. Я бы на вашем месте реально попробовал так упростить и проверить прямо на проце. Тем более, что мой отладчик (IAR 4.20) это проглатил и не подавился. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 18 мая, 2006 Опубликовано 18 мая, 2006 · Жалоба typedef void * xQueueHandle; typedef xQueueHandle xSemaphoreHandle; typedef void * xTaskHandle; А здесь-то криминал-то в чем? Совершенно разные типы. Я 'дико извиняюсь', но это typedef а не define - любой компилятор находясь в твердом уме и здравой памяти обломает подмену безвариантно. Нет, я работал с 3.2.2, как проект сдал больше на FreeRTOS.org не заглядывал. Посмотрю обязательно, спасибо. Кстати :-) обратите внимание, там в переключении контекстов 'nop'-чик недавно добавился... Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться