ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
25 июля
122969
Evgeny_CD, Архитектор (14.06.2008 01:53, просмотров: 3398)
Техника точных засечек времени в малоразрядных системах. Вроде сложилось. Одна их самых противных проблем малоразрядных (8 и 16) систем - атоммарность при работе с большими структурами данных. Пусть у нас есть 16 битный таймер, у которого есть регистр match. По совпадению происходит прерывание. Точное время состоит из U16, прочитанного из таймера, и U32, прочитанного из системной области памяти. При тактовой 8 Мгц переполнение такого счетчика наступит более, чем через год ((2^48)*(1/(8*(10^6))))/(3600*24) = более 407 дней Если такой таймер "питать" от 32768 гц, то будет ваще здорово :) ((2^48)*(1/32768))/(3600*24*365)=272 года. "Вы здохните раньше, чем Ваше устройство. 30 мкс разрешение - не так уж и плохо для многих практических применений. В варианте 16 битной системной переменной имеем ((2^32)*(1/32768))/(3600*24) = 1.5 дня, что тоже достаточно для многих практических задач. Когда мы читаем U16, у нас есть опасность, что прерывание уже взведено, но не отработало, и системную переменную никто не увеличил. Если пытаться проверить контроллер прерываний, то он, чего доброго, еще сбросит какой-нибудь флаг, это долго и нудно. Мы пойдем другим путем. Кроме U32, есть еще некая системная переменная U16, которая описывает, когда таймер достигнет порога прерывания. При обработке прерывания вначале инкрементируется U32, затем U16 timer_limit перед самым выходом из прерывания. В юзеровском потоке читаем эту переменную timer_limit, и читаем таймер. Если таймер меньше (с учетом кольцевого счета!) переменной, прерывание не достигнуто, можно читать U32 из системной области. Если таймер >= timer_limit, то системная переменная пока не валидна, и надо подождать, пока не изменится timer_limit. Как только она изменилась - все, прерывание отработало, можно "идти" за системной переменной U32. В отличие от приходивших мне в голову ранее идей, такой подход не требует какой-либо записи в счетные регистры таймера, что гарантирует высокую равномерность его работы. Ну а для нас появляется инструмент точного хронометража прохождения участков кода. Кстати, приведенный выше подход можно слегка усовершенствовать. Compare всгда ставится на "старший бит таймера". Т.е. для 16 битного таймера 0x8000. Служебная системная переменная показывает, какой "половинке" таймера соотвествует U32 в памяти. Если мы не перешли половинку, то U32 валидна. Если перешли, и это обнаруживается по разнице служебной переменной и таймера, то можно самостоятельно проинкрементировать U32 :) Можно написать код, который дас нам одинаковое время "определения засечки" при любом варианте, что устранит ненужный джиттер. Критика идеи, делал ли так кто-нибудь?