|
|
|
Начало работы with scmRTOS, Несколько вопросиков |
|
|
|
Mar 5 2008, 04:55
|
Adept
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343
|
Цитата(Сергей Борщ @ Mar 4 2008, 22:02) Где определяется A90_PROC_OPTION я не нашел - ни в исходниках, ни в описании ассемблера. Неопределенный символ считается равным нулю. Можно предположить, что перед этим должна быть (утерянная) строка Код #define A90_PROC_OPTION ((__TID__ >> 4) & 0x0F) Действительно, косяк. Как он вкрался, не помню хоть убей. Пофиксено. P.S. Лишний раз "порадовался" "красоте" иаровского подхода - поменял имя МК и началось... Регистра TIMSK там уже нет, вместо него есть TIMSK0 и т.д. Я понимаю, что одного регистра не хватает, но зачем было имя-то менять? Пусть бы для совместимости осталось. То же самое касается TCCR0, которого уже тоже нет, а есть два с буквами на конце. Почему бы было не оставить для совместимости старое имя? Не понимаю. И уж зачем вообще было менять имя вектора ANA_COMP_vect на ANALOG_COMP_vect? А если заменили, то и вставили бы код для совместимости. И такие косяки у них с незапамятных времен. Такое впечатление, что о портировании кода даже внутри семейства они вообще не думают, а заголовки для разных процов лабают разные люди, которые никак свои действия друг с другом не координируют. Про упомянутое /* SREG */ #define I 7 #define T 6 #define H 5 #define S 4 #define V 3 #define N 2 #define Z 1 #define C 0 я вообще молчу - яркий образчик бездумного подхода и безответственности. Причем что интересно - это не у всех процов есть такое определение, а только у избранного круга: iom164.h iom324.h iom644.h iom644p.h iopwm2.h iopwm3.h Т.е. больше похоже на чью-то личную инициативу, нежели на общий подход. Бардак, короче.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Mar 5 2008, 07:36
|
Знающий
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447
|
Цитата(dxp @ Mar 5 2008, 08:55) Регистра TIMSK там уже нет, вместо него есть TIMSK0. Бардак, короче. Вот только мне не понятно для чего добавили 0 в имена битов SPI ? Цитата /* SPSR */ #define SPIF0 7 #define WCOL0 6 #define SPI2X0 0
/* SPCR */ #define SPIE0 7 #define SPE0 6 #define DORD0 5 #define MSTR0 4 #define CPOL0 3 #define CPHA0 2 #define SPR01 1 #define SPR00 0 Не может же быть несколько SPI-интерфейсов на борту... Или может? Мне кажется, что это они скорее сделали по привычке... Хотя в даташите указаны "правильные" имена. По поводу регистра TIMSK0... Почему не исправлено? Добавить то всего три строчки. Цитата #ifndef TIMSK0 #define TIMSK TIMSK0 #endif Если гора не идет к Магомету, то Магомет идет к горе Цитата(dxp @ Mar 5 2008, 08:55) Действительно, косяк. Как он вкрался, не помню хоть убей. Еще не начал работать с OS, а уже отлавливаю косяки. То ли еще будет Цитата(IgorKossak @ Mar 5 2008, 00:09) Сдаётся мне, что если откроете overview завтра, то там окажется завтрашнее число. Точно Цитата(alux @ Mar 4 2008, 20:09) Имеет ли значение уровень оптимизации компилятора для smcRTOS ? Дело в том, что у jacOS есть примечание для IAR C/EC++ for AVR 4.11A/W32 : Цитата Вероятны проблемы при установке опций оптимизации Code motion (?) Cross Call (?) И последнее. Рискну задать глупый вопрос. Если в проекте используется прерывание, но оно не является источником события для процессов, обязательно ли обработчик прерывания должен иметь тип OS_INTERRUPT и на входе ISR создавать объект OS::TISRW_SS ISRW ? И можно ли разрешать глобальные прерывания до OS::Run() ?
|
|
|
|
|
Mar 5 2008, 10:49
|
Гуру
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095
|
Цитата(alux @ Mar 5 2008, 09:36) Вот только мне не понятно для чего добавили 0 в имена битов SPI ? Не может же быть несколько SPI-интерфейсов на борту... Или может? Я думаю что может. И скорее всего добавление 0 вызвано тем, что они начали таки движение в сторону унификации. Для новых кристаллов биты и регистры будут "пронумерованы" а старые потихоньку вымрут. Процесс перехода всегда сложный, но что поделать... Цитата(alux @ Mar 5 2008, 09:36) Еще не начал работать с OS, а уже отлавливаю косяки. То ли еще будет Вы же понимаете, что мы не можем проверить наши исходники на всех возможных процессорах Мы можем только предполагать, что раз программа работает на ATmegaX (LPC2xxx, BFxxx и т.д.), то она будет работать и на ATmegaY (LPC2yyy, BFyyy и т.д.), потому что все AVR (LPC2, BF и т.д.) похожи. К сожалению, они похожи не во всем, отсюда и такие косяки. Чем больше их найдете вы - тем меньше их останется тем, кто будет использовать ее после вас. Кроме того, я, например, уже не работаю с ADuC70xx и STR71x, порты для которых написал. Для STR71x у меня не осталось железа, на котором я мог бы проверить вносимые изменения. Поэтому исправления найденных в других портах багов или улучшения переносятся в этот порт без проверки. Вы бы что предпочли - старую версию, в которой есть известные глюки или новую, в которой они исправлены, но, возможно, внесены новые? Цитата(alux @ Mar 5 2008, 09:36) Рискну задать глупый вопрос. Если в проекте используется прерывание, но оно не является источником события для процессов, обязательно ли обработчик прерывания должен иметь тип OS_INTERRUPT и на входе ISR создавать объект OS::TISRW_SS ISRW ? При отсуствиии в этом прерывании разрешения вложенных - нет, не обязательно. Но помните о размере стека - прерывание будет работать на стеке текущего процесса, значит стеки всех процессов надо будет увеличить на размер, требуемый прерыванию. Если использовать ISRW_SS, то для прерываний организуется отдельный стек, но за это надо платить увеличением времени обработки прерывания. Цитата(alux @ Mar 5 2008, 09:36) И можно ли разрешать глобальные прерывания до OS::Run() ? Если в разрешаемых прерываниях не используются сервисы ОС, их обработчики не имеют OS::TISRW(__SS), то можно, но зачем?
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Mar 5 2008, 11:14
|
Adept
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343
|
Цитата(alux @ Mar 5 2008, 13:36) Почему не исправлено? Добавить то всего три строчки. Это должы добавлять те, кто модифицируют код. Чтобы для пользователя было прозрачно и портирование рабочего кода на новый кристалл проходило по максимуму безболезненно. Цитата(alux @ Mar 5 2008, 13:36) Если гора не идет к Магомету, то Магомет идет к горе Цитата(alux @ Mar 5 2008, 13:36) Еще не начал работать с OS, а уже отлавливаю косяки. То ли еще будет Уже начали. Кстати, у меня эта ошибка не проявилась. Видимо, потому, что вектор достал до адреса. В любом случае этот не опасный баг - он отлавливается на этапе сборки. Вот те, которые при сборке не проявляются, а на рантайме вылезают - эти опасные. Цитата(alux @ Mar 5 2008, 13:36) И можно ли разрешать глобальные прерывания до OS::Run() ? Можно. Но зачем? Ведь после OS::Run() управление будет передано сразу процессам, они загрузят свои стеки и свои значения регистра SREG, поэтому разрешение прерываний до запуска оси смысла имеет мало. Если только не планируете долго сидеть до запуска, чтобы успеть по прерываниям попрыгать.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Mar 6 2008, 06:53
|
Группа: Новичок
Сообщений: 9
Регистрация: 15-02-08
Пользователь №: 35 076
|
Цитата(Сергей Борщ @ Mar 5 2008, 14:49) Но помните о размере стека - прерывание будет работать на стеке текущего процесса, значит стеки всех процессов надо будет увеличить на размер, требуемый прерыванию. Как узнать максимальное потребление стека задачами? Можно ли проинициализировать все стеки каким-либо значением вроде 0xA5, как в FreeRTOS, и главное, как сделать это проще всего в scmRTOS? Или например в бутлоадере забить всю память байтами 0xA5, а затем прыгать на начало основной программы?
|
|
|
|
|
Mar 6 2008, 13:26
|
Гуру
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095
|
Цитата(Сергей С. @ Mar 6 2008, 08:53) Как узнать максимальное потребление стека задачами? Можно ли проинициализировать все стеки каким-либо значением вроде 0xA5, как в FreeRTOS, и главное, как сделать это проще всего в scmRTOS? Память стеков уже по умолчанию проинициализирована значением, только не 0xA5 а 0. В портах для ARM на верхушке контекста лежит содержимое CPSR, который не может быть равен нулю (конструкция у него такая). Поэтому я смотрю визуально (отладчиком или через терминал), где первый "не-ноль" - там было занято. Если есть желание забить каким-то своим значением - допишите memset в конструктор TProcess. Цитата(Сергей С. @ Mar 6 2008, 08:53) Или например в бутлоадере забить всю память байтами 0xA5, а затем прыгать на начало основной программы? Не пройдет - стеки попадают в область глобальных неинициализированных переменных и cstartup обнуляет эту область.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Mar 6 2008, 20:14
|
Группа: Новичок
Сообщений: 9
Регистрация: 15-02-08
Пользователь №: 35 076
|
Цитата(Сергей Борщ @ Mar 6 2008, 17:26) Если есть желание забить каким-то своим значением - допишите memset в конструктор TProcess. Всего одна строчка кода - а сколько пользы! Вся память как на ладони. Спасибо.
|
|
|
|
|
Mar 9 2008, 21:15
|
Знающий
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447
|
Мне не понятно, почему для генерации программного прерывания удобней использовать прерывание от аналогового компаратора? На мой взгляд лучше и удобней использовать внешнее прерывание. Во-первых, приоритет у него выше. Во-вторых, у большинства мк есть прерывния PCINT (pin change interrupt). Таким образом можно назначить практически любой вывод под это дело. В третьих, для переключения вывода в противоположное состояние достаточно записать PINy |= (1<<PINx); т.е. атомарную операцию SBI PINy, X. И было бы неплохо, чтобы в конфигурационном файле была возможность выбора источника программного прерывания: от компаратора или от внешнего прерывния. И также назначить символические имена выводам, которые используются для прерывания. В общем, максимально "загрузить" препроцессор, чтобы пользователь делал минимум телодвижений. И ошибок...
|
|
|
|
|
Mar 10 2008, 01:42
|
Гуру
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095
|
Цитата(alux @ Mar 9 2008, 23:15) Мне не понятно, почему для генерации программного прерывания удобней использовать прерывание от аналогового компаратора? На мой взгляд лучше и удобней использовать внешнее прерывание. Во-первых, приоритет у него выше. Исторически сложилось, как самое ненужное. Приоритет ему как раз нужен в идеале самый низкий. ReAl в своем порте реализовал переключение по прерыванию SPM, в этом случае нога не нужна вообще. Цитата(alux @ Mar 9 2008, 23:15) В третьих, для переключения вывода в противоположное состояние достаточно записать PINy |= (1<<PINx); Посмотрите порт ReAl, в нем (до SPM) было реализовано именно такое поведение - если процессор умеет перекидывать ногу одной командой, компаратор срабатывал от каждого перепада. Цитата(alux @ Mar 9 2008, 23:15) И было бы неплохо, чтобы в конфигурационном файле была возможность выбора источника программного прерывания: от компаратора или от внешнего прерывния. Это и так реализовано - все функции, завязанные на прерывание переключения контекста находятся в файле scmROS_Target_cfg.h, который находится в папке приложения.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Mar 10 2008, 04:40
|
Знающий
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447
|
Цитата(Сергей Борщ @ Mar 10 2008, 05:42) Приоритет ему как раз нужен в идеале самый низкий. Почему? Цитата(Сергей Борщ @ Mar 10 2008, 05:42) ReAl в своем порте реализовал переключение по прерыванию SPM, в этом случае нога не нужна вообще. Так нужно как минимум три маш. цикла на переключение. Пытаюсь настроить переключение по прерыванию PCINT. Сделал следующее: Код #if scmRTOS_CONTEXT_SWITCH_SCHEME == 1
INLINE inline void RaiseContextSwitch() { PINC |= (1 << PINC7); // PORTB |= (1 << 3); PORTB &= ~(1 << 3); // set flag } INLINE inline void BlockContextSwitch() { PCMSK2 &= ~(1 << PCINT23); } // disable interrupt //{ ACSR &= ~(1 << ACIE); } // disable interrupt Как изменится в таком случае этот кусок? Код class TNestedISRW { public: INLINE TNestedISRW() : State(ACSR) { BlockContextSwitch(); __enable_interrupt(); } INLINE ~TNestedISRW() { __disable_interrupt(); ACSR = State; if(State & (1 << ACI)) RaiseContextSwitch(); } private: byte State; }; Не судите строго, я еще не совсем ориентируюсь в объектно-ориентированном программировании
|
|
|
|
|
Mar 10 2008, 09:08
|
Нечётный пользователь.
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417
|
Цитата(alux @ Mar 10 2008, 06:40) Почему? Так нужно как минимум три маш. цикла на переключение. Потому что если вдруг возникнет ещё какое-то прерывание от аппаратуры, оно должно быть обработано, а оно задержится на время переключения контекстов. У задачи, на которую идёт переключение, это прерывание от аппаратуры хоть так, хоть сяк (хоть до переключения, хоть сразу после) время заберёт, т.е. она всё равно реально начнёт работать позже. А само будет задержано переключателем контекстов. А "три цикла"... По сравнению с сотнями на собственно переключение - что три (in/ori/out для SPMCSR в IO), что два (sbi PIN для компаратора либо PCINT), что четыре (sbi PORT/cbi PORT либо in/ldi/eor/out для компаратора на старых кристаллах), что пять (lds/ori/sts для SPMCSR вне адресов IO) - на практике несущественны. Хотя можно в примеры вернуть (под условную компиляцию либо в разные примеры разный метод) и прерывание от компаратора (хотя у меня он имеет больше шансов быть занятым, чем PCINT), и даже PCINT, хоть я не хотел использовать именно потому, что оно слишком приоритетное. Кроме того, это блокирует использование PCINT от других ног этого порта. Цитата Пытаюсь настроить переключение по прерыванию PCINT. Сделал следующее: Код INLINE inline void BlockContextSwitch() { PCMSK2 &= ~(1 << PCINT23); } // disable interrupt //{ ACSR &= ~(1 << ACIE); } // disable interrupt Кстати, где как, но если уж считать такты, то у меги168 PCMSK* расположены в области памяти и работа с ними сожрёт весь выигрыш от sbi PIN по сравнению с in SPMCSR/ori/OUTSPMCSR. А в tiny85 у меня как-то рука не поднимается scmRTOS ставить, на 512 байтах ОЗУ только демонстрашку сделать можно. Да и там работа с SPMCSR и PCINT по сумме баллов мало отличаться будут. Я бы для PCINT сделал что-то в духе (для той же меги168), всё равно остальные PCINT из этого порта как входы прерываний использовать нельзя: Код #define PCINT_PIN C,7,H #define PCINT_BIT PCIE2
#if scmRTOS_CONTEXT_SWITCH_SCHEME == 1
INLINE inline void RaiseContextSwitch() { CPL(PCINT_PIN); }
INLINE inline void BlockContextSwitch() { PCICR &= ~(1 << PCINT_BIT); } // disable PCINT interrupt
class TNestedISRW { public: INLINE TNestedISRW() : State(PCICR) { BlockContextSwitch(); sei(); } INLINE ~TNestedISRW() { cli(); if( State & (1 << PCINT_BIT) ) PCICR |= (1 << PCINT_BIT); } private: byte State; }; Естественно, где-то в начале (до вызова OS::Run()) надо настроить разрешение для нужной ноги.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Mar 10 2008, 09:56
|
Знающий
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447
|
Спасибо за разъяснение. Маленькое уточнение: sbi PINC, 0x01 занимает один такт. В моем проекте на Меге324P есть один лишний вывод на PC7. Вот я к PCINT и "привязался". Хотя после вышесказанного возможно настрою на SPM. Вывод дороже... Прокомментируйте, пожалуйста, этот код Цитата(ReAl @ Mar 10 2008, 13:08) class TNestedISRW { public: INLINE TNestedISRW() : State(PCICR) { BlockContextSwitch(); sei(); } INLINE ~TNestedISRW() { cli(); if( State & (1 << PCINT_BIT) ) PCICR |= (1 << PCINT_BIT); } private: byte State; };[/code] Не понятно в строке конструктора : State(PCICR). PS. Кстати, только что обратил внимание, у Меги324P SPMCSR находится по адресу 0x37. Т.е можно применять команды IN / OUT. А PCMSK2 - 0x6D. Т.е. уже только ST/STS/STD и LD/LDS/LDD. Наверное в данном случае лучше применить прерывание от SPM . PS2. Решил попробовать вариант с SPM. Код #if defined(SPMCSR) #define SPM_CONTROL_REG SPMCSR #elif defined(SPMCR) #define SPM_CONTROL_REG SPMCR #else #error "SPM control register not defined" #endif Компилятор выдает ошибку Код Fatal Error[Pe035]: #error directive: "SPM control register not defined" Хотя файл <ioavr.h> подключен. Как правильно определить SPMCSR ? Неужели просто перед #if defined(SPMCSR) написать #define SPMCSR ?
|
|
|
|
|
Mar 10 2008, 15:36
|
Нечётный пользователь.
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417
|
Цитата(alux @ Mar 10 2008, 11:56) Маленькое уточнение: sbi PINC, 0x01 занимает один такт. В моем проекте на Меге324P есть один лишний вывод на PC7. Вот я к PCINT и "привязался". Хотя после вышесказанного возможно настрою на SPM. Вывод дороже... Я уже думал, что я серьёзно отстал от жизни и mega324P отличается от других AVR-ок. Глянул в описание - sbi/cbi выполняются за два такта. Под рукой нет для проверки. Цитата Прокомментируйте, пожалуйста, этот код Не понятно в строке конструктора : State(PCICR). Инициализация поля State значением PCICR (это не совсем одно и то же, что State = PCICR; в теле конструктора). Цитата PS2. Решил попробовать вариант с SPM. ... Компилятор выдает ошибку Код Fatal Error[Pe035]: #error directive: "SPM control register not defined" Хотя файл <ioavr.h> подключен. Как правильно определить SPMCSR ? Неужели просто перед #if defined(SPMCSR) написать #define SPMCSR ? Кто такой ioavr.h ? Имеется ввиду <avr/io.h> ? Только что взял снапшот http://scmrtos.ginps.com/scmrtos-avr-gcc-snapshot.rarраспаковал, заменил в 1-EventFlag/makefile тип процессора: MCU := atmega324p всё скомпилировалось. Не знаю, в чём может быть проблема. -------- Тьху, это, наверно, IAR ? Ну тогда ничем не могу помочь, у меня его на компе нет.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Mar 10 2008, 16:00
|
Знающий
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447
|
Цитата(ReAl @ Mar 10 2008, 19:36) Глянул в описание - sbi/cbi выполняются за два такта. Прошу прощения. Заработался ..Не туда глянул Действительно 2 такта. А вопрос с ошибкой компиляции я перенес в другой (IAR) форум. Не могу одолеть. Ну в смысле, если просто везде заменить TIMSK на TIMSK0 , то все OK. А вот для SPMCSR просто тупо вставил Код #include <ioavr.h> #define SPMCSR
#if defined(SPMCSR) #define SPM_CONTROL_REG SPMCSR #elif defined(SPMCR) #define SPM_CONTROL_REG SPMCR #else #error "SPM control register not defined" #endif Но это же за уши притянуто.. Хочется принципиально для себя решить этот вопрос.
|
|
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|