|
|
  |
scmRTOS. Вопросы и ответы. |
|
|
|
Oct 1 2007, 09:35
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Из-за того, что мои предложения повисли в воздухе, решил открыть тему здесь. У меня вопросы по scmRTOS (извините, если они покажутся дилетанскими, я только начал мучить ОС). Раньше считал, что в uC OS лишняя заморочка, сейчас уже так не считаю. Общие вопросы для общего развития. 1. Зачем понадобилось иметь порядок приоритетов сверху вниз (насколько я понял из-за Blackfin только). a&-a немногим проигрывает. 2. Я хочу ограничиться #if scmRTOS_CONTEXT_SWITCH_SCHEME == 0, т.е. использовать всегда программное прерывание. Правильно ли это ? 3. Про OS::TChannel сказано, что этот объект оставлен для совместимости с версией 1. Рекомендуется пользоваться OS::channel. Мне же показалось, несмотря на универсальность OS::channel, применение его для байтовых каналов слишком расточительным. Я бы рассматривал бы как чистый FIFO буфер, как-то так #define TFIFO OS::Channel и изменил он нем представление как об атавизме. Или я чего-то не понял ? Платформозависимые вопросы. Я использую LPC2148 с IAR 5.10. Использовал порт Сергея Борщ с незначительными собственными доработками. 1. Интересует особенности использования векторных прерываний, кроме системного времени. На что следует обращать внимание. 2. Или их использовать нежелательно. PS. Не считайте мои вопросы наездом, scmRTOS - замечательная вещь.
|
|
|
|
|
Oct 1 2007, 11:11
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(alexander55 @ Oct 1 2007, 16:35)  1. Зачем понадобилось иметь порядок приоритетов сверху вниз (насколько я понял из-за Blackfin только). a&-a немногим проигрывает. Не понял, что дает a & -a. У Blackfin'a есть специальная команда, которая сразу вычисляет позицию первого ненулевого бита. Оба порядка приоритетов сущестувуют, чтобы можно было оптимизировать операцию вычисления приоритета для конкретного процессора. Пока это только Blackfin. Но кто знает, может есть и еще какие. Кажется у FR32 (Fujitsu) тоже есть такая аппаратная возможность. Цитата(alexander55 @ Oct 1 2007, 16:35)  2. Я хочу ограничиться #if scmRTOS_CONTEXT_SWITCH_SCHEME == 0, т.е. использовать всегда программное прерывание. Правильно ли это ? Надо указать в конфиге: #define scmRTOS_CONTEXT_SWITCH_SCHEME 1. Цитата(alexander55 @ Oct 1 2007, 16:35)  3. Про OS::TChannel сказано, что этот объект оставлен для совместимости с версией 1. Рекомендуется пользоваться OS::channel. Мне же показалось, несмотря на универсальность OS::channel, применение его для байтовых каналов слишком расточительным. Я бы рассматривал бы как чистый FIFO буфер, как-то так #define TFIFO OS::Channel и изменил он нем представление как об атавизме. Или я чего-то не понял ? Вы сравнили производительность OS::TChannel и OS::channel<byte> и она оказалась в пользу первого? Или на основании чего такая оценка?
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Oct 1 2007, 11:42
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(alexander55 @ Oct 1 2007, 12:35)  Из-за того, что мои предложения повисли в воздухе, решил открыть тему здесь. А это всегда так. Чтобы что-то сдвинулось - надо сделать это самому Цитата(alexander55 @ Oct 1 2007, 12:35)  1. Зачем понадобилось иметь порядок приоритетов сверху вниз (насколько я понял из-за Blackfin только). a&-a немногим проигрывает. Не только для blackfin. Это для любого процессора, у которого есть встроенная инструкция clz - подсчета количества ведущийх нулей. Тогда нахождение самого приоритетного процесса, ожидающего выполнения сводится к одной этой команде. Такой же подход, если не изменяет память, реализован в порте для фуджиков. Ядро ARM имеет такую команду начиная с v5, поэтому для таких ARMов обратный порядок приоритетов будет давать выигрыш в объеме кода и, главное, времени переключения контекста. В текущем порте для ARM поддержка обратного порядка приоритетов является атавизмом, тянущемся со второй версии, когда для обратного порядка приоритетов pr0 был самым низкоприоритетным процессом. Тогда я реализовал поддержку обратного порядка для упрощения портирования между платформами. В третьей версии мы придумали простой способ объявлять pr0 самым высоким приоритетом вне зависимости от прямого/обратного порядка. Наверное нужно в следующем релизе поддержку обратного порядка из порта исключить, а задание scmRTOS_PRIORITY_ORDER перенести из пользовательских исходников в исходники порта, тем более что для количества процессов меньше 6 GetPrioTag() вычисляется таблично и разницы нет ни по времени, ни по объему, а для большего кол-ва процессов вычисление для прямого порядка компилируется в более эффективный код. Цитата(alexander55 @ Oct 1 2007, 12:35)  2. Я хочу ограничиться #if scmRTOS_CONTEXT_SWITCH_SCHEME == 0, т.е. использовать всегда программное прерывание. Правильно ли это ? Программное прерывание это #define scmRTOS_CONTEXT_SWITCH_SCHEME 1. Да, это более эффективный метод - весь контекст сохранятется/восстанавливается только когда необходимо перепланирование, а не в каждом прерывании - но, к сожалению, он не работает на кристаллах без контроллера прерываний (ADuC). В любом случае вы всегда можете его изменить, сравнить результаты и выбрать более подходящий. Про TCannel лучше ответит dxp. Цитата(alexander55 @ Oct 1 2007, 12:35)  Платформозависимые вопросы. 1. Интересует особенности использования векторных прерываний, кроме системного времени. На что следует обращать внимание. 1)Не забывать в прерываниях, которые используют сервисы ОС заводить в начале обработчика объект типа OS::TISRW 2) Не забывать, что некоторые сервисы (тот же channel) при отсутствии/избытке данных могут захотеть перевести текущий процесс в спячку, что для прерывания невозможно. 3) Пока не реализована поддержка вложенных прерываний. Я с трудом представляю, с какой стороны к этому подступиться. Если реализуете - не забудьте поделиться Других ограничений вроде как нет. P.S. и не стесняйтесь склонять мою фамилию
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Oct 1 2007, 13:10
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(alexander55 @ Oct 1 2007, 19:49)  Приведите, пожалуйста, пример аналога Push-Pop для channel. Не понял вопроса. В чем затруднение? Все аналогично: Код OS::channel<byte, 16> queue; // очередь на 16 байт
... queue.push(10);
...
byte x; queue.pop(x); Отличия, конечно, имеются - OS::channel::pop(), в частности, поддерживает таймауты, поэтому будет работать чуть медленнее. Мне не совсем понятна суть исходного вопроса. Если имеелось в виду, почему рекомендуется шаблонный сервис, то ответ такой: - OS::TCannel использует макроподстановки, что не есть гуд.
- OS::channel имеет расширенную функциональность (таймауты и возможность, например, помещать элемент не только в конец очереди, но и в начало).
- Для единства стиля.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Oct 1 2007, 13:36
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(Сергей Борщ @ Oct 1 2007, 15:42)  В третьей версии мы придумали простой способ объявлять pr0 самым высоким приоритетом вне зависимости от прямого/обратного порядка. Наверное нужно в следующем релизе поддержку обратного порядка из порта исключить У меня нюх как у собаки. Цитата(Сергей Борщ @ Oct 1 2007, 15:42)  Программное прерывание это #define scmRTOS_CONTEXT_SWITCH_SCHEME 1. Я считал также, но в Вашем порте сделано наоборот, поэтому я так и решил. Но это не принципиально. Цитата(Сергей Борщ @ Oct 1 2007, 15:42)  Да, это более эффективный метод - весь контекст сохранятется/восстанавливается только когда необходимо перепланирование, а не в каждом прерывании - но, к сожалению, он не работает на кристаллах без контроллера прерываний (ADuC). В любом случае вы всегда можете его изменить, сравнить результаты и выбрать более подходящий. Это соответствует моим представлениям. Цитата(Сергей Борщ @ Oct 1 2007, 15:42)  1)Не забывать в прерываниях, которые используют сервисы ОС заводить в начале обработчика объект типа OS::TISRW Понял, также как с системным таймером. Цитата(Сергей Борщ @ Oct 1 2007, 15:42)  2) Не забывать, что некоторые сервисы (тот же channel) при отсутствии/избытке данных могут захотеть перевести текущий процесс в спячку, что для прерывания невозможно. Хочется поподробнее осветить этот момент. Цитата(Сергей Борщ @ Oct 1 2007, 15:42)  3) Пока не реализована поддержка вложенных прерываний. Я с трудом представляю, с какой стороны к этому подступиться. Если реализуете - не забудьте поделиться Других ограничений вроде как нет. Насколько я знаю по Keil, вложенные прерывания реализуются через макросы при входе и выходе из прерывания, но т.к. на возврат используется один регистр приходится пользоваться стеком, чтобы не затереть. Вложенные прерывания, на мой взгляд, извращение (но я не догматик). Тем более создатели ARM, я надеюсь, солидарны со мной. Цитата(Сергей Борщ @ Oct 1 2007, 15:42)  P.S. и не стесняйтесь склонять мою фамилию  Спасибо dxp и Сергею Борщу за оперативность (я тоже исправляюсь).  Цитата(dxp @ Oct 1 2007, 17:10)  Не понял вопроса. В чем затруднение? Все аналогично: Код OS::channel<byte, 16> queue; // очередь на 16 байт
... queue.push(10);
...
byte x; queue.pop(x); Отличия, конечно, имеются - OS::channel::pop(), в частности, поддерживает таймауты, поэтому будет работать чуть медленнее. Понял, это мой глюк. Цитата(dxp @ Oct 1 2007, 17:10)  Мне не совсем понятна суть исходного вопроса. Если имеелось в виду, почему рекомендуется шаблонный сервис, то ответ такой: - OS::TCannel использует макроподстановки, что не есть гуд.
- OS::channel имеет расширенную функциональность (таймауты и возможность, например, помещать элемент не только в конец очереди, но и в начало).
- Для единства стиля.
А это как раз понятно.
|
|
|
|
|
Oct 1 2007, 14:53
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(alexander55 @ Oct 1 2007, 16:36)  Хочется поподробнее осветить этот момент. Ну например прерывание передачи по UART забирает данные из OS:channel<uint8_t>. А данные там кончились... В этом случае pop() попытается передать управление другой задаче, и это приведет к краху. Поэтому прежде чем вызвать pop() надо проверить - а есть ли данные. Аналогично для push(). Для TEventFlag есть специальная функция SignalISR() - ее можно использовать в прерываниях без опаски. Она при необходимости может поставить какую-либо задачу в очередь готовых к выполнению, но саму перепланировку не выполняет - перепланировка будет выполнена после выхода из прерывания. Цитата(alexander55 @ Oct 1 2007, 16:36)  Я считал также, но в Вашем порте сделано наоборот, поэтому я так и решил. Но это не принципиально. В каком месте? Покажите, может там ошибка...
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Oct 2 2007, 04:43
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(Сергей Борщ @ Oct 1 2007, 18:53)  Ну например прерывание передачи по UART забирает данные из OS:channel<uint8_t>. А данные там кончились... В этом случае pop() попытается передать управление другой задаче, и это приведет к краху. Поэтому прежде чем вызвать pop() надо проверить - а есть ли данные. Аналогично для push(). Для TEventFlag есть специальная функция SignalISR() - ее можно использовать в прерываниях без опаски. Она при необходимости может поставить какую-либо задачу в очередь готовых к выполнению, но саму перепланировку не выполняет - перепланировка будет выполнена после выхода из прерывания. Понял. Цитата(Сергей Борщ @ Oct 1 2007, 18:53)  В каком месте? Покажите, может там ошибка... Откуда я залил уже не помню. Файл OS_Target_asm.s79 Дата файла от 08.02.07 //****************************************************************************** //* //* FULLNAME: Single-Chip Microcontroller Real-Time Operating System //* //* NICKNAME: scmRTOS //* //* PROCESSOR: ARM7 //* //* TOOLKIT: EWARM (IAR Systems) //* //* PURPOSE: Target Dependent Low-Level Stuff //* //* Version: 3.00-beta //* //* $Revision: 31 $ //* $Date: 2007-02-08 18:51:14 +0600 (╨є╤й, 08 ╤д╨╡╨▓ 2007) $ //* //* Copyright © 2003-2006, Harry E. Zhurov //* //* Permission is hereby granted, free of charge, to any person //* obtaining a copy of this software and associated documentation //* files (the "Software"), to deal in the Software without restriction, //* including without limitation the rights to use, copy, modify, merge, //* publish, distribute, sublicense, and/or sell copies of the Software, //* and to permit persons to whom the Software is furnished to do so, //* subject to the following conditions: //* //* The above copyright notice and this permission notice shall be included //* in all copies or substantial portions of the Software. //* //* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, //* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF //* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. //* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY //* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, //* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH //* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. //* //* ================================================================= //* See http://scmrtos.sourceforge.net for documentation, latest //* information, license and contact details. //* ================================================================= //* //****************************************************************************** //* ARM port by Sergey A. Borshch, Copyright © 2006 #include "scmRTOS_CONFIG.h" #include "scmRTOS_TARGET_CFG.h" #include "OS_Target_core.h" module scmRTOS_Asm #define MODE_USER 0x10 #define MODE_FIQ 0x11 #define MODE_IRQ 0x12 #define MODE_SVC 0x13 #define MODE_ABORT 0x17 #define MODE_UND 0x1B #define MODE_SYS 0x1F #define NIRQ (1<<7) #define NFIQ (1<<6) #define THUMB (1<<5) // Context structure: // lo address // CPSR // R14 (LR) // R0 // R1 // R2 // R3 // R4 // R5 // R6 // R7 // R8 // R9 // R10 // R11 // R12 // Process interrupt point (return address) // hi address CODE32 ;------------------------------------------------------------------------------- #if scmRTOS_CONTEXT_SWITCH_SCHEME == 0 COMMON INTVEC:CODE:ROOT org 0x00000008 LDR PC, Context_Switcher_Adr ; Branch to swi_handler org 0x00000018 LDR PC, IRQ_Wrapper_Adr org 0x00000020 org 0x00000028 Context_Switcher_Adr: DC32 Context_Switcher org 0x00000038 IRQ_Wrapper_Adr: DC32 IRQ_Wrapper ;------------------------------------------------------------------------------- RSEG ICODE:CODE IRQ_Wrapper: MSR CPSR_c, #(NIRQ | MODE_SYS) ; switching to System mode, because context has to be saved ; on top of user mode stack, enable FIQ STMFD SP!, {R0-R12,LR} ; store R0_R12, dummy store LR to reserve space in context STMFD SP!, {R1,LR} ; reserve space for CPSR, store LR_user on top of context MOV R0, SP ; store context pointer in non-banked register MSR CPSR_c, #(NIRQ | MODE_IRQ) ; switching back to IRQ mode SUB LR, LR, #4 ; adjusting return address STR LR, [R0, #4*15] ; store return address in reserved space (instead of saved LR_user) MRS R1, SPSR ; move stored CPSR of process to non-banked register STR R1, [R0] ; store SPSR in reserved space (instead of saved R1) IRQ_SWITCH ; call IRQ handler MSR CPSR_c, #(NIRQ | MODE_SYS) ; switching to System mode, because context has to be restored ; from user mode stack, enable FIQ MOV R0, SP B ContextRestore ; restore saved IRQ context RSEG ICODE:CODE PUBLIC SaveSP PUBLIC Set_New_SP SaveSP: // __arm void SaveSP(TStackItem** Curr_SP) MSR CPSR_c, #(NIRQ | MODE_SYS) ; switching to System mode, to get access to sp_user STR SP, [R0] MSR CPSR_c, #(NIRQ | MODE_IRQ) ; switching back to IRQ mode BX LR Set_New_SP: // __arm void SetNewSP(TStackItem* New_SP) MSR CPSR_c, #(NIRQ | MODE_SYS) ; switching to System mode, to get access to sp_user MOV SP, R0 MSR CPSR_c, #(NIRQ | MODE_IRQ) ; switching back to IRQ mode BX LR ;------------------------------------------------------------------------------- // __swi __arm void OS_ContextSwitcher(TStackItem** Curr_SP, TStackItem* Next_SP); Context_Switcher: MSR CPSR_c, #(NIRQ | MODE_SYS) ; switching to System mode, because context has to be saved ; on top of user mode stack, enable FIQ STMFD SP!, {R0-R12,LR} ; store R0_R12, dummy store LR to reserve space in context SUB R2, SP, #4*2 ; store context pointer in non-banked register (reserve space for CPSR, LR) MSR CPSR_c, #(NIRQ | MODE_SVC) ; switching back to supervisor mode STR LR, [R2, #4*15] ; store return address in reserved space (instead of saved LR_user) MRS R3, SPSR ; move stored CPSR of process to non-banked register MSR CPSR_c, #(NIRQ | MODE_SYS) ; switching back to System mode STMFD SP!, {R3,LR} ; store CPSR, LR_user on top of context and adjust SP_user STR SP,[R0] MOV R0, R1 ContextRestore LDMFD R0!, {R1, LR} ; restoring LR_user, saved CPSR_user ADD SP, R0, #4*14 ; set process SP MSR CPSR_c, #(NIRQ | MODE_IRQ) ; switch to IRQ mode to get access to SPSR_irq MSR SPSR_cxsf, R1 ; store process CPSR to SPSR_irq to restore at return from irq LDMFD R0, {R0-R12,PC}^ ; restoring remaining context, CPSR and reti #else //if scmRTOS_CONTEXT_SWITCH_SCHEME == 1; ------------------------------------------------------------------------------- COMMON INTVEC:CODE:ROOT org 0x00000018 IRQ_SWITCH ; ∩σ≡σ⌡εΣ ∩ε αΣ≡σ±≤ Φτ ΓσΩ≥ε≡φεπε Ωεφ≥≡εδδσ≡α ;------------------------------------------------------------------------------- RSEG ICODE:CODE // TStackItem* OS_ContextSwitchHook(TStackItem* sp); EXTERN OS_ContextSwitchHook PUBLIC ContextSwitcher_ISR ContextSwitcher_ISR: MSR CPSR_c, #(NIRQ | MODE_SYS) ; switching to System mode, because context has to be saved ; on top of user mode stack, enable FIQ STMFD SP!, {R0-R12,LR} ; store R0_R12, dummy store LR to reserve space in context SUB R0, SP, #4*2 ; store context pointer in non-banked register (reserve space for CPSR, LR) MSR CPSR_c, #(NIRQ | MODE_IRQ) ; switching back to IRQ mode SUB LR, LR, #4 ; adjusting return address STR LR, [R0, #4*15] ; store return address in reserved space (instead of saved LR_user) MRS R1, SPSR ; move stored CPSR of process to non-banked register MSR CPSR_c, #(NIRQ | MODE_SYS) ; switching back to System mode STMFD SP!, {R1,LR} ; store CPSR, LR_user on top of context and adjust SP_user ; to use process stack in OS_ContextSwitchHook _BLF OS_ContextSwitchHook, Hook_Relay ; store context pointer(R0), get new context pointer(R0) IRQ_DONE ; reset interrupt controller ContextRestore LDMFD R0!, {R1, LR} ; restoring LR_user, saved CPSR_user ADD SP, R0, #4*14 ; set process SP MSR CPSR_c, #(NIRQ | MODE_IRQ) ; switch to IRQ mode to get access to SPSR_irq MSR SPSR_cxsf, R1 ; store process CPSR to SPSR_irq to restore at return from irq LDMFD R0, {R0-R12,PC}^ ; restoring remining context, CPSR and reti RSEG ICODE:CODE Hook_Relay: LDR R1, =OS_ContextSwitchHook ; call Thumb mode routine BX R1 #endif ;------------------------------------------------------------------------------- RSEG CSTACK:DATA RSEG ICODE:CODE // Set SP_irq to main() stack, restore context referenced by R0 // void OS_Start(TStackItem* sp); PUBLIC OS_Start OS_Start: MSR CPSR_c, #(NIRQ | NFIQ | MODE_IRQ) ; switching to IRQ mode, disable FIQ & IRQ LDR SP, =SFE(CSTACK) & 0xFFFFFFF8 ; End of CSTACK MSR CPSR_c, #(NIRQ | NFIQ | MODE_SYS) ; switching back to System mode, disable FIQ & IRQ ; ContextRestore typically called from System mode B ContextRestore ; Restore context = run process ;------------------------------------------------------------------------------- ENDMOD END PS. Я в тесте выделил красным и зеленым цветом места. Я текст исходный.
Сообщение отредактировал alexander55 - Oct 2 2007, 04:48
|
|
|
|
|
Oct 2 2007, 07:57
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(alexander55 @ Oct 2 2007, 07:43)  PS. Я в тесте выделил красным и зеленым цветом места. Нет, это не то. В scmRTOS под "программным прерыванием" понимается обычное прерывание, которое генерится из программы: Код #if scmRTOS_CONTEXT_SWITCH_SCHEME == 1 // #define used instead of inline function to ensure inlining to both ARM and THUMB functions. #define RaiseContextSwitch() \ do \ { \ AT91C_BASE_AIC->AIC_ISCR = (1<<CONTEXT_SWITCH_INT); \ } \ while (0) // set flag and enable interrupt #endif ... #else //if scmRTOS_CONTEXT_SWITCH_SCHEME == 1 ;------------------------------------------------------------------------------- PUBLIC ContextSwitcher_ISR ContextSwitcher_ISR: MSR CPSR_c, #(NIRQ | MODE_SYS) ; switching to System mode, because context has to be saved ; on top of user mode stack, enable FIQ Его преимущество именно в том, что даже если его сгенерировать внутри прерывания, в обработчик мы попадем "с чистого листа", т.е. из фона, когда на стеке нет данных из обработчиков других прерываний. Это сильно упрощает процесс переключения контекста. Поскольку swi не маскируется - его использовать для этой цели не получилось. А в нулевом варианте swi используется просто как быстрый способ вызвать функцию с переходом в ARM-режим.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Oct 2 2007, 09:19
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
[quote name='Сергей Борщ' date='Oct 2 2007, 11:57' post='301622'] Нет, это не то. В scmRTOS под "программным прерыванием" понимается обычное прерывание, которое генерится из программы [/quote] Я считал "программным прерыванием" SWI. Отсюда вся путаница. Теперь мне надо возвратиться в исходное и все продумать сначала. [quote name='Сергей Борщ' date='Oct 2 2007, 11:57' post='301622'] Его преимущество именно в том, что даже если его сгенерировать внутри прерывания, в обработчик мы попадем "с чистого листа", т.е. из фона, когда на стеке нет данных из обработчиков других прерываний. [/quote] Я считал, что в Supervisor (если не разрешать вложенные прерывания) можно попасть только из System режима (т.е. из фона). Т.е. SWI является отложенным прерыванием, хотя и с высоким приоритетом. Опять какая-то неувязка. [/quote] Теперь, еще один вопрос. С каким приоритетом внутри VIC лучше использовать прерывание по системному таймеру ?
|
|
|
|
|
Oct 3 2007, 09:46
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(alexander55 @ Oct 3 2007, 11:40)  Вопрос, конечно, правильный. Можно все завести в один процесс, но хочется для самообразования это знать. Вопрос решил так. OS::TEventFlag FL1; OS::TEventFlag FL2; OS::TEventFlag FL3; //--------------------------------------------------------------------------- OS_PROCESS void TProc1::Exec() { FL1.Signal(); for(;;) { if(FL1.Wait()) { ... FL2.Signal(); } } } //--------------------------------------------------------------------------- OS_PROCESS void TProc2::Exec() { for(;;) { if(FL2.Wait()) { ... FL3.Signal(); } } } //--------------------------------------------------------------------------- OS_PROCESS void TProc3::Exec() { for(;;) { if(FL3.Wait()) { ... FL1.Signal(); } } } //--------------------------------------------------------------------------- Хочу увидеть критику и ценные замечания.
Сообщение отредактировал alexander55 - Oct 3 2007, 09:47
|
|
|
|
|
Oct 3 2007, 10:38
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(alexander55 @ Oct 3 2007, 12:46)  Хочу увидеть критику и ценные замечания. Код OS::TEventFlag FL1(OS::TEventFlag::efOn); OS_PROCESS void TProc1::Exec() { for(;;) Но это шлифовка. В остальном должно работать.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Oct 4 2007, 10:00
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(alexander55 @ Oct 4 2007, 10:34)  Правильно ли я понимаю, что минимальный джентальментский набор средств межпроцессного взаимодействия (при этом сохраняя всю функциональность): 1.OS:message 2.OS::channel Нет, OS::TService  Оно работает, но еще не готово к выпуску в широкие массы. А если серьезно - вопрос философский. Я TEventFlag и TMutex использую чаще чем channel и message.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Oct 4 2007, 10:36
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(Сергей Борщ @ Oct 4 2007, 14:00)  Нет, OS::TService  Оно работает, но еще не готово к выпуску в широкие массы. И когда ждать? Я себя отношу к широким массам. Цитата(Сергей Борщ @ Oct 4 2007, 14:00)  А если серьезно - вопрос философский. Вот меня и интересует философия scmRTOS. Мне казалось, автор хотел дать минимальный набор универсальных инструментов для решения максимального количества задач.
|
|
|
|
|
Oct 4 2007, 11:53
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(alexander55 @ Oct 4 2007, 17:36)  И когда ждать? Я себя отношу к широким массам. Возьмите из репозитория и пробуйте себя в роли автора.  Цитата(alexander55 @ Oct 4 2007, 17:36)  Вот меня и интересует философия scmRTOS. Мне казалось, автор хотел дать минимальный набор универсальных инструментов для решения максимального количества задач. Универсальных в полном смысле нет и быть не может. Как правило, наиболее часто используемые TEventFlag и TMutex. Исходная идея была, действительно, иметь минимально необходимый набор разнокачественных средств, но так, чтобы не страдала производительность и гибкость от недостатка оных.  Движение в сторону TService обусловлено тем, что все-таки есть случаи, когда кому-то хочется более специализированного поведения и функциональности, чем имеется в наборе.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Oct 8 2007, 05:44
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Спасибо всем за ответы. Предлагаю выкладывать в этом топике ответы на вопросы по использованию встроенных средств межпроцессного взаимодействия в scmRTOS. Это будет интересно всем, кто использует scmRTOS. Например (мой скромный вклад)  . Вопрос. Как средствами scmRTOS организуется выполнение процесса с заданной частотой. Ответ. ... OS::TEventFlag FL3; ... OS_PROCESS void TProc3::Exec() { for(;;) { FL3.Wait(100); ... } } Пояснение. Процесс 3 запускается через 100 тактов системного таймера (период процесса 3 - 100 мс при периоде таймера 1 мс).
|
|
|
|
|
Oct 8 2007, 06:03
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(alexander55 @ Oct 8 2007, 12:44)  Спасибо всем за ответы. Предлагаю выкладывать в этом топике ответы на вопросы по использованию встроенных средств межпроцессного взаимодействия в scmRTOS. Это будет интересно всем, кто использует scmRTOS. Например (мой скромный вклад)  . Вопрос. Как средствами scmRTOS организуется выполнение процесса с заданной частотой. Ответ. ... OS::TEventFlag FL3; ... OS_PROCESS void TProc3::Exec() { for(;;) { FL3.Wait(100); ... } } Пояснение. Процесс 3 запускается через 100 тактов системного таймера (период процесса 3 - 100 мс при периоде таймера 1 мс). Код OS_PROCESS void TProc3::Exec() { for(;;) { Sleep(100); ... } }
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Oct 8 2007, 11:12
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(Сергей Борщ @ Oct 8 2007, 12:05)  Оба варианта неправильные - не учитывают время исполнения самого процесса. По-честному надо бы считывать системное время, смотреть сколько осталось до "Часа Х" и засыпать уже на это время. Вот только есть одна грабля - если времени не осталось, то вместо исполнения без ожидания получим Sleep(0), т.е. навечно, а если не успели и "час Х" уже прошел - то опять же вместо исполнения без паузы получим ожидание на время переполнения системного таймера. Вы правы Сергей. Если понадобится точное время, я могу предложить такой вариант. //------------------------------------------------- class TTimer { int Delay; int Setting; public: TTimer(x) { Setting=x;Delay=x;}; void Run(void) { if(--!Delay) {Delay=Setting; FL.Signal();};}; }; //-------------------------------------------------- TTimer Tim100(100); ... И где-то в системном таймере ... Tim100.Run(); ... //-------------------------------------------------- Ну а в процессе OS::TEventFlag FL3; ... OS_PROCESS void TProc3::Exec() { for(;;) { FL.Wait(); ... } } PS. Так вроде чисто получается.
|
|
|
|
|
Oct 8 2007, 11:27
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(alexander55 @ Oct 8 2007, 14:12)  PS. Так вроде чисто получается.  Ну, совсем для красоты я бы сделал FL3 членом TTImer. Инкапсуляция, так сказать. А сам решаю так: Код typedef TTimeout timeout_t; timeout_t Time_X = OS::GetTickCount() + timeout; // now + timeout
for(;;) { timeout_t Timeout = Time_X - OS::GetTickCount(); if((timeout_t)(Timeout - 1) > timeout ) return 0; if(!pUART->getchar(RxData, Timeout)) // timeout, packet broken return 0;
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Oct 8 2007, 11:58
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(Сергей Борщ @ Oct 8 2007, 15:27)  Ну, совсем для красоты я бы сделал FL3 членом TTImer. Здесь есть подводный камень с инициализацией (хотя можно наследовать виртуально). Я бы не стал так делать. Цитата(Сергей Борщ @ Oct 8 2007, 15:27)  Код typedef TTimeout timeout_t; timeout_t Time_X = OS::GetTickCount() + timeout; // now + timeout
for(;;) { timeout_t Timeout = Time_X - OS::GetTickCount(); if((timeout_t)(Timeout - 1) > timeout ) return 0; if(!pUART->getchar(RxData, Timeout)) // timeout, packet broken return 0; return 0; Здесь будет выход из цикла for. Это потенциально опасно.
|
|
|
|
|
Oct 8 2007, 13:27
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(alexander55 @ Oct 8 2007, 14:58)  Здесь есть подводный камень с инициализацией (хотя можно наследовать виртуально). Я бы не стал так делать. Какой камень? Что-то я сегодня туго соображаю. Цитата(alexander55 @ Oct 8 2007, 14:58)  return 0; Здесь будет выход из цикла for. Это потенциально опасно.  Это только кусочек функции, которая возвращает количество принятых байт в пакете или 0 если прием не сложился. Этим куском я хотел продемонстрировать вычисление оставшегося тайм-аута и обход упомянутых в предыдущем сообщении "граблей"
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Oct 9 2007, 04:41
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(Сергей Борщ @ Oct 8 2007, 17:27)  Какой камень? Что-то я сегодня туго соображаю. Ну допустим //------------------------------------------------- class TTimer : public OS::TEventFlag { int Delay; int Setting; public: TTimer(x) { Setting=x;Delay=x;}; void Run(void) { if(--!Delay) {Delay=Setting; FL.Signal();};}; }; TTimer Tim100(100); Все нормально, но мы откажемся от возможности начальной инициализации TEventFlag (только по умолчанию). Но это не страшно. Цитата(Сергей Борщ @ Oct 8 2007, 17:27)  Это только кусочек функции, которая возвращает количество принятых байт в пакете или 0 если прием не сложился. Этим куском я хотел продемонстрировать вычисление оставшегося тайм-аута и обход упомянутых в предыдущем сообщении "граблей" Понятно. Я почему-то подумал про for процесса. PS. Я вчера тоже под конец дня зациклился.
|
|
|
|
|
Oct 9 2007, 10:24
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(alexander55 @ Oct 9 2007, 07:41)  class TTimer : public OS::TEventFlag Вчера был явно день торможения, хотя у меня, например, выходные прошли без возлияний  : Код class TTimer { int Delay; int Setting; OS::TEventFlag Flag; public: TTimer(x) : Flag(OS::TEventFlag::efOff) { Setting=x;Delay=x;} void Run(void) { if(--!Delay) {Delay=Setting; Flag.Signal();}} bool Wait() { return Flag.Wait(); } };
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Oct 9 2007, 12:47
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(Сергей Борщ @ Oct 9 2007, 17:24)  Вчера был явно день торможения, хотя у меня, например, выходные прошли без возлияний  : Код class TTimer { int Delay; int Setting; OS::TEventFlag Flag; public: TTimer(x) : Flag(OS::TEventFlag::efOff) { Setting=x;Delay=x;} void Run(void) { if(--!Delay) {Delay=Setting; Flag.Signal();}} bool Wait() { return Flag.Wait(); } }; Мущщины, я в упор не понимаю, почему вы используете для генерации задержек флаг события, а не специально существующую для этого функцию Sleep. Ведь она легче и быстрее, а флаг тянет за собой дополнительную функциональность, которая здесь не используется. Оверхед и загромождение кода.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Oct 9 2007, 13:05
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(dxp @ Oct 9 2007, 16:47)  Мущщины, я в упор не понимаю, почему вы используете для генерации задержек флаг события, а не специально существующую для этого функцию Sleep. Ведь она легче и быстрее, а флаг тянет за собой дополнительную функциональность, которая здесь не используется. Оверхед и загромождение кода. Вопрос стал о точном среднем выдерживании по времени процессных задач (ради чистого искусства). PS. Предложение. Давайте обсудим какую-нибудь полезную тему типа "Обмен ModBus пакетами средствами scmRTOS". Я знаю, у Сергея есть наработки, у меня тоже кое-что есть.
|
|
|
|
|
Oct 9 2007, 14:24
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(alexander55 @ Oct 9 2007, 16:05)  Я знаю, у Сергея есть наработки, у меня тоже кое-что есть. Нету. С MODBUS никогда не работал. Цитата(dxp @ Oct 9 2007, 15:47)  Мущщины, я в упор не понимаю, почему вы используете для генерации задержек флаг события, а не специально существующую для этого функцию Sleep. Мы всех окончательно запутали  Я в последних сообщениях обсуждал возможность использовать какой-либо сервис как члена какого-либо объекта. А против Sleep() не возражал, только отметил, что для периодического выполнения какого-либо куска время задержки надо бы рассчитывать, чтобы вычесть из него собственно время выполнения самого полезного кода.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Oct 10 2007, 04:27
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(Сергей Борщ @ Oct 9 2007, 18:24)  Нету. С MODBUS никогда не работал. Хорошо, тогда предлагаемая тема для обсуждения "Обмен пакетами по RS485 с помощью средств scmRTOS". Цитата(dxp @ Oct 10 2007, 07:57)  Ну, и пожалуйста - заверните Sleep в свой объект TTimer, внутри которого будут вычисляться точные значения аргумента Sleep, и все. Флаг события-то тут зачем? Идея ясна.
|
|
|
|
|
Oct 11 2007, 05:52
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(alexander55 @ Oct 10 2007, 08:27)  Хорошо, тогда предлагаемая тема для обсуждения "Обмен пакетами по RS485 с помощью средств scmRTOS". Я так понял, что молчание - знак согласия. Ну тогда поехали. Вопросы для обсуждения (хочется применительно к LPC). Выскажу свое видение вопроса. 1. Приоритет прерывания по приему символов . Для определенности. Выше системного таймера, но ниже, чем готовность данных ADC. 2. Для обработки принятого пакета - формирования пакета ответа - передачи подготовленного пакета организуется свой процесс (назовем процессом на передачу). 2.1. Запуск процесса на передачу для master. - запуск процесса осуществляется по таймеру временных интервалов (пакет запроса с передачей); - запуск процесса от органов управления (с передачей); - обработка принятых данных от slave (без передачи). 2.2. Запуск процесса на передачу для slave. - по истечению таймаута на отсутствие принятых символов (с передачей или без нее); - по каким-то явным признакам прошедшего или сбойного пакета запроса (с передачей или без нее). 3. Прерывание по приему символов осуществляет запись в приемный буфер, с которым и производится работа в процессе на передачу. Думаю, вопросов для начала обсуждения пока достаточно.
|
|
|
|
|
Nov 9 2007, 16:15
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
"UP" Цитата(dxp @ Oct 10 2007, 05:57)  Ну, и пожалуйста - заверните Sleep в свой объект TTimer, внутри которого будут вычисляться точные значения аргумента Sleep, и все. Флаг события-то тут зачем? +1 Более того - если от момента, когда время Sleep для данного процесса истекло (его занесли в готовые), до того, как он реально получит управление, проходит меньше времени одного системного тика - то вообще ничего не надо. В среднем будет всё нормально. Конечно - если процесс по приоритету где-то внизу и старшие вечно толпятся - то будет проскакивать. Тогда действительно обернуть в класс с поведением "типа OCR += PERIOD". А если задержки до "всплытия" процесса могут быть такими большими, что оставшееся время может оказаться равно 0 - то оно и "отрицательным" может оказаться, тут уж переход к TEventFlag тоже ничего не даст.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Dec 8 2007, 14:37
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Привет всем! решил поиграться с scmRTOS. Скачал исходники версии 3.0. Скомпилил - НО то ли день не мой, то ли дело не в бобине... Компилятор IAR 4.30A/W32 [Evaluation] (4.30.1.3). Попробовал поэмулировать ОС с примером из папки [3-Channel] в AVRStudio 4.12 SP2. В конфиге scmRTOS_config.h установил Код #define scmRTOS_CONTEXT_SWITCH_SCHEME 0 После запуска симулятор выдает предупреждение Цитата AVR Simulator: Invalid opcode 0xffff at address 0x00ffff Это возникает после выхода из процедуры OS_Start(sp) Где грабли, не пойму. Просвятите, плиз. Сенькс.
--------------------
|
|
|
|
|
Dec 8 2007, 15:44
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(dxp @ Dec 8 2007, 22:29)  А разве оно должно выходить из этой функции? Оно в нее заходит и далее запускаются все процессы, никакого выхода быть не должно. Посмотрите код этой функции, он очень простой и короткий. Расскажу по порядку, что у меня происходит: 1. выполняется конструктор OS::Kernel 2. выполянется конструктор OS::PrioMaskTable 3. выполняются последовательно кострукторы 3-х процессов 4. вызывается OS::Run() 5. в OS::Run() вызывается OS_Start(sp) 6. Попадаем в OS_Target_asm.s90 на метку OS_Start: 7. Далее переход на метку L_RestoreContext: 8. После команды RET симулятор вываливает Код AVR Simulator: Invalid opcode 0xffff at address 0x00ffff
--------------------
|
|
|
|
|
Dec 8 2007, 20:12
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(prottoss @ Dec 9 2007, 00:06)  В файле OS_Target_asm.s90 есть макросы #if HAS_RAMPZ == 1 ... #endif - так вот, они почемуто не хотятЪ работать:-( Сделал в данном файле принудительно #define HAS_RAMPZ 1 - все заработало... Я в тонкостях компиляторов не сильно силен, как победить баг? Макрос HAS_RAMPZ генерируется компилятором из заданного процессора. Но это компилятором. А ассемблер, насколько помню, не поддерживает задание конкретного типа процессора, там все опции целевого процессора надо задавать через -v и -m опции. Соответственно, означенный макрос ассемблер не генерирует, поэтому его надо задавать руками. Удобно сделать это через опции проекта, а не править исходник. Если сборка идет из командной строки (makefile etc), то задать макрос через ключ командной строки -D, если из оболочки, что в опциях проекта, в разделе асма, во вкладке define указать макрос.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Dec 9 2007, 09:43
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(dxp @ Dec 9 2007, 03:12)  Макрос HAS_RAMPZ генерируется компилятором из заданного процессора. Но это компилятором. А ассемблер, насколько помню, не поддерживает задание конкретного типа процессора, там все опции целевого процессора надо задавать через -v и -m опции. Соответственно, означенный макрос ассемблер не генерирует, поэтому его надо задавать руками. Удобно сделать это через опции проекта, а не править исходник. Если сборка идет из командной строки (makefile etc), то задать макрос через ключ командной строки -D, если из оболочки, что в опциях проекта, в разделе асма, во вкладке define указать макрос. Да, наверное так и надо... НО, думаю тогда надо вписать данное предупреждение в начале S90-файла, типа /* ... Warning! bla-bla-bla ... */
--------------------
|
|
|
|
|
Dec 13 2007, 12:18
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(ReAl @ Dec 13 2007, 17:07)  В порте для avr-gcc с этим проще. Тип процессора передаётся и ассемблеру, достаточно включить <avr/io.h> и символ RAMPZ определён только для тех процессоров, у которых он есть. После чего #ifdef RAMPZ что в С, что в асме. кстати, в ассемблер на IAR тоже можно включать C-шные хедеры, так что я думаю, что можно побороть эту проблему. К сожалению,я счас загружен по макушку проектом, и не могу все это попробовать:-(
--------------------
|
|
|
|
|
Dec 27 2007, 09:45
|
Частый гость
 
Группа: Свой
Сообщений: 78
Регистрация: 10-01-07
Пользователь №: 24 270

|
С 1 - понятно, хотел просто уточнить. Цитата(jorikdima @ Dec 27 2007, 12:32)  2. За блокировкой идет то, что вы напишете, а не захват ресурса. И если вы проверите результат TMutex::LockSoftly() на правду/ложь и будете захватывать ресурс только в случае true, то все будет в порядке. Mutex-ом как-раз блокируют используемый ресурс, просто-так блокировку вызывать бессмысленно, так-что за блокировкой всегда идёт именно работа с ресурсом. TMutex::LockSoftly() - не возвращает значение, она "мягко" блокирует. Вот как именно "мягко" я и хочу понять
|
|
|
|
|
Dec 27 2007, 13:24
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(bus16 @ Dec 27 2007, 15:45)  Mutex-ом как-раз блокируют используемый ресурс, просто-так блокировку вызывать бессмысленно, так-что за блокировкой всегда идёт именно работа с ресурсом. TMutex::LockSoftly() - не возвращает значение, она "мягко" блокирует. Вот как именно "мягко" я и хочу понять Код INLINE bool LockSoftly() { TCritSect cs; if(ValueTag) return false; else Lock(); return true; } как видно, функция возврящает bool. Если вернула true, то семафор захвачен, можно работать с ресурсом, если false, то семафор уже был захвачен другим процессом, тут его захватить не удалось, работать с ресурсом нельзя - можно заняться чем-то другим.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Dec 27 2007, 13:27
|

тут может быть ваша реклама
    
Группа: Свой
Сообщений: 1 164
Регистрация: 15-03-06
Из: Санкт-Петербург/CA
Пользователь №: 15 280

|
В том изаключается мягкость, что если ресурс уже заблокирован, то программисту дается возможность не ждать в спячке разблокировки, а поделоть что либо другое, естественно без использования упомянутого ресурса, ибо он занят. Чтобы дать разработчику понять захватился ли мютекс мягко или нет и придумано возвращения значения функции LockSoftly(). Если правда, то все хорошо, ресурс залочен - пользуйтесь. А если ложь, то сообщается, что ресурс занят можешь делать что либо другое. Если вам не нужна такая функциональность, то пользуйтесь Lock(). За блокировкой действительно всегда идет работа с ресурсом. Но я имел в виду, что по проверки условия возвращаемого значения можно и не идти на работу с ресурсом, а пойти по другим делам, если таковые имеются.
|
|
|
|
|
Jan 17 2008, 07:35
|

Частый гость
 
Группа: Свой
Сообщений: 107
Регистрация: 6-09-06
Из: Москва
Пользователь №: 20 118

|
Возник вопрос по обработке прерываний от системной периферии под ARM7 (AT91SAM7x256): Как известно прерывания от DBGU и PIT совмещены. PIT- системный таймер. По DBGU приходят данные со скоростью 9600 почти без перерыва. Полученные данные записываются в к-либо буфер и обрабатываются. Как лучше это сделать? Может лучше в качестве системного таймера использовать TC0? Код void OS::SystemTimerUserHook() { if(AT91C_BASE_DBGU->DBGU_CSR&(AT91C_US_RXRDY|AT91C_US_OVRE)) { volatile unsigned int dummy = AT91C_BASE_DBGU->DBGU_CSR; AT91C_BASE_DBGU->DBGU_CR=AT91C_US_RSTSTA; Buf=(AT91C_BASE_DBGU->DBGU_RHR); If (Buf==...) FDbguDataReceived.SignalISR(); AT91C_BASE_AIC->AIC_IVR = 1; // ? AT91C_BASE_AIC->AIC_EOICR = 1; // ? } } Перестаёт срабатывать прерывание системного таймера OS::SystemTimer_ISR при активности DBGU, причём даже в условие не заходит ниразу. P.S. В пошаговом режиме заходит в условие.
Сообщение отредактировал LessNik - Jan 17 2008, 07:49
|
|
|
|
|
Jan 17 2008, 08:59
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(LessNik @ Jan 17 2008, 09:35)  Перестаёт срабатывать прерывание системного таймера OS::SystemTimer_ISR при активности DBGU, причём даже в условие не заходит ниразу. Что-то сразу не соображу, где может быть засада. Делал обмен по DBGU, правда, короткими пакетами. 115200. Код void OS::SystemTimerUserHook() { pUpLink->Handler(); } template<uint8_t rx_size, uint8_t tx_size> void uart_t<rx_size, tx_size>::Handler() { uint32_t Flags = pUART->US_CSR; Flags &= pUART->US_IMR;
if(Flags & AT91C_US_TXRDY) { if(TxBuffer.get_count()) { uint8_t Data; TxBuffer.pop(Data, 1); pUART->US_THR = Data; } else pUART->US_IDR = AT91C_US_TXRDY; }
if(Flags & AT91C_US_RXRDY) { uint8_t Data = pUART->US_RHR; // read anyway pUART->US_CR = AT91C_US_RSTSTA; // clear errors if any if(RxBuffer.get_free_size()) RxBuffer.push(Data);
} } Посмотрел, как в OS_Target_cpp.cpp сделан обработчик прерывания - там баг, который я исправил в своем проекте, но не перенес исправление в репозиторий. В вашем коде SystemTimerUserHook(); вызывается только если прерывание пришло от таймера. Надо сделать такое изменнение: Код inline __arm void OS::SystemTimer_Handler() { Kernel.SystemTimer(); }
OS_INTERRUPT void OS::SystemTimer_ISR() { scmRTOS_ISRW_TYPE ISR;
SYSTEM_TIMER_HANDLER();
#if scmRTOS_SYSTIMER_HOOK_ENABLE == 1 SystemTimerUserHook(); #endif
IRQ_DONE(); } Спасибо, что нашли эту багу - сейсчас поправлю. Посмотрел внимательнее ваш код - запись AT91C_BASE_AIC->AIC_EOICR = 1; // ? не нужна, это делается в самом обработчике, в макросе IRQ_DONE. А что вы хотели получить записью AT91C_BASE_AIC->AIC_IVR = 1; // ? мне совсем непонятно.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jan 17 2008, 13:07
|

Частый гость
 
Группа: Свой
Сообщений: 107
Регистрация: 6-09-06
Из: Москва
Пользователь №: 20 118

|
Всё заработало. Пока ещё не смог сломать Цитата(Сергей Борщ @ Jan 17 2008, 11:59)  А что вы хотели получить записью AT91C_BASE_AIC->AIC_IVR = 1; // ? мне совсем непонятно. Это скопировал из другого проекта. Использовал при отладке. Предварительно перешел в Protect Mode. Но в этом проекте не использую Protect Mode. Надо удалить будет
|
|
|
|
|
Jan 18 2008, 07:07
|

Частый гость
 
Группа: Свой
Сообщений: 107
Регистрация: 6-09-06
Из: Москва
Пользователь №: 20 118

|
Цитата Посмотрел, как в OS_Target_cpp.cpp сделан обработчик прерывания - там баг, который я исправил в своем проекте, но не перенес исправление в репозиторий. В вашем коде SystemTimerUserHook(); вызывается только если прерывание пришло от таймера. Надо сделать такое изменнение: ... Может там ещё нужно где-то поправить? У меня периодически отваливаются прерывания от системного таймера при большой активности DBGU. Программа постоянно сидит в void OS::IdleProcessUserHook() {} Если не трудно, можно выложить обновление здесь?
|
|
|
|
|
Jan 18 2008, 09:19
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(LessNik @ Jan 18 2008, 09:07)  Может там ещё нужно где-то поправить? У меня периодически отваливаются прерывания от системного таймера при большой активности DBGU. DBGU при этом продолжает работать?Стека для прерываний достаточно выделено? Цитата(LessNik @ Jan 18 2008, 09:07)  Программа постоянно сидит в void OS::IdleProcessUserHook() {} Это нормально, если ей больше нечего делать. Цитата(LessNik @ Jan 18 2008, 09:07)  Если не трудно, можно выложить обновление здесь? Да там только приведенные выше две функции OS::SystemTimer_Handler() и OS::SystemTimer_ISR() изменились. http://scmrtos.svn.sourceforge.net/viewvc/...1=71&r2=105
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jan 18 2008, 14:36
|

Частый гость
 
Группа: Свой
Сообщений: 107
Регистрация: 6-09-06
Из: Москва
Пользователь №: 20 118

|
Цитата(Сергей Борщ @ Jan 18 2008, 12:19)  DBGU при этом продолжает работать?Стека для прерываний достаточно выделено?Это нормально, если ей больше нечего делать.Да там только приведенные выше две функции OS::SystemTimer_Handler() и OS::SystemTimer_ISR() изменились. http://scmrtos.svn.sourceforge.net/viewvc/...1=71&r2=105GBGU перестаёт работать и перестаёт вызываться системное прерывание вообще OS_INTERRUPT void OS::SystemTimer_ISR() и Программа постоянно сидит в void OS::IdleProcessUserHook() {}, периодически реагируя на прерывание от другого таймера TC0. Для верности объявил: typedef OS::process<OS::pr0, 1000> TDBGUProc; всё равно не работает.
|
|
|
|
|
Jan 19 2008, 00:47
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(LessNik @ Jan 18 2008, 16:36)  GBGU перестаёт работать и перестаёт вызываться системное прерывание вообще OS_INTERRUPT void OS::SystemTimer_ISR() и Программа постоянно сидит в void OS::IdleProcessUserHook() {}, периодически реагируя на прерывание от другого таймера TC0. Очень похоже, что ваша программа некорректно (без записи в AIC_EOICR) завершает какое-то из прерываний. При этом перестают вызываться прерывания с таким же и более низкими приоритетами. На это косвенно указывет и то, что программа крутится в Idle,т.е. не вызывается и переключатель контекста. Возможно, в каком-то из прерываний вы забыли завести объект OS:TISRW, в деструкторе которого и выпоняется эта запись. Если какое-либо ваше прерывание не использет никакие сервисы ОС, то можно не заводить в нем объект OS:TISRW, но тогда вы должны сами в конце этого прерывания вручную прописать AIC_EOICR. Вот такая версия. Надеюсь, что ОС в данном случае не виновата. Но если вы все же найдете в ней недоработку-обязательно сообщите. И даже если не в ОС дело-все равно отпишитесь здесь, интересно же  Цитата(prottoss @ Dec 13 2007, 14:18)  кстати, в ассемблер на IAR тоже можно включать C-шные хедеры, так что я думаю, что можно побороть эту проблему. Увы, насколько я понял рассматривая заголовочные файлы компилятора, __HAS_RAMPZ__ определяется не в заголовочном файле (который подключен к OS_Target_asm.s90), а самим компилятором на основе указанного ему типа процессора. А вот в ассемблере аналогичное определение они почем-то не сделали  Выход есть - написать в начале файла свой большой #if defined (__ATMEGA128__) и определить в нем __HAS_RAMPZ__ для всех процессоров, в которых он есть. Надо занести это в трекер, чтобы не забыть сделать к ближайшему релизу
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jan 22 2008, 06:40
|

Частый гость
 
Группа: Свой
Сообщений: 107
Регистрация: 6-09-06
Из: Москва
Пользователь №: 20 118

|
Цитата(Сергей Борщ @ Jan 19 2008, 03:47)  Очень похоже, что ваша программа некорректно (без записи в AIC_EOICR) завершает какое-то из прерываний. При этом перестают вызываться прерывания с таким же и более низкими приоритетами. На это косвенно указывет и то, что программа крутится в Idle,т.е. не вызывается и переключатель контекста. Возможно, в каком-то из прерываний вы забыли завести объект OS:TISRW, в деструкторе которого и выпоняется эта запись. Если какое-либо ваше прерывание не использет никакие сервисы ОС, то можно не заводить в нем объект OS:TISRW, но тогда вы должны сами в конце этого прерывания вручную прописать AIC_EOICR. Получается, если я завожу объект OS:TISRW, то мне не нужно прописывать AIC_EOICR? Я не нашел в деструкторе этого объекта записи в AIC_EOICR. Я обычно прописывал AT91C_BASE_AIC->AIC_EOICR = 0; И в примере тоже вручную прописывали: Код OS_INTERRUPT void Timer_ISR() { OS::TISRW ISRW; volatile dword Tmp = AT91C_BASE_TCB->TCB_TC0.TC_SR; // read to clear int flag
AT91C_BASE_PIOA->PIO_SODR = (1 << 0); Timer_Ovf.SignalISR();
AT91C_BASE_AIC->AIC_EOICR = 0; } Если не дописывать, то прерывание больше не вызывается Попробовал так: Код OS_INTERRUPT void TimerCounter0Interrupt(void) { OS::TISRW ISRW; volatile dword Tmp = AT91C_BASE_TCB->TCB_TC0.TC_SR; // read to clear int flag
// AT91C_BASE_AIC->AIC_EOICR = 0; без этой строчки не работает
}
|
|
|
|
|
Jan 31 2008, 10:24
|

Частый гость
 
Группа: Свой
Сообщений: 107
Регистрация: 6-09-06
Из: Москва
Пользователь №: 20 118

|
Цитата(Сергей Борщ @ Jan 19 2008, 03:47)  Надеюсь, что ОС в данном случае не виновата. Но если вы все же найдете в ней недоработку-обязательно сообщите. И даже если не в ОС дело-все равно отпишитесь здесь, интересно же  Нашёл! При настройке AIC, нужно использовать не AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE, как было в примере, а AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL. Тогда всё работает стабильно: Код AT91C_BASE_AIC->AIC_SMR[AT91C_ID_SYS] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL/*AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE*/ | AT91C_AIC_PRIOR_LOWEST + 1;
|
|
|
|
|
Jan 31 2008, 13:02
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(LessNik @ Jan 31 2008, 12:24)  При настройке AIC, нужно использовать не AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE, как было в примере, а AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL. Тогда всё работает стабильно: Угу. Действительно. В моем проекте, где используется DBGU тоже стоит AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL. Внесу изменения в примеры ОСи. Спасибо! Интересно, кто-нибудь знает, зачем я там делал EDGE? P.S. гляньте вот сюда: ветка на сахаре. Обнаружился баг в TEeventFlag, там идет обсуждение путей его ликвидации.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 5 2008, 06:11
|

Шаман
     
Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221

|
Цитата(spf @ Feb 4 2008, 17:21)  Все работает, народ подтягивается. По данной ссылке http://index.php/?showtopic=42800&hl= так и не могу зайти. Ссылка правильная? PS Нашёл правильную ссылку в соседней ветке.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|