• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Вопрос Реально ли считать длительность импульса с шагом 0.1мкс ?

nikolz

Well-known member
pvvx,
с последним вопросом вроде разобрался
остался первый вопрос с оператором if
 

pvvx

Активный участник сообщества
взял ваше решение для получения точного времени.
не могу понять логику функции
get_mac_time()
вот этот момент
------------------------------
ux.dw[0]=ptr[0];
ux. dw[1]=ptr[1];
if (ux.dw[1]!=ptr[1]) {...}
-------------------------------
но условие никогда не исполнится т к выше ux. dw[1]=ptr[1];
Нет, не равно. Счетчик 64-х битный, за время считывания по 32 бита может измениться... Это и есть проверка, что за время считывания счет в следующих 32-х разрядах не изменился.
 

pvvx

Активный участник сообщества
pvvx,
можете объяснить следующий эффект.
Беру Ваше значение как вы его называете: "принятый TSF от внешней AP"
*((volatile uint32 *)MAC_TIMER64BIT_COUNT_ADDR);
и беру значение системного времени функцией
system_get_time();
далее делаем следующий тест
в user_init()
запоминаем начальные значения
T1=*((volatile uint32 *)MAC_TIMER64BIT_COUNT_ADDR);
T2=system_get_time();
далее запускаем таймер с циклическим перезапуском на 10 секунд
а в колбеке таймера вычисляем прошедшее время от старта
T3=*((volatile uint32 *)MAC_TIMER64BIT_COUNT_ADDR)-T1;
T4=system_get_time()-T2;
===================================
естественно ожидать
что T3 будет прыгать относительно T4 ну хотя бы микросекунд на 100
но в действительности получаем статистическую разницу в 2 мкс вне зависимости 10 секунд прошло или 1000
иногда но редко в минус 2 мкс.
например
T3=11100000021
T4=11100000023
----------------------
вопрос За что боролись?
MAC_TIMER64BIT - это аппаратный таймер блока WiFi, а не значение TSF, принятое от AP.
 

pvvx

Активный участник сообщества
звучит фантастично....
С учетом того что я еще ничего не видел про доступ к таймерам этого процессора.
А вам таймер не нужен. Все имеющиеся таймеры в ESP8266 используются системой или другими спец.функциями.
Доступ к счетчику тактов CPU:
Код:
extern "C" unsigned xthal_get_ccount(void)
#define system_get_cpu_clk_count() xthal_get_ccount()
Ещё надо учесть это:
https://esp8266.ru/forum/threads/spi.59/page-2#post-5508
 

nikolz

Well-known member
Нет, не равно. Счетчик 64-х битный, за время считывания по 32 бита может измениться... Это и есть проверка, что за время считывания счет в следующих 32-х разрядах не изменился.
это на одном ядре?
но тогда и после этого надо все время проверять а вдруг изменился
и когда вышли из этой функции тоже
т е все 100 мс проверять на вдруг изменился.
 

nikolz

Well-known member
за интервал 450 секунд время по системным часам и этому счетчику разошлось на 6.4 мс причем в одну сторону
без заменой случайной составляющей (наверное в эфире никого нет)
т е относительное отклонение 1.4*10-5
------------------------
 

pvvx

Активный участник сообщества
это на одном ядре?
но тогда и после этого надо все время проверять а вдруг изменился
и когда вышли из этой функции тоже
т е все 100 мс проверять на вдруг изменился.
:) :) Старшие 32 бита изменяются 1 раз в 4294.967296 сек.
Когда попадет на этот момент, что считанные младшие 32 бита от других старших, то и произойдет пересчитывание. :p
 

pvvx

Активный участник сообщества
И там надо поменять:
ux. dw[1]=ptr[1];
ux.dw[0]=ptr[0];
if (ux.dw[1]!=ptr[1]) {...}
 

nikolz

Well-known member
убрал статическое смещение получил
относительное отклонение системных часов и счетчика 1.5*10^-6
пока не понял что же счетчик нам дает
если погрешность времени в пределах погрешности кварца
единственно что дает
старт отсчета
без счетчика получим на уровне нескольких ms.
Со счетчиком - точнее.
На сколько пока под вопросом .
 

pvvx

Активный участник сообщества
убрал статическое смещение получил
относительное отклонение системных часов и счетчика 1.5*10^-6
пока не понял что же счетчик нам дает
если погрешность времени в пределах погрешности кварца
единственно что дает
старт отсчета
без счетчика получим на уровне нескольких ms.
Со счетчиком - точнее.
На сколько пока под вопросом .
millis() и micros() и system_get_time() считывают тот-же счетчик. От куда у вас погрешность? :eek:
Этим таймером тактируются и другие аппаратные счетчики. К нему есть и аппаратные компараторы, дающие прерывания и работающие со смещением (тоже аппаратно). Но всё заюзано в дровах WiFi.
 

nikolz

Well-known member
millis() и micros() и system_get_time() считывают тот-же счетчик. От куда у вас погрешность? :eek:
Этим таймером тактируются и другие аппаратные счетчики. К нему есть и аппаратные компараторы, дающие прерывания и работающие со смещением (тоже аппаратно). Но всё заюзано в дровах WiFi.
не знаю
но можете сами проверить

примите в колбеке таймера на 10 секунд
значение системного времени
и вашей функции get_tsf_station()
зафиксируйте их в первый вызов колбека
после этого вычисляйте разницу всех последующих и зафиксированного значения
получается следующее:
10000000,10013399
20000000,20025182
30000000,30037821
и т д
как видим есть набег по времени это и есть статическое смещение
13399
25182
37821
если возьмем первое значение и вычтем его из последующих умножая на номер измерения получим
0
-1116
-2376 получилось на порядок меньше
 

pvvx

Активный участник сообщества
не знаю
но можете сами проверить

примите в колбеке таймера на 10 секунд
значение системного времени
и вашей функции get_tsf_station()
зафиксируйте их в первый вызов колбека
после этого вычисляйте разницу всех последующих и зафиксированного значения
получается следующее:
10000000,10013399
20000000,20025182
30000000,30037821
и т д
как видим есть набег по времени это и есть статическое смещение
13399
25182
37821
если возьмем первое значение и вычтем его из последующих умножая на номер измерения получим
0
-1116
-2376 получилось на порядок меньше
Если есть смешение, то PLL у CPU и WiFi разные?
На это не похоже, а похоже на уход программного таймера. Он же китайский от Espressif :p
Они уже несколько раз его исправляли... Сначала меняли коэф., потом перенесли в прошивку SDK, разместив в IRAM...
 

pvvx

Активный участник сообщества
Я так и не понял, что вы хотите получить?
Измерить уход счетчиков непонятных полусофт-таймеров и 64-х битного аппаратного счетчика на 1 us в WiFi блоке?
Кварц у всех один. PLL в чипе тоже одна. Все, включая CPU, от PLL и тактируются, исключая часть периферии CPU на шине, тактируемой от кварца.
 

nikolz

Well-known member
Я так и не понял, что вы хотите получить?
Измерить уход счетчиков непонятных полусофт-таймеров и 64-х битного аппаратного счетчика на 1 us в WiFi блоке?
Кварц у всех один. PLL в чипе тоже одна. Все, включая CPU, от PLL и тактируются, исключая часть периферии CPU на шине, тактируемой от кварца.
пока просто разобрался как получить данные с помощью ваших функций
получил непонятки
таймер отсчитывает интервалы правильно
т е я задал 10 000 000 интервал при настройке таймера
в колбеке получаю
10 000 000
20 000 000
30 000 000
и т д
т е четко 10 секунд интервал
время считается от первого вызова колбека
тоже самое я пытаюсь считать вашим счетчиком
т е первый вызов колбека я запомнил значение вашего счетчика
во второй вызов т е через 10 секунд я прочитал значение вашего счетчика и вычел из него запомненное
я ожидаю получить что-то типа 10 000 000
а я получаю 10012722 откуда 12722 мкс?
непонятно.
 

nikolz

Well-known member
и далее я получаю от вашего счетчика
вместо 10 000 000, 20 000000,30 000 000
значения
10012722
20025766
30038619
откуда это запаздывание?
-------------
это не у китайского таймера
а у вашей функции
таймер-то все дает четко
 

pvvx

Активный участник сообщества
APB_CLK_FREQ = 80*1000000 //unit: Hz
TIMER_CLK_FREQ (APB_CLK_FREQ>>8) //divided by 256
Т.е. таймер идет с дискретом в 312500 Гц
Если вы не попадаете в дискретность, то набегает 1/312500=3.1999999999999999000E-006 или 3.2 us на каждый заряд таймера.
 

nikolz

Well-known member
APB_CLK_FREQ = 80*1000000 //unit: Hz
TIMER_CLK_FREQ (APB_CLK_FREQ>>8) //divided by 256
Т.е. таймер идет с дискретом в 312500 Гц
Если вы не попадаете в дискретность, то набегает 1/312500=3.1999999999999999000E-006 или 3.2 us на каждый заряд таймера.
в каком месте набегает и как это пересчитать на интервал в 10 секунд?
 

nikolz

Well-known member
предположим что вы правы
я задал интервал таймера 10 секунд
ошибка расчета интервала будет в один квант т е 3.2 мкс как вы написали но не на разряд таймера, а на 10 000 000 мксекунд т е на весь интервал ошибка в квант
вопрос повторю -откуда в ваших функциях ошибка в 12 тысяч мкс?
 

pvvx

Активный участник сообщества
в каком месте набегает и как это пересчитать на интервал в 10 секунд?
Ну подумайте сами. Если счетчик таймера на прерывание заряжается на единицу меньше или больше... Такие поправки разные в разных SDK - китайский Espressif.
Тем более вы используете программный таймер. Он, как и system_get_time() работает от одного аппаратного таймера, со своим prescaler и прерывание для него устанавливается с учетом стека программных таймеров... выбирая ближайшее событие для них. А само прерывание таймера ставит только флаг для распределителя процессов, который крутится в процедуре ets_run(). В ней, периодически, после любого прерывания (CPU там стоит на команде ожидания прерывания), по приоритету, рассматривается таблица назначенных функций и из неё уже вызывается ваш код прерывания таймера :)
Затем вы читаете счетчик этого таймера с помощью system_get_time(), а он дискретен на prescaler
 

pvvx

Активный участник сообщества
Т.е. занимаетесь лабудой - измеряете какую-то задержку вашей личной компоновки пользовательских процедур в одном из вариантов закрытых SDK от Espressif :) :)
 
Сверху Снизу