Перейти к содержанию
    

Скорость работы пина зависит от других пинов. Это нормально?

Привет, народ!

 

Заметил такую странность, которую не знаю как объяснить. Плата STM32F103C8T6 (Blue Pill)

Я хотел сделать мигание светодиодом на ноге A0 при инициализации контроллера на 72MHz.

Взял сделанный ранее проект и стал его упрощать. И вот когда оставил в проекте, по-сути, только:

 

- инициализацию на 72Mhz
- включение тактирования портов
- настройку пина A0,

 

то заметил, что код мигания стал работать медленнее! Т. е. мигание, сделанное в бесконечном цикле, стало в 1.5-2 раза медленнее, чем было до.

 

Я стал разбираться, что могло на это повлиять. И вернул вызов ненужной функции, в которой инициализировались пины A8, A9, B3, B4, B6, B7. И о чудо, мигание стало опять быстрым! Повторюсь, в этой функции делается только инициализация пинов, и она вызывается один раз в начале программы, ничего более.

 

Вот полный код: https://pastebin.com/Z7d0LZif

 

А вот код функции, которая "разгоняет" выполнение кода:
 

// Настройка пинов A8, A9, B3, B4, B6, B7
void otherPortInit(void)
{
    // Для начала сброс конфигурации всех используемых портов в ноль
    GPIOA->CRH &= ~(GPIO_CRH_MODE8 | GPIO_CRH_CNF8);
    GPIOA->CRH &= ~(GPIO_CRH_MODE9 | GPIO_CRH_CNF9);

    GPIOB->CRL &= ~(GPIO_CRL_MODE3 | GPIO_CRL_CNF3);
    GPIOB->CRL &= ~(GPIO_CRL_MODE4 | GPIO_CRL_CNF4);
    GPIOB->CRL &= ~(GPIO_CRL_MODE6 | GPIO_CRL_CNF6);
    GPIOB->CRL &= ~(GPIO_CRL_MODE7 | GPIO_CRL_CNF7);


    uint32_t mode;
    uint32_t cnf;

    mode=0b11; // Режим выхода, с максимальной частотой 50 МГц
    cnf=0b00;  // Режим push-pull
    GPIOA->CRH |= (mode << GPIO_CRH_MODE8_Pos) | (cnf << GPIO_CRH_CNF8_Pos);
    GPIOA->CRH |= (mode << GPIO_CRH_MODE9_Pos) | (cnf << GPIO_CRH_CNF9_Pos);

    mode=0b00; // Режим входа
    cnf=0b01;  // Режим плавающего входа, подтяжки нет
    GPIOB->CRL |= (mode << GPIO_CRL_MODE3_Pos) | (cnf << GPIO_CRL_CNF3_Pos);
    GPIOB->CRL |= (mode << GPIO_CRL_MODE4_Pos) | (cnf << GPIO_CRL_CNF4_Pos);
    GPIOB->CRL |= (mode << GPIO_CRL_MODE6_Pos) | (cnf << GPIO_CRL_CNF6_Pos);
    GPIOB->CRL |= (mode << GPIO_CRL_MODE7_Pos) | (cnf << GPIO_CRL_CNF7_Pos);
}


Я не могу эту вещь объяснить. Почему настройки пинов, которые не используются в коде, так странно влияют на скорость выполнения программы контроллером? Мало того, в базовом проекте, на точно таком же коде я обнаружил обратный эффект: вызов этой функции инициализации портов замедляет мигание, а комментирование ее вызова - ускоряет.

 

В общем, я в недоумении. Я вообще не ожидал, что такое поведение возможно. Это тормозит разработку домашнего проекта, потому то в нем критична реакция на сигналы длительностью ~500нс, и тут я вижу, что тупой бесконечный цикл работает с разной скоростью в зависимости от инициализации неиспользуемых портов.

 

Вопрос 1: Как единственный вызов этой функции может влиять на скорость выполнения основного цикла?
Вопрос 2: Почему вызов этой функции может давать строго обратный эффект?

Изменено пользователем xintrea

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сравните листинги функций msDelay для разных сборок. От того, как компилятор их реализует многое будет зависеть.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

16 minutes ago, adnega said:

Сравните листинги функций msDelay для разных сборок. От того, как компилятор их реализует многое будет зависеть.

Опции компиляции всех проектов у меня одинаковые. Оптимизация везде -Os и все.

Или хотите сказать, что в разном окружающем коде компилятор будет по-разному компилировать msDelay?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

21 минуту назад, xintrea сказал:

Опции компиляции всех проектов у меня одинаковые. Оптимизация везде -Os и все.

Или хотите сказать, что в разном окружающем коде компилятор будет по-разному компилировать msDelay?

Я другого объяснения придумать не могу, и это легко проверить.

Кста, про скорость, вроде -03, а -Os это про размер.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

 

1 hour ago, adnega said:

Сравните листинги функций msDelay для разных сборок. От того, как компилятор их реализует многое будет зависеть.

В общем, проверил. Функция msDelay() в обеих случаях закомпилилась одинаково, байт в байт:

 

2022-05-03-23-03-26.png

 

24 minutes ago, adnega said:

Кста, про скорость, вроде -03, а -Os это про размер.

Я же для микроконтроллера компилю, по дефолту оптимизация по размеру.

Изменено пользователем xintrea

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

22 minutes ago, xintrea said:

Функция msDelay() в обеих случаях закомпилилась одинаково, байт в байт

Вот только адреса разные. Скорость выполнения зависит от смещения кода в 64 (или 128?) битном блоке.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Проверяйте настройку тактовой системы. 

ф. int clockInit(void) даже возвращает ошибки, обработку которых я не увидел. Тем более на предельных режимах тактовой.

Неплохо было бы убедиться аппаратно, что тактовая реально установилась на 72MHz.

Возможно "играет рояль" то, что комментируемая строка вносит задержку после кода инициализации.

В цикле мигалки уменьшите или увеличьте значения задержек в 2 раза, проконтролируйте что частота мигания также увеличилась (уменьшилась) в 2 раза.

Используйте осциллограф на светодиоде, тк может оказаться, что "мигание" это ШИМ.

ps

1 hour ago, xintrea said:

. . .  Это тормозит разработку домашнего проекта, потому то в нем критична реакция на сигналы длительностью ~500нс, и тут я вижу, что тупой бесконечный цикл работает с разной скоростью в зависимости от инициализации неиспользуемых портов. . . .

Я конечно сильно извиняюсь, не мое это дело, но Вы собираетесь события с порядком "длительности" 500ns фиксировать методом опроса ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

48 minutes ago, k155la3 said:

Проверяйте настройку тактовой системы. 

ф. int clockInit(void) даже возвращает ошибки, обработку которых я не увидел. Тем более на предельных режимах тактовой.

Неплохо было бы убедиться аппаратно, что тактовая реально установилась на 72MHz.

Да, там реально 72MHz устанавливается. Функция инициализации такая же как и здесь: https://webhamster.ru/mytetrashare/index/mtb0/1649356037vhemuctihu и на ноге 12 в этом коде реально 60нс на осциллографе видно.

 

48 minutes ago, k155la3 said:

Возможно "играет рояль" то, что комментируемая строка вносит задержку после кода инициализации.

Где про обязательность задержки можно прочитать? Что-то в даташите не нашел таких ограничений.

 

48 minutes ago, k155la3 said:

В цикле мигалки уменьшите или увеличьте значения задержек в 2 раза, проконтролируйте что частота мигания также увеличилась (уменьшилась) в 2 раза.
 

Да, частота видимых миганий изменяется в двое.

 

48 minutes ago, k155la3 said:

Используйте осциллограф на светодиоде, тк может оказаться, что "мигание" это ШИМ.

Ну какой ШИМ, там же просто включется-выключется нога с задержкой.

 

48 minutes ago, k155la3 said:

Я конечно сильно извиняюсь, не мое это дело, но Вы собираетесь события с порядком "длительности" 500ns фиксировать методом опроса ? 

Можете предложить другой метод? На таком оборудовании через прерывания ловить события не получится, потому что только на вход в прерывание больше 500нс уходит. Если приплюсовать сюда выход и задержку прохода сигнала прерывания, то получится что с прирываниями работать вообще не вариант. А методом опроса можно ловить события, и еще 15-25 тактов останется на логику, а мне больше и не надо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 минут назад, xintrea сказал:

Можете предложить другой метод?

А что за сигнал/обработка? Таймеры/FPGA/CPLD/рассыпуха ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 часов назад, xintrea сказал:

Или хотите сказать, что в разном окружающем коде компилятор будет по-разному компилировать msDelay?

Учитесь использовать таймер для учёта и выдержки временных интервалов. Иначе всё время будете спотыкаться о такие "чудеса".

5 часов назад, xintrea сказал:

Можете предложить другой метод?

Пока не расскажете о решаемой задаче, никто ничего путного предложить не сможет.

Судя по вашему описанию - движетесь в неверном направлении.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 hours ago, xintrea said:

методом опроса можно ловить события

Лучше уж таймер настроить в режиме измерения длительности входного импульса. Запустил, через миллисекунду проверил. Если ноль - события не было...

А еще лучше - правильно сформулировать свою задачу. Возможно, ее можно решить простым способом.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 hours ago, xintrea said:

Где про обязательность задержки можно прочитать? Что-то в даташите не нашел таких ограничений.

Это не "обязательность", а симптом вашей проблемы. Все-таки, как с кодом результата работы ClockInit(), то  что в Вашей ссылке

// Настройка тактирование системы от внешнего кварца
// через PLL на максимально возможных частотах.
// Внешний кварц должен быть на 8МГц
// Возвращает:
//  0 - завершено успешно
//  1 - не запустился кварцевый генератор
//  2 - не запустился PLL
// Итоговая настройка делается на 72МГц
int ClockInit(void)

Если уж решать задачу "тупо и в лоб", залазите в otherPortInit() и блочно/построчно отлавливаете что влияет на "симптом".

То что "функция инициализации такаяже как здесь" не гарантирует, что она корректно работает.

На какой пин процессора подключен светодиод ? (проверить прозвонкой) д.б. на PC13 пин процессора 2.

Другой метод можно предложить, но для этого нужно, как писали выше, описание входных сигналов - а именно частота их возникновения и длительность. Ну, и количество линий. А использовать такой процессор в режиме опроса "негуманно". Ну, еслиб это был у вас 8-разрядный контроллер с 64 бит RAM и 256 байт программной памяти ... без прерываний .... без таймера ....  тогда может быть да, режим "опроса" со-скрипом подходит.

 

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

18 hours ago, jcxz said:

Пока не расскажете о решаемой задаче, никто ничего путного предложить не сможет.

Я пытаюсь сделать эмулятор ПЗУ для клона Радио-86РК. Он подключается в разъем, на который выведена ША а ШД этого компьютера, и еще несколько системных сигналов.

Под подключаемые внешние модули (эмулятор ПЗУ-это и есть внешний модуль) в компьютере отведено адресное пространство 8000h-BFFFh (объем 16Кб). Задача эмулятора ПЗУ - держать пины ШД, к котором подключен контроллер STM, в высокоимпендансном состоянии, и следить за адресом на ША. Если адрес попадает в обслуживаемый эмулятором диапазон, и приходит сигнал на чтение, пины ШД переводятся в состояние выхода и на них выставляется нужный байт. Длительность сигнала на чтение - 500нс. Все.

14 hours ago, k155la3 said:

Ну, еслиб это был у вас 8-разрядный контроллер с 64 бит RAM и 256 байт программной памяти ... без прерываний .... без таймера ....  тогда может быть да, режим "опроса" со-скрипом подходит.

Такой контроллер не подойдет, одна только эмулируемая прошивка будет занимать 16Кб программной памяти.

Изменено пользователем xintrea

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Возьми МК с FSMC. По-другому ты ничего не добьешься: изменение состояния ног при помощи ODR/BSR/BSRR будет медленней и менее надежно, чем при помощи FSMC, таймера либо другой периферии!

P.S. вот здесь у меня отлично работала адресная светодиодная лента на WS2815 при помощи таймера с DMA (длительности импульсов в 333нс и 667нс). Ногодрыгом так не сделать.

Изменено пользователем Eddy_Em

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Можно использовать двухпортовое ОЗУ (или гибрид SPI - параллельная шина). С одной стороны МК грузит прошивку (легко обновлять), с другой стороны ее вычитывает клон (минимальные аппаратные издержки).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...