Slash 0 19 декабря, 2016 Опубликовано 19 декабря, 2016 · Жалоба Здравствуйте! Сделана плата на основе микроконтроллера. Нужно одновременно поддерживать несколько версий встроенного ПО. Помимо логики работы, версии отличаются инициализацией периферийных модулей. Если с логикой работы более-менее приемлемо получается директивами условной компиляции, то с разными версиями инициализации периферийных модулей не знаю что делать. Если модули обобщать, чтобы они были более гибкими, и в разных версиях просто настраивались по-разному, боюсь, модуль сильно разрастется. И не всегда получается хорошо абстрагировать модуль, чтобы охватывались все варианты. Пока остановился на такой реализации периферии: класс с минимально-необходимым интерфейсом. 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 И тогда придется еще вводить для каждой версии свое пространство имен, если хочу сохранить имя класса единое. Не эстетично :rolleyes: 3. Как-то организовать на уровне системы контроля версий. Пока не понимаю как, при условии, что все версии нужно вести параллельно. 4. Сделать header only файлы периферии. Не очень красиво, не рекомендуют. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 20 декабря, 2016 Опубликовано 20 декабря, 2016 · Жалоба 1. Можно раскинуть по папкам version1/uart1.cpp version2/uart1.cpp Но не компилируется - объектные файлы с одинаковыми именами. Не включайте в проект не относящиеся к нему директории. Ибо даже если вы дадите файлам разные имена и оно у вас скомпилируется - не пройдет линковка, ведь у вас в этих файлах функции с одинаковыми названиями. 3. Как-то организовать на уровне системы контроля версий. Пока не понимаю как, при условии, что все версии нужно вести параллельно.Я совсем недавно пришел к такой системе - в одном репозитории хранится общий для многих проектов код - заголовочные файлы CMSIS, исходники scmRTOS, lwIP, реализация AES-декодирования для загрузчика, какие-то специфичные файлы, использующиеся более чем в одном проекте. Проекты хранятся в других репозиториях, каждый проект состоит из директорий common (общие для этого железа файлы), bootloader, application. В application может быть несколько директорий для разных вариантов ПО. Общий репозиторий я подключаю как внешний (svn:externals) в директорию common. А дальше уже в makefile подключаю к проекту только те директории, которые мне нужны в этом проекте. При этом в общем репозитории у меня лежит generic_uart.cpp с реализацией неизменных функций, а на уровне проекта у меня есть файл uart.cpp с реализацией недостающих функций под конкретный проект. И если у меня УАСПП во всех исполнениях ПО инициализируются одинаково, то я делаю один uart.cpp с функцией uart::init(), кладу его в common/uart и подключаю ее к проекту. Если в каком-то одном исполнении или в загрузчике мне нужна другая инициализация - то я кладу другой uart.cpp в директорию bootloader или application/variant1 и убираю из makefile этой прошивки подключение common/uart. Еще вариант - в общем репозитории хранится класс generic_uart, а в проекте - отнаследованный от него uart, у которого добавлена функция init. Третий вариант - в общем репозитории класс generic_uart делается шаблоном, параметр шаблона используется как базовый класс. А уже этот базовый класс реализуется в каждом конкретном проекте - таким образом я использую два варианта dma (потоки и каналы) в исходниках для разных stm32. Да, в процессе перевода на эту систему кучи проектов с большим количеством почти одинакового кода пришлось несколько раз довольно радикально "перетрахивать" структуру директорий этого общего репозитория и править под нее по несколько раз уже переведенные проекты (и этот процесс еще не закончен), но я доволен - теперь при исправлении какой-либо ошибки в общем коде мне не нужно вспоминать, в каком еще проекте использовался этот код и править эту же ошибку там - достаточно просто обновиться в очередном проекте и все правки общего репозитория подтягиваются автоматически. При фиксации стабильной версии в tags я делаю правку в svn:externals, указывая там текущую на момент фиксации версию внешнего общего репозитория. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 20 декабря, 2016 Опубликовано 20 декабря, 2016 · Жалоба Я совсем недавно пришел к такой системе - ... Легко Вам - пишете всё под один МК. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardEgor 64 20 декабря, 2016 Опубликовано 20 декабря, 2016 · Жалоба Сделана плата на основе микроконтроллера. Нужно одновременно поддерживать несколько версий встроенного ПО. Помимо логики работы, версии отличаются инициализацией периферийных модулей. Если у вас всё такое разное - то не вижу смысла усложнять, делайте отдельные каталоги для каждого проекта и всё. А так вы усложняете код множеством условных директив и запутываете поддержку. Возможно какие-то общие алгоритмы стоит вынести в отдельные файлы и всё. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DogPawlowa 0 24 декабря, 2016 Опубликовано 24 декабря, 2016 · Жалоба Легко Вам - пишете всё под один МК. Какая разница? У меня есть в одном воркспейсе два проекта под разные контроллеры одного семейства, есть в двух воркспейсах два проекта, использующие общие файлы, для разных контроллеров разных семейств. Что касается директив условной компиляции, то стараюсь не злоупотреблять, если зашкаливает, делаю разные файлы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 0 24 декабря, 2016 Опубликовано 24 декабря, 2016 · Жалоба Легко Вам - пишете всё под один МК. Какая разница? У меня достаточно похоже, на то, что описал Сергей. Но, например, проект над которым вот прямо сейчас работаю, собирается из достаточно большого количества общих исходников и заголовков на: 1) Cortex-M3 1) ARM7 2) BA2 3) M8C 4) PC/Win 5) PC/Lin При этом ARM7 - две железки BA2 - 2 железки и 6 (пока только)вариантов софта M8C - два варианта софта Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться