STM32 новичку в ARM что к чему
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: STM32 новичку в ARM что к чему
смотрите: триграфы есть испокон века. диграфы так же никто не отменял. операторов из двух символов уже полно, теперь добавляется оператор из трех символов. если тренд построить, то вскоре большинство комбинаций из 2 и 3 символов станут зарезервированными... а там недолго и до ситуации, о которой я писал: любой случайный набор символов станет корректной записью какой-то конструкции языка.VladislavS писал(а):и оператором <=>
чем это будет отличаться о брейнфака?
к чему приводить язык к уровню клинописи? неужели на самом деле проблема сравнений настолько велика, что вместо написания нескольких строк кода следует изменять стандарт языка, вводя очередной оператор?!
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: STM32 новичку в ARM что к чему
ARV, вы даже не подозреваете, насколько далеко обсуждение оператора <=> теме "Для новичка". Так что, оставьте свои фантазии, ничего общего даже близко не имеющие с реальностью, при себе.
Спойлер
https://habr.com/ru/company/microsoft/blog/458242/- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: STM32 новичку в ARM что к чему
но ведь не я его в тему "для новичка" привнес! почему же вы мне затыкаете рот?VladislavS писал(а):насколько далеко обсуждение оператора <=> теме "Для новичка"
а хабр я читал по этой теме (еще до того, как вы возбудились на мои слова), не буду озвучивать выводы, к которым я пришел
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: STM32 новичку в ARM что к чему
[uquote="ARV",url="/forum/viewtopic.php?p=3907571#p3907571"]а хабр я читал по этой теме[/uquote]Если бы читали, то не писали бы вот эту глупость[uquote="ARV",url="/forum/viewtopic.php?p=3907552#p3907552"]что вместо написания нескольких строк кода следует изменять стандарт языка, вводя очередной оператор?![/uquote]
Re: STM32 новичку в ARM что к чему
О минусах C++ пишут те кто его знать не знает, а о плюсах С++ пишут те кто знает и С и С++. Интересный диалог...
Иван Сусанин - первый полупроводник 
- Oxford
- Опытный кот
- Сообщения: 819
- Зарегистрирован: Вт окт 23, 2012 13:17:25
- Откуда: Прокопьевск
- Контактная информация:
Re: STM32 новичку в ARM что к чему
И что интересного нашли?
Инженер R@D
Telegram чат: https://t.me/radiowolf или в поиске приложения @radiowolf. Личка:@cncoxford
Telegram чат: https://t.me/radiowolf или в поиске приложения @radiowolf. Личка:@cncoxford
- alex38779
- Потрогал лапой паяльник
- Сообщения: 386
- Зарегистрирован: Чт окт 31, 2013 10:54:32
- Контактная информация:
Re: STM32 новичку в ARM что к чему
Помогите оптимизировать код. Хочу получить задержки в ~0.3 и ~0.9мкс на пине 2 порта С. Допускается +- 0.15мкс
Контроллер stm32f100rbt6 частота 24 МГц
Переписываю код с стм8 на 32 битный, на стм8 делал подобное на асме, так же на частоте 24МГц.
Написал такой код на ассемблере, все это в цикле while. Пробую просто вкл и выкл пин.
В 1 строчке мы загружаем адрес PORTC_ODR_pin2 в регистр r2. Следующими строками загружаю 1 или 0 в регистр.
В итоге получаю картину

Время в сост включенном 2,542мкс, время в выключенном состоянии - 0,25мкс.
Как мне оптимизировать этот код, что бы время во включенном состоянии было примерно = в выключенном.
Контроллер stm32f100rbt6 частота 24 МГц
Переписываю код с стм8 на 32 битный, на стм8 делал подобное на асме, так же на частоте 24МГц.
Написал такой код на ассемблере, все это в цикле while. Пробую просто вкл и выкл пин.
Код: Выделить всё
asm("ldr r2, =(0x42000000+(0x4001100c-0x40000000)*32+2*4)");
asm("mov r1,#0");
asm("str r1, [r2]");
asm("mov r1,#1");
asm("str r1, [r2]");В 1 строчке мы загружаем адрес PORTC_ODR_pin2 в регистр r2. Следующими строками загружаю 1 или 0 в регистр.
В итоге получаю картину
Время в сост включенном 2,542мкс, время в выключенном состоянии - 0,25мкс.
Как мне оптимизировать этот код, что бы время во включенном состоянии было примерно = в выключенном.
Re: STM32 новичку в ARM что к чему
Шимить не проще?
- alex38779
- Потрогал лапой паяльник
- Сообщения: 386
- Зарегистрирован: Чт окт 31, 2013 10:54:32
- Контактная информация:
Re: STM32 новичку в ARM что к чему
[uquote="Reflector",url="/forum/viewtopic.php?p=3911985#p3911985"]Шимить не проще?[/uquote]
Нет, по сути делаю простой протокол для связи с одним устройством, и там нужны подобные задержки в 0,3 0,6 0,9 мкс и ресет в 80мкс
Нет, по сути делаю простой протокол для связи с одним устройством, и там нужны подобные задержки в 0,3 0,6 0,9 мкс и ресет в 80мкс
Re: STM32 новичку в ARM что к чему
с регистрами напряг?
до цикла их загрузить нельзя?
на 329 стр. приводил пример компиляции Кейла, там ногодрыг регистром bsrr:
для записи и 0 и 1 используются два регистра (константа, адрес) значение формируется смещением.
до цикла их загрузить нельзя?
на 329 стр. приводил пример компиляции Кейла, там ногодрыг регистром bsrr:
для записи и 0 и 1 используются два регистра (константа, адрес) значение формируется смещением.
- alex38779
- Потрогал лапой паяльник
- Сообщения: 386
- Зарегистрирован: Чт окт 31, 2013 10:54:32
- Контактная информация:
Re: STM32 новичку в ARM что к чему
[uquote="a797945",url="/forum/viewtopic.php?p=3912107#p3912107"]на 329 стр. приводил пример компиляции Кейла, там ногодрыг регистром bsrr:
для записи и 0 и 1 используются два регистра (константа, адрес) значение формируется смещением.[/uquote]
Спасибо. Кое что сдвинулось.
Сейчас мой код такой, может кому пригодится.
Порт С, регистр BSRR, вкл-выкл 2 пин
Настройка:
Непосредственно включение и выключение пина
для записи и 0 и 1 используются два регистра (константа, адрес) значение формируется смещением.[/uquote]
Спасибо. Кое что сдвинулось.
Сейчас мой код такой, может кому пригодится.
Порт С, регистр BSRR, вкл-выкл 2 пин
Настройка:
Код: Выделить всё
asm("ldr r2, =0x40011010");
asm("movs r0,#0x04");
asm("mov.w r1,#0x40000");Непосредственно включение и выключение пина
Код: Выделить всё
asm("str r0, [r2]");
asm("str r1, [r2]");- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: STM32 новичку в ARM что к чему
Во-первых, эффективнее BSRR и BRR использовать.
Во-вторых, не страдайте ерундой, на Си всё сильно проще.А на С++ ещё прощеРазбавить __NOP() по вкусу.
В-третьих, как вам уже говорили, PWM с DMA. STM32 WS2812B
Во-вторых, не страдайте ерундой, на Си всё сильно проще.
Код: Выделить всё
GPIOC->BSRR = GPIO_BSRR_BS2;
GPIOC->BRR = GPIO_BRR_BR2;
GPIOC->BSRR = GPIO_BSRR_BS2;
GPIOC->BRR = GPIO_BRR_BR2;
LDR.N R0,??main_0 ;; 0x40011010
MOVS R1,#+4
STR R1,[R0, #+0]
STR R1,[R0, #+4]
STR R1,[R0, #+0]
STR R1,[R0, #+4]
Код: Выделить всё
template<unsigned N, typename F>
__attribute__((always_inline)) inline void RepeatL(F f)
{
if constexpr (N>0) {f(); RepeatL<N-1>(f);}
}
RepeatL<5>([]{ GPIOC->BSRR=GPIO_BSRR_BS2; GPIOC->BRR=GPIO_BRR_BR2; });
LDR.N R0,??main_0 ;; 0x40011010
MOVS R1,#+4
STR R1,[R0, #+0]
STR R1,[R0, #+4]
STR R1,[R0, #+0]
STR R1,[R0, #+4]
STR R1,[R0, #+0]
STR R1,[R0, #+4]
STR R1,[R0, #+0]
STR R1,[R0, #+4]
STR R1,[R0, #+0]
STR R1,[R0, #+4]В-третьих, как вам уже говорили, PWM с DMA. STM32 WS2812B
- Oxford
- Опытный кот
- Сообщения: 819
- Зарегистрирован: Вт окт 23, 2012 13:17:25
- Откуда: Прокопьевск
- Контактная информация:
Re: STM32 новичку в ARM что к чему
[uquote="alex38779",url="/forum/viewtopic.php?p=3911989#p3911989"][uquote="Reflector",url="/forum/viewtopic.php?p=3911985#p3911985"]Шимить не проще?[/uquote]
Нет, по сути делаю простой протокол для связи с одним устройством, и там нужны подобные задержки в 0,3 0,6 0,9 мкс и ресет в 80мкс[/uquote]
Тот случай когда человек не знает архитектуру микроконтроллера и пытается делать ногодрыгом управление светодиодами.
С++ здесь тоже не нужен.
Нет, по сути делаю простой протокол для связи с одним устройством, и там нужны подобные задержки в 0,3 0,6 0,9 мкс и ресет в 80мкс[/uquote]
Тот случай когда человек не знает архитектуру микроконтроллера и пытается делать ногодрыгом управление светодиодами.
С++ здесь тоже не нужен.
Инженер R@D
Telegram чат: https://t.me/radiowolf или в поиске приложения @radiowolf. Личка:@cncoxford
Telegram чат: https://t.me/radiowolf или в поиске приложения @radiowolf. Личка:@cncoxford
- alex38779
- Потрогал лапой паяльник
- Сообщения: 386
- Зарегистрирован: Чт окт 31, 2013 10:54:32
- Контактная информация:
Re: STM32 новичку в ARM что к чему
Спасибо всем за пинки:) Настало время изучить новую периферию в виде DMA 
Re: STM32 новичку в ARM что к чему
Добрый день, хочется усыпить МК, и пробудить его по внешнему прерыванию. На выводе A1 этот код работает, на A0 не усыпает.
Код: Выделить всё
EXTI->IMR |= EXTI_IMR_MR0;
__DSB();
__wfi();
Re: STM32 новичку в ARM что к чему
а двойным:
__wfi();
__wfi();
скажу честно, совет не научный, просто самому однажды пришлось продублировать инструкцию, но объяснить не могу (f103c8). а без нее - врал.
"
EXTI->PR = flag; // RESET event
EXTI->EMR = flag; // SET bit MASK
__WFE(); // SLEEP
__WFE(); // дубль
if ((GPIOA->IDR&ARC_P)) x |=1; // bit7
x=x<<1;
EXTI->PR = flag;
__WFE();
if ((GPIOA->IDR&ARC_P)) x |=1; // bit6
x=x<<1;
EXTI->PR = flag;
__WFE();
...
"
__wfi();
__wfi();
скажу честно, совет не научный, просто самому однажды пришлось продублировать инструкцию, но объяснить не могу (f103c8). а без нее - врал.
"
EXTI->PR = flag; // RESET event
EXTI->EMR = flag; // SET bit MASK
__WFE(); // SLEEP
__WFE(); // дубль
if ((GPIOA->IDR&ARC_P)) x |=1; // bit7
x=x<<1;
EXTI->PR = flag;
__WFE();
if ((GPIOA->IDR&ARC_P)) x |=1; // bit6
x=x<<1;
EXTI->PR = flag;
__WFE();
...
"
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: STM32 новичку в ARM что к чему
Утренний кофе навеял пример как С++ "не нужен" для управления умными диодами. Напомню как на STM32 обычно генерируют сигнал управления с помощью DMA и таймера в режиме PWM. Цвет каждого диода представляют в RGB (24 бита - по байту на цвет). Затем из него формируют массив на 24 байт для каждого диода, в котором в каждом байте записано значение длительности "0" или "1", которое DMA автоматически передаёт в таймер для формирования битовой последовательности. При формировании этого буфера ещё и Гамма-коррекцию делают. Один из легко находимых в интернете и уже набивший оскомину пример на Си делает это вот так.
Замерим скорость преобразования на STM32G071 с тактовой 64 МГц.Для одного диода 3 мкс, а восьми диодов 25 мкс или 10% процессорного времени. На 48 МГц F0 будет ещё больше.
Ну что же, будем ускорять. Вспоминаем совет Reflector о табличном преобразовании. Сформируем в памяти таблицу, где каждому байту составляющей цвета поставим в соответствие 8 байт для PWM-последовательности. На неё же можно наложить Гамма-коррекцию. Как представил, как эти таблицы на Си генерить... Да ещё надо либо отдельно PWM и Гамма, либо одну PWM+Гамма. То есть, для универсальности три таблицы надо. Да ну на. Давайте сделаем почеловечески.
Собственно и всё. Таблица посчитается на этапе компиляции и ляжет во flash. Причём, хочешь с гамма-кореккцией, хочешь без совершенно бесплатно.
Замер скорости преобразования одного диода 0.67 мкс, а восьми диодов 5,9 мкс.С такой скоростью уже можно не создавать pwm-буфер для всей ленты, который жирноватый получается, а преобразовывать в прерывании по несколько диодов.
Ну и включим DMA+PWM, не зря же клаву топтали.

Для особо любознательных расскажу, что если использовать "константный диод", то даже таблица кодировки не будет использоваться. Компилятор просчитает всё без неё и будет ещё быстрее. К примеру, вот этот код всего 0,34 мкс для одного и 1,9 мкс для восьми диодов выполняется.
Спойлер
Код: Выделить всё
uint8_t LEDGamma(uint8_t v)
{
return (v * v + v) >> 8;
}
struct RGB_t
{
uint8_t r, g, b;
};
struct PWM_t
{
uint8_t g[8], r[8], b[8];
};
static void RGB2PWM(RGB_t *rgb, PWM_t *pwm)
{
uint8_t r = LEDGamma(rgb->r);
uint8_t g = LEDGamma(rgb->g);
uint8_t b = LEDGamma(rgb->b);
uint8_t mask = 128;
for (int i = 0; i < 8; i++)
{
pwm->r[i] = r & mask ? TIM_HI : TIM_LO;
pwm->g[i] = g & mask ? TIM_HI : TIM_LO;
pwm->b[i] = b & mask ? TIM_HI : TIM_LO;
mask >>= 1;
}
}
PWM_t pwm_buf[16];
RGB_t rgb_leds[16];
Код: Выделить всё
TEST_PIN::set();
for(uint32_t i=0; i<8; i++)
RGB2PWM(&rgb_leds[i],&pwm_buf[i]);
TEST_PIN::clear();
Ну что же, будем ускорять. Вспоминаем совет Reflector о табличном преобразовании. Сформируем в памяти таблицу, где каждому байту составляющей цвета поставим в соответствие 8 байт для PWM-последовательности. На неё же можно наложить Гамма-коррекцию. Как представил, как эти таблицы на Си генерить... Да ещё надо либо отдельно PWM и Гамма, либо одну PWM+Гамма. То есть, для универсальности три таблицы надо. Да ну на. Давайте сделаем почеловечески.
Спойлер
Код: Выделить всё
template<uint32_t N, bool GammaCorrection=true>
class COLOR2PWM
{
uint64_t value[N]{};
static inline constexpr uint8_t LEDGamma(uint8_t v) { return (v * v + v) >> 8; }
public:
constexpr COLOR2PWM()
{
for (uint32_t n = 0; n < N; n++)
for (uint32_t i = 0; i < 8; i++)
value[n] += (GammaCorrection ? LEDGamma(n) : n) & 1<<(7-i) ? (uint64_t)TIM_HI<<i*8 : (uint64_t)TIM_LO<<i*8;
}
constexpr uint64_t operator()(uint8_t n) const { return value[n]; }
};
constexpr COLOR2PWM<256> color2pwm;
struct RGB
{
uint8_t g;
uint8_t r;
uint8_t b;
};
struct PWM_RGB_BUF
{
uint64_t g;
uint64_t r;
uint64_t b;
inline PWM_RGB_BUF& operator=(RGB rgb)
{
this->g = color2pwm(rgb.g);
this->r = color2pwm(rgb.r);
this->b = color2pwm(rgb.b);
return *this;
}
};
PWM_RGB_BUF dma_pwm_buf[16];
RGB leds[16] = { {0x12, 0x34, 0x56}, {0x78, 0x9A, 0xBC}, {0x00, 0x00, 0x00} };Замер скорости преобразования одного диода 0.67 мкс, а восьми диодов 5,9 мкс.
Код: Выделить всё
TEST_PIN::set();
for(uint32_t i=0; i<8; i++)
dma_pwm_buf[i] = leds[i]; //Тут скрыто идёт преобразование
TEST_PIN::clear();
Ну и включим DMA+PWM, не зря же клаву топтали.
Спойлер
Для особо любознательных расскажу, что если использовать "константный диод", то даже таблица кодировки не будет использоваться. Компилятор просчитает всё без неё и будет ещё быстрее. К примеру, вот этот код всего 0,34 мкс для одного и 1,9 мкс для восьми диодов выполняется.
Код: Выделить всё
constexpr RGB green_led = {0x80,0,0};
for(uint32_t i=0; i<8; i++)
dma_pwm_buf[i] = green_led;Код: Выделить всё
dma_pwm_buf[0] = green_led;
LDR R3,??DataTable1_1
ADR R0,??DataTable1_2
LDM R0,{R0,R1}
STM R3!,{R0,R1}
SUBS R3,R3,#+8
MOV R0,R1
MOVS R5,R3
ADDS R5,R5,#+8
STM R5!,{R0,R1}
MOVS R5,R3
ADDS R5,R5,#+16
STM R5!,{R0,R1}
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: STM32 новичку в ARM что к чему
Я только одного не понял: кому надо выводить на светодиоды константную картинку? Хорошо бы поглядеть на объем и быстродействие кода, который реализует динамическое изменение цветов светодиодов. И с учетом того, что пока предыдущий "кадр" не ушел, менять массив "картинки" нельзя.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: STM32 новичку в ARM что к чему
[uquote="ARV",url="/forum/viewtopic.php?p=3916089#p3916089"]Я только одного не понял: кому надо выводить на светодиоды константную картинку? Хорошо бы поглядеть на объем и быстродействие кода, который реализует динамическое изменение цветов светодиодов.[/uquote]
Речь о скорости заполнения буфера. На входе цвета в RGB, можно проверять каждый бит цвета и копировать нужный байт, а можно для каждого из 3-х байт скопировать из таблицы 64-х битное значение, на ARM само копирование - одна инструкция выполняемая за 2 или 3 такта. А далее из таблицы данные выводит DMA, т.е. практически все время можно потратить на получение этих самых RGB.
Речь о скорости заполнения буфера. На входе цвета в RGB, можно проверять каждый бит цвета и копировать нужный байт, а можно для каждого из 3-х байт скопировать из таблицы 64-х битное значение, на ARM само копирование - одна инструкция выполняемая за 2 или 3 такта. А далее из таблицы данные выводит DMA, т.е. практически все время можно потратить на получение этих самых RGB.