IgorKossak 0 4 марта, 2008 Опубликовано 4 марта, 2008 · Жалоба В overview XMK, которое можно найти в исходниках указана сегодняшняя дата (March 4, 2008). Выглядит подозрительно ;) Сдаётся мне, что если откроете overview завтра, то там окажется завтрашнее число. B) Имеет ли значение уровень оптимизации компилятора для smcRTOS ? Я всегда ставлю MAX. И я тоже. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 58 5 марта, 2008 Опубликовано 5 марта, 2008 · Жалоба Где определяется 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 Т.е. больше похоже на чью-то личную инициативу, нежели на общий подход. Бардак, короче. :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 5 марта, 2008 Опубликовано 5 марта, 2008 · Жалоба Регистра 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 Если гора не идет к Магомету, то Магомет идет к горе ;) Действительно, косяк. Как он вкрался, не помню хоть убей.Еще не начал работать с OS, а уже отлавливаю косяки. То ли еще будет ;) Сдаётся мне, что если откроете overview завтра, то там окажется завтрашнее число. B)Точно :) Имеет ли значение уровень оптимизации компилятора для smcRTOS ? Дело в том, что у jacOS есть примечание для IAR C/EC++ for AVR 4.11A/W32 : Вероятны проблемы при установке опций оптимизации Code motion (?) Cross Call (?) И последнее. Рискну задать глупый вопрос. Если в проекте используется прерывание, но оно не является источником события для процессов, обязательно ли обработчик прерывания должен иметь тип OS_INTERRUPT и на входе ISR создавать объект OS::TISRW_SS ISRW ? И можно ли разрешать глобальные прерывания до OS::Run() ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 5 марта, 2008 Опубликовано 5 марта, 2008 · Жалоба Вот только мне не понятно для чего добавили 0 в имена битов SPI ? Не может же быть несколько SPI-интерфейсов на борту... Или может? Я думаю что может. И скорее всего добавление 0 вызвано тем, что они начали таки движение в сторону унификации. Для новых кристаллов биты и регистры будут "пронумерованы" а старые потихоньку вымрут. Процесс перехода всегда сложный, но что поделать... Еще не начал работать с OS, а уже отлавливаю косяки. То ли еще будет ;)Вы же понимаете, что мы не можем проверить наши исходники на всех возможных процессорах :( Мы можем только предполагать, что раз программа работает на ATmegaX (LPC2xxx, BFxxx и т.д.), то она будет работать и на ATmegaY (LPC2yyy, BFyyy и т.д.), потому что все AVR (LPC2, BF и т.д.) похожи. К сожалению, они похожи не во всем, отсюда и такие косяки. Чем больше их найдете вы - тем меньше их останется тем, кто будет использовать ее после вас. Кроме того, я, например, уже не работаю с ADuC70xx и STR71x, порты для которых написал. Для STR71x у меня не осталось железа, на котором я мог бы проверить вносимые изменения. Поэтому исправления найденных в других портах багов или улучшения переносятся в этот порт без проверки. Вы бы что предпочли - старую версию, в которой есть известные глюки или новую, в которой они исправлены, но, возможно, внесены новые? ;) Рискну задать глупый вопрос. Если в проекте используется прерывание, но оно не является источником события для процессов, обязательно ли обработчик прерывания должен иметь тип OS_INTERRUPT и на входе ISR создавать объект OS::TISRW_SS ISRW ?При отсуствиии в этом прерывании разрешения вложенных - нет, не обязательно. Но помните о размере стека - прерывание будет работать на стеке текущего процесса, значит стеки всех процессов надо будет увеличить на размер, требуемый прерыванию. Если использовать ISRW_SS, то для прерываний организуется отдельный стек, но за это надо платить увеличением времени обработки прерывания.И можно ли разрешать глобальные прерывания до OS::Run() ?Если в разрешаемых прерываниях не используются сервисы ОС, их обработчики не имеют OS::TISRW(__SS), то можно, но зачем? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 58 5 марта, 2008 Опубликовано 5 марта, 2008 · Жалоба Почему не исправлено? Добавить то всего три строчки. Это должы добавлять те, кто модифицируют код. Чтобы для пользователя было прозрачно и портирование рабочего кода на новый кристалл проходило по максимуму безболезненно. Если гора не идет к Магомету, то Магомет идет к горе ;) :( Еще не начал работать с OS, а уже отлавливаю косяки. То ли еще будет ;) Уже начали. :) Кстати, у меня эта ошибка не проявилась. Видимо, потому, что вектор достал до адреса. В любом случае этот не опасный баг - он отлавливается на этапе сборки. Вот те, которые при сборке не проявляются, а на рантайме вылезают - эти опасные. И можно ли разрешать глобальные прерывания до OS::Run() ? Можно. Но зачем? Ведь после OS::Run() управление будет передано сразу процессам, они загрузят свои стеки и свои значения регистра SREG, поэтому разрешение прерываний до запуска оси смысла имеет мало. Если только не планируете долго сидеть до запуска, чтобы успеть по прерываниям попрыгать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sespivak 0 6 марта, 2008 Опубликовано 6 марта, 2008 · Жалоба Но помните о размере стека - прерывание будет работать на стеке текущего процесса, значит стеки всех процессов надо будет увеличить на размер, требуемый прерыванию. Как узнать максимальное потребление стека задачами? Можно ли проинициализировать все стеки каким-либо значением вроде 0xA5, как в FreeRTOS, и главное, как сделать это проще всего в scmRTOS? Или например в бутлоадере забить всю память байтами 0xA5, а затем прыгать на начало основной программы? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 6 марта, 2008 Опубликовано 6 марта, 2008 · Жалоба Как узнать максимальное потребление стека задачами? Можно ли проинициализировать все стеки каким-либо значением вроде 0xA5, как в FreeRTOS, и главное, как сделать это проще всего в scmRTOS?Память стеков уже по умолчанию проинициализирована значением, только не 0xA5 а 0. В портах для ARM на верхушке контекста лежит содержимое CPSR, который не может быть равен нулю (конструкция у него такая). Поэтому я смотрю визуально (отладчиком или через терминал), где первый "не-ноль" - там было занято. Если есть желание забить каким-то своим значением - допишите memset в конструктор TProcess.Или например в бутлоадере забить всю память байтами 0xA5, а затем прыгать на начало основной программы?Не пройдет - стеки попадают в область глобальных неинициализированных переменных и cstartup обнуляет эту область. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sespivak 0 6 марта, 2008 Опубликовано 6 марта, 2008 · Жалоба Если есть желание забить каким-то своим значением - допишите memset в конструктор TProcess. Всего одна строчка кода - а сколько пользы! Вся память как на ладони. Спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 9 марта, 2008 Опубликовано 9 марта, 2008 · Жалоба Мне не понятно, почему для генерации программного прерывания удобней использовать прерывание от аналогового компаратора? На мой взгляд лучше и удобней использовать внешнее прерывание. Во-первых, приоритет у него выше. Во-вторых, у большинства мк есть прерывния PCINT (pin change interrupt). Таким образом можно назначить практически любой вывод под это дело. В третьих, для переключения вывода в противоположное состояние достаточно записать PINy |= (1<<PINx); т.е. атомарную операцию SBI PINy, X. И было бы неплохо, чтобы в конфигурационном файле была возможность выбора источника программного прерывания: от компаратора или от внешнего прерывния. И также назначить символические имена выводам, которые используются для прерывания. В общем, максимально "загрузить" препроцессор, чтобы пользователь делал минимум телодвижений. И ошибок... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 10 марта, 2008 Опубликовано 10 марта, 2008 · Жалоба Мне не понятно, почему для генерации программного прерывания удобней использовать прерывание от аналогового компаратора? На мой взгляд лучше и удобней использовать внешнее прерывание. Во-первых, приоритет у него выше.Исторически сложилось, как самое ненужное. Приоритет ему как раз нужен в идеале самый низкий. ReAl в своем порте реализовал переключение по прерыванию SPM, в этом случае нога не нужна вообще. В третьих, для переключения вывода в противоположное состояние достаточно записать PINy |= (1<<PINx);Посмотрите порт ReAl, в нем (до SPM) было реализовано именно такое поведение - если процессор умеет перекидывать ногу одной командой, компаратор срабатывал от каждого перепада.И было бы неплохо, чтобы в конфигурационном файле была возможность выбора источника программного прерывания: от компаратора или от внешнего прерывния.Это и так реализовано - все функции, завязанные на прерывание переключения контекста находятся в файле scmROS_Target_cfg.h, который находится в папке приложения. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 10 марта, 2008 Опубликовано 10 марта, 2008 · Жалоба Приоритет ему как раз нужен в идеале самый низкий. Почему? 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; }; Не судите строго, я еще не совсем ориентируюсь в объектно-ориентированном программировании :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 10 марта, 2008 Опубликовано 10 марта, 2008 · Жалоба Почему? Так нужно как минимум три маш. цикла на переключение. Потому что если вдруг возникнет ещё какое-то прерывание от аппаратуры, оно должно быть обработано, а оно задержится на время переключения контекстов. У задачи, на которую идёт переключение, это прерывание от аппаратуры хоть так, хоть сяк (хоть до переключения, хоть сразу после) время заберёт, т.е. она всё равно реально начнёт работать позже. А само будет задержано переключателем контекстов. А "три цикла"... По сравнению с сотнями на собственно переключение - что три (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()) надо настроить разрешение для нужной ноги. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 10 марта, 2008 Опубликовано 10 марта, 2008 · Жалоба Спасибо за разъяснение. Маленькое уточнение: sbi PINC, 0x01 занимает один такт. В моем проекте на Меге324P есть один лишний вывод на PC7. Вот я к PCINT и "привязался". Хотя после вышесказанного возможно настрою на SPM. Вывод дороже... Прокомментируйте, пожалуйста, этот код 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 ? :05: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 10 марта, 2008 Опубликовано 10 марта, 2008 · Жалоба Маленькое уточнение: 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 ? :05: Кто такой ioavr.h ? Имеется ввиду <avr/io.h> ? Только что взял снапшот http://scmrtos.ginps.com/scmrtos-avr-gcc-snapshot.rar распаковал, заменил в 1-EventFlag/makefile тип процессора: MCU := atmega324p всё скомпилировалось. Не знаю, в чём может быть проблема. -------- Тьху, это, наверно, IAR ? Ну тогда ничем не могу помочь, у меня его на компе нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 10 марта, 2008 Опубликовано 10 марта, 2008 · Жалоба Глянул в описание - sbi/cbi выполняются за два такта.Прошу прощения. Заработался ..Не туда глянул :01: Действительно 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 Но это же за уши притянуто.. Хочется принципиально для себя решить этот вопрос. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться