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

ViKo,

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

А вообще люди пишут свои USB библиотеки, TCP стеки, Оси, да что там говорить - компиляторы пишут :biggrin: . Так что на этом фоне работать с регистрами это не такой уж страшный велосипед (или фобия).

Изменено пользователем kan35

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Конкретно указанная выше функция занимет 70 байт.

Я наверное просто лопнул бы от счастья сьекономить на ней 10-20 байт....

Когда я начинал программировать STM32F103, инициализация с использованием библиотеки заняла у меня что-то около 2,7 KB. Меня это удивило.

 

Ваша функция adc_init() занимет 70 байтов? Не желаете ли сделать еще одно усилие, и посчитать в листинге? Было бы интересно узнать, сколько же заняла.

Моя ADC_init() заняла 80 байтов.

 

P.S. Но примечательно другое - я написал сообщение вчера днем.

И за весь вечер и все утро не нашлось ни одного человека. который бы чем-то помог.

На это есть очевидная причина. :)

 

Так что на этом фоне работать с регистрами это не такой уж страшный велосипед (или фобия).

Так это мне в плюс или в минус? :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это плюс несомненно.

А вообще, вы задавались вопросом "почему появились библиотеки периферии" - очень просто: периферия стала жутко сложная, регистры 32 битные - битов дополна. И программировать их напрямую как минимум долго, неудобно и надо постоянно рыться в референсмануале на 1000 страниц. Некоторым головастым и рукастым мужикам это вполне подсилу и они непринужденно лопатят горы информации. А таким как мне на это уйдет куча времени и сил. И за несколько лет не встретилось мне еще задачи где потребовалась бы прямая работа с регистрами.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Лично я не сталкивался (не помню), но на форуме проскакивали сообщения, где говорилось про ошибки в библиотеке. А чтобы найти такие ошибки, придется и по функциям пройтись, и по регистрам. Вот это, действительно, кошмар.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это плюс несомненно.

А вообще, вы задавались вопросом "почему появились библиотеки периферии" - очень просто: периферия стала жутко сложная, регистры 32 битные - битов дополна. И программировать их напрямую как минимум долго, неудобно и надо постоянно рыться в референсмануале на 1000 страниц.

 

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

 

О сложностях, кстати.

Да, периферия стала сложная поэтому не надо ее еще усложнять дополнительными абстракциями.

Для меня, например, не постижимо по названию функции TIM2_Init понять зачем она нужна и что делает.

Запомнить ее назначение можно только постоянно с ней имея дело (вынужденно, поскольку дольше приходится писать инициализацию) и детально просмотрев ее код, поскольку здесь нет ничего интуитивно понятного.

Гораздо проще найти в мануале описание таймера где все регистры описаны на паре страниц, и записать этот десяток регистров используя битовые маски.

 

Заимствовать исходники нужно когда они выполняют действительно объемные задачи.

А здесь пару строк записи в регистры заменяют огромными библиотеками.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А здесь пару строк записи в регистры заменяют огромными библиотеками.

Меня эти ST-шные "библиотеки" тоже раздражают. Сделано не слишком умно, против принципа Оккама идут - умножают сущности сверх необходимого. Особенно если нужно подсмотреть пример кода, который иллюстрирует какую-нибудь особенность работы аппаратуры - пока эту гору мусора перелопатишь и уяснишь интересующий момент...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для меня, например, не постижимо по названию функции TIM2_Init понять зачем она нужна и что делает.

Запомнить ее назначение можно только постоянно с ней имея дело (вынужденно, поскольку дольше приходится писать инициализацию) и детально просмотрев ее код, поскольку здесь нет ничего интуитивно понятного.

Гораздо проще найти в мануале описание таймера где все регистры описаны на паре страниц, и записать этот десяток регистров используя битовые маски.

Резонное замечание. Однако для того, чтобы впадать в отчаяние видя гору функций с непонятными именами (хотя на мой взгляд достаточно понятными) можно обратиться к примерам, которые включены в библиотеку, а так же включен пустой шаблон (template) от которого можно быстро стартовать. В этих примерах разобраны наиболее востребованные режимы работы периферии, например, для ADC приведено кажется более 10 способов обслуживания. Просто копируете оттуда нужный код и его модифицируете.

Библиотека selfdocumented и с помощью "go to definition" можно быстро прыгнуть к поснению.

Есть еще мощная штука - "Find in files" :-) - быстро все ставит на свои места

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

static void uart_init_rcc(uart_t* const uart)
{
switch ((uint32_t)uart->sfr)
{
	case USART1_BASE: RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); break;
	case USART2_BASE: RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); break;
	case USART3_BASE: RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); break;
#ifdef USART4
	case USART4_BASE: RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART4, ENABLE); break;
#endif

#ifdef USART5
	case USART5_BASE: RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART5, ENABLE); break;
#endif
	default: return;
}

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);  // Enable AFIO clock
}

static void uart_init_nvic(uart_t* const uart)
{
switch ((uint32_t)uart->sfr)
{
	case USART1_BASE: NVIC_EnableIRQ(USART1_IRQn); break;
	case USART2_BASE: NVIC_EnableIRQ(USART2_IRQn); break;
	case USART3_BASE: NVIC_EnableIRQ(USART3_IRQn); break;
#ifdef USART4
	case USART4_BASE: NVIC_EnableIRQ(USART4_IRQn); break;
#endif

#ifdef USART5
	case USART5_BASE: NVIC_EnableIRQ(USART5_IRQn); break;
#endif
	default: return;
}
}

Работа с GPIO у меня полностью своя, кочующая из проекта в проект, независимо от архитектуры контроллера.

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

А что то до экономии пары сотен байт байт то это смешно. И аргументы насчёт непонятных названий библиотечный функций тоже для меня не понятны...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А почему все зациклились на инициализации? Разве библиотека не навязывает использование ее же в обработчиках прерываний и вообще в любой точке кода, в которой нужно обращение к периферии? Интересно узнать от использующих библиотеку, во что выливается библиотечная функция чтения флага прерывания? Во что выливается сброс флага или двух флагов? Без библиотеки я знаю, чего мне это стоит:

 151:././../common/rf/transmitter.cpp ****         DMA1->IFCR = DMA_IFCR_CHTIF3 | DMA_IFCR_CTCIF3;
1027                      .loc 1 151 0
1028 003c 3C4B             ldr    r3, .L76+8    @ tmp165,
1029 003e 4FF4C062         mov    r2, #1536    @ tmp166,
1030 0042 5A60             str    r2, [r3, #4]    @ tmp166, MEM[(struct DMA_TypeDef *)1073872896B].IFCR

Могу ли я позволить себе тут полноценный вызов функции с подготовкой ее параметров и прочими накладными расходами? Наверное конкретно в этом случае могу, даже несмотря на то, что это обработчик прерывания. Но этот вызов будет лишь способствовать глобальному потеплению. А где-то эта лишняя задержка может уже существенно ударить по энергопотреблению или производительности конечного устройства. Полагаю, что все эти наши споры происходят лишь по одной причине - если бы обращения к библиотеке компилировались бы в такие же обращения к регистрам без лишних накладных расходов, то противников библиотеки практически не осталось бы. Я бы сам первый начал ее использовать. И чем больше людей бы ее использовали, тем быстрее в ней нашлись бы все (почти:) ) ошибки. Но пока добавляемые библиотекой накладные расходы лично для меня неприемлемы.

Кстати, будет интересно посмотреть, во что выливается DMA1->IFCR = DMA_IFCR_CHTIF3 | DMA_IFCR_CTCIF3; при использовании библиотеки.

 

P.S. Вообще все эти войны С/Асм, С/С++, Регистры/библиотека очень напоминают замечательный мультик: http://www.youtube.com/watch?v=JMJXvsCLu6s...player_embedded

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А почему все зациклились на инициализации? Разве библиотека не навязывает использование ее же в обработчиках прерываний и вообще в любой точке кода, в которой нужно обращение к периферии?
Мне она ничего не навязывает, флаги в прерываниях я без неё дёргаю, а всю инициализацию с ней. Так дело обстоит именно по озвученной вами причине. Писатели этой библиотеки не самые хорошие программисты, но как-то приходится с этим жить (свои костыли подставлять по мере реальной необходимости).

А мультик отличный! :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

__INLINE void TestPinOn(void)    { GPIOD->BSRRL = GPIO_Pin_15; }      // 1=on, 
__INLINE void TestPinOff(void)   { GPIOD->BSRRH = GPIO_Pin_15; }    // 0=off
__INLINE void TestPinToggle(void){ GPIOD->ODR  ^= GPIO_Pin_15; }

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

__INLINE void TestPinOn(void)    { GPIOD->BSRRL = GPIO_Pin_15; }      // 1=on, 
__INLINE void TestPinOff(void)   { GPIOD->BSRRH = GPIO_Pin_15; }    // 0=off
__INLINE void TestPinToggle(void){ GPIOD->ODR  ^= GPIO_Pin_15; }

Уууу.... Макросы имени Аскольда Волкова вам в помощь и гугл тоже:-)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Уууу.... Макросы имени Аскольда Волкова вам в помощь и гугл тоже:-)

А что "Уууу"?

Надо выход изменить - записал в OUTSET/OUTCLR нужного порта число.

Зачем тут макросы? Сахар это? Нет?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тот кто привык щи лаптем хлебать того уже более прогрессивным прибором не заманишь к столу.

Без обид...

 

Вы внимательнее ознакомьтесь с этими макросами и возможно осознаете всю их прелесть.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Уууу.... Макросы имени Аскольда Волкова вам в помощь и гугл тоже:-)

 

Я и без гугла в курсе, но мне так удобнее.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...