Перейти к содержанию

Darth Vader

Участник
  • Публикаций

    70
  • Зарегистрирован

  • Посещение

Репутация

0 Обычный

Информация о Darth Vader

  • Звание
    Участник

Посетители профиля

134 просмотра профиля
  1. Пришлось-таки использовать директивы. Чтобы скрыть компиляторозависимую часть кода - обернул её макросом. Пока что определил только часть для Кейла. Когда понадобится использовать код в других IDE с другими компиляторами - надо будет взамен #error определить соответствующие директивы размещения. #include <stdint.h> // Простая структура для примера struct MyConfig_st { uint8_t Field1; uint8_t Field2; uint8_t Field3; }; #define CONFIG_ADR 0x1E800 // Адрес структуры конфигурации в памяти EEPROM // Макрос атрибута размещения объекта по адресу ADR_VAL #if defined ( __CC_ARM ) // for ARM Compiler #define __AT_ADDR(ADR_VAL) __attribute__((at(ADR_VAL))) #elif defined ( __ICCARM__ ) // for IAR Compiler #error __AT_ADDR(ADR_VAL) не определён для компилятора IAR! #elif defined ( __GNUC__ ) // for GNU Compiler #error __AT_ADDR(ADR_VAL) не определён для компилятора GNU! #elif defined ( __TASKING__ ) // for TASKING Compiler #error __AT_ADDR(ADR_VAL) не определён для компилятора TASKING! #elif defined ( __CMCARM__ ) // for Phyton CMC-ARM Compiler #error __AT_ADDR(ADR_VAL) не определён для компилятора Phyton CMC-ARM! #else #error __AT_ADDR(ADR_VAL) не определён для используемого компилятора! #endif // Объявляем и инициализируем константную структуру конфигурации по адресу CONFIG_ADR const MyConfig_st MyConfig __AT_ADDR(CONFIG_ADR) ={0x66,0x41,0x7};
  2. 2018 Вопросы начинающих

    Нет. Есть такой тип компонентов - перемычки (Jumper). Если конт. площадки на одной ПП внутри заготовки соединить с такими же на другой ПП и назначить им Type=Jumper и одинаковое ненулевое значение JumperID, то Альтиум будет знать, что они соединены внешним проводом - перемычкой. Тогда никакого конфликта или ошибок не будет.
  3. 2018 Вопросы начинающих

    Нет. Это будут 3 проекта: два PCB- проекта, и один проект мультиборд. Причем у каждого из PCB-проектов будет своя схема. А то, что я имею ввиду, это один PCB-проект с одной схемой со сквозной нумерацией компонентов (она может состоять из нескольких листов), элементы которой раскиданы по двум или более печатным платам. Причем эти платы в проекте присутствуют именно в виде PCB, а не в виде ссылок на другие PCB-проекты. И нумерация компонентов на них полностью соответствует схеме.
  4. 2018 Вопросы начинающих

    Возможно, это не то, о чём был вопрос. А может и оно. Это появился новый тип проектов - прибор (или устройство). Т.е. несколько электрически и механически связанных между собой PCB, ЭРИ, соединителей, жгутов/проводов. Полезная штука. В предыдущих версиях этого не хватало. Из-за этого приходилось схему всего прибора делать, как PCB-проект, содержащий только листы схем без PCB. А функциональные блоки ( в т.ч. печатные платы) изображать прямоугольниками с контактными площадками (соединителями), чисто графически. Естественно, возможностей для автоматической проверки и выявления ошибок такого проекта было мало. А вопрос, возможно, был в том, что концепция PCB-проекта Альтиума - это один проект - одна печатная плата. А не появилась ли в 18 версии возможность результатом одного PCB-проекта иметь более одной печатной платы? Типа, раскидать схему на две PCB, а затем сделать из них склейку, связав цепи на платах перемычками из проводов?
  5. Для описанной задачи этого не требуется. Всё, что надо для этого знать я сообщил компилятору двумя макросами: #define CONFIG_ADR 0x20000 // Адрес стр-ры конфигурации в памяти EEPROM #define MyConfig_ptr ((MyConfig_st*)CONFIG_ADR) // Указатель на стр-ру конфигурации в памяти EEPROM и описанием типа (структуры) MyConfig_st. От языка/компилятора требуется лишь поддержка инициализации объекта по указателю на него (тот самый (MyConfig_st*)CONFIG_ADR ). А с этим, как оказалось, засада. Указатель создать можно. Его можно использовать в коде для обращения к объектам: записи/чтения в/из них значений. На этом принципе построено обращение ко всем регистрам периферии. Но вот инициализировать объект по нему списком инициализации почему-то оказалось нельзя. По имени объекта можно, а по указателю на него нельзя. Было бы можно - задача решилась бы. Жаль.
  6. Что-то типа такого? #include <stdint.h> // Простая структура для примера struct MyConfig_st { uint8_t Field1; uint8_t Field2; uint8_t Field3; }; #define CONFIG_ADR 0x20000 // Адрес стр-ры конфигурации в памяти EEPROM #define MyConfig_ptr ((MyConfig_st*)CONFIG_ADR) // Указатель на стр-ру конфигурации в памяти EEPROM // Заполнение стр-ры значениями // S - указатель на стр-ру // F1, F2, F3 - значения полей void MyConfigInic (MyConfig_st* S,uint8_t F1,uint8_t F2,uint8_t F3) { S->Field1 = F1; S->Field2 = F2; S->Field3 = F3; } uint8_t tmp; // Сюда будем считывать данные из стр-ры int main () { // Присваиваем значение полям стр-ры MyConfigInic (MyConfig_ptr,0x66,0x41,0x7); // Считываем значения полей стр-ры tmp = MyConfig_ptr->Field1; // Прочитали значение 0x66 tmp = MyConfig_ptr->Field2; // Прочитали значение 0x41 tmp = MyConfig_ptr->Field3; // Прочитали значение 0x7 } Такое нормально сработает, если область размещения стр-ры будет в ОЗУ. При вызове функции MyConfigInic() с указателем на стр-ру и значениями для заполнения полей произойдёт присваивание полям стр-ры новых значений из аргументов ф-ции. Далее с полями стр-ры можно будет работать, обращаясь к ним через указатель. Но если стр-ра должна размещаться в области флеш-памяти, т.е. там же, где и код программы, то такой код не сможет инициализировать стр-ру данными. Простое присваивание данным во флеш-памяти новых значений не запишет там ничего.
  7. А есть ли стандартный, т.е. не выходящий за синтаксис С/С++ способ инициализации объекта по точно указанному адресу? Под объектом понимается объект данных любого типа - простого встроенного или составного пользовательского. Например целое число, перечисление, массив или структура. Вот пример кода, где объявляется и инициализируется константная структура с тремя полями данных. Из неё можно считывать данные - см. в main(). Но адрес её размещения в памяти выбирает линкер. #include <stdint.h> // Некая структура для примера struct MyConfig_st { uint8_t Field1; uint8_t Field2; uint8_t Field3; }; // Инициализация константной структуры const MyConfig_st MyConfig = {.Field1=0x66,.Field2=0x41,.Field3=0x7}; uint8_t tmp; // Сюда будем считывать данные структуры int main () { tmp=MyConfig.Field1; tmp=MyConfig.Field2; tmp=MyConfig.Field3; while(1); } Как штатными средствами C/C++ задать для этой структуры точный адрес? Я могу сделать указатель на неё и присвоить ему значение адреса при помощи приведения типа целого к указателю на структуру. Но инициализировать структуру по такому указателю я не могу. На строку с инициализацией компилятор (Keil Arm Compiler V5.06) ругается. #include <stdint.h> // Некая структура для примера struct MyConfig_st { uint8_t Field1; uint8_t Field2; uint8_t Field3; }; #define CONFIG_ADR 0x20000 // Адрес стр-ры конфигурации в памяти EEPROM #define MyConfig_ptr ((MyConfig_st*)CONFIG_ADR) // Указатель на стр-ру конфигурации в памяти EEPROM // Объявляем и инициализируем стр-ру в памяти EEPROM const MyConfig_st *MyConfig_ptr = {.Field1=0x66,.Field2=0x41,.Field3=0x7}; // Компилятор ругается !!! int main() { while(1); } Есть ли возможность сделать такое без использования директив размещения, которые в разных IDE и компиляторах/линкерах разные? Хотелось бы написать универсальный код, одинаково работающий везде, вне зависимости от среды разработки и компилятора.
  8. 2018 Вопросы начинающих

    Вход обратной связи (он же подстроечный, он же регулировочный) - это именно вход. Так что тип его in (или passive). Но уж точно не out (выход) и не power (цепи питания). А вход и выход линейного стабилизатора напряжения - они хотя для него являются in и out, но для всей прочей схемы это power. Так что скорее всего, лучше присвоить им тип power.
  9. 2018 Вопросы начинающих

    Их не так много: ЭСЛ, ТТЛ, ТТЛШ, N-MOS (N-МОП), CMOS (КМОП). Большинство современных российских и белорусских серий ИМС, таких, как 1554, 1564, 1594, 5584 изготавливаются по КМОП технологии. ИМС с повышенной стойкостью к воздействию спецфакторов - по КНИ (или КНС - это то же самое). Это те же структуры из КМОП-транзисторных ячеек, но на подложке из изолятора (сапфира). Из современных микросхем ТТЛ - серия 1533. Из названия следует, что MOS (МОП или МДП - это одно и то же). Это английская аббревиатура для полевого транзистора со структурой металл-окисел (диэлектрик)-полупроводник. Все современные ключевые/переключательные/импульсные полевые транзисторы - с индуцированным каналом - чтобы при напряжении затвор-исток близком к нулю транзистор был закрыт.
  10. 2018 Вопросы начинающих

    Правый нижний угол - клик на панель Design Compiller - в раскрывшемся списке ставьте галку на Navigator. Появится панель навигатора в которой будут видны все компоненты и цепи.
  11. отладка в Keil

    Спасибо. Так, вероятно, проще всего. И понятней. Сразу виден алгоритм: сначала зануляем всё битовое поле целиком ((reg) & ~(msk)), после чего выставляем в нем 1 в нужных разрядах ( | ((val) << (pos) & (msk)) ).
  12. отладка в Keil

    С макросом оказалось всё немного сложнее. При введении в него промежуточной переменной tmp появилась необходимость указывать её тип. Он должен совпадать с типом reg. А т.к. он в общем случае разный и заранее неизвестный, то придётся его вводить одним из параметров макроса. Как-то так // Макрос записи в регистр reg битовой последовательности val // в позицию pos (по младшему разряду), msk - маска битового поля #define TuneBitField(typename,reg,val,pos,msk) \ do { \ typename tmp=reg; \ tmp |= (((val) << (pos))&(msk)); \ tmp &= (((val) << (pos))|~(msk)); \ reg=tmp; \ } while (0) В С++ этот макрос можно (а скорее нужно) переоформить в виде шаблонной подставляемой (inline) функции, где параметром шаблона как раз и будет имя типа регистра reg, а аргументом функции будет ссылка на регистр, чтобы его содержимое можно было изменить. Второй вариант выхода из ситуации (для Си без плюсов) - переписать макрос без использования промежуточной переменной, приведя его к виду: do {reg=(reg&msk1)|msk2;} while (0) // Макрос записи в регистр reg битовой последовательности val // в позицию pos (по младшему разряду), msk - маска битового поля #define TuneBitField(reg,val,pos,msk) \ do { \ reg = ((reg)&(((val) << (pos)))|~(msk))|(((val) << (pos))&(msk)); \ } while (0)
  13. отладка в Keil

    Да, ошибся. Проверил. Действительно, выдаёт ошибку. Это он не ругается на ; после блока в конструкциях вида: operator1; { operator2; operator3; }; operator4; while (SomeExpr1) { if (SomeExpr2) { operator1; operator2; }; } хотя ; после } там не нужна. Возможно, он воспринимает ; после } как пустой оператор, поэтому и не имеет ничего против.
  14. отладка в Keil

    Так и есть. Лучше давать таким константам осмысленные имена. Так и читается легче и вносить изменения в код проще. Компактна - да, возможно, в некоторых случаях. Но далеко не всегда и не везде. Что компактней: в некотором регистре установить какой-то бит в 1 (сбросить бит в 0) или вызвать функцию с 2-3 параметрами? В обоих случаях это будет одна строка кода. Наглядна - нет. Если бы библиотеки делали код менее наглядным их бы не писали в принципе. А библиотеки как раз и пишутся для повышения наглядности. Они повышают уровень абстракции. Работая с регистрами вам надо знать не только "что делать", но и "как это делать" - какие битовые поля в каких регистрах в какие значения установить. Работая с библиотекой надо знать лишь "что делать". Вопрос "как это сделать" библиотечная функция взяла на себя. Она сама внутри своего тела оперирует регистрами, битами, их позициями в регистрах, сдвигами и масками битовых полей. Снаружи ничего этого не видно и знать не нужно. Не сокращает и не повышает. Но если надо сделать что-то, чего не умеют библиотечные функции, либо сделать то, что могут и они, но как-то по-другому - то для этого пишутся свои функции. Специализированные, под конкретные задачи. Точно, вспомнил - из-за точки с запятой. Просто компилятор Кейла допускает конструкцию типа { }; и не ругаются на неё, связывая идущий после этого else с последним if. Так что забыл про этот неприятный момент, хотя и читал про это ранее (забыл уже где).
  15. отладка в Keil

    Согласен с замечанием. Так лучше? // Макрос записи в регистр reg битовой последовательности val в позицию pos (по младшему разряду) // msk - маска битового поля #define TuneBitField(reg,val,pos,msk) \ do { \ tmp=reg; \ (tmp) |= (((val) << (pos))&(msk)); \ (tmp) &= (((val) << (pos))|~(msk)); \ reg=tmp; \ } while (0); А здесь - не могу представить себе пример кода, когда обрамляющие фигурные скобки (блок {} ) работают хуже (да просто не точно так же), как конструкция do {} while (0); Приведите пример, если можете.