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

ViKo, не слушайте АНТОХА, его аргументация всегда через одно место сделана. Иначе не умеет.

 

Класс AbstractPin создан не просто так. Он необходим для возможности передавать экземпляры пинов в другие модули (по ссылке, разумеется). Например, для автоматически привязки на нужную Alternative функцию.

Вот пример:

Hardware::SerialPortUSART6 serialPort;

Hardware::Pin<PC6> pinTX;
Hardware::Pin<PC7> pinRX;
          
....
          
	serialPort.initialize();
...
      
	serialPort.setPinTx(pinTX);
	serialPort.setPinRx(pinRX);
...
    serialPort.run();

 

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


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

Ладно, с "местами" - ничья. Ваши взаимные отношения не остались без внимания общественности. :prankster2: Поговорили. 

Мне бы по моим мелким вопросикам просветиться.

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


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

11 minutes ago, ViKo said:

И не создаются функции в main.c, когда там использую. По паре nop вижу. Я очень плохо понимаю весь этот синтаксис. В чем ошибки?

Потому что нельзя просто так умножать на true/false. В данном случае для компилятора просто нет никакой разницы между HsAdc_tm<true, true> и HsAdc_tm<false, false>;

Перепишите HsAdc_tm так, чтобы исключить такие вещи. Например, явно внутри проверяя s1 и s2 через свои if.

Не страшно что будет чуть-больше текста, зато подобные ошибки будут сразу видны. Компилятор умеет все нормально оптимизировать, не пытайтесь делать это за него ;)

 

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


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

На unsigned s1 и s2 (0, 1) тоже не может умножать inline, что ли?

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


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

6 minutes ago, ViKo said:

На unsigned s1 и s2 (0, 1) тоже не может умножать inline, что ли?

Так у вас 

template <bool s1, bool s2>

зы. Кстати, понять по этому шаблону, что именно делают s1 и s2 без поллитра не получится :mda:

 

Если у вас всего четыре ADC и явно прописаны названия функций, то не вижу смысла городить огород из в целом не читаемого шаблона, когда внутри HsAdc1_select и остальных можно сразу явно вызывать GpioLowHigh_set с нужными параметрами. Выходной код будет такой же по объему. Но читать это будет гораздо проще.

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


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

21 минуту назад, ViKo сказал:

Это все в main.h. На последние 4 выдается:

Source\main.h(146): warning:  #174-D: expression has no effect
        HsAdc_tm<true, false>;

И не создаются функции в main.c, когда там использую. По паре nop вижу. Я очень плохо понимаю весь этот синтаксис. В чем ошибки?

Скобочки надо, это же функция, её нужно вызывать:

HsAdc_tm<false, false>();

И я не вижу, где вы используете класс Pin_st. Он как-то сам по себе, а остальные функции - сами по себе.

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


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

	Pin_st <'B', 13> Adc1s_n;
	Pin_st <'B', 14> Adc2s_n;

Получилось. Для

    HsAdc1_select();
    HsAdc2_select();
    HsAdc_select();
    HsAdc_deselect();

С оптимизацией O3 имею:

00001a  480a              LDR      r0,|L1.68|
00001c  4908              LDR      r1,|L1.64|
00001e  6181              STR      r1,[r0,#0x18]
000020  ea4f4131          ROR      r1,r1,#16
000024  6181              STR      r1,[r0,#0x18]
000026  f04f41c0          MOV      r1,#0x60000000
00002a  6181              STR      r1,[r0,#0x18]
00002c  1409              ASRS     r1,r1,#16
00002e  6181              STR      r1,[r0,#0x18]

 

2 минуты назад, Forger сказал:

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

Оно в h-файле и есть.

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


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

А для -O0, однако, функцию хочет вызвать. Где, возьмет, не понимаю. Нашлось в конце.

;;;56         HsAdc1_select();
00001e  bf00              NOP      
000020  f7fffffe          BL       _ZN28_INTERNAL_8_Main_cpp_TimCapt8HsAdc_tmILb1ELb0EEEvv ; void [local to Main_cpp]::HsAdc_tm<(bool)1, (bool)0>()
000024  bf00              NOP      

13 минут назад, Forger сказал:

умение долго удерживать в голове эти магические аббревиатуры

Зачем? Главное знать интерфейс функций, которыми пользуешься. В данном случае, 4 простейших функции:

    HsAdc1_select();
    HsAdc2_select();
    HsAdc_select();
    HsAdc_deselect();

Два АЦП. Выбираются по одному, оба, или не выбираются. Это на их CS идет.

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


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

17 minutes ago, ViKo said:

    HsAdc1_select();
    HsAdc2_select();
    HsAdc_select();
    HsAdc_deselect();

Два АЦП. Выбираются по одному, оба, или не выбираются. Это на их CS идет.

Имхо, ни разу не очевидно :mda:

Впрочем, это - ваш код, хозяин-барин :)

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


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

23 минуты назад, ViKo сказал:

	Pin_st <'B', 13> Adc1s_n;
	Pin_st <'B', 14> Adc2s_n;

Получилось. Для

    HsAdc1_select();
    HsAdc2_select();
    HsAdc_select();
    HsAdc_deselect(); 

Отлично. Теперь сделайте следующий шаг: вместо шаблонной функции HsAdc_tm(), которая умеет работать только с двумя ножками, добавьте в структуру Pin_st функции on() и off().

После этого ваш код будет выглядеть примерно так:

using Adc1Cs = Pin_st <'B', 13>;
using Adc2Cs = Pin_st <'B', 14>;

Adc1Cs::off();
Adc2Cs::off();
Adc1Cs::on();
Adc2Cs::on();

Потом вам захочется инициализировать ножки. И вы добавите функцию init(mode).

Потом вам покажется удобным добавить третий параметр - активный уровень ('L' для низкого, 'H' - для высокого). И у вас получится мой pin.h :)))

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


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

:heat: Ну, когда-нибудь... 

Зато я могу сразу две ножки изменить. Для того и страдал. А до этого дефайнами влегкую махал ногами без накладных расходов.

Кстати, эти Pin_st в памяти  МК создаются или нет?

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


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

Ну так и в моём примере сразу две ножки :)

1 час назад, ViKo сказал:

Кстати, эти Pin_st в памяти  МК создаются или нет? 

В моём примере точно не создаются - используются типы и их статические функции.

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

Ну или если возьмёте адрес созданного объекта ( call_some_func(&Adc1s_n) ) - тоже создадутся.

 

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


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

17 часов назад, AHTOXA сказал:

Ну так и в моём примере сразу две ножки :)

Хочу вернуться к этому вопросу. У меня одной командой включаются или выключаются CS для двух устройств, по двум битам порта, в любой из 4-х комбинаций вкл/выкл.

Могу ли я, пользуясь using для каждого из битов, создать 4 функции? Ведь структура, описывающая бит порта, ничего не знает о соседнем бите. Это надо уже для двух битов структуру сочинять.

Почему так работает:

Спойлер

template <char port, unsigned bit>
struct Pin_st {
	static constexpr GPIO_TypeDef *Port = 
		port == 'A' ? GPIOA :
		port == 'B' ? GPIOB :
		port == 'C' ? GPIOC :
		port == 'D' ? GPIOD :
		port == 'E' ? GPIOE :
		port == 'G' ? GPIOG :
		GPIOH;
	static constexpr unsigned Bit = bit;
	static constexpr uint16_t Mask = 1 << bit;
};

// using	Adc1s_n = Pin_st <'B', 13>;
// using	Adc2s_n = Pin_st <'B', 14>;
Pin_st <'B', 13> Adc1s_n;
Pin_st <'B', 14> Adc2s_n;


inline void GpioLowHigh_set(GPIO_TypeDef *port, uint16_t mask_low, uint16_t mask_high)
{
	port->BSRR = mask_low << 16 | mask_high;
}


template <bool s1, bool s2>
static void HsAdc_tm()
{
	GpioLowHigh_set(GPIOB,
		Adc1s_n.Mask * s1 | Adc2s_n.Mask * s2,
		Adc1s_n.Mask * !s1 | Adc2s_n.Mask * !s2);
}

inline void HsAdc1_select(void)
{
	HsAdc_tm<true, false>();
}

inline void HsAdc2_select(void)
{
	HsAdc_tm<false, true>();
}

inline void HsAdc_select(void)
{
	HsAdc_tm<true, true>();
}

inline void HsAdc_deselect(void)
{
	HsAdc_tm<false, false>();
}

 

А так - нет:

using    Adc1s_n = Pin_st <'B', 13>;
using    Adc2s_n = Pin_st <'B', 14>;

 

Source\main.h(140): error:  #254: type name is not allowed
                Adc1s_n.Mask * s1 | Adc2s_n.Mask * s2,

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


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

Когда вы обращаетесь к статическому члену класса/структуры, то это надо делать через двоеточие:

Adc1s_n::Mask

То же и для вызова функций:

Adc1s_n::off();

А вот если вы объявите экземпляр этого класса, то через точку:

Adc1s_n Adc1s;

Adc1s.Mask;
Adc1s.off();

 

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


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

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

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

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

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

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

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

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

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

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