STM32 новичку в ARM что к чему

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Опытный кот
Аватара пользователя
Сообщения: 819
Зарегистрирован: Вт окт 23, 2012 13:17:25
Откуда: Прокопьевск

Сообщение Oxford »

Так я сделал и пользуюсь по человечески :))) Проект я этот сделал за 2 дня на второй день плату изготовил и впаял в телек. :tea: Теперь у меня ящик включается и выключается от пульта ТВ приставки ))) :))) Одной кнопкой два девайса. И голову не забивал всякой ерундой и время не тратил.
Инженер R@D

Telegram чат: https://t.me/radiowolf или в поиске приложения @radiowolf. Личка:@cncoxford
Контактная информация:
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Знаешь, я бы постеснялся такое выкладывать

Код: Выделить всё

   TIM3->DIER |= TIM_DIER_CC1IE;
   TIM3->DIER |= TIM_DIER_CC2IE;
   TIM3->DIER |= TIM_DIER_CC3IE;
   TIM3->DIER |= TIM_DIER_CC4IE;
Реклама
Опытный кот
Аватара пользователя
Сообщения: 819
Зарегистрирован: Вт окт 23, 2012 13:17:25
Откуда: Прокопьевск

Сообщение Oxford »

А я не стесняюсь. Но ты можешь навести красоту и сэкономить. Все в твоих руках дерзай.
А мне так код воспринимать легче. Не все требует оптимизации. Оптимизация должна быть разумная.
Последний раз редактировалось Oxford Вт окт 13, 2020 02:57:17, всего редактировалось 2 раза.
Инженер R@D

Telegram чат: https://t.me/radiowolf или в поиске приложения @radiowolf. Личка:@cncoxford
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Я неоднократно выкладывал разные классы USB на разные контроллеры. Утаптываются в 2 кб. Любуйся.
Реклама
Эиком - электронные компоненты и радиодетали
Опытный кот
Аватара пользователя
Сообщения: 819
Зарегистрирован: Вт окт 23, 2012 13:17:25
Откуда: Прокопьевск

Сообщение Oxford »

VladislavS да нет мне не нужно я не использую сторонние библиотеки в своих проектах. Максимум от вендоров проверенные либы через тестирование, если надо будет я напишу что мне нужно.
Если говорить о USB-UART я микрухи ставлю так проще и надежнее.
Инженер R@D

Telegram чат: https://t.me/radiowolf или в поиске приложения @radiowolf. Личка:@cncoxford
Контактная информация:
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Чипы стоят денег, занимают место и потребляют энергию. :dont_know:
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01

Сообщение Eddy_Em »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3905820#p3905820"]А "портянки" это точно не ко мне, я как раз за лаконичность и читаемость кода.[/uquote]
Это С++ читаемый? Ну-ну…
Особенно когда там используются шаблоны. Прямо читабельный донельзя!
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="Eddy_Em",url="/forum/viewtopic.php?p=3905894#p3905894"]Это С++ читаемый? Ну-ну…
Особенно когда там используются шаблоны. Прямо читабельный донельзя![/uquote]
Что в шаблонах нечитаемого? Угловые скобки вместо обычных?
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

이 텍스트는 한국어를 아는 사람이 쉽게 읽을 수 있습니다.
Этот текст легко читает любой знающий корейский язык. Намёк понятен? Почему каждый считает, что должен с лёгкостью читать неизвесьный ему язык программирования?
Опытный кот
Аватара пользователя
Сообщения: 819
Зарегистрирован: Вт окт 23, 2012 13:17:25
Откуда: Прокопьевск

Сообщение Oxford »

Я уже говорил ansi c стандарт. Все остальное твоя личная головная боль.
Инженер R@D

Telegram чат: https://t.me/radiowolf или в поиске приложения @radiowolf. Личка:@cncoxford
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

За меня не надо думать и переживать. За себя лучше беспокойтесь. Вам даже оператор l= избыточен. Смотрите какая штука есть. :)

Добавлено after 14 minutes 9 seconds:
Дабы новичкам было интересно и полезно читать тему, она всё же для них, предлагаю в качестве обучения выгрести весь избыточный код из функции представленной вот в этом сообщении.

Добавлено after 4 minutes 30 seconds:
Oxford, так что там про вход в прерывания на С++ было до удаления? Форум всё помнит, нельзя просто так взять и стереть :)
Опытный кот
Аватара пользователя
Сообщения: 819
Зарегистрирован: Вт окт 23, 2012 13:17:25
Откуда: Прокопьевск

Сообщение Oxford »

Ниче тебе это знать не надо
Инженер R@D

Telegram чат: https://t.me/radiowolf или в поиске приложения @radiowolf. Личка:@cncoxford
Контактная информация:
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18789
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Reflector писал(а):Что в шаблонах нечитаемого?
как по мне, "специалисту" С++, в шаблонах крайне сложно уследить за тем, что куда подставляется и когда. т.е. где "шаблон" для подстановки, а где "как есть" все останется. вот я на все эти ваши С++ версии смотрю - вроде нутром понимаю, как там и что, но страшно даже пробовать...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

ARV, вы же в аргументах функций не путаетесь. В круглых скобках пишете переменные и константы. С шаблоном всё то же самое, только скобки угловые и параметры это типы и константы.

Добавлено after 10 minutes 15 seconds:
[uquote="Oxford",url="/forum/viewtopic.php?p=3905942#p3905942"]Ниче тебе это знать не надо[/uquote]Фух, а то я уже думал что-то такое страшное открылось. :shock:

Код: Выделить всё

extern "C" void SysTick_Handler()
{
  PA_15::toggle();
}

Код: Выделить всё

SysTick_Handler:
        LDR.N    R1,??DataTable1_6  ;; 0x4001080c
        LDR      R2,[R1, #+0]       ;; Read ODR
        LSLS     R3,R2,#+16
        MOV      R0,#+32768
        BPL.N    ??SysTick_Handler_0
        STR      R0,[R1, #+8]       ;; Write BRR
        BX       LR
??SysTick_Handler_0:
        STR      R0,[R1, #+4]       ;; Wtite BSRR
        BX       LR                 ;; return    
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Сообщение Dimon456 »

VladislavS, что бы поморгать светодиодом, мне в проект пришлось добавить 12 каких-то файлов (со счету сбился) + одну папку, там куча файлов, + еще одну папку, там то же куча файлов,
и поморгать-то поморгал,
но вот это

Код: Выделить всё

typedef PinList<Pb1, Pb0, Pb2, Pb1, Pc3, Pc4, Pc5> Group1;
к сожалению не собралось, может что то отсутствует, может еще кучу файлов подкинуть надо?
Вы бы свой примерчик не выложили в минимальной конфигурации?
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="ARV",url="/forum/viewtopic.php?p=3905949#p3905949"]как по мне, "специалисту" С++, в шаблонах крайне сложно уследить за тем, что куда подставляется и когда. т.е. где "шаблон" для подстановки, а где "как есть" все останется. вот я на все эти ваши С++ версии смотрю - вроде нутром понимаю, как там и что, но страшно даже пробовать...[/uquote]
А с макросами не то же самое? Только при написании макроса придется для каждой строки слеши добавлять, аргументы в скобки брать и все вместе в цикл заворачивать, потом при вызове опять аргументы в скобки и при этом еще и типы не известны, соответственно никакого контроля типов тоже нет.
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Извини, библиотека не для распространения. Давай я лучше простенький пример придумаю как С++ позволяет оптимизировать код. Заодно и шаблон пощупаем. Как раз для начинающих.

Задача: функция toggle для произвольного количества бит в порту STM32F1.

Для начала обзаведёмся служебной функцией, которая считает количество установленных бит.

Код: Выделить всё

static inline constexpr uint32_t countSetBits(uint32_t value)
{
  uint32_t bits = 0;

  while (value)
  {
    value &= value - 1;
    bits++;
  }
  return bits;
}
Вроде ничего особенного, но если на входе константа, то компилятор посчитает значение этой функции на этапе компиляции.

Ну, всё готово, чтобы сделать наш класс. Естественно, он будет шаблонным.

Код: Выделить всё

template <uint32_t GpioID, uint16_t PM=0xFFFF>
class TSimplePort
{  
  static_assert(PM>0, "Wrong mask"); 

  static inline auto base() { return (GPIO_TypeDef*)GpioID; } 

public:

  TSimplePort() = default;
    
  static inline void toggle()
  {
    if constexpr (PM == 0xFFFF)
      base()->ODR = ~base()->ODR;
    else
      if constexpr (countSetBits(PM)==1)
        if(base()->ODR & PM) base()->BRR = PM; else base()->BSRR = PM;
      else  
        base()->BSRR = (PM << 16) | (~base()->ODR & PM);
  }
  
};
Начинается всё с параметров шаблона

Код: Выделить всё

template <uint32_t GpioID, uint16_t PM=0xFFFF>
В первый будем передавать с каким портом контроллера работать (GPIOA, GPIOB и так далее). Во второй маску, какие биты в порту будут задействованы. Второму параметру зададим значение по умолчанию - оно будет использоваться, если параметр не будет указан.

Попросим компилятор проверить, что пользователь не захотел пустую маску использовать. В нашем примере это неуместно.

Код: Выделить всё

static_assert(PM>0, "Wrong mask");
Дальше идёт приватная функция base().

Код: Выделить всё

static inline auto base() { return (GPIO_TypeDef*)GpioID; }
Её значение мы будем использовать как указатель на используемый порт. Наш класс не знает же до момента компиляции с каким портом будет работать.

Конструктор. Тут всё статическое, конструктор по сути и не нужен, пускай компилятор сам разберётся с ним.

Код: Выделить всё

TSimplePort() = default;
Ну всё, все подготовительные работы закончены. Осталось метод toggle() разобрать. Тут будут наши оптимизации. С ходу просматривается три варианта развития событий:
1. Используются все биты в порту. Тогда напрашивается cделать инверсию ODR = ~ODR. Мы ведь ничего не испортим.
2. Если ипользуется один бит в порту, то смотрим в каком состоянии вывод и сбрасываем/устанавливаем его записью маски в BRR/BSRR.
3. Используется несколько бит в порту. Наиболее общий случай. Читаем ODR и через BSRR что надо скидываем, что надо устанавливаем.

Ну что, проверим на практике?
1. Будем работать со всем портом. Маску не будем указывать, она задастся по умолчанию.

Код: Выделить всё

using TestPort = TSimplePort<uint32_t(GPIOA_BASE)>;
TestPort::toggle();
        LDR.W    R5,??main_0      ;; 0x4001080c
        LDR      R0,[R5, #+0]     ;; Read ODR
        MVNS     R0,R0            
        STR      R0,[R5, #+0]     ;; Write ODR
2. Попробуем с одним пином в порту.

Код: Выделить всё

using TestPort = TSimplePort<uint32_t(GPIOA_BASE), (1<<2)>;
TestPort::toggle();
        LDR.W    R5,??main_0      ;; 0x4001080c
        LDR      R0,[R5, #+0]     ;; Read ODR
        LSLS     R1,R0,#+29 
        ITTEE    MI 
        MOVMI    R0,#+4
        STRMI    R0,[R5, #+8]     ;; Write BRR
        MOVPL    R1,#+4
        STRPL    R1,[R5, #+4]     ;; Write BSRR
3. А теперь два бита в порту

Код: Выделить всё

using TestPort = TSimplePort<uint32_t(GPIOA_BASE), (1<<2)|(1<<1) >;
TestPort::toggle();
        LDR.W    R5,??main_0      ;; 0x4001080c
        LDR      R0,[R5, #+0]     ;; Read ODR
        MVNS     R0,R0
        AND      R0,R0,#0x6
        ORR      R0,R0,#0x60000
        STR      R0,[R5, #+4]     ;; Write BSRR

Благодаря возможностям языка программирования компилятор на этапе компиляции просчитал значение функции countSetBits(), внутри метода toggle() выбрал наилучший вариант кода и выкинул остальные!

Вроде для начала ничего сложного, правда ведь?

2Злопыхатели: это учебный пример!
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18789
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

надо бы это в тему про С++ перенести.

зачем base()? для этого примера ведь это не нужно?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="ARV",url="/forum/viewtopic.php?p=3905992#p3905992"]зачем base()? для этого примера ведь это не нужно?[/uquote]Нужно. Передача указателей на структуры портов типа (GPIO_TypeDef*) через параметры шаблонов нарушают условия constexpr из-за того что там volatile внутри спрятан. Это ограничения языка такие. Напрашивалось передать GPIOA сразу через шаблон, но это не будет работать.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18789
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

но ведь в параметре шаблона у нас uint32_t, что мешает его по месту использования принудительно кастовать к нужному типу?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Ответить

Вернуться в «ARM»