• Где хранятся ваши константы на микроконтроллере CortexM (на примере С++ IAR компилятора)
    0
    А объявление constexpr FlashStorage koeff0(77); не хочет компилироваться.

    Да все верно, так как volatile в constexpr запрещены


    А где мне нужно снимать const у const volatile?

    вот тут у вас, вы приводите указатель const volatile int к указателю int, там как раз и выполнился const_cast...


    //int ptr = (int)&_data; /
  • Где хранятся ваши константы на микроконтроллере CortexM (на примере С++ IAR компилятора)
    0

    Я работу с записью во флеш тоже сделал через статический класс, ну т.е. все методы и атрибуты статические у него.

  • Где хранятся ваши константы на микроконтроллере CortexM (на примере С++ IAR компилятора)
    0

    А как вы снимите только const у const volatile? const_cast все снимет, а это UB, volatile тоже нельзя снимать.
    https://www.viva64.com/en/w/v2567/

  • Где хранятся ваши константы на микроконтроллере CortexM (на примере С++ IAR компилятора)
    0

    Это __ro_placement практически равносилен constexpr, по-крайней мере, все где не компилятор не ругается на невозможность constexpr ложится в __ro_placement, а где ругается, там не ложится…
    Можно еще конечно явно адрес в ПЗУ указать переменной varInflash… через собаку.

  • Где хранятся ваши константы на микроконтроллере CortexM (на примере С++ IAR компилятора)
    0

    Значит чудес не бывает… :) Наверное самое правильное указывать конкретный сегмент. В таком случае можно обмануть компилятор, UB не будет, переменная для компилятора изменяемая, просто он её должен положить в другой сегмент. А линкеру указать, чтобы этот сегмент по адресам во флеше разместил.
    Как проверить, что сегмента нет — не знаю...

  • Где хранятся ваши константы на микроконтроллере CortexM (на примере С++ IAR компилятора)
    0

    Проверьте с mutable куда все ложится? Ryppka дело сказал, и UB не будет.

  • Где хранятся ваши константы на микроконтроллере CortexM (на примере С++ IAR компилятора)
    0

    Кстати да...


    #include <iostream>
    
    class FlashStorage {
    public:
        constexpr FlashStorage(int init):_data(init){};
        const int& data() const {return _data;};
    
        void SetValue(int val) const {
            // магия с флеш контроллером и записью страниц
            _data = val;
        }
    
    private:
        mutable int _data;
    };
    
    //#pragma location = ".flashdata" //сегмент во флеш.
    //int varInflash = 77;
    const FlashStorage koeff0(77 ); // ложится куда-то в о флеш
    
    int main() {
      std::cout << koeff0.data();
      koeff0.SetValue(88);
      std::cout << koeff0.data();
    }
  • Где хранятся ваши константы на микроконтроллере CortexM (на примере С++ IAR компилятора)
    0

    В данном случае да, но можно что сделать тогда:


    ```cpp
    #include <iostream>
    
    class FlashStorage {
    public:
        constexpr FlashStorage(int init):_data(init){};
        const int& data() const {return _data;};
    
        void SetValue(int val) const {
            // магия с флеш контроллером и записью страниц
            _data = val;
        }
    
    private:
        mutable int _data;
    };
    
    //#pragma location = ".flashdata" //сегмент во флеш.
    //int varInflash = 77;
    const FlashStorage koeff0(77 ); // ложится куда-то в о флеш
    
    int main() {
      std::cout << koeff0.data();
      koeff0.SetValue(88);
      std::cout << koeff0.data();
    }

  • Где хранятся ваши константы на микроконтроллере CortexM (на примере С++ IAR компилятора)
    0

    Тогда лучше этот хак скрыть от пользователя… в классе:


    #include <iostream>
    
    class FlashStorage {
    public:
        constexpr FlashStorage(const int& init):_data(init){};
        const int& data() const {return _data;};
    
        void SetValue(int val) const {
            // магия с флеш контроллером и записью страниц
            *const_cast<int*>(&_data) = val;
        }
    
    private:
        const int& _data;
    };
    
    constexpr int varInflash = 77;
    const FlashStorage koeff0(varInflash); // ложится куда-то в о флеш
    
    int main() {
      std::cout << koeff0.data();
      koeff0.SetValue(88);
      std::cout << koeff0.data();
    }
  • Где хранятся ваши константы на микроконтроллере CortexM (на примере С++ IAR компилятора)
    0

    Тогда так, но это хак


    #include <iostream>
    
    class FlashStorage {
    public:
        constexpr FlashStorage(int& init):_data(init){};
        const int& data() const {return _data;};
    
        void SetValue(int val) const {
            // магия с флеш контроллером и записью страниц
            _data = val;
        }
    
    private:
        int& _data;
    };
    
    constexpr int varInflash = 77;
    const FlashStorage koeff0(*(const_cast<int*>(&varInflash))); // ложится куда-то в о флеш
    
    int main() {
      std::cout << koeff0.data();
      koeff0.SetValue(88);
      std::cout << koeff0.data();
    }
  • Где хранятся ваши константы на микроконтроллере CortexM (на примере С++ IAR компилятора)
    0

    Либо статик еще можно и сразу её положить во flash


    #include <iostream>
    
    class FlashStorage {
    public:
        constexpr FlashStorage(){};
        const int& data() const {return _data;};
    
        void SetValue(int val) const {
            // магия с флеш контроллером и записью страниц
            _data = val;
        }
    
    private:
        #pragma location = ".flashdata" //сегмент по которому вы хотите расположить данные
        inline static int _data = 77;
    };
    
    const FlashStorage koeff0; // ложится куда-то в о флеш
    
    int main() {
      std::cout << koeff0.data();
      koeff0.SetValue(88);
      std::cout << koeff0.data();
    }
  • Где хранятся ваши константы на микроконтроллере CortexM (на примере С++ IAR компилятора)
    0

    Сделайте ссылку на _data


    class FlashStorage {
    public:
        constexpr FlashStorage(int& init):_data(init){};
        const int& data() const {return _data;};
    
        void SetValue(int val) const {
            // магия с флеш контроллером и записью страниц
            _data = val;
        }
    
    private:
        int& _data;
    };
    
    int varInflash = 77;
    const FlashStorage koeff0(varInflash ); // ложится куда-то в о флеш
    
    int main() {
      cout << koeff0.data();
      koeff0.SetValue(88);
      cout << koeff0.data();
    }
  • Виртуальные функции в микроконтроллерах — темная сторона
    0

    Статический полиморфизм через using


    //в вашей реализации вы должны определить псевдоним базового 
    //типа, который используется внутри библиотеки.
    using BaseUDP = UDP<EthernetUDP> ; 
    //или так:
    using BaseUDP = UDP<OtherUDP> ;
    
    //в самой библиотеке просто всегда:
    BaseUDP udp ;
    udp.write(..)
  • Виртуальные функции в микроконтроллерах — темная сторона
    0

    Я не много не ту ссылку вам дал:
    Правильная ссылка


    И если теперь сделать в реализации так:


    using BaseUDP = UDP<EthernetUDP>
    
    //то в самой библиотеке это будет использоваться так
    BaseUDP.write(..)
    
  • Виртуальные функции в микроконтроллерах — темная сторона
    0

    Да, все верно, чтобы подставить разную реализацию, но нужно же знать, реализацию чего, если нет интерфейса, что реализовывать то?

  • Виртуальные функции в микроконтроллерах — темная сторона
    0

    Инстанс то один будет для каждого объекта, который будет содержать в себе и методы базового класса и методы наследника. Но так как методы базового класса инлайн, то они вырождаются в прямые вызовы метода наследника, поэтому их не будет…


    Пример

  • Виртуальные функции в микроконтроллерах — темная сторона
    0

    А почему код должен размножаться? В базовом классе все методы инлайновые, по сути преобразуются в прямой вызов методов наследников. И оптимизацию тут просто компилятор сделает.


    Как раз для вашего случая хорошо подойдет. Ну имеется ввиду, если бы сразу так библиотека была бы организована для разделения интерфейсов и реализаций.


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

    В данном случае оправдано, так как это библиотека и каким-то макаром нужно все равно интерфейс определить. Другое дело, что, как выше сказали можно было это сделать через Странно рекурсивный шаблон.


    Но в любом случае, как бы вы узнали какие функции нужно реализовывать, если нет интерфейса? Методом проб и ошибок?

  • Поиск ошибки FDCAN, которой нет
    0

    Была похожая история с Atmega, использовали термодатчик и опцию АЦП, уже точно не помню, но, что то типа уменьшения частоты семплирования, для уменьшения потребления. Все работало, устройства пошли в серию, потом бах и через пол года при авторском надзор и проверке погрешностей, стали замечать, что температурная погрешность за пределами спецификации.
    Начали разбираться, показания с термодатчика морозятся в одно значение после нескольких измерений.
    Оказалось, сменилась ревизия проца и там этот модуль поменялся… А в старой ревизии оказывается он и вовсе был отключён, т. Е. по факту никакого уменьшения частоты семплирования не происходило, а в новом он включён, но не работает. В итоге с Atmel мы попрощались

  • Типобезопасная работа с регистрами без оверхеда на С++17: value-based метапрограммирование
    0

    Спасибо за статью, очень познавательно, тоже этой темой озадачивался.
    Пока вижу только одну проблемку — скорее всего без оптимизации кода будет много из-за этого:


    Address(Pointer address) { value = reinterpret_cast<std::size_t>(address); }

    В результате Address::value не может быть constexpr, а значит и в set() передаваться будет рантайм значение, поэтому без оптимизации точно будет куча кода. Думаю, что с оптимизацией компилятор кончено все сам высчитает.
    А так идея хорошая… возьму на вооружение. Спасибо.

  • 10 признаков того, что хороший программист из вас не получится
    0

    Чтобы случайно под другим юзером не зайти..

  • 10 признаков того, что хороший программист из вас не получится
    0

    Неявные требования тоже требования. Если есть закон о персональных данных, то это тоже требование…

  • 10 признаков того, что хороший программист из вас не получится
    –1

    И что? У нас, например внутренняя система учёта времени, там мой пароль 1. Ну утечет он, что с этого? Данные с этой системы чисто информативные для сотрудников…
    Зачем там сложная система аутентификации? 7

  • 10 признаков того, что хороший программист из вас не получится
    –1
    А тебе попадается необъяснимое поведение в ЯП

    Это странно, потому что обычно все объясняется стандартом ЯП, иногда бывает необъяснимое поведение компилятора, но тогда скорее всего надо просто прочитать Errata на него.

  • 10 признаков того, что хороший программист из вас не получится
    –1

    Если в требованиях не было про то, как должны храниться пароли, то вполне себе нормальное решение. Может там защита не нужна… Например, какой-нить внутрикорпоративный сервис, для поиска общедоступной информации… Зачем городить огород, где он не нужен?


    Реализовано правильно, это когда по требованиям.

  • 10 признаков того, что хороший программист из вас не получится
    +3

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


    Я вот свой код 3 летней давности считал тогда простым и оптимальным. А сейчас смотрю и удивляюсь, как такая лажа в продукт шла? Но если бы я 3 года назад продолжил бы искать более оптимальное и понятное решение, то возможно, уже программистом и не был бы — уволили бы меня.

  • Еще раз про усложненность архитектуры и порог входа
    0

    Не понимаю, почему усложнения? Казалось бы наоборот, каждый класс, ну или функция отвечает за одну вещь. Это и тестируется проще и понимается тоже и архитектура не усложняется. Или в вашем понимании, простая архитектура, это когда чем меньше классов, тем проще? Но это ведь не так.
    С моей точки зрения, простая, это когда понятнее.
    Второй ваш пример, явно понятнее первого.

  • Что такое MISRA и как её готовить
    +1
    for (int i = 0; i < n; ++i);
    {
      do_something();
    }

    Ну прямо с субботней проверки лабораторных, только было что-то типа этого


    if (true && false);
    {
      //делать что-то если true
    }

    Студентка час искала, почему у неё внутрь скобок заходит..., потом позвала меня, я в начале тоже в шоке был :), но быстро догадался…
    Для этого сказал, чтобы перед точкой запятой пробел ставили всегда, тогда её видно из далека.


    if (true && false) ;
    {
      //делать что-то если true
    }

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

  • Работа со списком Pinов, на С++ для микроконтроллеров (на примере CortexM)
    0
    Зачем? Если есть дубликаты, то срабатывает ассерт, и компиляция прекращается.

    Чтобы список портов сделать…
    Вначале берем Pinы, и вытаскиваем из них все порты на которых они сидят
    Например:


    using Pin1 = Port<GPIOB, 3>;
    using Pin2 = Port<GPIOB, 3>;
    using Pin3 = Port<GPIOA, 3>;
    
    Typelist<Pin1, Pin2, Pin3> ;

    из него получается список портов:


    Typelist<GPIOB, GPIOB, GPIOA> ;

    и его нужно сократить до:


    Typelist<GPIOB, GPIOA> ;

    А потом уже пробежаться по 2 портам только и записать в них рассчитанные значения.
    Собственно, чтобы велик не делать, я делаю так:


    using Ports = typename 
                         NoDuplicates<Collection<typename Ts::PortType...>>::Result ;

    А заодно этот NoDuplicates еще использую для проверки того, что сам список Pinов не имеет дубликатов.

  • Хакеры-вымогатели атаковали Norsk Hydro: как это было
    +2

    Они не одни такие, еще пару глобальных заводиков атакой накрыло и общение было через бумаги и телефон. Это называется низкая культура кибербезопасности(локальные админы на компах в доменах, открывания всяких непонятных емайлов, установка самостоятельного софта и так далее). Интересно, если бы они в свое время тратили бы N сумму на развитие кибер безопасности, то это покрыло бы убыток от того, что произошло или нет?

  • Работа со списком Pinов, на С++ для микроконтроллеров (на примере CortexM)
    0

    Я еще повнимательнее посмотрел, и подумал, что от дубликатов то все равно надо будет избавляться… Кроме проверки на уникальность, нужно формировать список портов, по которым бегать. (Не очень эффективно для компилятора, но зато кода не так много, так используется NoDuplicates из Loki)


    // Формируем список пинов без дубликатов
       using  TPins =  typename NoDuplicates<Collection<Ts...>>::Result;
       // Проверяем совпадает ли исходный список пинов со списком без дубликатов
       static_assert(std::is_same<TPins, Collection<Ts...>>::value, 
                     "Беда: Одинаковые пины в списке") ;   
       // Формируем список уникальных портов
       using Ports = typename 
                         NoDuplicates<Collection<typename Ts::PortType...>>::Result;

    Можно конечно его формировать по другому, просто идти и смотреть, что таких портов еще нет в списке добавляем, есть не добавляем — не через Loki, но почему бы уже готовым велосипедом не воспользоваться, тем более, что он используется для двух целей: Формирование списка уникальных портов и проверки списка пинов на уникальность


    А вызов через fold expression для установки портов — замечательная идея, немного подправлю и если время будет новую статью забабахаю :)

  • Работа со списком Pinов, на С++ для микроконтроллеров (на примере CortexM)
    0

    Фу блин спутал с unique :) все понял ...

  • Работа со списком Pinов, на С++ для микроконтроллеров (на примере CortexM)
    0

    Спасибо, как говорится век живи век учись. В
    IAR C++ 17 появился только 6 месяцев назад, полноценный, начиная с версии 8.40.2, поэтому опыта использования его было не много. С fold expression только только начал пользоваться и уже понял, что они существенно могут сократить гемор.
    И момент такой, что хоть IAR и поддерживает синтаксис C++17, библиотечные функции в нем не все реализованы, надо проверить, есть ли там all_unique. Подозреваю, что нет.
    Ещё раз спасибо, как всегда, очень полезное замечание.

  • Разработка «простого генератора напряжения» в соответствии с ГОСТ Р МЭК 61508 (IEC 61508)
    0

    Все верно… это приводит к увеличению размера данных в ОЗУ.

  • Разработка «простого генератора напряжения» в соответствии с ГОСТ Р МЭК 61508 (IEC 61508)
    0

    Да, отказ ОЗУ можно зафиксировать, но например, проверить, что бит в ОЗУ был изменен с 0 на 1 уже найти не так просто, если константа там лежит долго, то вместе с ней придется хранить и контрольную сумму, либо использовать для хранения таких данных ОЗУ с ЕСС, у STM есть такие микроконтроллеры, которые имеют небольшую область ОЗУ с ЕСС

  • Разработка «простого генератора напряжения» в соответствии с ГОСТ Р МЭК 61508 (IEC 61508)
    0

    Факт слёта флеша сам по себе не является преградой для получения SIL сертификата, потому что флеш слетит в любом случае, вопрос только когда и какова вероятность этого. А она значительно ниже, чем слёт ОЗУ.


    Но важно другое, надёжное устройство должно определить факт этого слёта и перевести устройство в безопасный режим, т. е. не исправить ошибку (исправление ошибок, как раз не рекомендуется), а выставить сигнал Аварии, чтобы остальная система знала, что датчику доверять нельзя. В токовых датчиках — это выставить сигнал ниже 3.6 мА, или выше 23 mA..

  • Статическая подписка с использованием шаблона Наблюдатель на примере С++ и микроконтроллера Cortex M4
    0

    Точно :}, оператор "," поддерживается для fold expression. Застрял в С++14 с этим passом. Добавлю в статью.

  • Разработка «простого генератора напряжения» в соответствии с ГОСТ Р МЭК 61508 (IEC 61508)
    +2

    Вообще с GCC могут проблемы (его не засчитают обычно), так как у него нет сертификата безопасности, зато он есть еще у GreenHill и IAR.


    MDR_PORTE->CLRTX

    Миландр :)


    Хочу еще отметить, что для получения сертификата на ПО недостаточно следовать только рекомендациям по используемым алгоритмам, но еще необходимо следовать процессам...


    По которым должны быть требования к ПО, отдельно требования к частям которые влияют на надежность, архитектура ПО должна полностью трассироваться с требованиями, отдельно в ней также должны быть выделены части критические по надежности и опять же трейс с требованиями должен быть от кода до требований, чтобы можно было посмотреть, вот код, который покрывает вот эту часть архитектуры, которая покрывает вот эти требования.


    Тоже самое касается наличия юнит тестов и статического анализа — они должны быть обязательно для Си и С++, должен быть файл с результатами и покрытием. Для статического анализатора, все задавленные предупреждения должны быть объяснены и выведены в отчет.


    В общем, Безопасность по этому МИК определяется не только наличием диагностики ALU, ОЗУ, ПЗУ, регистров… и хорошим тулом для проверки, но и процессами. И это не маловажный факт, который при сертификации обязательно спрашивают (Ну по крайней мере при международной)

  • Статическая подписка с использованием шаблона Наблюдатель на примере С++ и микроконтроллера Cortex M4
    0

    Попробую проверить дома, сейчас под рукой нет компилятора...

  • Статическая подписка с использованием шаблона Наблюдатель на примере С++ и микроконтроллера Cortex M4
    0

    Просто сделать subscribers.HandleEvent()... нельзя. Потому что использовать переменное количество параметров можно только через Function argument lists, Parenthesized initializers, Brace-enclosed initializers, Template argument lists, Function parameter list, Template parameter list, Base specifiers and member initializer lists, Lambda captures, Fold-expressions, Using-declarations, Dynamic exception specifications, The sizeof… operator.
    Более подробно здесь можно прочитать.


    И просто subscribers.HandleEvent()... ни под один из этих вариантов не подходит.


    Через initializer_list можно, но придется вводить общий интерфейс для подписчиков, так как типы подписчиков разные, а в initializer_list можно передавать только объекты одного типа. Что-то типа этого, могу ошибиться, не компилил...


        auto subscribersList  = {(ISubscriber *)(&subscribers)...} ;
    
        for(auto subsriber: subscribersList)
        {
            subsriber->HandleEvent() ;
        }      

    Ну и плюсом сама переменная subscribersList типа initializer_list и её обход через цикл, тоже ресурсы отъедает. Он конечно при оптимизации скорее всего свернется, но без оптимизации там точно будут накладные расходы.


    А так, никаких накладных, если еще сделать все принудительно inline, вообще ровно в 3 строчки развернется...

  • Статическая подписка с использованием шаблона Наблюдатель на примере С++ и микроконтроллера Cortex M4
    0

    Согласен можно через fold expression, там только думаю компилятор ворнинг может дать, что результат выражения нигде использоваться не будет. А с предупреждением жить не очень хорошо.