vet 0 11 сентября, 2006 Опубликовано 11 сентября, 2006 · Жалоба Кто-нибудь может скинуть рабочий код для PIT? так инициализируется таймер в uCOS-II: static void Tmr_TickInit (void) { INT32U counts; /* Set the vector address for PIT */ AT91C_BASE_AIC->AIC_SVR[AT91C_ID_SYS] = (INT32U)Tmr_TickISR_Handler; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_SYS] = AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE | AT91C_AIC_PRIOR_LOWEST; AT91C_BASE_AIC->AIC_ICCR = 1 << AT91C_ID_SYS; AT91C_BASE_AIC->AIC_IECR = 1 << AT91C_ID_SYS; counts = (F_MCK / 16 / OS_TICKS_PER_SEC) - 1; AT91C_BASE_PITC->PITC_PIMR = AT91C_PITC_PITEN | AT91C_PITC_PITIEN | counts; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 11 сентября, 2006 Опубликовано 11 сентября, 2006 · Жалоба Кто-нибудь может скинуть рабочий код для PIT? //Инициализация #define MAINCLK 4032000L #define PLLMUL 36 #define PLLDIV 3 #define MCK ((MAINCLK * PLLMUL) / PLLDIV) #define RTOS_TICK_RATE 100 // Hz // RTOS Timer AT91C_BASE_PITC->PITC_PIMR = (((MCK / 16) / RTOS_TICK_RATE - 1) & AT91C_PITC_PIV) \ | (1 * AT91C_PITC_PITEN) | (1 * AT91C_PITC_PITIEN); AT91C_BASE_AIC->AIC_SMR[AT91C_ID_SYS] = AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE | AT91C_AIC_PRIOR_LOWEST; AT91C_BASE_AIC->AIC_SVR[AT91C_ID_SYS] = (uint32_t)OS::SystemTimer_Wrapper; AT91C_BASE_AIC->AIC_IECR = (1<<AT91C_ID_SYS); //обработчик: OS_INTERRUPT void OS::SystemTimer_Wrapper() { volatile dword Tmp = AT91C_BASE_PITC->PITC_PIVR >> 20; while(Tmp--) { SystemTimer_ISR(); } } При этом если не читать PIVR флаг прерывания не снимается.Да, именно. НЕ СНИМАЕТСЯ ЕСЛИ НЕ ЧИТАТЬ PIVR. Я вот удивляюсь - а документацию кто читать должен? Уже на gaw.ru и перевод сделали для тех, кому лень выучить необходимые для пониманий 90% текста 50 слов и сочетаний по-английски. Отсюда вопрос каким образом от данного таймера получить интервал прерываний больший 20-разрядной части 1) Уменьшить MCLK 2) Организовать в прерывании этого таймера хоть 128-битный программный счетчик. и зачем вообще нужен PICNT? Для формирования периодических прерываний с постоянным интервалом. Например системный таймер RTOS, который обычно генерит прерывания с частотой 100-1000Гц. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SpiritDance 0 12 сентября, 2006 Опубликовано 12 сентября, 2006 · Жалоба 1) Уменьшить MCLK 2) Организовать в прерывании этого таймера хоть 128-битный программный счетчик. Я вобщем не спрашивал как организовать счетчик. Просто я так понял что больший интервал аппаратных прерываний чем записывается в PIVR получить нельзя. Для формирования периодических прерываний с постоянным интервалом. Например системный таймер RTOS, который обычно генерит прерывания с частотой 100-1000Гц. Не понял. При чем здесь счетчик переполнений? Он же сбрасывается при считывании PIVR? Что касается документации то да, признаю, я часто бываю невнимателен. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 12 сентября, 2006 Опубликовано 12 сентября, 2006 · Жалоба Я вобщем не спрашивал как организовать счетчик. Просто я так понял что больший интервал аппаратных прерываний чем записывается в PIVR получить нельзя.Да, нельзя. Тогда я не понял вопроса. А какой таймер позволяет делать больший чем разрядность таймера? Не понял. При чем здесь счетчик переполнений? Он же сбрасывается при считывании PIVR?Извиняюсь, я тоже бываю невнимателен. Почему-то показалось, что вопрос был про PIT вообще. Видимо чтобы узнать сколько прерываний было потеряно если это прерывание было запрещено надолго и потом программно вызвать обработчик нужное количество раз: volatile dword Tmp = AT91C_BASE_PITC->PITC_PIVR >> 20; while(Tmp--) { SystemTimer_ISR(); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SpiritDance 0 12 сентября, 2006 Опубликовано 12 сентября, 2006 · Жалоба Да, нельзя. Тогда я не понял вопроса. А какой таймер позволяет делать больший чем разрядность таймера? Ну вообще-то полная разрядность таймера PIT 20 + 12 :) Хотя если подумать для чего сделан данный таймер то вобщем достаточно и 20 разрядов. Жаль только частота фиксированная. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gladov 0 3 декабря, 2006 Опубликовано 3 декабря, 2006 · Жалоба P.S. Этот таймер далеко не так прост, как может показаться на первый взгляд. Использовать прерывание в данном случае я бы однозначно не рекомендовал. P.P.S. Но раз уж взялись - придется только добить. А поясните, пожалуйста, почему этот таймер не так прост и не рекомендуется использовать прерывания? Тоже только недано начал ковырять АРМ на AT91SAMx256 борде. И тоже попробовал поднять RTT. Поллинг работает, а прерывание стартует только в режиме LEVEL, но почему-то рабоает нормально без запрета прерывания в прерывании и последующем его разрешении в основном цикле. Если меняю режим на EDGE то прерывание просто не запускается. Вообще. Если кому не напряжно глянуть в мои каракули, может подскажете где грабли? // Initialize the timer AT91F_RTTC_CfgPMC(); //Enable a clock source AT91F_RTTClearAlarmINT(AT91C_BASE_RTTC); AT91F_RTTSetPrescaler(AT91C_BASE_RTTC, 0x4000); AT91F_RTTRestart(AT91C_BASE_RTTC); AT91F_RTTSetRttIncINT(AT91C_BASE_RTTC); // AIC initialization AT91F_AIC_CfgPMC(); AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SYS, AT91C_AIC_PRIOR_LOWEST, // AT91C_AIC_SRCTYPE_HIGH_LEVEL, AT91C_AIC_SRCTYPE_POSITIVE_EDGE, (void (*)())isr_system); AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SYS); // Loop forever while (1) { int c; c = AT91F_RTTReadValue(AT91C_BASE_RTTC); if (c != cval) { cval = c; if (AT91F_PIO_IsOutputDataStatusSet(AT91C_BASE_PIOB, led_mask[1])) AT91F_PIO_ClearOutput(AT91C_BASE_PIOB, led_mask[1]); else AT91F_PIO_SetOutput(AT91C_BASE_PIOB, led_mask[1]); } } __irq void isr_system() { if (AT91F_PIO_IsOutputDataStatusSet(AT91C_BASE_PIOB, led_mask[3])) AT91F_PIO_ClearOutput(AT91C_BASE_PIOB, led_mask[3]); else AT91F_PIO_SetOutput(AT91C_BASE_PIOB, led_mask[3]); //If this is RTT interrupt if (AT91F_RTTGetStatus(AT91C_BASE_RTTC) != 0) { if (AT91F_PIO_IsOutputDataStatusSet(AT91C_BASE_PIOB, led_mask[0])) AT91F_PIO_ClearOutput(AT91C_BASE_PIOB, led_mask[0]); else AT91F_PIO_SetOutput(AT91C_BASE_PIOB, led_mask[0]); } AT91C_BASE_AIC->AIC_EOICR = 0; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 4 декабря, 2006 Опубликовано 4 декабря, 2006 · Жалоба А поясните, пожалуйста, почему этот таймер не так прост и не рекомендуется использовать прерывания? Тоже только недано начал ковырять АРМ на AT91SAMx256 борде. И тоже попробовал поднять RTT. Поллинг работает, а прерывание стартует только в режиме LEVEL, но почему-то рабоает нормально без запрета прерывания в прерывании и последующем его разрешении в основном цикле. Вопрос в том, действительно ли прерывание RTT нормально работает в режиме LEVEL. Как я уже писал раньше, оно снимается через 2 цикла SCLK, то есть обработчик может вызываться несколько раз подряд, пока линия прерывания остается активной. А если количество вызовов будет нечетным, то на внешнем поведении светодиодов это не отразится :) Если меняю режим на EDGE то прерывание просто не запускается. Вообще. Режим EDGE для системного прерывания использовать не совсем корректно, так как у него может быть несколько источников, объединенных через логическое ИЛИ. То есть, если при выходе из обработчика останется активным хотя бы один из источников, дальнейшая работа будет заблокирована, что Вы, возможно, и наблюдаете. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gladov 0 4 декабря, 2006 Опубликовано 4 декабря, 2006 · Жалоба Вопрос в том, действительно ли прерывание RTT нормально работает в режиме LEVEL. Как я уже писал раньше, оно снимается через 2 цикла SCLK, то есть обработчик может вызываться несколько раз подряд, пока линия прерывания остается активной. А если количество вызовов будет нечетным, то на внешнем поведении светодиодов это не отразится :) Согласен полностью Если меняю режим на EDGE то прерывание просто не запускается. Вообще. Режим EDGE для системного прерывания использовать не совсем корректно, так как у него может быть несколько источников, объединенных через логическое ИЛИ. То есть, если при выходе из обработчика останется активным хотя бы один из источников, дальнейшая работа будет заблокирована, что Вы, возможно, и наблюдаете. Почему системное прерывание не желательно использовать по фронту понятно, но я больше никакие системные прерывания кроме RTT не разрешаю. Конечно они могут быть у какой-либо периферии разрешены после старта (я конечно весь DS пока не прочитал), но здравый смысл подсказывает, что после старта вся периферия должна быть выключена. Выяснились новые подробности. Если перед основным циклом прочесть RTTC_RTSR то все работает как часы, из чего я делаю вывод, что иногда при старте прерывание от RTT уже активно! Сбросить его некому, т.к. у меня чтение его производится только из прерывания. Отсюда вопрос: а почему оно может быть активно после старта? Я же делаю ему (RTT) резет! Может я что-то не так инициализирую? В принципе, глюк ясен и понятен. Как бороться тоже ясно и вопрос почти снят, но хочется узнать где же были грабли.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 5 декабря, 2006 Опубликовано 5 декабря, 2006 · Жалоба Сейчас уже не помню, в чем было дело, но кажется прерывание работало только при инициализации таймера одной командой - *AT91C_RTTC_RTMR = 0x00008000 | AT91C_RTTC_RTTINCIEN | AT91C_RTTC_RTTRST - а когда сброс выполнялся отдельно, то возникали проблемы. Имеет смысл посмотреть свежую errat'у - там, кажется, упоминался RTT. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gladov 0 5 декабря, 2006 Опубликовано 5 декабря, 2006 · Жалоба Сейчас уже не помню, в чем было дело, но кажется прерывание работало только при инициализации таймера одной командой - *AT91C_RTTC_RTMR = 0x00008000 | AT91C_RTTC_RTTINCIEN | AT91C_RTTC_RTTRST - а когда сброс выполнялся отдельно, то возникали проблемы. Имеет смысл посмотреть свежую errat'у - там, кажется, упоминался RTT. errat'у свежую смотрел, но там написано только что SR нельзя часто опрашивать, иначе он теряет события. На этот глюк я тоже нарывался :) Инициализация одной строкой тоже не помогла - не сбрасывается он корректно! Ну и черт с ним. Проехали и забыли. Будем считать это багом, хотя я ни разу еще в железках не нарывался на недокументированные ошибки... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 5 декабря, 2006 Опубликовано 5 декабря, 2006 · Жалоба Инициализация одной строкой тоже не помогла - не сбрасывается он корректно! Ну и черт с ним. Проехали и забыли. Будем считать это багом, хотя я ни разу еще в железках не нарывался на недокументированные ошибки...Отлаживаете через JTAG? Учитываете, что кнопка "сброс" в оболочке сбрасывает только ядро, но не периферию, т.е. если перед нажатием кнопки "сброс" таймер был включен, то он продолжает тикать? Учитываете, что если открыто окно с регистрами периферии, это вызывает их чтение и сброс некоторых флагов (и другие действия по чтению некоторых регистров)? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gladov 0 5 декабря, 2006 Опубликовано 5 декабря, 2006 · Жалоба Инициализация одной строкой тоже не помогла - не сбрасывается он корректно! Ну и черт с ним. Проехали и забыли. Будем считать это багом, хотя я ни разу еще в железках не нарывался на недокументированные ошибки...Отлаживаете через JTAG? Учитываете, что кнопка "сброс" в оболочке сбрасывает только ядро, но не периферию, т.е. если перед нажатием кнопки "сброс" таймер был включен, то он продолжает тикать? Учитываете, что если открыто окно с регистрами периферии, это вызывает их чтение и сброс некоторых флагов (и другие действия по чтению некоторых регистров)? Нет, JTAG'а нет вообще. А сброс непричем, т.к. я же в начале программы даю резет для RTT. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 6 декабря, 2006 Опубликовано 6 декабря, 2006 (изменено) · Жалоба Нет, JTAG'а нет вообще. А сброс непричем, т.к. я же в начале программы даю резет для RTT.Тогда не представляю :-( Изменено 6 декабря, 2006 пользователем Сергей Борщ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gladov 0 6 декабря, 2006 Опубликовано 6 декабря, 2006 · Жалоба Итак, подводим итоги. Может быть кому-нибудь пригодится. Вообще-то я пришел к выводу, что RTT в sam'ах кривоват. И кривой он из-за своей природы, т.к. тактируется от RC-цепочки, котороая по-определению нестабильна в той или иной степени. Поэтому использовать его как средство для отсчета равных точных промежутков времени (как обычно используют таймеры) не получается. А раз так, то и прерывания от него особо не нужны... Но мне все-таки было интересно из принципа доковырять этот девайс до максимальной ясности. При использовании прерываний по уровню все работает (см. посты от aaarrr). С прерываниями по фронту есть проблема, но ее решать смысла нет, т.к. (опять же см. aaarrr) системные прерывания по фронту включать крайне нежелательно. А проблема в том, что сброс RTT, а именно бит RTTRST, не сбрасывает бит RTTINC в регистре RTSR. Поэтому после сброса ядра процессора бит RTTINC может оказаться в активном состоянии, следовательно, фронта никогда не произойдет, поэтому и прерывание не стработает, а тогда не будет чтения из регистра RTSR и бит RTTINC не сбросится. Выход - после сброса RTT читать RTSR один раз чтобы принудительно сбросить флаг инкремента. Спасибо всем за помощь в изучении проблемы :cheers: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться