STM32 новичку в ARM что к чему

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="Oxford",url="/forum/viewtopic.php?p=3905447#p3905447"]VladislavS Да я всегда так и делаю. И ты так же сделаешь возьмешь мануал и будешь ебошить. :tea: Так все программируют. Только я сразу ебошу напрямую и не пишу говнолибу.[/uquote]Только я предпочитаю два раза в один мануал не лазить. Ну вот маршрут разработки на примере микросхем EEPROM 24Сxxx. Определим её интерфейс. Что ей надо для работы? Порт I2C, функция задержки чтобы паузу между записью страниц делать, конкретный тип микросхемы в серии и адрес. Халява, сэры, пишем шаблон

Код: Выделить всё

template<typename TI2C, typename TDelay, EEType eeType, uint8_t HW_ADR>
class EE_24C
{
  //...
};
Реализуем в нём функции чтения и записи согласно мануалу. Да, без него никуда не денешься. Один раз.
А дальше, там где мне эта микросхема нужна будет, можно быстро её использовать.

Код: Выделить всё

#define EE_HW_ADR 0     //Адрес заданный ножками A2,A1,A0

// Привязываем EEPROM к конкретному контроллеру
using EEPROM = EE_24C<I2C::i2c1<I2CTiming::SysCLK_1MHz>, 
                      TDelay<uint32_t(TIM2_BASE)>, 
                      EEType::AT24C512, 
                      EE_HW_ADR>;

// Используем по назначению
if(uint8_t tmp; EEPROM::ReadByte(EE_NET_ADR,&tmp))
{
  if((tmp>0)&&(tmp<255)) 
    uart.SetNetAdr(tmp);
  else 
    uart.SetNetAdr(DEFAULT_PPM_P_ADR);
}
else
  uart.SetNetAdr(DEFAULT_PPM_P_ADR);
Реклама
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="Oxford",url="/forum/viewtopic.php?p=3905436#p3905436"]А еще отладка и анализ кода C++[/uquote]
Что отладка и анализ кода? В С++ типизация на порядок выше, в простейшем случае можно написать:

Код: Выделить всё

Periph::enableClock(AhbPeriph::Gpios | AhbPeriph::Dma1);
Если шины разные, то еще до получения ошибки компиляции IDE красным пораскрашивает, а на С и регистрах можно объединить периферию висящую на APB1 и APB2, а затем записать это все в регистр для AHB, что периодически начинающие и делают.
а еще долгая компиляция C++ кофе можно попить пока компилит более менее проект
Очередные страшилки. У меня в одном проекте на этапе компиляции генерится таблица размеров 70KB, что должно быть не так и быстро, ведь по сути этот код интерпретируется, но если сгенерить эту таблицу и подключить как хедер, то компиляция будет еще медленнее.
а еще то что на разной платформе по разному C++ может работать и поддержка C++ не всеми компиляторами, тогда как ANSI С утюг поддерживает.
Проблемы возможны, даже для ARM есть среды в которых gcc и clang поставляются с кастрированными С++ либами, то же касается AVR, там похоже другого gcc и не существует. В то же время такого любителя как я совершенно не беспокоит тот факт, что помимо gcc 9 мой код нигде не соберется :) А VladislavS наоборот использует разные компиляторы и просто в плане поддержки стандартов находится немного позади.
Реклама
Друг Кота
Сообщения: 6457
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

[uquote="AVI-crak",url="/forum/viewtopic.php?p=3905308#p3905308"]Да причём тут весь порт?[/uquote]
Порт, как некое известное количество пинов, чтобы было, что сравнивать. При сравнении пересчитываем накладные расходы на инициализацию порта тем или иным способом.
У меня функция для инициализации одного контакта - универсальная, весом 212 байт. Именно столько она занимает в прошивке.
К этому добавляются еще две команды вызова этой функции на каждый пин. По итогу набегает прилично.
Когда я говорю что невозможно допустить ошибку - я имею в виду именно этот факт (там просто нет других вариантов).
От всех ошибок это не уберегает. Глаз может замылиться, рука дрогнуть и из списков вместо нужного выбора можно сделать ошибочный.
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="a5021",url="/forum/viewtopic.php?p=3905485#p3905485"]К этому добавляются еще две команды вызова этой функции на каждый пин.[/uquote]
К двум командам добавляется еще 4-х байтовая константа которую они читают из флеша, итого 8 байт на пин.
Реклама
Эиком - электронные компоненты и радиодетали
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Вот ещё один простенький случай. Датчик температуры ADT7410. Мне от него нужно только чтение температуры в целых градусах. Как всегда, формализуем интерфейс. Ему надо порт I2C и адрес на шине. Ещё большая халява, сэры. Пишем шаблон :)

Код: Выделить всё

template<typename TI2C=I2C::i2c1, uint32_t num=0>
struct TADT7410
{
  TADT7410(){}
  static inline bool Read_1gradlsb(int8_t *data)
  {    
    uint8_t tmp[2];
    if( TI2C::ReadReg(hw_adr,(uint8_t)0x00, tmp, (uint8_t)2) )      
    {
      *data = Convert2Grad((tmp[0]<<8) + tmp[1]);
      return true;
    }
    else return false;
  }          
  //Преобразовать считанное значение в целые градусы
  static inline int8_t Convert2Grad(uint16_t x)
  {
    if(x&0x8000)
      return ((x>>3)-8192)>>4; //Отрицательная температура
    else
      return x>>7; // Положительная температура
  }
  
  static_assert(num<4,"Only 0...3 ADT7410 numbers");
  static constexpr uint8_t hw_adr = 0x90 + ((num&0x3)<<1);
};
И вдруг понимаем, что этих датчиков надо по максимуму навешать. Задействуем два порта I2C, доступных в контроллере. По 4 на порт.

Код: Выделить всё

using T0 = TADT7410<I2C::i2c1,0>;
using T1 = TADT7410<I2C::i2c1,1>;
using T2 = TADT7410<I2C::i2c1,2>;
using T3 = TADT7410<I2C::i2c1,3>;
using T4 = TADT7410<I2C::i2c2,0>;
using T5 = TADT7410<I2C::i2c2,1>;
using T6 = TADT7410<I2C::i2c2,2>;
using T7 = TADT7410<I2C::i2c2,3>;
И используй по назначению. А мало будет 8 датчиков, можно сделать I2C ногодрыгом и точно так же прицепим ещё кучу датчиков. Класс датчика даже не заподозрит такого подвоха.
Реклама
Друг Кота
Сообщения: 6457
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

[uquote="Reflector",url="/forum/viewtopic.php?p=3905482#p3905482"]а на С и регистрах можно объединить периферию висящую на APB1 и APB2, а затем записать это все в регистр для AHB, что периодически
начинающие и делают.[/uquote] Не ведаю, где вы таких начинающих находите, т.к. нужно иметь глаза на жопе, чтобы в регистр RCC->AHBENR начать заталкивать определения RCC_ABP1ENR_xxx, например.

Где-то с полтора назад я кидал сюда скрипт на питоне, который на входе принимает название регистра и имя заголовочного файла, а на выходе выдает полную его инициализацию в виде, скажем

Код: Выделить всё

  RCC->APB1ENR = (
    0 * RCC_APB1ENR_TIM2EN       | /*  0x00000001 Timer 2 clock enabled         */
    0 * RCC_APB1ENR_TIM3EN       | /*  0x00000002 Timer 3 clock enable          */
    0 * RCC_APB1ENR_WWDGEN       | /*  0x00000800 Window Watchdog clock enable  */
    0 * RCC_APB1ENR_USART2EN     | /*  0x00020000 USART 2 clock enable          */
    0 * RCC_APB1ENR_I2C1EN       | /*  0x00200000 I2C 1 clock enable            */
    0 * RCC_APB1ENR_CAN1EN       | /*  0x02000000 CAN1 clock enable             */
    0 * RCC_APB1ENR_BKPEN        | /*  0x08000000 Backup interface clock enable */
    0 * RCC_APB1ENR_PWREN        | /*  0x10000000 Power interface clock enable  */
    0 * RCC_APB1ENR_TIM4EN       | /*  0x00000004 Timer 4 clock enable          */
    0 * RCC_APB1ENR_SPI2EN       | /*  0x00004000 SPI 2 clock enable            */
    0 * RCC_APB1ENR_USART3EN     | /*  0x00040000 USART 3 clock enable          */
    0 * RCC_APB1ENR_I2C2EN       | /*  0x00400000 I2C 2 clock enable            */
    0 * RCC_APB1ENR_USBEN          /*  0x00800000 USB Device clock enable       */
  );
Нужно несколько секунд, чтобы получить шаблон под инициализацию любого регистра любого камня. Ошибиться невозможно.

[uquote="VladislavS",url="/forum/viewtopic.php?p=3905318#p3905318"]Хейтеров не слушайте, они в паре битов ошибаются.[/uquote]
И когда такой случай наблюдался в последний раз?

[uquote="VladislavS",url="/forum/viewtopic.php?p=3905410#p3905410"]Хорошо вам, чип один и тот же, код тоже - ксерь себе да ксерь. А тут и чипов целый зоопарк и проектов ни одного похожего.[/uquote]
Вообще, более-менее приличный проект -- это не быстрое занятие. Мож с год, а то и не один. "Зоопарк" же свидетельствует скорее о игре в бирюльки -- схватили одно, бросили, схватили в другое и так без конца.
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="a5021",url="/forum/viewtopic.php?p=3905500#p3905500"]Не ведаю, где вы таких начинающих находите[/uquote]Да тут же на форуме. Сколько раз уже было: "Cемён Семёныч, куда же я смотрел!"

[uquote="a5021",url="/forum/viewtopic.php?p=3905500#p3905500"]И когда такой случай наблюдался в последний раз?[/uquote]
Да вот, автор считает, что порт на выход сконфигурил, в комментарии же написано...

[uquote="a5021",url="/forum/viewtopic.php?p=3905500#p3905500"]Вообще, более-менее приличный проект -- это не быстрое занятие. Мож с год, а то и не один.[/uquote]В наше время это непозволительная роскошь. Заказчик хочет здесь и сейчас. Мы АФАР за 9 месяцев разрабатываем, а за год локатор. Вот для этого соответствующий инструментарий и нужен, иначе с битами действительно заковыряешься.

[uquote="a5021",url="/forum/viewtopic.php?p=3905500#p3905500"]"Зоопарк" же свидетельствует скорее о игре в бирюльки -- схватили одно, бросили, схватили в другое и так без конца.[/uquote]Или о широком спектре разрабатываемых изделий. В тот же космос на F103 не полетишь. Да и за брошенное изделие денег не получишь.
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="a5021",url="/forum/viewtopic.php?p=3905500#p3905500"]Не ведаю, где вы таких начинающих находите, т.к. нужно иметь глаза на жопе, чтобы в регистр RCC->AHBENR начать заталкивать определения RCC_ABP1ENR_xxx, например.[/uquote]
Постоянно на форумах с таким сталкиваюсь, причем не обязательно иметь дело напрямую с регистрами, HAL/SPL функции от подобных ошибок тоже не уберегут, достаточно взглянуть на прототип:

Код: Выделить всё

void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
Периферия передается как uint32_t, потому что, допустим, (RCC_APB2Periph_TIM1 | RCC_APB1Periph_TIM2) имеет тип int, даже если изначально речь шла о типах двух разных перечислений. В С++ есть строгие перечисления которые к int автоматически не приводятся, к сожалению '|' для них не работает, но есть перегрузка операторов и шаблоны, с ними можно добавить данный оператор для любых типов. Также есть концепты, они позволяют ограничить такую перегрузку только перечислениями и, наконец, есть перегрузка функций, она позволяет не указывать название шины в имени функции, т.к. ошибиться можно и здесь. В итоге получаем функцию которая если компилируется, то гарантированно работает. А где же классы? Правильно, все вышеперечисленное работает и на уровне простых функций, С++ - это далеко не только классы.
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Reflector, вот это сейчас cложно было для тех кто не варится в С++ :( Выстрел в молоко :)
Друг Кота
Сообщения: 6457
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3905515#p3905515"]Да вот, автор считает, что порт на выход сконфигурил, в комментарии же написано...[/uquote]
Вот этот код?

Код: Выделить всё

GPIOB->CRL |= GPIO_CRL_MODE4_1; // PORTB.4 OUTPUT 2MHz
По вашему это не выход? Нда-с.
Вот для этого соответствующий инструментарий и нужен, иначе с битами действительно заковыряешься.
Сказки не рассказывайте. Заинитить железо -- это пустяк на фоне прикладных алгоритмов. Негде там заковыряться.
В тот же космос на F103 не полетишь.
В космос только на F7 ?
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="a5021",url="/forum/viewtopic.php?p=3905531#p3905531"]

Код: Выделить всё

GPIOB->CRL |= GPIO_CRL_MODE4_1; // PORTB.4 OUTPUT 2MHz
По вашему это не выход? Нда-с.[/uquote]Конечно нет. Без знания CNF как это можно утверждать?

[uquote="a5021",url="/forum/viewtopic.php?p=3905531#p3905531"]Сказки не рассказывайте. Заинитить железо -- это пустяк на фоне прикладных алгоритмов. Негде там заковыряться.[/uquote]А кто только про инит говорит? Последнюю страницу перечитайте. Но где-то же вы годами ковыряетесь? Не я же про года писал.

[uquote="a5021",url="/forum/viewtopic.php?p=3905531#p3905531"]В космос только на F7 ?[/uquote]Опять же, если почитать последние страницы, то там примеры с космического проца пару раз проскакивали. Только тсссс, это тайна :)
Прорезались зубы
Аватара пользователя
Сообщения: 202
Зарегистрирован: Сб янв 09, 2016 15:51:17

Сообщение AVI-crak »

[uquote="a5021",url="/forum/viewtopic.php?p=3905485#p3905485"]
Когда я говорю что невозможно допустить ошибку - я имею в виду именно этот факт (там просто нет других вариантов).
От всех ошибок это не уберегает. Глаз может замылиться, рука дрогнуть и из списков вместо нужного выбора можно сделать ошибочный.[/uquote]
Шанс создания ошибки разный, а шанс обнаружения ошибки намного выше вашего варианта. Мой вариант заточен под использование внутренней периферии, та самая часть в вашем варианте выглядит как магия. Вам для проверки потребуется открытие мануала, а у меня и так видно.

Ага, маниакально посчитали все мои затраты на вызов несчастной функции, ну а теперь посмотрите на свой вариант - так-же пристально. От момента размещения констант в регистрах ядра мк - до вызова функции. В этом плане мне особенно нравятся функции хала, там сначала долго и упорно ногами избивают стек, а после вызывают функцию.
Контактная информация:
Друг Кота
Сообщения: 6457
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3905549#p3905549"]Конечно нет. Без знания CNF как это можно утверждать?[/uquote]
Я не знаю, каким таинственным способом идентифицируют выход секретные космические разработчики, но выход здесь определяется содержимым битов MODE, а не CNF. Похоже, вы со всего размаху ударили лицом в грязь. Обличитель, блин. Так обосраться...

предупреждение за хамство. В следующий раз длительный бан. FAKIR.
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Битами CNF можно задать режим AF, который не обязательно выход.
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

В режиме AF направлением вывода управлеяет периферийный модуль, к которому этот вывод привязан. Вот, например, на FSMC шина данных двунаправленная, вопреки тому что в бите MODE стоит.
Изображение
Изображение
fsmc1.png
(47.92 КБ) 560 скачиваний
fsmc2.png
(49.05 КБ) 552 скачивания
Друг Кота
Сообщения: 6457
Зарегистрирован: Пт сен 13, 2013 13:11:31

Сообщение a5021 »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3905748#p3905748"]В режиме AF направлением вывода управлеяет периферийный модуль, к которому этот вывод привязан.[/uquote]
Не надо сову на глобус, Славик. Не поможет. Пункт "9.1.11 GPIO configurations for device peripherals":

Изображение

Читать умеете?

Даже если периферия умеет реверсировать линии, порт конфигурируется, как OUTPUT/PUSH-PULL.

п 2-3 бан - 7дней за хамство после предупреждения. FAKIR.
Вложения
fsmc.jpg
(22.35 КБ) 537 скачиваний
Опытный кот
Аватара пользователя
Сообщения: 819
Зарегистрирован: Вт окт 23, 2012 13:17:25
Откуда: Прокопьевск

Сообщение Oxford »

Ну и все че если надо AF значит конфигуришь AF че еще надо то? или чтобы пару строк написать нужно C++ изучать? :))) ему обьясняешь что достаточно пару строк, а он тебе говорит, нет надо C++ и портянки

FAKIR ты только банить можешь? ну обосрался чел значит обосрался, хамства тут нет

STM32F030

Код: Выделить всё

int ini_timer1(void)
{
 	GPIOA->MODER &= ~GPIO_MODER_MODER6;
  GPIOA->MODER |= GPIO_MODER_MODER6_1; 
	GPIOA->AFR[0]  |= _VAL2FLD(GPIO_AFRL_AFSEL6, 1); 
	
	RCC->APB1ENR |= RCC_APB1ENR_TIM3EN | RCC_APB1ENR_TIM14EN;
	
	TIM14->PSC = 8-1;
	
  NVIC_EnableIRQ(TIM3_IRQn);
	
	TIM3->PSC = 8-1;
	TIM3->CCMR1 |= TIM_CCMR1_CC1S_0; 
	TIM3->CCER |= TIM_CCER_CC1P; 
	
	TIM3->CCMR1 |= TIM_CCMR1_CC2S_1; 
	
	
	TIM3->SMCR |= TIM_SMCR_TS_0 | TIM_SMCR_TS_2; 
	TIM3->SMCR |= TIM_SMCR_SMS_2; 
                                
	TIM3->CCER |= TIM_CCER_CC1E; 
	TIM3->CCER |= TIM_CCER_CC2E; 
	
	TIM3->SMCR |= TIM_SMCR_MSM; 
                          
	TIM3->CCR3 = 15000;
	TIM3->CCR4 = 48000;
	
	TIM3->DIER |= TIM_DIER_CC1IE;
	TIM3->DIER |= TIM_DIER_CC2IE;
	TIM3->DIER |= TIM_DIER_CC3IE;
	TIM3->DIER |= TIM_DIER_CC4IE;
	
	TIM3->SR = 0;
	TIM3->CR1 |= TIM_CR1_CEN;
}
Порты в этом коде 3 строки, остальное настройка таймеров для аппаратного декодирования. у плюсов от этого кода плохого станет, тут одни регистры непонятные. :tea:
Инженер R@D

Telegram чат: https://t.me/radiowolf или в поиске приложения @radiowolf. Личка:@cncoxford
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="Oxford",url="/forum/viewtopic.php?p=3905800#p3905800"]или чтобы пару строк написать нужно C++ изучать?[/uquote]Вам не надо. А тем кто хочет что-то больше знать и уметь стОит попробовать. Лишним оно всё равно не будет. Не зайдёт в эмбедде, так на компе пригодится.

[uquote="Oxford",url="/forum/viewtopic.php?p=3905800#p3905800"]:))) ему обьясняешь что достаточно пару строк, а он тебе говорит, нет надо C++ и портянки[/uquote]Реальные программы никогда не состоят из пары строк. Но чтобы показать на форуме сильные стороны даже и пары строк бывает достаточно. В раельной программе эффект усиливается с её ростом. А "портянки" это точно не ко мне, я как раз за лаконичность и читаемость кода.
Опытный кот
Аватара пользователя
Сообщения: 819
Зарегистрирован: Вт окт 23, 2012 13:17:25
Откуда: Прокопьевск

Сообщение Oxford »

Ну напиши мой код на C++ читаемо и лаконично, пока я другой проект прогаю. :tea: Хоть полюбуюсь.
Мк программироваться должен и исполнять нужный функционал. А не красотой блестать:tea: Профессионализм не от красоты зависит.

Весь проект у меня составил 2272 байта, хотя на борту 16кб флеша (stm32f030f4p6), аппаратное декодирование NEC пульта и эмуляция команд с другим протоколом. При этом я не думал экономить какие то байты никогда это не делал.
Последний раз редактировалось Oxford Пн окт 12, 2020 22:29:07, всего редактировалось 1 раз.
Инженер R@D

Telegram чат: https://t.me/radiowolf или в поиске приложения @radiowolf. Личка:@cncoxford
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="Oxford",url="/forum/viewtopic.php?p=3905800#p3905800"]у плюсов от этого кода плохого станет, тут одни регистры непонятные. :tea:[/uquote]Вот иж испугал регистрами. На плюсах разве не в регистры пишется? В них же, только вместо шифрограмм можно один раз сделать осмысленное задание режимов работы того же таймера и пользоваться по человечески.
Ответить

Вернуться в «ARM»