singlskv 0 20 мая, 2008 Опубликовано 20 мая, 2008 · Жалоба Насчет каждый такт на счету - не верю, не может каждый такт быть на счету для чего-то настолько длительного, что ест аж 4 периода таймера и в то же время настолько редкого, что происходит раз в 100 периодов таймера. Нестукуется с таким событием понятие каждый такт на счету.Ну и почему же это не стыкуется ? допустим хочу: - передачу по SPI на максимальной скорости(кб этак 250-500 в сек) но при этом чтобы джиттер был минимален и предсказуем - опрос кнопок(типа процесс в 100 раз более медленный) - запись в EEPROM когда надо(тоже не быстро). - итд итп ну и кто мешает это все совместить ? Кстати, я очень обижен на атмел в том, что битики force output compare у таймеров не вызывают соответствующее прерывание output compare :-(А Вы ими пробовали вобще пользоваться ? (битиками) я нет, поэтому и интересно... но кстати таймером тож можно чего-нить такое намутить, тока топикстартер не сознается какие узлы кроме комаратора у него еще не задействованны... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
defunct 0 20 мая, 2008 Опубликовано 20 мая, 2008 · Жалоба Ну и почему же это не стыкуется ? Несктыкуется это событие (длиной в 4 периода таймера) с надобностью обработки в прерывании. допустим хочу: - передачу по SPI на максимальной скорости(кб этак 250-500 в сек) но при этом чтобы джиттер был минимален и предсказуем - опрос кнопок(типа процесс в 100 раз более медленный) - запись в EEPROM когда надо(тоже не быстро). - итд итп ну и кто мешает это все совместить ? Ничто и не помешает все это совместить если обработку события длиной в 4 периода таймера кинуть в основной цикл. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
singlskv 0 20 мая, 2008 Опубликовано 20 мая, 2008 · Жалоба Несктыкуется это событие (длиной в 4 периода таймера) с надобностью обработки в прерывании. Ничто и не помешает все это совместить если обработку события длиной в 4 периода таймера кинуть в основной цикл. А кто сказал что это событие обязательно нужно обработать за один присест ? Вне зависимости от того где оно будет обрабатывться, всегда есть возможность обработать его по частям. Те просто делаем автомат обработки события с внутренним разбиением на части... Те например пусть нам нужно записать X байт в EEPROM, запись каждого байта это процесс который может растянуться на очень много периодов нашего таймера, но у нас автомат который запустил запись X байтов и пока они все не записались он не освободился. Ну конечно если там голые рассчеты без всяких ожиданий то они конечно должны жить в главном цикле... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
galjoen 0 20 мая, 2008 Опубликовано 20 мая, 2008 · Жалоба Несктыкуется это событие (длиной в 4 периода таймера) с надобностью обработки в прерывании. Тут прерывание ТОЛЬКО для того, чтоб приоритет этого события поднять, а основной цикл отдать кому то другому (на, делай в нём что хочешь, всё равно мне не навредишь). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
defunct 0 20 мая, 2008 Опубликовано 20 мая, 2008 · Жалоба Те просто делаем автомат обработки события с внутренним разбиением на части... Ну так ведь ничто не мешает этот автомат сделать в основном цикле. Ввести там сколько надо приоритетов 10-100-1000 (на скоко памяти хватит) и следовать им. Тут прерывание ТОЛЬКО для того, чтоб приоритет этого события поднять Если только для этого, то обрабатывать можно в том же прерывании, зачем еще одно плодить? результат одинаковый будет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Don_Ambrosio 0 21 мая, 2008 Опубликовано 21 мая, 2008 · Жалоба У меня для "быстрых" потоков, которые должны вызваться не позднее одного тика таймера после возникновения Event-а, требующего их вмешательства, есть регистр , в котором каждый битик является Ready-флагом соответствующего потока. И перед выходом из ISR системного таймера я проверяю не стоит ли Ready-флажок какого-нить потока. Если стоит, то запускаю соответ.поток в порядке приоритета (от 7 к 0 ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DogPawlowa 0 21 мая, 2008 Опубликовано 21 мая, 2008 · Жалоба Ну так ведь ничто не мешает этот автомат сделать в основном цикле. Ввести там сколько надо приоритетов 10-100-1000 (на скоко памяти хватит) и следовать им. Автоматами только в основном цикле, как правило, не обойтись. У меня обычно автоматы и на процессах в прерываниях. Признаюсь, что тоже отношусь к темным, которые не понимают, зачем это все нужно. Приоритеты двух прерываний реализуются (извращенно :) )несимметричностью разрешения прерывания (в одном ISR разрешаем, в другом нет), защита от переполнения стека в случае длинного и/или чрезмерно частого более приоритетного прерывания реализуется счетчиком низкоприоритетного прерывания. __interrupt void low_priority_interrupt() { interrupt_no++; if (interrupt_no>1) DISABLE_HIGH_PRIORITY_INTERRUPT(); __enable_interrupt(); ... } Ну и попытка все устройства сделать на AVR , выжимая все соки? Даже в 8080 была система приоритетных прерываний, что других контроллеров не существует? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 21 мая, 2008 Опубликовано 21 мая, 2008 · Жалоба Ну вообщем, проверил на железе - не приводит к установке флага прерывания от компаратора дрыг режимом фронт/спад. Плохо, конечно. Пришлось перенести на прерывание от EEPROM и завести флаг запроса. Теперь это выглядит примерно так #define TASK2_LOCK GPIOR0_Bit0 #define TASK3_LOCK GPIOR0_Bit1 #define TASK2_WAKEUP GPIOR0_Bit2 #define DISABLE_TASK2() {EECR_EERIE=0;} #define ENABLE_TASK2() {EECR_EERIE=1;} #define WAKEUP_TASK2() {TASK2_WAKEUP=1;} #pragma diag_suppress=Ta006 __interrupt void TASK2(void) { __no_operation(); //.... //....много всякой долгой каки... main(); //Например так //.... __no_operation(); } #pragma diag_default=Ta006 #pragma vector=EE_RDY_vect __interrupt __raw void TASK2dispatch(void) { DISABLE_TASK2(); TASK2_LOCK=1; TASK2_WAKEUP=0; __enable_interrupt(); ((void(*)(void))TASK2)(); __disable_interrupt(); TASK2_LOCK=0; if (TASK2_WAKEUP) ENABLE_TASK2(); } #pragma diag_suppress=Ta006 __interrupt void TASK3(void) { __no_operation(); //.... //....не очень много всякой долгой каки... if (PINB_Bit0) WAKEUP_TASK2(); //К примеру //.... __no_operation(); } #pragma diag_default=Ta006 #pragma vector=TIMER0_OVF_vect __interrupt __raw void TASK3dispatch(void) { if (TASK3_LOCK) return; TASK3_LOCK=1; DISABLE_TASK2(); __enable_interrupt(); ((void(*)(void))TASK3)(); __disable_interrupt(); TASK3_LOCK=0; if (TASK2_LOCK) return; if (TASK2_WAKEUP) ENABLE_TASK2(); } #pragma vector=INT0_vect __interrupt void TASK4(void) { //Тут тоже колдовство, запрещаем все прерывания, например TIMSK0=0; //Запрещаем и TASK2 DISABLE_TASK2(); __enable_interrupt(); //Чего-то делаем, тут еще бывает INT1, но это уже не суть __disable_interrupt(); if (PINB_Bit1) WAKEUP_TASK2(); //К примеру TIMSK0=1<<TOV0; if (TASK3_LOCK) return; if (TASK2_LOCK) return; if (TASK2_WAKEUP) ENABLE_TASK2(); } И код RSEG CODE:CODE:NOROOT(1) // 48 __interrupt void TASK2(void) TASK2: // 49 { ST -Y, R24 ST -Y, R31 ST -Y, R30 ST -Y, R3 ST -Y, R2 ST -Y, R1 ST -Y, R0 ST -Y, R23 ST -Y, R22 ST -Y, R21 ST -Y, R20 ST -Y, R19 ST -Y, R18 ST -Y, R17 ST -Y, R16 IN R24, 0x3F // 50 __no_operation(); NOP // 51 //.... // 52 //....много всякой долгой каки... // 53 main(); //Например так RCALL main // 54 //.... // 55 __no_operation(); NOP // 56 } OUT 0x3F, R24 LD R16, Y+ LD R17, Y+ LD R18, Y+ LD R19, Y+ LD R20, Y+ LD R21, Y+ LD R22, Y+ LD R23, Y+ LD R0, Y+ LD R1, Y+ LD R2, Y+ LD R3, Y+ LD R30, Y+ LD R31, Y+ LD R24, Y+ RETI // 57 #pragma diag_default=Ta006 // 58 // 59 // 60 #pragma vector=EE_RDY_vect RSEG CODE:CODE:NOROOT(1) // 61 __interrupt __raw void TASK2dispatch(void) TASK2dispatch: // 62 { // 63 DISABLE_TASK2(); CBI 0x1F, 0x03 // 64 TASK2_LOCK=1; SBI 0x1E, 0x00 // 65 TASK2_WAKEUP=0; CBI 0x1E, 0x02 // 66 __enable_interrupt(); SEI // 67 ((void(*)(void))TASK2)(); RCALL TASK2 // 68 __disable_interrupt(); CLI // 69 TASK2_LOCK=0; CBI 0x1E, 0x00 // 70 if (TASK2_WAKEUP) ENABLE_TASK2(); SBIC 0x1E, 0x02 SBI 0x1F, 0x03 // 71 } ??TASK2dispatch_0: RETI REQUIRE _A_EECR REQUIRE _A_GPIOR0 // 72 // 73 #pragma diag_suppress=Ta006 RSEG CODE:CODE:NOROOT(1) // 74 __interrupt void TASK3(void) TASK3: // 75 { // 76 __no_operation(); NOP // 77 //.... // 78 //....не очень много всякой долгой каки... // 79 if (PINB_Bit0) WAKEUP_TASK2(); //К примеру SBIC 0x03, 0x00 SBI 0x1E, 0x02 // 80 //.... // 81 __no_operation(); ??TASK3_0: NOP // 82 } RETI REQUIRE _A_GPIOR0 REQUIRE _A_PINB // 83 #pragma diag_default=Ta006 // 84 // 85 #pragma vector=TIMER0_OVF_vect RSEG CODE:CODE:NOROOT(1) // 86 __interrupt __raw void TASK3dispatch(void) TASK3dispatch: // 87 { // 88 if (TASK3_LOCK) return; SBIC 0x1E, 0x01 RJMP ??TASK3dispatch_0 // 89 TASK3_LOCK=1; SBI 0x1E, 0x01 // 90 DISABLE_TASK2(); CBI 0x1F, 0x03 // 91 __enable_interrupt(); SEI // 92 ((void(*)(void))TASK3)(); RCALL TASK3 // 93 __disable_interrupt(); CLI // 94 TASK3_LOCK=0; CBI 0x1E, 0x01 // 95 if (TASK2_LOCK) return; SBIC 0x1E, 0x00 RJMP ??TASK3dispatch_0 // 96 if (TASK2_WAKEUP) ENABLE_TASK2(); SBIC 0x1E, 0x02 SBI 0x1F, 0x03 ??TASK3dispatch_0: RETI REQUIRE _A_EECR REQUIRE _A_GPIOR0 // 97 } // 98 // 99 #pragma vector=INT0_vect RSEG CODE:CODE:NOROOT(1) // 100 __interrupt void TASK4(void) TASK4: // 101 { ST -Y, R17 ST -Y, R16 IN R17, 0x3F // 102 //Тут тоже колдовство, запрещаем все прерывания, например // 103 TIMSK0=0; LDI R16, 0 STS 110, R16 // 104 //Запрещаем и TASK2 // 105 DISABLE_TASK2(); CBI 0x1F, 0x03 // 106 __enable_interrupt(); SEI // 107 //Чего-то делаем, тут еще бывает INT1, но это уже не суть // 108 __disable_interrupt(); CLI // 109 if (PINB_Bit1) WAKEUP_TASK2(); //К примеру SBIC 0x03, 0x01 SBI 0x1E, 0x02 // 110 TIMSK0=1<<TOV0; ??TASK4_0: LDI R16, 1 STS 110, R16 // 111 if (TASK3_LOCK) return; SBIC 0x1E, 0x01 RJMP ??TASK4_1 // 112 if (TASK2_LOCK) return; SBIC 0x1E, 0x00 RJMP ??TASK4_1 // 113 if (TASK2_WAKEUP) ENABLE_TASK2(); SBIC 0x1E, 0x02 SBI 0x1F, 0x03 ??TASK4_1: OUT 0x3F, R17 LD R16, Y+ LD R17, Y+ RETI В принципе, из-за того, что управление прерыванием доступно через SBI/CBI время нахождения в состоянии с запрещенным прерыванием даже уменьшилось... Красота только пропала ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
galjoen 0 21 мая, 2008 Опубликовано 21 мая, 2008 · Жалоба #pragma vector=TIMER0_OVF_vect __interrupt __raw void TASK3dispatch(void) { if (TASK3_LOCK) return; TASK3_LOCK=1; DISABLE_TASK2(); __enable_interrupt(); ((void(*)(void))TASK3)(); __disable_interrupt(); TASK3_LOCK=0; if (TASK2_LOCK) return; if (TASK2_WAKEUP) ENABLE_TASK2(); } Не совсем понял вот этот кусок, поэтому м.б. задам глупый вопрос. if (TASK3_LOCK) return; TASK3_LOCK=1; Это видимо антирекурсия, так? Почему вы, любитель красоты в программировании (я наверное такой-же) использовали для этого лишний бит (#define TASK3_LOCK GPIOR0_Bit1), а не сам бит разрешения прерывания TOIE0 из регистра TIMSK? Это из-за того, что в вашем процессоре он не доступен командами cbi, sbic и поэтому требует вспомогательного регистра (и его сохранения) в т.ч. для проверки в прерывании INT0? Зато прерывания от таймера вообще возникать не будут - уменьшение времени нахождения с запрещёнными прерываниями ну и красота. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 21 мая, 2008 Опубликовано 21 мая, 2008 · Жалоба В принципе предложений накидали. :) Обсуждать подход автора, считаю глупым, так как он к нам за этим не обращался, к тому же постановка вопроса близка и понятна мне. В XMEGA будет проще данную проблему решать. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DogPawlowa 0 21 мая, 2008 Опубликовано 21 мая, 2008 · Жалоба Обсуждать подход автора, считаю глупым, так как он к нам за этим не обращался, к тому же постановка вопроса близка и понятна мне. А поговорить? :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 21 мая, 2008 Опубликовано 21 мая, 2008 · Жалоба Зато прерывания от таймера вообще возникать не будут - уменьшение времени нахождения с запрещёнными прерываниями ну и красота. В общем итоге - с запрещением через TIMSK хуже. В XMEGA будет проще данную проблему решать. А то, там костыль есть для генерации эвентов вручную. О нас подумали ;) А поговорить? Неси литру, поговорим :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sKWO 0 21 мая, 2008 Опубликовано 21 мая, 2008 · Жалоба В принципе, из-за того, что управление прерыванием доступно через SBI/CBI время нахождения в состоянии с запрещенным прерыванием даже уменьшилось... Красота только пропала ;) Это уже есть мысль. Круто Да и не сказалбы я что красота пропала Есть в общем над чем поломать голову и поучиться :a14: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
galjoen 0 21 мая, 2008 Опубликовано 21 мая, 2008 · Жалоба М.б. конечно я уже надоел своим занудством, но... В общем итоге - с запрещением через TIMSK хуже. Мне вот это всё не нравится (некрасивым кажется): // 88 if (TASK3_LOCK) return; // вот это (лишних 12 тактов при возникновении прерывания от таймера при TASK3_LOCK=1) SBIC 0x1E, 0x01 RJMP ??TASK3dispatch_0 // 89 TASK3_LOCK=1; SBI 0x1E, 0x01 // 90 DISABLE_TASK2(); CBI 0x1F, 0x03 // 91 __enable_interrupt(); SEI // 92 ((void(*)(void))TASK3)(); // и ОСОБЕННО это (3+4=7 тактов лишних при КАЖДОМ вызове) RCALL TASK3 // 93 __disable_interrupt(); CLI // 94 TASK3_LOCK=0; CBI 0x1E, 0x01 // 95 if (TASK2_LOCK) return; SBIC 0x1E, 0x00 RJMP ??TASK3dispatch_0 // 96 if (TASK2_WAKEUP) ENABLE_TASK2(); SBIC 0x1E, 0x02 SBI 0x1F, 0x03 ??TASK3dispatch_0: Всё это ведь сделано что-бы регистры при возникновении прерывания при TASK3_LOCK=1 не сохранялись. А если в прерывании от таймера __interrupt void использовать, а там и TASK3_LOCK=1 устанавливать (для INT0), и TIMSK запрещать (всего 3 такта лишних)? Вроде по всем параметрам лучше. Ну а главное красивее :) . Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 21 мая, 2008 Опубликовано 21 мая, 2008 · Жалоба Мне вот это всё не нравится (некрасивым кажется): Ну попробуйте переделать. Рыба, которую я привел - она компилируется... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться