Таймер и gpio

Andrey

New member
Пришёл ко мне один модуль и я выкладываю свои изыскания.

Я сделал простую программу которая дёргает ногой GPIO2 по прерыванию от таймера.
Напишу сразу выводы
1. Дерганье ногой.
По таймеру я устанавливаю 1 и сразу же устанавливаю 0.
LOCAL void ICACHE_FLASH_ATTR hello_cb(void *arg)
{
REG_SET_BIT(0x60000304, BIT2);
REG_SET_BIT(0x60000308, BIT2);

// gpio_output_set(BIT2, 0, BIT2, 0);
// gpio_output_set(0, BIT2, BIT2, 0);
}
Самое быстрое что получилось дёрнуть это 200нс. Это при условии что мы пишем в регистры напрямую и частота установлена 160мгц. Если использовать функцию gpio_output_set(BIT2, 0, BIT2, 0) и частоту по умолчанию 80мгц то получается 600нс. Это время между двумя командами.
SCR03.PNG

2. Таймер не получилось запустить быстрее чем 20 мкс. При 1 мкс модуль работает полсекунды и виснет. При 5 мкс он тоже не работает. и при 15. вместо одного импульса получаем пачку импульсов.
SCR04.PNG
Как ни странно удаление ICACHE_FLASH_ATTR никак ни повлияло на работу.
Ещё при перестройке частоты на 160мгц (в два раза), длительность импульса уменьшилось. Что понятно. Но период 25мкс остался. Это тоже понятно. Произошёл пересчёт тактов и стало больше тактов. Но при этом если поставить 15 мкс период всё равно сбоит. Это не понятно. Вроде больше тактов стало и должно хватать по крайней мере в два раза для обработки прерывания. Предположу что этот таймер не единственный кто работает по прерыванию, и не важно какая частота, ядро занимает себе такты, и не может отдать время меньше 20 мкс.

3. Похоже таймер имеет низкий приоритет. И делать на нём что то времязависимое и точное нельзя. Его может оборвать в любой момент ядро. По этому похоже и такая длительная обработка прерывания (минимум 20мкс). Это видно по осциллограмме. Импульсы не стоят ровно а дёргаются.
SCR02.PNG
В общем результат не тот на который рассчитывал. Придётся делать по другому. Может кто то имеет какие то секретные знания о том как можно получить стабильный таймер на 1 мкс? и как можно дёрнуть ногой на 80мгц. Был бы рад узнать. :)

PS: Ещё предложение админам. Может пора сделать FAQ? Типа вопросы как настроить таймер? как дёрнуть ногой? как установить частоту процессора? и.т.д.
 
Последнее редактирование:

pvvx

Активный участник сообщества
Может кто то имеет какие то секретные знания о том как можно получить стабильный таймер на 1 мкс? и как можно дёрнуть ногой на 80мгц. Был бы рад узнать. :)
"CИкретное" знание в том, что надо повесить на прерывание таймера свой обработчик.
 

Andrey

New member
Такое возможно? Подозреваю что для этого нужны исходники ядра, которых ни у кого нет.
 

Victor

Administrator
Команда форума
PS: Ещё предложение админам. Может пора сделать FAQ? Типа вопросы как настроить таймер? как дёрнуть ногой? как установить частоту процессора? и.т.д.
Принимается. Жду предложений по составу и структуре: не хотелось бы в одну кучу валить вопросы программирования на С собственных прошивок и обращений к функциям SDK и вопросы работы с конкретной прошивкой (а их уже немало набирается).
Вот pvvx давно предложена должность модератора, но он скромничает и отшучивается отговорками, хотя больше всех, пожалуй, отвечает на вопросы :)
 

Andrey

New member
Я думаю что выделить на это форум. И каждая тема это один вопрос. Например форум называется "FAQ по программированию". Другой "FAQ прошивка такая то". Внутри тема "Работа с таймером" Первая тема описание а дальше обсуждение если нужно. Может уточнение. По сути как сделана эта тема. http://esp8266.ru/forum/threads/moja-sborka-espressif-devkit.32/ Первый пост редактируется. Если автор вдруг пропадёт то админ всегда сможет поправить первый топик.

Я исхожу из возможностей движка форума.
 

pvvx

Активный участник сообщества
Принимается. Жду предложений по составу и структуре: не хотелось бы в одну кучу валить вопросы программирования на С собственных прошивок и обращений к функциям SDK и вопросы работы с конкретной прошивкой (а их уже немало набирается).
Вот pvvx давно предложена должность модератора, но он скромничает и отшучивается отговорками, хотя больше всех, пожалуй, отвечает на вопросы :)
Я могу исчезать на неопределенный срок в связи со своими работами. По этому не могу ничего гарантировать, тем более не собираюсь стирать чужие сообщения, что требуется для модератортсва...
Такое возможно? Подозреваю что для этого нужны исходники ядра, которых ни у кого нет.
Как раз это есть, нет только описания аппаратуры WiFi, но если поднапрячься то и то можно выудить из исходников.
Если намерены потратить на проверку работы по прерываниям некоторое время, то можно собрать все необходимые заголовки и описания процедур. Надо?
/* Interrupts */
#define INT_GPIO 4
#define INT_UART 5
#define INT_WDT_TIMER 8
#define INT_TIMER1 9
...
/* In ROM */
void ets_isr_attach(int, void*, void*); (_xtos_set_interrupt_handler_arg)
void ets_isr_mask(int); (_xtos_ints_off)
void ets_isr_unmask(int); (_xtos_ints_on)
В принципе это есть в ets_sys.h

0x3fffc208: таблица текущих назначенных адресов на прерывания.
в основном там указатели на _xtos_unhandled_interrupt
 
Последнее редактирование:

Victor

Administrator
Команда форума
тем более не собираюсь стирать чужие сообщения, что требуется для модератортсва...
Да бросьте, у нас тут все очень либерально - никто ничего не удаляет/не корректирует. Мне за все время удалять пришлось только один пост и тот за мат. Но, вы бы ведь также поступили?
Здесь все люди серьезные, ничего удалять не приходится, а вот человек, который поможет с FAQ мне бы очень пригодился.
 

pvvx

Активный участник сообщества
GPIO12, int_us_init(10):
GPIO12_10us.gif
(фронты rise/fail менее 1.4 нс на 6 пф)
Одновременно работает WEB-сервер.
 

Вложения

Последнее редактирование:

Игорь

New member
А можно глянуть, что получилось из этого на ассемблере.
Есть подозрение, что как всегда в таких случаях, накладных много...
 

pvvx

Активный участник сообщества
А можно глянуть, что получилось из этого на ассемблере.
Есть подозрение, что как всегда в таких случаях, накладных много...
Накладных к чему? В прерывании всего 1 and и 2 or c адресами в памяти (регистром подтверждения прерывания и регистрами порта) :
Код:
void pwm_tim1_intr_handler(void)
{
    RTC_CLR_REG_MASK(FRC1_INT_ADDRESS, FRC1_INT_CLR_MASK);
40100c4c:    fffd21           l32r    a2, 40100c40 <init_done_cb+0x1c>
40100c4f:    e37c         movi.n    a3, -2
40100c51:    0020c0           memw
40100c54:    0248         l32i.n    a4, a2, 0
40100c56:    103430           and    a3, a4, a3
40100c59:    0020c0           memw
40100c5c:    0239         s32i.n    a3, a2, 0
    REG_SET_BIT(0x60000304, BIT12);
40100c5e:    fff921           l32r    a2, 40100c44 <init_done_cb+0x20>
40100c61:    fcf031           l32r    a3, 40100024 <call_user_start+0x20>
40100c64:    0020c0           memw
40100c67:    0248         l32i.n    a4, a2, 0
40100c69:    204430           or    a4, a4, a3
40100c6c:    0020c0           memw
40100c6f:    0249         s32i.n    a4, a2, 0
    REG_SET_BIT(0x60000308, BIT12);
40100c71:    fff521           l32r    a2, 40100c48 <init_done_cb+0x24>
40100c74:    0020c0           memw
40100c77:    0248         l32i.n    a4, a2, 0
40100c79:    203430           or    a3, a4, a3
40100c7c:    0020c0           memw
40100c7f:    0239         s32i.n    a3, a2, 0
40100c81:    f00d         ret.n
6-ть команд asm между выводом в порт и итог строб в 200 нс. Работает стробирование внутренней шины к порту или стробирование работы самого порта. Регистра переключения делителей внутренних клоков на порты (и есть ли они) я пока не знаю - не искал.
Хотя OR там не нужен, но оставлено для аналогии с замерами Andrey.
Или листинг (asm) всей прошивки? Он более 4-х Мб.
Вроде менее 5us нельзя. Выходит WDT и прочее, т.к. система тоже хочет доступ к процессору :)
При 5us у процессора всего 400 CLK 80MHz между срабатываниями таймера...
Ножками за счет CPU никто не дергает - это плохой тон и детсад (Espressif-цам и Lua-шникам - можно - им всё равно :)).
Попробуйте подергать ножками на Intel Core i7 в LPT. Получите те-же 200нс или более (если OR) :p.

Без ненужного OR и с работой WEB сервера (CPU 160MHz) уже 2us тянет:
2us.gif
 
Последнее редактирование:

Игорь

New member
Не, весь не надо.
Накладные - это вызов пп обработки прерывания. Что он там в стек кладет? Ну кроме адреса...
 

pvvx

Активный участник сообщества
Не, весь не надо.
Накладные - это вызов пп обработки прерывания. Что он там в стек кладет? Ну кроме адреса...
Вы собрались писать всю систему на asm и вас не устраивает 2us между обработкой аппаратного прерывания у процессора с тактом в 12.5ns (80MHz по умолчанию)? :rolleyes:
Тогда просим изучить Tensilica RC-2010.1 Documentation (93.2 Мб). Потом у вас будем спрашивать всякое :) и на сколько долей процента удалось сократить никому не нужную функцию. :)
И для изучения реального времени исполнения всё в ваших руках - исходники и прочее барахло полностью представлено...

Беда в SDK - там неправильно ведут себя все функции связанные с программным таймером. Espressif-вский программер похоже опять насочинял всякого...
Они уже заменили ROM функцию ets_timer_arm на ets_timer_arm_new (которая всё равно вызывает timer_insert() в ROM), но опять неудачно. С задержками us какие-то проблемы...
Приходится таймер использовать только как отложенный вызов другой процедуры: ets_timer_arm(&struct_timer, 0, 0 ) :mad:
 
Последнее редактирование:

pvvx

Активный участник сообщества
Можете у меня спрашивать всякое, я работаю в этой конторе в отделе OS/debug.
Основные вопросы по периферии :). Нет битов управления аппаратными таймерами.
Всё, что известно, и то путем тыка:
0x60000600: делитель
0x60000604: текущий счетчик
0x60000608:
бит0: =1 TM_LEVEL_INT, =0 TM_EDGE_INT
бит1..3: =0 DIVDED_BY_1, = 1 DIVDED_BY_16, =2 DIVDED_BY_256
бит6: =1 автозагрузка делителя
бит7: =1 timer enable
 
Последнее редактирование:

jcmvbkbc

New member
А это и есть самая нужная информация. Остальное - компилятор СИ, С++ и asm, уже есть.
Поздравляю. Однако в доках на которые вы дали ссылку об этом нет ни слова. Тем не менее, если у вас есть вопросы по этим докам, по архитектуре или по компилятору -- можете спрашивать.
 

pvvx

Активный участник сообщества
Поздравляю. Однако в доках на которые вы дали ссылку об этом нет ни слова. Тем не менее, если у вас есть вопросы по этим докам, по архитектуре или по компилятору -- можете спрашивать.
Вопрос у народу задан выше: перевожу - сколько тактов тратит CPU на вход и выход в call.
+ сколько уходит на прерывание.
 

jcmvbkbc

New member
Вопрос у народу задан выше: перевожу - сколько тактов тратит CPU на вход и выход в call.
Один такт на выполнение команды + 2 либо 3 такта (в зависимости от того, попадает ли команда по адресу перехода целиком в одно выравненное 4-байтное слово, или нет) за переход. Ровно то же самое на выход.
+ сколько уходит на прерывание.
Вход в прерывание занимает минимум 7 тактов и может увеличиться на несколько тактов, в зависимости от прерываемой операции. Это количество тактов от получения запроса на прерывание до окончания выполнения первой инструкции по вектору обработчика. Выход -- как и возврат из функции: 3/4 такта. Обработчик должен как минимум очистить запрос на прерывание, если прерывание настроено по фронту.
 

pvvx

Активный участник сообщества
Ещё не ясно вот это:
WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_OUT_W1TS_ADDRESS, TEST_PIN_IO); // SET_PIN_IO (*((volatile uint32_t *)(0x60000300 + 0x04))) = (uint32_t)(0x00001000)
40100c3a: fcfa21 l32r a2, 40100024
40100c3d: fff831 l32r a3, 40100c20
40100c40: 0020c0 memw
40100c43: 0329 s32i.n a2, a3, 0
WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + GPIO_OUT_W1TC_ADDRESS, TEST_PIN_IO); //СLR_PIN_IO (*((volatile uint32_t *)(0x60000300 + 0x08))) = (uint32_t)(0x00001000)
40100c45: fff731 l32r a3, 40100c24
40100c48: 0020c0 memw
40100c4b: 0329 s32i.n a2, a3, 0
40100c4d: f00d ret.n


1) Почему не работает оптимизация у транслятора - два раза грузится адрес: 0x60000304 и 0x60000308. Можно было использовать смещение.
2) Время между SET_PIN_IO и СLR_PIN_IO равно 75ns при CLK у CPU 160MHz (осциллограмма дана выше). Не ясно кто дает задержку в 12 тактов CPU.
При 80MHz у CPU имеем строб 100.4ns.
 
Последнее редактирование:
Сверху Снизу