Jump to content

    

Slash

Участник
  • Content Count

    202
  • Joined

  • Last visited

Community Reputation

0 Обычный

About Slash

  • Rank
    Местный

Контакты

  • Сайт
    http://
  • ICQ
    0

Информация

  • Город
    Санкт-Петербург

Recent Profile Visitors

3558 profile views
  1. Цитата(krdmitry @ Feb 1 2018, 22:19) Вашим весомым преимуществом будет подтвержденный опыт в: Командной разработке по методологиям Agile либо Kanban. Как можно подтвердить опыт в разработке по методологиям?
  2. Цитата(Dmitriyspb @ Nov 7 2017, 11:15) Не рекомендую! Расскажите, пожалуйста, если есть какая-то информация. Если я правильно понимаю, то речь идет о предприятии, где делают беспилотник имени рода хищных птиц из подсемейства канюков семейства ястребиных )) Видел статью, где были приведены суммы госзаказов за 2015, 2016 год. Двукратный рост. Не думаю, что есть предпосылки, к тому, что рост не сохраниться. Кому-то эти заказы надо делать. На предприятии (вроде бы) около 500 разработчиков. 10% рост коллектива при таком росте заказов - это не много(на XX.ру висят где-то 40 вакансий разработчиков).
  3. Выпаяйте родной разъем USB и впаяйте гребенку.
  4. Здравствуйте! Сделана плата на основе микроконтроллера. Нужно одновременно поддерживать несколько версий встроенного ПО. Помимо логики работы, версии отличаются инициализацией периферийных модулей. Если с логикой работы более-менее приемлемо получается директивами условной компиляции, то с разными версиями инициализации периферийных модулей не знаю что делать. Если модули обобщать, чтобы они были более гибкими, и в разных версиях просто настраивались по-разному, боюсь, модуль сильно разрастется. И не всегда получается хорошо абстрагировать модуль, чтобы охватывались все варианты. Пока остановился на такой реализации периферии: класс с минимально-необходимым интерфейсом. Кодclass Uart1 { public:     enum Baudrate     {       ...     };     Uart1();     void setBaudrate(Baudrate b);     void write(uint8_t * data, uint32_t size); ... private:     DMA_HandleTypeDef mDmaTx;     UART_HandleTypeDef mUart; ... }; Реализация по месту, без особых обобщений. Кодvoid Uart1::write(uint8_t * data, uint32_t size) {     __HAL_DMA_DISABLE(&mDmaTx);          mUart.Instance->CR3 &= ~USART_CR3_DMAT;     mDmaTx.Instance->CPAR = reinterpret_cast<uint32_t>(&mUart.Instance->TDR);     mDmaTx.Instance->CMAR = reinterpret_cast<uint32_t>(data);          const uint32_t dataLength = size;     mDmaTx.Instance->CNDTR = dataLength;          mUart.Instance->CR3 |= USART_CR3_DMAT;     __HAL_DMA_ENABLE(&mDmaTx); } Если нужна другая инициализация модуля - меняю *cpp файл модуля. Пока думаю, что проект для всех вариантов ПО должен быть один и все версии файлов должны быть в нем. Так вот, что делать с файлами периферии? 1. Можно раскинуть по папкам version1/uart1.cpp version2/uart1.cpp Но не компилируется - объектные файлы с одинаковыми именами. 2. Можно менять им имена в зависимости от версии uart1_ver1.cpp uart1_ver2.cpp И тогда придется еще вводить для каждой версии свое пространство имен, если хочу сохранить имя класса единое. Не эстетично 3. Как-то организовать на уровне системы контроля версий. Пока не понимаю как, при условии, что все версии нужно вести параллельно. 4. Сделать header only файлы периферии. Не очень красиво, не рекомендуют.
  5. Для С++ есть Clang Format. http://format.krzaq.cc/ тут можно поиграть онлайн. Но если переменные называть i, j, k, l, m - тут ничего не поможет. В смысле, все нормально, рабочее место за вами.
  6. Или так на шаблонах (по-русски с подробным объяснением) http://easyelectronics.ru/rabota-s-portami...erov-na-si.html
  7. brag, можете показать реализацию variable element-size queue? Как у меня сделано: очередь выдрана из mbed CODE#include <stdint.h> #include <string.h> #include "cmsis_os.h" #include "mbed_error.h" bool handlerMode() { return __get_IPSR() != 0; } // Очередь с ленивой инициализацией - инициализируется в момент первого использования. // Сделано для обхода проблемы с неопределенным порядком инициализации глобальных объектов. // Очереди создаются глобально и менеджер памяти создается глобально. // Очередь использует выделение памяти в куче, поэтому должна быть создана после менеджера памяти. // Поэтому и сделана ленивая инициализация. // Бывают случаи, когда первое использование очереди происходит в прерывании, что недопустимо. // На этот случай, нужно вызывать метод create() явно, до первого использования. template<typename T, size_t N> class Queue { public: Queue(const char * name = NULL) : mName(name) {} /** Put a message in a Queue. @param data data. @param millisec timeout value or 0 in case of no time-out. (default: 0) @return status code that indicates the execution status of the function. */ bool put(const T & data, uint32_t millisec = 0) { if (!mQueueId) { create(); } portBASE_TYPE taskWoken = pdFALSE; // не понятно, зачем это надо if (handlerMode()) { if (xQueueSendToBackFromISR(mQueueId, reinterpret_cast<const void *>(&data), &taskWoken) == pdTRUE) { portEND_SWITCHING_ISR(taskWoken); return true; } } else { TickType_t ticks = millisec / portTICK_PERIOD_MS; if (ticks == 0) { ticks = 1; } if (xQueueSendToBack(mQueueId, reinterpret_cast<const void *>(&data), ticks) == pdTRUE) { return true; } } return false; } /** Get a message or Wait for a message from a Queue. @param millisec timeout value or 0 in case of no time-out. (default: osWaitForever). @return event information that includes the message and the status code. */ bool hasMessage(uint32_t millisec = osWaitForever) { if (!mQueueId) { create(); } bool hasMessage = false; portBASE_TYPE taskWoken = pdFALSE; if (handlerMode()) { hasMessage = xQueueReceiveFromISR(mQueueId, reinterpret_cast<void *>(&mData), &taskWoken) == pdTRUE; portEND_SWITCHING_ISR(taskWoken); } else { TickType_t ticks = 0; if (millisec == osWaitForever) { ticks = portMAX_DELAY; } else if (millisec != 0) { ticks = millisec / portTICK_PERIOD_MS; if (ticks == 0) { ticks = 1; } } hasMessage = xQueueReceive(mQueueId, reinterpret_cast<void *>(&mData), ticks) == pdTRUE; } return hasMessage; } const T & message() const { return mData; } T & message() { return mData; } size_t spaceAvailable() const { return uxQueueSpacesAvailable(mQueueId); } // нельзя вызывать из прерывания. void create() { // неплохо бы проверять, что мы находимся не в прерывании mQueueId = xQueueCreate(N, sizeof(T)); if (!mQueueId) { error("Error initialising the queue object\n"); } if (mName) { vQueueAddToRegistry(mQueueId, mName); } } private: const char * mName; QueueHandle_t mQueueId; T mData; }; В очередь пихаю свой доморощенный Variant: CODE#include <algorithm> template <size_t N> class Variant { public: Variant() {} template <typename T> Variant(const T & t) { std::copy(reinterpret_cast<const uint8_t *>(&t), reinterpret_cast<const uint8_t *>(&t) + sizeof(mData), mData); } template <typename T> T get() const { return *reinterpret_cast<const T *>(mData); } template <typename T> T * value() { return reinterpret_cast<T *>(mData); } Variant & operator= (const Variant & other) { std::copy(other.mData, other.mData + sizeof(mData), mData); return *this; } float toFloat() const { return get<float>(); } uint32_t toUInt32() const { return get<uint32_t>(); } private: uint8_t mData[N]; }; Использование: CODE struct Message { ... }; typedef Variant<sizeof(Message)> MessageVariant; // знаю, что структура Message самая большая из помещаемых в MessageVariant Queue<MessageVariant, 10> queue; ... if (queue.hasMessage()) { const MessageVariant & msgVar = queue.message(); const Message & msg = msgVar .data().get<Message>(); } Реализация на моем уровне знания шаблонов.
  8. Использовал провод МПО http://tcentr.su/p12883913-provod-montazhnyj-mpo.html Изоляция очень неохотно плавится от паяльника, разноцветный, многожильный, луженый.
  9. Embedded C++.

    Цитата(Jenya7 @ May 23 2016, 15:56) Вы как понимающий знаете что и где колхозить. а что делать начинающему? Учиться. Нужны материалы? Просто С++ - любые 3 хорошие книги (читать в фоне). Со спецификой embedded - мне очень понравилась эта книга https://vk.com/wall-112797241_4 Быстрый старт. 1. Начните использовать ссылки. 2. Начните использовать С++ приведения типов reinterpret_cast, static_cast, const_cast. Запретите себе приведение типов в стиле C. 3. Используйте namespace. 4. Используйте перегрузку функций (если надо конечно). 3. Пробуйте проектировать простые классы. Напишите класс светодиода, пусть плохенький (для начала). Это уже объектно-ориентированный анализ и проектирование, есть отдельные книги. Спрашивайте здесь, как написать класс под ту или иную задачу.
  10. Embedded C++.

    Цитата(AlexandrY @ May 23 2016, 15:06) Строковые типы? В embedded? На Cortex-M4 с сотней килобайт RAM-а на борту? Это очень самоуверенно я вам скажу. Если имеется ввиду std::string, то да, лучше не использовать. Но со строками как-то работать надо, поэтому колхозим свой велосипед: Код#pragma once #include <cstring> #include <string> #include <algorithm> #include <stdio.h> #include <string.h> #include <stdlib.h> namespace mylib{      template <size_t S> struct String {     String()     {         clear();     }          String(const char * str)     {         clear();         copy(str);     }          size_t size() const     {         return S;     }          // количество символов в буфере, исключая терминирующий \0     size_t occupied() const     {         return std::char_traits<char>::length(buf);     }          void clear()     {         std::fill(buf, buf + S, 0);     }          bool contains(const char * str) const     {         return std::strstr(buf, str) != NULL;     }          String<S> & operator=(const char * str)     {         copy(str);         return *this;     }              char buf[S];      private:     // копируем по указателю str символов не более (размер нашей строки - 1).     // если копируемая строка меньше (размер нашей строки - 1), остаток добивается \0     void copy(const char * str)     {         size_t size = std::min(S - 1, std::char_traits<char>::length(str));         std::char_traits<char>::copy(buf, str, size);     }     }; } Класс добивается своими методами по потребностям. Можно полностью содрать интерфейс с std::string. Если встречу хорошо написанный класс строки, с удовольствием выкину свою поделку
  11. Embedded C++.

    Цитата(Jenya7 @ May 22 2016, 10:49) Я хочу выучить С++ под ембедед. Подскажите какие нибудь он лайн курсы или другой материал. Хотелось бы также посмотреть готовые проекты на С++ чтоб прочувствовать все аспекты. С++ в embedded обычный, поэтому изучайте по любой книге. Специфика embedded в ограниченности ресурсов, поэтому нужно отчетливо понимать "сколько стоит" та или иная языковая конструкция. К примеру, RTTI - тяжелая вещь, ее не применяют в первую очередь (хотя можно, если хочется). https://vk.com/wall-112797241_4 https://vk.com/wall-112797241_104?w=away-112797241_104 https://vk.com/wall-112797241_147
  12. Цитата(addi II @ May 20 2016, 08:29) Вот устанавливал qt-opensource-windows-x86-msvc2013_64-5.5.1 и галки нигде не снимал Т.к. вы выбрали msvc2013, в комплекте с Qt не шел компилятор. Его нужно установить отдельно (Visual C++ Compiler). И в настройках его прописать. Тут нужно не ошибиться с версий компилятора, точно не помню, то ли устанавливать точно 2013 года, то ли можно самый новый. Но, рекомендую установить пакет qt-opensource-windows-x86-mingw492-5.5.1.exe. Там уже идет компилятор в комплекте. Все настраивается. В прошлый раз я неправильно показал, какую галку нужно ставить - та галка просто предкомпилированные компоненты. Вот картинки 2-х установщиков, первый c MinGW, второй с MSVC. Обратите внимание, что во втором случае компилятора нет. Галка с компилятором MinGW по умолчанию НЕ стоит.
  13. Скачайте offline установщик с сайта qt. При установке не снимайте галок с компилятора, и все установится нормально. В настройках у вас должно быть примерно так, как на картинке.
  14. Сделать SD-карту Read-Only. Для этого настраиваете демон логгирования rsyslogd (или используете другой, если настройки не позволяют), чтобы он писал логи на ваш NAS. Отключаете swap файл или перенаправляете его на NAS. В общем, все, что должно писать на SD-карту или отключаете или перенаправляете на NAS. Делаете карту read-only.
  15. примеры под stm32tpl

    Цитата(SergNK @ May 3 2016, 11:09) А для завязки подкину задачку. Есть на шине I2C память и ЖК-индикатор. Драйвер I2C должен быть общим. А его должны юзать драйверы устройств: lcd и mem. Подскажите, как это сделать в scmRTOS из разных задач. Как вариант, сделать владельцем драйвера I2C одну задачу. Общение с драйвером должно вестись сообщениями через очередь. Привожу почти псевдокод такого общения. КодQueue<Message, 10> queue; // создали очередь из 10 элементов типа Message void i2cTask(const void * arg) {     I2c i2c(SCL, SDA); // создаем объект класса I2c     const uint8_t memoryAddr = 0x62;     MemoryI2c memory(i2c, memoryAddr); // создаем объект класса MemoryI2c, который использует I2C в качестве интерфейса доступа к памяти     const uint8_t screenAddr = 0x72;     ScreenI2c screen(i2c, screenAddr);          while (true)     {         if (queue.hasMessage()) // если есть сообщение         {             const Message & msg = queue.message(); // выбираем сообщение из очереди             switch (msg.id()) // определяем назначение данных             {             case MemorySave:                 const Data data = msg.data();                 memory.save(data);                 break;             case MemoryLoad:                 const Data data = memory.load();                 someQueue.put(data);                 break;             case Screen:                 ...                 screen.send(...);                 break;             }         }     } } Конечно, это не вариант на все случаи жизни. Как часто нужно работать с памятью? Может достаточно редко, и все время будет занято экраном. И мьютексы будут не нужны.