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


      Всем доброго здравия!


      В преддверии Нового года хочу продолжить рассказывать про использование С++ на микроконтроллерах, на этот раз попытаюсь рассказать про использование шаблона Наблюдатель (но далее я буду называть его Издатель-Подписчик или просто Подписчик, такой вот каламбур), а также реализацию статической подписки на С++17 и преимущества этого подхода в некоторых приложениях.

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


        Всем доброго здравия!


        В прошлой статье я обещал написать о том, как можно работать со списком портов.
        Сразу скажу, что уже все было решено до меня аж в 2010 году, вот статья: Работа с портами ввода-вывода микроконтроллеров на Си++ . Человек написавший это в 2010 просто красавчик.


        Мне было немного неловко, что я будут делать то, что уже сделано 10 лет назад, поэтому я решил не дожидаться 2020 года, а сделать это в 2019, чтобы повторить решение еще пока 9 летней давности, это будет не так стремно.


        В выше указанной статье работа со списками типов была сделана с помощью C++03, когда еще шаблоны имели фиксированное число параметров, а функции не могли быть constexpr выражениями. С тех пор С++ "немного изменился", поэтому давайте попробуем сделать тоже самое, но на С++17. Добро пожаловать под кат:

        Читать дальше →
      • Трактат о Pinе. Мысли о настройке и работе с пинами на С++ для микроконтроллеров (на примере CortexM)

          Последнее время я сильно увлекся вопросом надежности софта для микроконтроллеров, 0xd34df00d посоветовал мне сильнодействующие препараты, но к сожалению руки пока не дошли до изучения Haskell и Ivory для микроконтроллеров, да и вообще до совершенно новых подходов к разработке ПО отличных от ООП. Я лишь начал очень медленно вкуривать функциональное программирование и формальные методы.


          Все мои потуги в этих направлениях это, как было сказано в комментарии ради любви к технологиям, но есть подозрение, что сейчас никто не даст мне применять такие подходы (хотя, как говориться, поживем увидим). Уж больно специфические навыки должны быть у программиста, который все это дело будет поддерживать. Полагаю, что написав однажды программу на таком языке, моя контора будет долго искать человека, который сможет принять такой код, поэтому на практике для студентов и для работы я все еще по старинке использую С++.


          Продолжу развивать тему о встроенном софте для небольших микроконтроллеров в устройствах для safety critical систем.


          На этот раз попробую предложить способ работы с конкретными ножками микроконтроллера, используя обертку над регистрами, которую я описал в прошлой статье Безопасный доступ к полям регистров на С++ без ущерба эффективности (на примере CortexM)


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


          using Led1Pin = Pin<Port<GPIOA>, 5U, PinWriteableConfigurable> ;
          using Led2Pin = Pin<Port<GPIOC>, 5U, PinWriteableConfigurable> ;
          using Led3Pin = Pin<Port<GPIOC>, 8U, PinWriteable> ;
          using Led4Pin = Pin<Port<GPIOC>, 9U, PinWriteable> ;
          using ButtonPin = Pin<Port<GPIOC>, 10U, PinReadable> ;
          
          //Этот вызов развернется в  2 строчки
          // GPIOA::BSRR::Set(32) ; // reinterpret_cast<volataile uint32_t *>(0x40020018) = 32U 
          // GPIOС::BSRR::Set(800) ; // reinterpret_cast<volataile uint32_t *>(0x40020818) = 800U 
           PinsPack<Led1Pin, Led2Pin, Led3Pin, Led4Pin>::Set() ; 
          
          //Ошибка компиляции, вывод к которому подключена кнопка настроен только на вход
          ButtonPin::Set() 
          
          auto res = ButtonPin::Get() ; 
          Читать дальше →
        • Безопасный доступ к полям регистров на С++ без ущерба эффективности (на примере CortexM)

            image
            Рис. взят с сайта www.extremetech.com/wp-content/uploads/2016/07/MegaProcessor-Feature.jpg

            Всем доброго здравия!

            В прошлой статье я рассмотрел вопрос о проблеме доступа к регистрам микроконтроллера с ядром CortexM на языке С++ и показал простые варианты решения части проблем.

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

            Всех кого заинтересовал, добро пожаловать под кат. Кода будет много.
            Читать дальше →
          • 10++ способов работать с аппаратными регистрами на С++ (на примере IAR и Cortex M)

              Choosing the safest path
              Рис. И. Кийко

              Всем доброго здравия!

              Помните наверное бородатый анекдот, а может быть и правдивую историю про то, как студента спрашивали о способе измерить высоту здания с помощью барометра. Студент привел, по-моему около 20 или 30 способов, при этом не назвав прямого(через разницу давления), которого ожидал преподаватель.

              Примерно в том же ключе я хочу продолжить обсуждение использования С++ для микроконтроллеров и рассмотреть способы как можно работать с регистрами используя С++. И хочу заметить, что для достижения безопасного обращения к регистрам простого пути не будет. Попытаюсь показать все плюсы и минусы способов. Если вы знаете еще способы, кидайте их в комментарии. Итак начнем:
              Читать дальше →
            • Синглтон, размещающий объекты в ROM и статические переменные(С++ на примере микроконтроллера Cortex M4)

                image

                В предыдущей статье Где хранятся ваши константы на микроконтроллере CortexM (на примере С++ IAR компилятора), был разобран вопрос о том, как расположить константные объекты в ROM. Теперь же я хочу рассказать, как можно использовать порождающий шаблон одиночка для создания объектов в ROM.
                Читать дальше →
              • Как поморгать 4 светодиодами на CortexM используя С++17, tuple и немного фантазии

                  Всем доброго здравия!

                  При обучении студентов разработке встроенного программного обеспечения для микроконтроллеров в университете я использую С++ и иногда даю особо интересующимся студентам всякие задачки для определения особо больных на голову одаренных учеников.

                  В очередной раз таким студентам была дана задача поморгать 4 светодиодами, используя язык С++ 17 и стандартную библиотеку С++, без подключения дополнительных библиотек, типа CMSIS и их заголовочных файлов с описанием структур регистров и так далее… Побеждает тот, у кого код в ROM будет занимать наименьший размер и меньше всего затрачено ОЗУ. Оптимизация компилятора при этом не должна быть выше Medium. Компилятор IAR 8.40.1.
                  Победитель едет на Канары получает 5 за экзамен.

                  Сам я до этого тоже эту задачу не решал, поэтому расскажу как её решили студенты и что получилось у меня. Предупреждаю сразу, навряд ли такой код можно будет использовать в реальных приложениях, потому и разместил публикацию в раздел «Ненормальное программирование», хотя кто знает.
                  Читать дальше →
                • Где хранятся ваши константы на микроконтроллере CortexM (на примере С++ IAR компилятора)

                    Я обучаю своих студентов работе с микроконтроллером STM32F411RE, на борту которого имеется аж целых 512 кБайт ROM и 128 кБайт ОЗУ
                    Обычно на этом микроконтроллере в ROM память записывается программа, а в RAM изменяемые данные и очень часто нужно сделать так, чтобы константы лежали в ROM.
                    В микроконтроллере STM32F411RE, ROM память расположена по адресам с 0x08000000...0x0807FFFF, а RAM с 0x20000000...0x2001FFFF.

                    И если все настройки линкера правильные, студент рассчитывает, что вот в таком незамысловатом коде его константа лежит в ROM:

                    class WantToBeInROM
                    {
                    private:
                      int i;
                    public:
                      WantToBeInROM(int value): i(value) {}
                      int Get() const
                      {
                        return i;
                      }
                    };
                    
                    const WantToBeInROM myConstInROM(10);
                    
                    int main()
                    {  
                      std::cout << &myConstInROM << std::endl ;
                    }
                    

                    Вы тоже можете пробовать ответить на вопрос: где лежит константа myConstInROM в ROM или в RAM?

                    Если вы ответили на этот вопрос, что в ROM, поздравляю вас, на самом деле скорее всего вы не правы, константа в общем случае будет лежать в RAM и чтобы разобраться, как правильно и законно расположить ваши константы в ROM — добро пожаловать под кат.
                    Читать дальше →
                  • Унифицированная обработка ошибок (C++ вариант для микроконтроллеров)

                      При разработке ПО для микроконтроллеров на С++ очень часто можно столкнуться с тем, что использование стандартной библиотеки может привести к нежелательным дополнительным расходам ресурсов, как ОЗУ, так и ПЗУ. Поэтому зачастую классы и методы из библиотеки std не совсем подходят для реализации в микроконтроллере. Существуют также некоторые ограничения в использовании динамически выделяемой памяти, RTTI, исключений и так далее. В общем случае, чтобы писать компактный и быстрый код нельзя просто так взять библиотеку std и начать пользоваться, скажем операторами типа typeid, потому что необходима поддержка RTTI, а это уже накладные расходы, хоть и не очень большие.

                      Поэтому иногда приходится изобретать велосипеды, чтобы выполнить все эти условия. Таких задач немного, но они есть. В данном посте, хотелось бы рассказать про вроде бы как простую задачку — расширить коды возврата существующих подсистем в ПО для микроконтроллера.
                      Читать дальше →
                    • С++ обертка для «всех» Операционных Систем Реального Времени для CortexM4

                        image

                        Я уже рассказывал о том как можно использовать FreeRtos для проектов, написанных на С++ в статье STM32, C++ и FreeRTOS. Разработка с нуля. Часть 1. С тех пор прошло целых 3 года, я серьезно постарел, потерял кучу нейронных связей, поэтому решил встряхнуть стариной для того, чтобы эти связи восстановить и замахнуться на обертку для «любой» популярной ОСРВ. Это конечно шутка, я намеренно взял «всех» в кавычки, но в каждой шутке есть доля правды.
                        Читать дальше →
                      • Можно ли использовать С++ вместо Си для небольших проектов в микроконтроллерах

                          Существует мнение, что использование С++ при разработке программного обеспечения для микроконтроллеров это как стрельба из пушки по воробьям. Мол код получается большого размера и неповоротливый, а мы привыкли бороться за каждый бит в ОЗУ или ПЗУ. И программное обеспечение для микроконтроллера может быть написано обязательно на Си. Действительно, ведь язык Си был задуман как альтернатива ассемблеру, код должен был быть такой же компактный и быстрый, а читаемость и удобство разработки позволять легко писать довольно большие программы. Но ведь когда-то и разработчики на ассемблере говорили тоже самое про Си, с тех пор утекло много воды и программистов, использующих только ассемблер, можно по пальцам пересчитать. Конечно, ассемблер еще играет важную роль в разработке кода для быстрых параллельных вычислений, написании ОСРВ, но это скорее исключение из правил. Так же как когда-то Си пробивал себе дорогу в качестве стандарта для встроенного ПО, так и язык С++ уже вполне может заменить Си в этой области. С++ стандарта С++14 и современные компиляторы имеют достаточно средств для того чтобы создавать компактный код и не уступать по эффективности коду, созданному на Си, а благодаря нововведениям быть понятнее и надежнее. Ниже приведен код поиска наименьшего числа в массиве из 5 целых чисел на двух языках Си и С++ на компиляторе IAR for ARM 8.20 с отключенной оптимизацией.
                          Читать дальше →
                        • STM32, C++ и FreeRTOS. Разработка с нуля. Часть 4 (Прерывания, UART и недоHART)

                          • Tutorial

                          Ведение


                          Попав в отпуске в город на Неве и посетив множество красивых мест, я все таки, вечерами за чашкой пива, разбирался с UARTом. Тем более, что я купил неплохие наушники Fisher FA011, к которым пришлось прикупить USB SOUND BLASTER X-FI HD и хотел послушать музыку.
                          Предыдущие статьи вначале переехали на Geektime потом я обратно их перегнал, даже и не знаю, куда теперь их деть :)
                          Но так на всякий случай они тут:
                          STM32, C++ и FreeRTOS. Разработка с нуля. Часть 1
                          STM32, C++ и FreeRTOS. Разработка с нуля. Часть 2 и
                          STM32, C++ и FreeRTOS. Разработка с нуля. Часть 3 (LCD и Экраны)
                          Читать дальше →
                          • +4
                          • 10.1k
                          • 2
                        • STM32, C++ и FreeRTOS. Разработка с нуля. Часть 4 (Прерывания, UART и недоHART)

                          • Tutorial

                          Ведение


                          Попав в отпуске в город на Неве и посетив множество красивых мест, я все таки, вечерами за чашкой пива, разбирался с UARTом. Тем более, что я купил неплохие наушники Fisher FA011, к которым пришлось прикупить USB SOUND BLASTER X-FI HD и хотел послушать музыку.
                          Предыдущие статьи вначале переехали на Geektime потом я обратно их перегнал, даже и не знаю, куда теперь их деть :)
                          Но так на всякий случай они тут:
                          STM32, C++ и FreeRTOS. Разработка с нуля. Часть 1
                          STM32, C++ и FreeRTOS. Разработка с нуля. Часть 2 и
                          STM32, C++ и FreeRTOS. Разработка с нуля. Часть 3 (LCD и Экраны)

                          UART


                          После детального изучения микроконтроллера, мне казалось, что все просто. Настройка и тестовая посылка байта в порт прошла без задоринки, все работало как часы, и тут я решил использовать прерывания. Нужно было сделать так, чтобы обработчик прерывания был статическим методом класса. И IAR в руководстве на компилятор, так и писал:
                          Special function types can be used for static member functions. For example, in the
                          following example, the function handler is declared as an interrupt function:
                          class Device
                          {
                           static __irq void handler();
                          };
                          

                          Но вот незадача, для Cortex M такой способ не подходит и
                          On ARM Cortex-M, an interrupt service routine enters and returns in the same way as a
                          normal function, which means no special keywords are required. Thus, the keywords
                          __irq, __fiq, and __nested are not available when you compile for ARM Cortex-M.

                          These exception function names are defined in cstartup_M.c and cstartup_M.s.
                          They are referred to by the library exception vector code:
                          NMI_Handler
                          HardFault_Handler
                          MemManage_Handler
                          BusFault_Handler

                          The vector table is implemented as an array. It should always have the name
                          __vector_table,

                          Или по простому, ваш обработчик прерывания должен иметь такое же имя, какое он имеет в таблице векторов определенной в startup файле. Это делается с помощью специального ключевого слова — слабой ссылки __weak (в ассемблере PUBWEAK), которая означает, что данное определение будет использоваться до тех пора, пока не найдется хотя бы одно совпадающее по написанию без ключевого слова __week. Ну т.е., если вы определите функцию с точно таким же именем без этой директивы, то компилятро будет использовать это определение, а если не определите, то которое помечено __weak.
                          Понятное дело, что я не могу в файл startup_stm32l1xx_md.s или startup_stm32l1xx_md.с вставить С++ имя статического метода типа cUart::USART2_IRQHandler(), ассемблер его просто не поймет.
                          А просто «USART2_IRQHandler» не совпадает с определением «cUart::USART2_IRQHandler()».
                          Можно использовать extern «C» { void USART2_IRQHandler(void) {...}}, но это означает, что я тут буду делать вставки из Си, что мне совсем не надо, и вообще доступа из такой функции к атрибутам моего класса, например буферу — не будет, и надо будет городить кучу некрасивого кода :).
                          Поэтому, я решил пойти другим путем и создать файл startup_stm32l1xx_md.cpp. Поиск в интернете обнаружил, что точно такая же проблема была у некоторых людей Вот например
                          В общем идея заключается в следующем: Объявляем в startup_stm32l1xx_md.cpp классы со статическими методами (которые и будут являться обработчиками прерываний), создаем таблицу __vector_table, где на каждом из векторов прерываний стоит указатель на эти статические методы. Дальше делаем __weak определение каждого метода
                          И теперь когда в коде компилятор видет реализацию void cUart1::handler(), он не задумываясь берет её. Конечно же при этом ваши классы и методы должны называться точь в точь так, как они определены в startup_stm32l1xx_md.cpp.
                          Нужно еще не забыть про функции FreeRtos: vPortSVCHandler, xPortPendSVHandler, xPortSysTickHandler и поставить их на нужное прерывание и вуаля — все работает:
                          startup_stm32l1xx_md.cpp
                          #pragma language = extended
                          #pragma segment = "CSTACK"
                          extern "C" void __iar_program_start( void );
                          extern "C" void vPortSVCHandler(void);
                          extern "C" void xPortPendSVHandler(void);
                          extern "C" void xPortSysTickHandler(void);
                          class cNMI
                          {
                          public:
                              static void handler(void);
                          };
                          class cHardFault
                          {
                          public:
                              static void handler(void);
                          };
                          class cMemManage
                          {
                          public:
                              static void handler(void);
                          };
                          class cBusFault
                          {
                          public:
                              static void handler(void);
                          };
                          class cUsageFault
                          {
                          public:
                              static void handler(void);
                          };
                          class cDebugMon
                          {
                          public:
                              static void handler(void);
                          };
                          class cWindowWatchdog
                          {
                          public:
                              static void handler(void);    
                          };
                          class cPvd
                          {
                          public:
                              static void handler(void);    
                          };
                          class cTamperTimeStamp
                          {
                          public:
                              static void handler(void);    
                          };
                          class cRtcWakeup
                          {
                          public:
                              static void handler(void);    
                          };
                          class cFlash
                          {
                          public:
                              static void handler(void);    
                          };
                          class cRcc
                          {
                          public:
                              static void handler(void);    
                          };
                          class cExti
                          {
                          public:
                              static void line0Handler(void);
                              static void line1Handler(void);
                              static void line2Handler(void);
                              static void line3Handler(void);
                              static void line4Handler(void);
                              static void line9Handler(void);
                              static void line15_10Handler(void);
                          };
                          class cDma
                          {
                          public:
                              static void channellHandler(void);    
                              static void channel2Handler(void);    
                              static void channel3Handler(void);    
                              static void channel4Handler(void);    
                              static void channel5Handler(void);    
                              static void channel6Handler(void);    
                              static void channel7Handler(void);    
                          };
                          class cAdc
                          {
                          public:
                              static void handler(void);    
                          };
                          class cDac
                          {
                          public:
                              static void handler(void);    
                          };
                          class cUsb
                          {
                          public:
                              static void highPriorityHandler(void);    
                              static void lowPriorityHandler(void);
                              static void fsWakeupHandler(void);
                          };
                          class cComp
                          {
                          public:
                              static void handler(void);    
                          };
                          class cLcdDriver
                          {
                          public:
                              static void handler(void);    
                          };
                          class cTim9
                          {
                          public:
                              static void handler(void);    
                          };
                          class cTim2
                          {
                          public:
                              static void handler(void);    
                          };
                          class cTim3
                          {
                          public:
                              static void handler(void);    
                          };
                          class cTim4
                          {
                          public:
                              static void handler(void);    
                          };
                          class cTim10
                          {
                          public:
                              static void handler(void);    
                          };
                          class cTim6
                          {
                          public:
                              static void handler(void);    
                          };
                          class cTim7
                          {
                          public:
                              static void handler(void);    
                          };
                          class cTim11
                          {
                          public:
                              static void handler(void);    
                          };
                          class cI2C1
                          {
                          public:
                              static void eventHandler(void);
                              static void errorHandler(void);
                          };
                          class cI2C2
                          {
                          public:
                              static void eventHandler(void);
                              static void errorHandler(void);
                          };
                          class cSpi1
                          {
                          public:
                              static void handler(void);    
                          };
                          class cSpi2
                          {
                          public:
                              static void handler(void);    
                          };
                          class cUart1
                          {
                          public:
                              static void handler(void);    
                          };
                          class cUart2
                          {
                          public:
                              static void handler(void);    
                          };
                          class cUart3
                          {
                          public:
                              static void handler(void);    
                          };
                          class cRtcAlarm
                          {
                          public:
                              static void handler(void);    
                          };
                          typedef void( *intfunc )( void );
                          typedef union { intfunc __fun; void * __ptr; } intvec_elem;
                          // The vector table is normally located at address 0.
                          // When debugging in RAM, it can be located in RAM, aligned to at least 2^6.
                          // If you need to define interrupt service routines,
                          // make a copy of this file and include it in your project.
                          // The name "__vector_table" has special meaning for C-SPY:
                          // it is where the SP start value is found, and the NVIC vector
                          // table register (VTOR) is initialized to this address if != 0.
                          #pragma location = ".intvec"
                          extern "C" const intvec_elem __vector_table[] =
                          {
                            { .__ptr = __sfe( "CSTACK" ) },
                            __iar_program_start,
                          
                            cNMI::handler,
                            cHardFault::handler,
                            cMemManage::handler,
                            cBusFault::handler,
                            cUsageFault::handler,
                            0,
                            0,
                            0,
                            0,
                            vPortSVCHandler,             //функции freeRTOS не трогать!
                            cDebugMon::handler,
                            0,
                            xPortPendSVHandler,          //функции freeRTOS не трогать!
                            xPortSysTickHandler,         //функции freeRTOS не трогать!
                            //External Interrupts
                            cWindowWatchdog::handler,    //Window Watchdog
                            cPvd::handler,               //PVD through EXTI Line detect
                            cTamperTimeStamp::handler,   //Tamper and Time Stamp
                            cRtcWakeup::handler,         //RTC Wakeup
                            cFlash::handler,             //FLASH
                            cRcc::handler,               //RCC
                            cExti::line0Handler,         //EXTI Line 0
                            cExti::line1Handler,         //EXTI Line 1
                            cExti::line2Handler,         //EXTI Line 2
                            cExti::line3Handler,         //EXTI Line 3
                            cExti::line4Handler,         //EXTI Line 4
                            cDma::channellHandler,       //DMA1 Channel 1
                            cDma::channel2Handler,       //DMA1 Channel 2
                            cDma::channel3Handler,       //DMA1 Channel 3
                            cDma::channel4Handler,       //DMA1 Channel 4
                            cDma::channel5Handler,       //DMA1 Channel 5
                            cDma::channel6Handler,       //DMA1 Channel 6
                            cDma::channel7Handler,       //DMA1 Channel 7
                            cAdc::handler,               //ADC1
                            cUsb::highPriorityHandler,   //USB High Priority
                            cUsb::lowPriorityHandler,    //USB Low  Priority
                            cDac::handler,               //DAC
                            cComp::handler,              //COMP through EXTI Line
                            cExti::line9Handler,         //EXTI Line 9..5
                            cLcdDriver::handler,         //LCD
                            cTim9::handler,               //TIM9
                            cTim10::handler,             //TIM10
                            cTim11::handler,             //TIM11
                            cTim2::handler,             //TIM2
                            cTim3::handler,              //TIM3
                            cTim4::handler,              //TIM4
                            cI2C1::eventHandler,         //I2C1 Event
                            cI2C1::errorHandler,         //I2C1 Error
                            cI2C2::eventHandler,         //I2C2 Event
                            cI2C2::errorHandler,         //I2C2 Error
                            cSpi1::handler,              //SPI1
                            cSpi2::handler,              //SPI2
                            cUart1::handler,             //USART1
                            cUart2::handler,             //USART2
                            cUart3::handler,             //USART3
                            cExti::line15_10Handler,     //EXTI Line 15..10
                            cRtcAlarm::handler,          //RTC Alarm through EXTI Line
                            cUsb::fsWakeupHandler,       //USB FS Wakeup from suspend
                            cTim6::handler,              //TIM6
                            cTim7::handler                //TIM7
                          };
                          __weak void cNMI::handler()          { while (1) {} }
                          __weak void cHardFault::handler()    { while (1) {} }
                          __weak void cMemManage::handler()    { while (1) {} }
                          __weak void cBusFault::handler()     { while (1) {} }
                          __weak void cUsageFault::handler()   { while (1) {} }
                          __weak void cDebugMon::handler()     { while (1) {} }
                          __weak void cWindowWatchdog::handler()  { while (1) {} }
                          __weak void cPvd::handler()             { while (1) {} }
                          __weak void cTamperTimeStamp::handler() { while (1) {} }
                          __weak void cRtcWakeup::handler()       { while (1) {} }
                          __weak void cFlash::handler()           { while (1) {} }
                          __weak void cRcc::handler()             { while (1) {} }
                          __weak void cExti::line0Handler()       { while (1) {} }
                          __weak void cExti::line1Handler()       { while (1) {} }
                          __weak void cExti::line2Handler()       { while (1) {} }
                          __weak void cExti::line3Handler()       { while (1) {} }
                          __weak void cExti::line4Handler()       { while (1) {} }
                          __weak void cExti::line9Handler()       { while (1) {} }
                          __weak void cExti::line15_10Handler()   { while (1) {} }
                          __weak void cDma::channellHandler()     { while (1) {} }
                          __weak void cDma::channel2Handler()     { while (1) {} }
                          __weak void cDma::channel3Handler()     { while (1) {} }
                          __weak void cDma::channel4Handler()     { while (1) {} }
                          __weak void cDma::channel5Handler()     { while (1) {} }
                          __weak void cDma::channel6Handler()     { while (1) {} }
                          __weak void cDma::channel7Handler()     { while (1) {} }
                          __weak void cAdc::handler()             { while (1) {} }
                          __weak void cUsb::fsWakeupHandler()     { while (1) {} }
                          __weak void cUsb::highPriorityHandler() { while (1) {} }
                          __weak void cUsb::lowPriorityHandler()  { while (1) {} }
                          __weak void cDac::handler()             { while (1) {} }
                          __weak void cComp::handler()            { while (1) {} }
                          __weak void cLcdDriver::handler()       { while (1) {} }
                          __weak void cTim2::handler()            { while (1) {} }
                          __weak void cTim3::handler()            { while (1) {} }
                          __weak void cTim4::handler()            { while (1) {} }
                          __weak void cTim6::handler()            { while (1) {} }
                          __weak void cTim7::handler()            { while (1) {} }
                          __weak void cTim9::handler()            { while (1) {} }
                          __weak void cTim10::handler()           { while (1) {} }
                          __weak void cTim11::handler()           { while (1) {} }
                          __weak void cI2C1::errorHandler()       { while (1) {} }
                          __weak void cI2C1::eventHandler()       { while (1) {} }
                          __weak void cI2C2::errorHandler()       { while (1) {} }
                          __weak void cI2C2::eventHandler()       { while (1) {} }
                          __weak void cSpi1::handler()            { while (1) {} }
                          __weak void cSpi2::handler()            { while (1) {} }
                          __weak void cUart1::handler()           { while (1) {} }
                          __weak void cUart2::handler()           { while (1) {} }
                          __weak void cUart3::handler()           { while (1) {} }
                          __weak void cRtcAlarm::handler()        { while (1) {} }
                          extern "C" void __cmain( void );
                          extern "C" __weak void __iar_init_core( void );
                          extern "C" __weak void __iar_init_vfp( void );
                          
                          #pragma required=__vector_table
                          void __iar_program_start( void )
                          {
                            __iar_init_core();
                            __iar_init_vfp();
                            __cmain();
                          }
                          


                          image

                          Читать дальше →
                          • +13
                          • 14.3k
                          • 2
                        • STM32, C++ и FreeRTOS. Разработка с нуля. Часть 3 (LCD и Экраны)

                          • Tutorial

                          Введение


                          В двух предыдущих частях STM32, C++ и FreeRTOS. Разработка с нуля. Часть 1 и STM32, C++ и FreeRTOS. Разработка с нуля. Часть 2 мною уже были реализованы требования SR0, SR7, SR4 и SR6. Опять нужно вспомнить, какие вообще требования есть.
                          SR0: Устройство должно измерять три параметра (иметь три переменных): Температуру микропроцессора, Напряжение VDDA, Напряжение с переменного резистора
                          SR1: Устройство должно выводить значение этих переменных на индикатор.
                          SR2: Единицы измерения для Температуры микропроцессора — градусы Цельсия, для остальных параметров — вольты.
                          SR3: При нажатии на кнопку 1, на индикаторе должен показываться экран со следующей измеряемой переменной,
                          SR4: При нажатии на кнопку 1 Светодиод 1 должен изменять свое состояние
                          SR5: При нажатии на кнопку 2, на индикаторе должен поменяться режим отображения переменных с постоянного показывания переменной на последовательное (менять экраны раз в 1.5 секунды) при следующем нажатии с последовательного на постоянное,
                          SR6: При нажатии на кнопку 2 светодиод 2 должен менять свое состояние.
                          SR7: Светодиод 3 должен моргать раз в 1 секунду.

                          Значит остались самые «вкусные» требования связанные c отображением всей измеренной информации на индикаторе: SR1, SR2, SR3, SR5. Ну что же начнем.
                          Читать дальше →
                        • STM32, C++ и FreeRTOS. Разработка с нуля. Часть 2

                          • Tutorial

                          Введение


                          В прошлой публикации STM32, C++ и FreeRTOS. Разработка с нуля. Часть 1 я остановился на том, как уехал на озеро как были релизованы требования SR7, SR4 и SR6. Напомню, какие требования вообще есть для проекта:
                          SR0: Устройство должно измерять три параметра (иметь три переменных): Температуру микропроцессора, Напряжение VDDA, Напряжение с переменного резистора
                          SR1: Устройство должно выводить значение этих переменных на индикатор.
                          SR2: Единицы измерения для Температуры микропроцессора — градусы Цельсия, для остальных параметров — вольты.
                          SR3: При нажатии на кнопку 1, на индикаторе должен показываться экран со следующей измеряемой переменной,
                          SR4: При нажатии на кнопку 1 Светодиод 1 должен изменять свое состояние
                          SR5: При нажатии на кнопку 2, на индикаторе должен поменяться режим отображения переменных с постоянного показывания переменной на последовательное (менять экраны раз в 1.5 секунды) при следующем нажатии с последовательного на постоянное,
                          SR6: При нажатии на кнопку 2 светодиод 2 должен менять свое состояние.
                          SR7: Светодиод 3 должен моргать раз в 1 секунду.
                          Читать дальше →
                        • STM32, C++ и FreeRTOS. Разработка с нуля. Часть 1

                          • Tutorial

                          Введение


                          Не так давно мой отдел столкнулся с трудностями поиска новых инженеров программистов для разработки встроенного ПО. Опытным и умным не нравился уровень зарплаты, а молодых просто нет в нашем городе. Поэтому под патронажем нашей доблестной глобальной компании со штаб квартирой где-то в Сент Луисе, мы начали сначала набирать студентов в интернатуру, а потом, решили пойти другим путем и сделать целых два курса по разработке ПО, а уже там самим выбирать самых “толковых” если понадобятся вдруг новые сотрудники. Это намного дешевле и позволяет охватить максимальное количество претендентов.
                          Немного отступлю от темы, сам я программировал последний раз очень давно, и вообще больше на С#, а последний глобальный проект на микроконтроллере (PIC16 на зыке Си) был сделан в далеком 2007 году.
                          Поэтому мне предстояло разобраться с современными микроконроллерами, языком С++ и операционной системой реального времени.
                          Конечно все наши проекты уже сейчас используют ОСРВ и пишутся на С++, но как разработчик я в них не учувствую, а занимаюсь тунеядством управлением проектами разработки такого ПО.

                          Выбор


                          Времени у меня на все про все было дано 1 месяц. С начала июня 2015 до начала июля 2015, потому что потом я собирался в отпуск, а после отпуска обычно полно работы. Надо было делать все быстро и четко.
                          Немного проконсультировавшись с коллегами, выяснил, что модное направление ARM Cortex различные ядра и из доступных отладочных плат можно заказать Olimex STM32P152 которые стоили 25 долларов. Они пришли очень быстро — 6 плат по цене примерно 2000 рублей. Стоит заметить, что эти платы были закуплены нами для университета, где собственно и будет проходить этот курс.
                          image
                          Читать дальше →
                        • Опыт использования TFS 2010: (Система контроля.Права и Политики)

                            image
                            В прошлый раз, я писал о создании веток, Опыт использования TFS 2010: (Система контроля.Ветки.Создание) и одном из вариантов их иерархии. В этой части я попытаюсь раскрыть работу с системой контроля и более подробно и остановлюсь на средствах контроля доступа к коду в ветках и политики CheckIn.
                            Читать дальше →
                          • Опыт использования TFS 2010: (Система контроля.Ветки.Создание)

                            image
                            Очень часто мне приходится слышать, что система контроля версий от Microsoft это некий костыль, сделанный на скорую руку. Я постараюсь, если не опровергнуть это, то показать, что со своими задачами эта система справляется. И если даже это и костыль, то очень качественный, цветной, функциональный, легкий и понятный в использовании.
                            Читать дальше →