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

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Собутыльник Кота
Аватара пользователя
Сообщения: 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
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 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
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 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
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

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

Сообщение VladislavS »

Вот так?

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

if(((GPIO_TypeDef*)GpioID)->ODR & PM) ((GPIO_TypeDef*)GpioID)->BRR = PM; else ((GPIO_TypeDef*)GpioID)->BSRR = PM;
Работать будет, но...
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

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

Сообщение VladislavS »

Принципиально что (GPIO_TypeDef*) через параметр шаблона не протащить в constexpr контексте. А если кастовать туда-сюда, то через функцию надёжней всего.
Собутыльник Кота
Аватара пользователя
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01

Сообщение Eddy_Em »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3905910#p3905910"]Почему каждый считает, что должен с лёгкостью читать неизвесьный ему язык программирования?[/uquote]
Я лет 20 назад учил С++ по классическому учебнику Бьерна Страуструпа. Там такой дичи, как лямбды, шаблоны и т.п., не было!

Я считаю, что этому Г не место в нормальном языке программирования. Пусть в жабе делают, что хотят, но не в С++ же!
[uquote="Reflector",url="/forum/viewtopic.php?p=3905989#p3905989"]А с макросами не то же самое?[/uquote]
Абсолютно не то же самое! С макросами все прозрачно и понятно.
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Eddy_Em, тебе сюда -> Национальная рабочая группа по стандартизации С++ (РГ21 С++ Россия). Там наверняка внимательно выслушают твои веские аргументы. :)))
Открыл глаза
Аватара пользователя
Сообщения: 56
Зарегистрирован: Вт дек 29, 2015 11:33:49

Сообщение pavell »

[uquote="Eddy_Em",url="/forum/viewtopic.php?p=3906040#p3906040"]Абсолютно не то же самое! С макросами все прозрачно и понятно.[/uquote]
ну так себе заявление )
Ответить

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