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

Подходит. Эта функция нужна чисто для проверки диапазона. Вызывается много раз, но всегда с константой.

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


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

Однако, для не целых аргументов такой способ не подходит. К примеру:

#define HMCAD_FSCALE(CNT)            \
        (((CNT >= 0 ? CNT : CNT - 0.3) * 100 + 15) / 30 + 32)

 

// Fine Gain (1.0077...0.0.9923)
#define    HMCAD_FGAIN_XX(XX)                \
       ((XX >= 1) ? (XX - 1 + 2E-14) / 2E-13 : 0x7F - (1 - XX + 2E-14) / 2E-13)

Здесь я не могу сделать inline функцию не только с вычислением результата, но и со static_assert проверкой диапазона аргумента.

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


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

Выброшу static_assert, буду использовать inline функции.

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


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

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

Подходит. Эта функция нужна чисто для проверки диапазона. Вызывается много раз, но всегда с константой.

Зачем тогда функция? Если аргумент всегда - константа, то логично написать макрос.

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


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

25 минут назад, jcxz сказал:

Зачем тогда функция? Если аргумент всегда - константа, то логично написать макрос.

С #error? Это не современно.

И функций у меня много разных. Надо в одном стиле всё делать.

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


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

Сделал иначе. Недопустимые диапазоны аргументов преобразовываю в граничные допустимые, операторами ?  :

И функции инлайнятся, и непотребного не выдают. 

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


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

Погружаюсь в шаблоны. Косячу.

template <GPIO_TypeDef *port, unsigned bit>
struct Pin_st {
    static constexpr GPIO_TypeDef *Port = port;
    static constexpr unsigned Bit = bit;
    static constexpr uint16_t Mask = 1 << bit;
};

using    Adc1s_n = Pin_st <GPIOB, 13>;
using    Adc2s_n = Pin_st <GPIOB, 14>;

Получаю.

Source\main.h(108): error:  #873: non-integral operation not allowed in nontype template argument

Указатели же допускаются.

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


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

5 minutes ago, ViKo said:

Source\main.h(108): error:  #873: non-integral operation not allowed in nontype template argument

У меня на этот пример ничего не ругается (ARM compiler v6, включен C++11).

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


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

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

У меня на этот пример ничего не ругается (ARM compiler v6, включен C++11).

Проверил, не ругается. Но ругается на многое другое. Так что пока остаюсь на v5.

Чего же там не хватает. Кажется, смогу заменить на

    static constexpr GPIO_TypeDef *Port = 
        port == 'A' ? GPIOA :
        port == 'B' ? GPIOB :
        port == 'C' ? GPIOC :

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


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

Заменил, как написал. Скомпилировалось. Не всё умеет v5.

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


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

42 minutes ago, ViKo said:

Заменил, как написал. Скомпилировалось. Не всё умеет v5.

Когда делал свой шаблон Pin, тогда сидел на v5 и тоже столкнулся с этой "руганью" компилятора.

Решил в лоб: всего один параметр в шаблоне, разбор идет в конструкторе абстрактного класса, например:

Hardware::Pin<PD1> pinCAN1_TX;
...
Hardware::DigitalOutputPin<PA9> pinON;

Но каждый такой pin требует доп. ОЗУ для хранения указателей на порт и маску. Учитывая, что чем больше число пинов у камня, тем больше у него ОЗУ, забил на этот "минус" ))

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


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

А как вы их распознаёте, PD1, PA9? Ну, как компилятор их интерпретирует?

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


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

40 minutes ago, ViKo said:

А как вы их распознаёте, PD1, PA9? Ну, как компилятор их интерпретирует?

Абстрактный класс, который в конструкторе разбирает соотв. параметр:

 

Spoiler

...
using PinName = enum
{
	PA0, PA1, PA2, PA3, PA4, PA5, PA6, PA7, PA8, PA9, PA10, PA11, PA12, PA13, PA14, PA15, // 0
	PB0, PB1, PB2, PB3, PB4, PB5, PB6, PB7, PB8, PB9, PB10, PB11, PB12, PB13, PB14, PB15, // 1
....
  NONE
};
  
.....

namespace stm32f4
{
	class AbstractPin
	{
		using Port = GPIO_TypeDef;
		using PortIndex = uint8_t;

	public:
		AbstractPin(PinName);
	
		void setAsDigitalInput();
		void setAsDigitalOutput();


....



	template <PinName pin = NONE> class Pin : public AbstractPin
	{
	public:
		Pin() : AbstractPin(pin) { }
	};
      
....
      
	template <PinName pin = NONE> class DigitalOutputPin : public AbstractPin
	{
	public:
		DigitalOutputPin() : AbstractPin(pin)
		{ 
			setAsDigitalOutputPin(); 
			setAsPushPull(); 
			setOutputSpeedNormal(); 
		}
	};
 

 

 

Spoiler

stm32f4::AbstractPin::AbstractPin(PinName pin)
{
	// Undefined pin
	if (pin == NONE)
	{ 
		port = reinterpret_cast<Port*>(GPIOA_BASE);
		setMask = 0;
		resetMask = 0;
		return;
	}
	
	pinIndex = (pin % 16);
	setMask = (1 << pinIndex);
	resetMask = (1 << (pinIndex + 16));
	
	switch (pin / 16)
	{
		case (0):
			port = reinterpret_cast<Port*>(GPIOA_BASE);
			SET_BIT(RCC->AHB1LPENR, RCC_AHB1LPENR_GPIOALPEN);
			SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOAEN);
			break;

		case (1):
			port = reinterpret_cast<Port*>(GPIOB_BASE); 
			SET_BIT(RCC->AHB1LPENR, RCC_AHB1LPENR_GPIOBLPEN);
			SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOBEN);
			break;
....
	
	setAsDigitalInput();
}

 

 

Хотя можно изголиться и все это сделать на шаблонах, но тогда скорее всего вырастет уже объем прошивки, хотя ОЗУ уже так тратиться не будет. 

В целом - экономии мизерные. Не вижу смысла особо заморачиваться.

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


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

ViKo, не слушайте Forger-а, у него всегда всё через одно место сделано. Вот правильные Pin-ы: тынц.

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


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

Спасибо всем!

Меня сейчас устраивает описание, как ниже сделано.

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(Adc1s.Port,
		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>;
}

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

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

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

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


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

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

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

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

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

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

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

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

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

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