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

Как я накололся с stm32f10x.h

Видать "Всемогущие гуру" хотели еще что-нить в скобочках...вписать :biggrin:

И как бы оно {в скобочках} работало после ; ? :w00t:

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


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

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

//не в тему

 

Столкнулся недавно с "библиотекой" для AD9837 на сайте AD

Я уж было свою наполовину написал, но решил приобщиться к культуре :)

Так Mihai & Bogdan там такого накуралесили..

void AD9837_SetRegisterValue(unsigned short regValue)
{
    unsigned char data[5] = {0x03, 0x00, 0x00};    
    
    data[1] = (unsigned char)((regValue & 0xFF00) >> 8);
    data[2] = (unsigned char)((regValue & 0x00FF) >> 0);
    ADI_CS_LOW;        
    SPI_Write(data,2);
    ADI_CS_HIGH;
}

//кончаю оффтоп

Похоже, место индусов потихоньку занимают славяне :)

А индусы - продвинулись до CEO MS

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


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

..Так Mihai & Bogdan там такого накуралесили....

 

исторически сложённый похоже.

в опен исходниках такое часто встречается... этим они и отличаются от боевых, коммерческих = нет повышенного

контроля (читай бездельников менагеров), и отсутствие тотального тестирования. У большинства когорты

потребителей(читай программистов) подход какой? хэлох-ты мир пишет, значит можно юзать. с возгласами ух-ты!!!

а вот то, что какое то состояние может выплыть нечаянно и всё встанет совсем поперёк - ну то через пару лет может

и аукнуться на каком-то проценте изделий...

 

к примеру - сейчас немного перетряхиваю lwip - так там так-же встречаются пёрлы. порой заметна даже разная кисть "мастера".

что поделать :)))

 

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


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

В библиотеку не хожу. Не хочу пользоваться. У меня - просто, понятно...

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

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


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

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

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

/*!****************************************************************************
*
@brief		System Clock STM32F100RBT6B initialize
@details	Установить тактовую частоту 24MHz
@param		
@return	
@note		Вызывается в startup.s
*/
void SystemInit(void) {

/* Задать начальное состояние (как после сброса) */
 RCC->CR = 0x00000083;		// HSI On, HSITRIM = 0x80
 RCC->CFGR = 0x00000000;	// HSI oscillator used as system clock
 RCC->CIR = 0x001F0000;	// Reset and disable all interrupts

/* Включить HSE генератор
  Счетчик таймаута старта HSE генератора, загружается числом из stm32f10x.h
  Ждать готовности генератора или окончания таймаута */
 uint32_t StartCount = HSE_STARTUP_TIMEOUT;
 RCC->CR |= RCC_CR_HSEON;
 while (--StartCount && !(RCC->CR & RCC_CR_HSERDY)) { }

/* Если HSE генератор включился (таймаут не вышел) */
 if (StartCount) {

/* Конфигурировать SYSCLK, HCLK, PCLK2, PCLK1, ADCPRE
  Задать коэффициенты деления частоты */
   RCC->CFGR = 
RCC_CFGR_SW_0		* 0 |	// SW[1:0] bits (System clock Switch): HSI
RCC_CFGR_HPRE_0		* 0 |	// HPRE[3:0] bits (AHB prescaler): SYSCLK / 1 = 24 MHz (max)
RCC_CFGR_PPRE1_0	* 0 |	// PRE1[2:0] bits (APB1 prescaler): HCLK / 1 = 24 MHz (max) 
RCC_CFGR_PPRE2_0	* 0 |	// PRE2[2:0] bits (APB2 prescaler): HCLK / 1 = 24 MHz
RCC_CFGR_ADCPRE_0	* 0 |	// ADCPRE[1:0] bits (ADC prescaler): PCLK2 / 2 = 12 MHz (max)
RCC_CFGR_PLLSRC		* 1 |	// PLL entry clock source: PREDIV1
RCC_CFGR_PLLXTPRE	* 1 |	// HSE divider for PLL entry: / 2 (4 MHz)
RCC_CFGR_PLLMULL_0	* 4 |	// PLLMUL[3:0] bits (PLL multiplication factor): * 6 = 24 MHz
RCC_CFGR_MCO_0		* 7 ;	// MCO[2:0] bits (Microcontroller Clock Output): PLL / 2 = 12 MHz

/* Пределитель для PLL, не обязательно
  Младший бит совпадает с RCC_CFGR_PLLXTPRE */
   RCC->CFGR2 = 
RCC_CFGR2_PREDIV1_0	* 1 ;	// PREDIV1 input clock divided by 2

/* Включить PLL (и защиту HSE от сбоев, если нужно)
  Ждать, пока нет готовности PLL */  
   RCC->CR |= 
RCC_CR_PLLON		* 1 |	// PLL enable
RCC_CR_CSSON		* 1 ;	// Clock Security System enable
   while (!(RCC->CR & RCC_CR_PLLRDY)) { }

/* Выбрать PLL как источник системной частоты
  Ждать, пока PLL не выберется как источник системной частоты */
   RCC->CFGR |= RCC_CFGR_SW_0	* 2 ;	// System clock Switch: PLL
   while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) { }

/* Выключить внутренний генератор HSI */
   RCC->CR &= ~RCC_CR_HSION;
 }

/* Если HSE генератор не запустился, работать от HSI */
}

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


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

RCC->CR = 0x00000083; // HSI On, HSITRIM = 0x80

RCC->CFGR = 0x00000000; // HSI oscillator used as system clock

RCC->CIR = 0x001F0000;

 

"Магические цифры" - тоже не "особенный" вариант. Потом начинаешь мучительно вспоминать, где чего и когда это было :laughing:

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


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

"Магические цифры" - тоже не "особенный" вариант. Потом начинаешь мучительно вспоминать, где чего и когда это было :laughing:

Это взято из мануала, состояние после сброса. Оно не особенно и нужно. Будет работать и без этого.

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


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

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

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

 

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


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

Если хотите очевидного, продемонстрируйте инициализацию порта, например. Желательно, с ассемблерным листингом. И укажите, для какого MCU. А после я покажу свой способ. :)

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


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

Если хотите очевидного, продемонстрируйте инициализацию порта, например. Желательно, с ассемблерным листингом.

  
/* GPIOD Periph clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);

  /* Configure PD0 and PD2 in output pushpull mode */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOD, &GPIO_InitStructure);

На счет листинга - сейчас нет возможности сделать.

MCU - STM32F103

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

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


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

Для STM32F100, 103. Такты задаю раньше, одной командой для всех устройств.

/*! Port bit configuration table */
typedef enum {
 IN_ANAL, GO_PP10, GO_PP02, GO_PP50,  // Input Analog, GP Output Push-pull 10-2-50MHz
 IN_FLOA, GO_OD10, GO_OD02, GO_OD50,  // Input Float*, GP Output Open-drain 10-2-50MHz
 IN_PDPU, AO_PP10, AO_PP02, AO_PP50,  // Input Pull-down/Pull-up, Alt Func Push-pull
 CM_NONE, AO_OD10, AO_OD02, AO_OD50   // none(illegal), Alt Func Open-drain 10-2-50MHz
} CONF_MODE;

/*!****************************************************************************
*
@brief		Port Low/High byte configuration
@details	Конфигурация байтов порта целиком
@param		PORT - имя порта (A..G)
@param		CM00..CM15 - конфигурация битов 0..15
@note		Используется перечисляемый тип CONF_MODE
@note		Для IN_PDPU нужный pull-down/pull-up задается в ODR
*/
#define GPIO_CONF(PORT,								\
CM00, CM01, CM02, CM03,							\
CM04, CM05, CM06, CM07,							\
CM08, CM09, CM10, CM11,							\
CM12, CM13, CM14, CM15);						\
GPIO##PORT->CRL = ((uint32_t)						\
CM00 <<  0 | CM01 <<  4 | CM02 <<  8 | CM03 << 12 |			\
CM04 << 16 | CM05 << 20 | CM06 << 24 | CM07 << 28);			\
GPIO##PORT->CRH = ((uint32_t)						\
CM08 <<  0 | CM09 <<  4 | CM10 <<  8 | CM11 << 12 |			\
CM12 << 16 | CM13 << 20 | CM14 << 24 | CM15 << 28);

#define GPIO_CONFL(PORT,							\
CM00, CM01, CM02, CM03,							\
CM04, CM05, CM06, CM07);							\
GPIO##PORT->CRL = ((uint32_t)						\
CM00 <<  0 | CM01 <<  4 | CM02 <<  8 | CM03 << 12 |			\
CM04 << 16 | CM05 << 20 | CM06 << 24 | CM07 << 28);

#define GPIO_CONFH(PORT,							\
CM08, CM09, CM10, CM11,							\
CM12, CM13, CM14, CM15);							\
GPIO##PORT->CRH = ((uint32_t)						\
CM08 <<  0 | CM09 <<  4 | CM10 <<  8 | CM11 << 12 |			\
CM12 << 16 | CM13 << 20 | CM14 << 24 | CM15 << 28);

/*!****************************************************************************
*
@brief		Bit of Low/High byte Port configuration
@details	Конфигурация одиночного бита порта
@param		PORT - имя порта (A..G)
@param		BIT - номер бита (0..15)
@param		CM - конфигурация бита
@note		Используется перечисляемый тип CONF_MODE
@note		Для IN_PDPU нужный pull-down/pull-up задается в ODR
*/
#define GPIO_CONFB(PORT, BIT, CM)						\
*(uint32_t *)((uint32_t)(GPIO##PORT) + BIT / 8 * 4) = 			\
*(uint32_t *)((uint32_t)(GPIO##PORT) + BIT / 8 * 4)			\
	& (~(0xF << (BIT % 8) * 4)) | (CM << (BIT % 8) * 4)

/* GPIO */
 GPIO_CONF(A,
IN_FLOA, IN_FLOA, IN_FLOA, IN_FLOA,	// User_Key, _ , _ , _
IN_ANAL, IN_ANAL, IN_FLOA, IN_FLOA,	// DAC-1, DAC-2, _ , _
AO_PP50, IN_FLOA, IN_FLOA, IN_FLOA,	// MCO, _ , _ , _ , _
IN_FLOA, IN_FLOA, IN_FLOA, IN_FLOA);

А вот листинг

;;;371    /* GPIO */
;;;372      GPIO_CONF(A,
00000e  49e1              LDR      r1,|L1.916|
000010  48df              LDR      r0,|L1.912|
000012  6008              STR      r0,[r1,#0]
000014  1d09              ADDS     r1,r1,#4
000016  48e0              LDR      r0,|L1.920|
000018  6008              STR      r0,[r1,#0]
;;;373        IN_FLOA, IN_FLOA, IN_FLOA, IN_FLOA,    // User_Key, _ , _ , _
;;;374        IN_ANAL, IN_ANAL, IN_FLOA, IN_FLOA,    // DAC-1, DAC-2, _ , _
;;;375        AO_PP50, IN_FLOA, IN_FLOA, IN_FLOA,    // MCO, _ , _ , _ , _
;;;376        IN_FLOA, IN_FLOA, IN_FLOA, IN_FLOA);

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


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

от стандартных CMSIS предпочитаю не отказыватся, типа

- stm32fxxx.c

- system_stm32f2xx.c

- core_cm3.c

Всё равно стартап вызывается только один раз вначале программы.

 

А вот STM32Fxxx_StdPeriph_Driver ( типа библиотеки GPIO, RCC, DMA ) стараюсь не использовать. Иногда проще пару битов вручную выставить, и тем самым Flash экономиить на пару килобайт.

Вы скажете, флеша и так хватает у STM? Это правда, но в режиме отладки, прошивка быстрее грузится в камень))) :smile3046:

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


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

Для STM32F100, 103. Такты задаю раньше, одной командой для всех устройств.

/*! Port bit configuration table */

typedef enum {...

В принципе, нормально. Только может значения CONF_MODE переименовать, чтобы было понятнее? А то IN_ANAL как-то режет глаз ;) Да и AO_PP02 менее понятно, чем GPIO_Speed_50MHz.

Иногда, в проекте под каждый датчик/исполнительное устройство есть отдельный файл, а то и несколько. Как в этом случае задавать настройки: какие порты и другие ресурсы контроллера будут использоваться этим датчиком? Если это делать в заголовочном (*.h) файле самого датчика, то иногда возникают ситуации, когда одни и те же ресурсы используются одновременно несколькими устройствами. Меня подмывает перенести все дефайны распределения ресурсов в один заголовочный файл. Стоит так делать?

Может есть что-нибудь вроде "Best practices in embedded systems programming" для начинающих? Посоветуйте.

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


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

В принципе, нормально. Только может значения CONF_MODE переименовать, чтобы было понятнее? А то IN_ANAL как-то режет глаз ;) Да и AO_PP02 менее понятно, чем GPIO_Speed_50MHz.

Иногда, в проекте под каждый датчик/исполнительное устройство есть отдельный файл, а то и несколько. Как в этом случае задавать настройки: какие порты и другие ресурсы контроллера будут использоваться этим датчиком? Если это делать в заголовочном (*.h) файле самого датчика, то иногда возникают ситуации, когда одни и те же ресурсы используются одновременно несколькими устройствами. Меня подмывает перенести все дефайны распределения ресурсов в один заголовочный файл. Стоит так делать?

Может есть что-нибудь вроде "Best practices in embedded systems programming" для начинающих? Посоветуйте.

Пусть режет. Автору виднее! Каждый думает в меру своей распущенности. На некоторых импортных осциллографах выход калибратора назывался "CAL".

У меня все настройки всего - это одна функция, не такая уж и большая. Правда, USB там нет.

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


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

Меня подмывает перенести все дефайны распределения ресурсов в один заголовочный файл. Стоит так делать?

Я так делаю. Именно потому что ноги процессора мультиплексируются и нужно смотреть, чтобы не пересекался функционал.

В cmsis сделана настройка ног из соответствующих модулей. На мой взгляд, это неудобно и чревато хитрыми багами.

 

По поводу оптимизации инициализации ног. Считаю, что бороться за чистоту листинга и прочую оптимизацию при первоначальной настройке ног нет никакого смысла. Сколько бы она тактов не съела, делается настройка один раз и больше на производительность кода не влияет.

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


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

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

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

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

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

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

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

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

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

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