Перейти к содержанию
    

abi

Участник
  • Постов

    23
  • Зарегистрирован

  • Посещение

Репутация

0 Обычный

Информация о abi

  • Звание
    Участник
    Участник
  • День рождения 02.01.1970

Контакты

  • ICQ
    Array

Информация

  • Город
    Array

Посетители профиля

1 184 просмотра профиля
  1. XMEGA прерывания

    Нашел причину. Попробую объяснить. Проект настроен на прямую передачу управления, т.е. #define scmRTOS_CONTEXT_SWITCH_SCHEME 0. Для примера запускаем проект с одним процессом. template<> void TProc1::exec() { for(;;) { sleep(10); delay_ms(500); } } 1. Заходим в sleep(10), выставляем timeout, сбрасываем флаг готовности процесса и выполняем перепланировку Kernel.scheduler(), т.к. рабочий процесс один и он ушел в спячку, система переключится на процесс IdleProc. 2. Периодически через заданный интервал времени от системного таймера возникают прерывания, в обработчике функция Kernel.system_timer() проверяет флаг готовности процесса Proc1. Если готовности нет, прерывание завершается без перепланировки и система продолжает оставаться в IdleProc. Тут отмечу, что выход из обработчика прерывания без перепланировки выполняется командой RETI, контроллер прерываний при этом сбрасывает флаг в PMIC.STATUS. Далее контроллер готов к выполнению других прерываний, если они есть в очереди или когда возникнут новые. 3. Если флаг готовности процесса Proc1 установлен, в обработчике прерывания системного таймера произойдет перепланировка процессов в функции os_context_switcher. Тут немного подробнее, при вызове этой функции в RStаck процесса IdleProc запишется адрес возврата, в CStack сохранится SP, сохранятся состояние регистров, далее для выполнения Proc1, из стека Proc1 восстановится SP и регистры, т.е. все готово для продолжения выполнения этого процесса. В конце функции os_context_switcher выполняется команда RET, в результате которой попадаем сразу в Proc1 и продолжаем его выполнение. В итоге получается, что обработка прерывания осталась не завершена, команды RETI не было, флаг в PMIC.STATUS = 1, прерывания одного уровня работать не будут даже при SREG = 0x80. 4. Далее по коду в Proc1, функция delay_ms(500) отработает без прерываний, зайдет в sleep(10), в которой произойдет перепланировка, восстановится процесс IdleProc, а т.к. он был ранее сохранен в обработчике прерывания, завершит его код с командой выхода RETI, и прерывания снова будут выполняться. Подскажите, пожалуйста, может есть какие мысли? Пока думаю над таким вариантом: в конце функции os_context_switcher сделать проверку флага PMIC.STATUS, если флаг установлен, то выполнять выход командой RETI, если нет, то RET. Но тут есть один момент, IdleProc при возобновлении в обработчике прерывания будет завершать его командой RETI, т.е. прерывание уже было завершено ранее командой RETI, и тут снова RETI.
  2. XMEGA прерывания

    У PMIC 3 регистра. PMIC.STATUS только для чтения. PMIC.INTPRI сохраняет вектор последнего подтвержденного низкоуровневого прерывания, если разрешен режим Round-Robin, но он отключен. PMIC.CTRL для настройки уровня разрешенных прерываний, т.к. у всех прерываний установлен Low Level, регистр настроен на LOLVLEN и всегда равен 1. Выводил состояние этого регистра в процессах, он не меняется и всегда равен 1. Поэтому думаю сохранять регистры PMIC в контекст смысла нет. А вот интересно при создании объекта IdleProc используется функция init_stack_frame () так же как и при создании рабочих процессов, т.е. все одинаково, а результат разный. Позже попробую добавить в IdleProc функцию sleep и скорее всего и IdleProc начнет блокировать прерывания.
  3. XMEGA прерывания

    Добавил в idle_process_user_hook() вывод состояния регистров. При активном процессе idle прерывания работают, это видно осциллографом и по состоянию регистров. Флаг регистра TCF0.INTFLAGS сброшен, состояние PMIC.STATUS всегда = 0. INTFLAGS SP INTPRI STATUS SREG f0 23a7 00 00 82 f0 23a7 00 00 80 f0 23a7 00 00 80 f0 23a7 00 00 80 f0 23a7 00 00 80 Не могу понять, почему в рабочих процессах всегда PMIC.STATUS = 1, а в процессе idle PMIC.STATUS = 0 и прерывания работают.
  4. XMEGA прерывания

    Да, как будто код в процессе находится в критической секции, но это не так, как показывал на примере выше прерывания разрешены и вроде все условия для выполнения прерывания есть. Если запустить несколько процессов, то каждый процесс будет откладывать прерывание на время его выполнения.
  5. XMEGA прерывания

    Для примера запущен таймер TCF0, который каждые 2 ms генерирует прерывания, в обработчике переключаю состояние пина, осциллографом видно что каждые 2 ms пин меняет состояние, т.е. работает правильно. Но когда работают процессы, прерывания от таймера не происходят, например #define delay_ms(ms) ( __delay_cycles((F_CPU / 1000UL) * (ms)) ) template<> void TProc1::exec() { unsigned char temp; unsigned int val; for(;;) { sleep(500); delay_ms(50); } } В течении 500 ms (когда процесс в sleep(500)) прерывания есть, как только процесс становится активным попадает в delay_ms(50) прерываний нет, и по осциллографу видно, что в течении 50 ms, пин не меняет состояние. Далее снова в течении 500 ms прерывания есть и т.д. В посту выше приводил пример с выводом данных через UART, пока в цикле выводятся данные прерываний нет, как только в процессе вызывается любой сервис OS в котором происходит перепланировка прерывания начинают работать.
  6. XMEGA прерывания

    Сделал несколько небольших изменений для работы с xmega, если кому интересно позже открою проект. Все прерывания установил на один уровень. Перепланирование процессов производится прямой передачи управления #define scmRTOS_CONTEXT_SWITCH_SCHEME 0. Изначально основной проект был сделан под mega128, затем решил адаптировать его под xmega. Проект заработал, но заметил при приеме данных по UART, временами пакеты принимаются с ошибкой. Позже выяснил причину, оказалось, что когда какой-либо процесс активный, прерывания процессор не выполняет. Прерывание откладывается на время выполнения кода процесса, т.е. до тех пор пока не произойдет перепланировка. Если процесс занимает короткое время данные по UART успевают приниматься, иначе несколько байт теряются. Для поиска причины сделал тестовый проект, в нем 3 процесса, в каждом процессе через UART вывожу состояния нескольких регистров. Для примера код одного процесса. template<> void TProc1::exec() { unsigned char temp; unsigned int val; for(;;) { sleep(2500); for (unsigned char i = 0; i < 10; i++) { temp = TCF0.INTFLAGS; ComPutchar(temp); val = SP; ComPutchar(val >> 8); ComPutchar(val & 0xFF); temp = PMIC.INTPRI; ComPutchar(temp); temp = PMIC.STATUS; ComPutchar(temp); temp = SREG; ComPutchar(temp); } } } Полученные данные Proc1 INTFLAGS SP INTPRI STATUS SREG f0 21b1 00 01 82 f0 21b1 00 01 80 f0 21b1 00 01 80 f1 21b1 00 01 80 f1 21b1 00 01 80 f1 21b1 00 01 80 f1 21b1 00 01 80 f1 21b1 00 01 80 f1 21b1 00 01 80 f1 21b1 00 01 80 Proc3 INTFLAGS SP INTPRI STATUS SREG f0 2337 00 01 82 f0 2337 00 01 80 f0 2337 00 01 80 f1 2337 00 01 80 f1 2337 00 01 80 f1 2337 00 01 80 f1 2337 00 01 80 f1 2337 00 01 80 f1 2337 00 01 80 f1 2337 00 01 80 Proc2 INTFLAGS SP INTPRI STATUS SREG f0 2274 00 01 82 f0 2274 00 01 80 f0 2274 00 01 80 f1 2274 00 01 80 f1 2274 00 01 80 f1 2274 00 01 80 f1 2274 00 01 80 f1 2274 00 01 80 f1 2274 00 01 80 f1 2274 00 01 80 Из лога видно, что прерывания всегда разрешены SREG = 0x80, I = 1. Таймер TCF0 после переполнения выставляет флаг (0x01), INTFLAGS = 0xf1. Непонятно почему в регистре PMIC.STATUS всегда 1, насколько я понял статус показывает какого уровня прерывание на данный момент выполняется и этот флаг должен быть сброшен после выполнения. В проекте всего два разрешенных прерывания, системный таймер OS - TCD0 (1 ms) и от таймера TCF0 (2 ms) который просто переключает состояние пина.
  7. XMEGA прерывания

    В цикле только одна функция используется, просто в UART передает данные void ComPutchar(char ch) { while ((USARTD1.STATUS & USART_DREIF_bm) == 0); USARTD1.DATA = ch; } Пробовал даже вместо цикла с выводом данных, вставлял простую функцию задержки, результат одинаковый. #define delay_ms(ms) ( __delay_cycles((F_CPU / 1000UL) * (ms)) ) for(;;) { sleep(1000); delay_ms(10); } В логе видно, что флаги устанавливаются, прерывания разрешены, вроде все условия для выполнения прерывания есть, но их нет до тех пор пока процесс не уходит в sleep
  8. XMEGA прерывания

    Здравствуйте. Помогите пожалуйста разобраться. Собрал для примера тестовый проект, МК ATxmega256A3U, scmRTOS 5.1.0. Во время выполнения процесса перестают работать прерывания, как только процесс уходит в sleep прерывания начинают работать. В чем может быть причина, что прерывания не работают во время выполнения кода процесса? Причем прерываний нет и от системного таймера OS TCDO, когда работает процесс. int main() { BspClockInit(); BspPin2Init(); BspComUartConnect(); ComSetFrameFormat(); ComSetBaudRate(Baud_19200BPS); TCD0.CTRLA = TC_CLKSEL_DIV1_gc; TCD0.CTRLB = TC_WGMODE_NORMAL_gc; TCD0.CTRLC = 0x00; TCD0.CTRLD = 0x00; TCD0.PER = 24000 - 1; TCD0.INTCTRLA = TC_OVFINTLVL_LO_gc; TCD0.CTRLFSET = TC_CMD_UPDATE_gc; TCD0.CTRLFCLR = TC_CMD_UPDATE_gc; TCD0.CTRLFSET = TC_CMD_RESTART_gc; TCD0.CTRLFCLR = TC_CMD_RESTART_gc; TCF0.CTRLA = TC_CLKSEL_DIV1024_gc; TCF0.CTRLB = TC_WGMODE_NORMAL_gc; TCF0.CTRLC = 0x00; TCF0.CTRLD = 0x00; TCF0.PER = 234 - 1; TCF0.INTCTRLA = TC_OVFINTLVL_LO_gc; TCF0.CTRLFSET = TC_CMD_UPDATE_gc; TCF0.CTRLFCLR = TC_CMD_UPDATE_gc; TCF0.CTRLFSET = TC_CMD_RESTART_gc; TCF0.CTRLFCLR = TC_CMD_RESTART_gc; PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_RREN_bm; OS::run(); } template<> void TProc1::exec() { unsigned char temp; for(;;) { sleep(1000); for (unsigned char i = 0; i < 50; i++) { unsigned int cnt = TCF0.CNT; ComPutchar(cnt >> 8); ComPutchar(cnt & 0xFF); temp = TCF0.INTFLAGS; ComPutchar(temp); temp = SREG; ComPutchar(temp); } } } #pragma vector=TCF0_OVF_vect OS_INTERRUPT void TimerF0_period_ISR() { BspPinTgl2(); } Во время выполнения процесса в цикле в UART вывожу состояния регистров таймера TCF0 и SREG CNT FLAGS SREG 0058 f0 82 В TCF0.INTFLAGS флаг переполнения сброшен, прерывания работали. 0065 f0 80 0095 f0 80 00c6 f0 80 000d f1 80 Произошло переполнение таймера, выставлен флаг переполнения в TCF0.INTFLAGS, 003e f1 80 в SREG I=1 прерывания разрешены 006e f1 80 009f f1 80 00d0 f1 80 Произошло повторное переполнение таймера, прерывания нет, флаг не сброшен. 0017 f1 80 0047 f1 80 0078 f1 80 Заранее спасибо за помощь.
  9. Попробуйте погонять в цикле другую команду, к примеру AT+GMM и посмотреть будут ли задержки. Думаю стоит зафиксировать скорость обмена AT+IPR=ххх т.к.повторные команды АТ заставляют модуль выполнять повторную синхронизацию при включенном автоопределением.
  10. Проверьте как настроен режим управления потоком в модуле командой AT+IFC? и соответственно настройте его под схему и программу. Возможно ошибаюсь или что-то не правильно понял, но судя по картинке модуль работает нормально, задержки около 50 мс. Время передачи команды "AT" и ответа "OK" с учетом \r и \n на скорости 9600 бит/с занимает примерно 4 мс, но т.к. горизонтальная развертка сжата, пакеты приема и передачи видны как вертикальные столбики (импульсы). По картинке видно по линии RX передается команда и примерно через 50 мс на линии TX виден ответ на команду. Причем во время ответа или почти сразу после него по линии RX передается повторная команда и на линии TX также через 50 мс виден ответ на вторую команду. Примерно через 2,18 с все повторяется.
  11. Согласен, внутреннего системного сброса не произойдет. В зависимости от замысла принудительного программного сброса, системный сброс может и не понадобиться. В любом случае используемая периферия будет проинициализирована программой.
  12. Вариант без WDT __disable_interrupt(); ((void (*)())0x0000)();
  13. 73 0x49 I 110 0x6E n 116 0x74 t 101 0x65 e 114 0x72 r 110 0x6E n 101 0x65 e 116 0x74 t 83 0x53 S 77 0x4D M 83 0x53 S
  14. Это не бит TP_UDHI, а длина заголовка UDH в байтах. И судя по этому заголовку, получается, что принят сегмент 2 из 2. Т.е. исходное сообщение превысило допустимую длину и было разбито на два сообщения. Красное 0037 0030 003A 0020, это просто текст . Возможно перед набором werwerwre, в поле ввода был какой то текст который заканчивался на 70: .
  15. Для примера есть Atmel AVR112: TWI Bootloader for Devices without Boot Section http://www.atmel.com/Images/doc8079.pdf http://www.atmel.com/Images/AVR112.zip
×
×
  • Создать...