Страница 604 из 628

Re: Мелкие вопросы по МК и ПЛИС.

Добавлено: Пт сен 06, 2019 20:38:36
Chettuser
Что то не пойму:
Перенёс проект из Atollic в IAR и теперь IAR'у не нравится такой #define:

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

#define SPI_Tx  while (SPI1->SR & SPI_SR_BSY); SPI1->DR = (uint16_t)
а код такой:

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

SPI_Tx (data|0x00);
ошибка такая:
Error[Pe018]: expected a ")" D:\My designs\PJT\IAR\Nokia_1616.c 101
А такой код:

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

SPI_Tx 0x11;
его устраивает.

Как переписать дефайн, чтобы заработало?
Макрофункцией? Тоже не работает (data|0x00);

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

#define SPI_Tx(cd)  while (SPI1->SR & SPI_SR_BSY); SPI1->DR = (uint16_t)cd

SPI_Tx(0x11);
есть ещё способы?

Спасибо.

Re: Мелкие вопросы по МК и ПЛИС.

Добавлено: Пт сен 06, 2019 21:38:48
VladislavS
[uquote="Chettuser",url="/forum/viewtopic.php?p=3695815#p3695815"]Как переписать дефайн, чтобы заработало?[/uquote]Оба варианта рабочие. Ошибка скорее всего где-то в другом месте по коду выше. Это и есть слабое место макросов - плохо отлаживать. Во втором варианте аргумент cd надо в скобки взять.

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

#define SPI_Tx(cd)  while (SPI1->SR & SPI_SR_BSY); SPI1->DR = (uint16_t)(cd)
[uquote="Chettuser",url="/forum/viewtopic.php?p=3695815#p3695815"]есть ещё способы?[/uquote]Функцию надо оформлять функцией и не парить себе мозги.

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

static inline void SPI_Tx(uint32_t cd)
{
  while (SPI1->SR & SPI_SR_BSY); 
  *(uint16_t *)&SPI1->DR = cd;
}
Обрати внимание, я включил интуицию и предположил, что тебе нужна 16-битная операция записи в регистр SPI->DR. Это делается так как у меня в функции, а не как у тебя в макросе. Ну и (data|0x00) это прикол такой? :)

ЗЫ: На самостоятельную проработку предлагаю подумать что будет с таким применением твоего макроса и функции.

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

if(data==0xAA)
  SPI_Tx(data|0x01);
else
  SPI_Tx(data|0x02);
Поэтому макрос вообще правильно вот так

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

#define SPI_Tx(cd)  do{while (SPI1->SR & SPI_SR_BSY); SPI1->DR = (uint16_t)(cd);}while(false)

Re: Мелкие вопросы по МК и ПЛИС.

Добавлено: Пт сен 06, 2019 21:42:23
ARV
а, извиняюсь, чего вы хотели добиться вот этим data|0x00 ?

Re: Мелкие вопросы по МК и ПЛИС.

Добавлено: Сб сен 07, 2019 05:36:29
VladislavS
А ещё вот так можно сделать

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

template<typename T>
static inline void SPI_Tx(uint32_t data)
{  
  while (SPI1->SR & SPI_SR_BSY); 
  *(T*)&SPI1->DR = data;
}
Или даже лучше вот так

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

template<typename T>
static inline void SPI_Tx(uint32_t data)
{  
  static_assert(std::is_same_v<T,uint8_t> || std::is_same_v<T,uint16_t>, "User fool");
  while (SPI1->SR & SPI_SR_BSY); 
  *(T*)&SPI1->DR = data;
}

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

  if(x>255)
    SPI_Tx<uint16_t>(x);
  else
    SPI_Tx<uint8_t>(x);
Всё контролируется и диагностируется на этапе компиляции, всё инлайнится и оптимизируется - красота.

Re: Мелкие вопросы по МК и ПЛИС.

Добавлено: Сб сен 07, 2019 08:49:14
Chettuser
data|0x00 - по шаблону написал, на время отладки, чтобы не путаться.
Всё оказалось просто - в IAR нет поддержки записи двоичных чисел. GCC судя по всему поддерживает.

Re: Мелкие вопросы по МК и ПЛИС.

Добавлено: Сб сен 07, 2019 09:08:44
Reflector
[uquote="VladislavS",url="/forum/viewtopic.php?p=3695868#p3695868"]Функцию надо оформлять функцией и не парить себе мозги.

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

static inline void SPI_Tx(uint32_t cd)
{
  while (SPI1->SR & SPI_SR_BSY); 
  *(uint16_t *)&SPI1->DR = cd;
}
[/uquote]
Конечно, только эта функция не рабочая, volatile нельзя пропускать:

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

static inline void SPI_Tx(uint32_t cd)
{
  while (SPI1->SR & SPI_SR_BSY) {}
  *(volatile uint16_t*)&SPI1->DR = cd;
}

Re: Мелкие вопросы по МК и ПЛИС.

Добавлено: Сб сен 07, 2019 10:34:15
VladislavS
[uquote="Chettuser",url="/forum/viewtopic.php?p=3696000#p3696000"]Всё оказалось просто - в IAR нет поддержки записи двоичных чисел. GCC судя по всему поддерживает.[/uquote]Вот так новость, а мы пользуемся и не подозреваем.

[uquote="Reflector",url="/forum/viewtopic.php?p=3696015#p3696015"]Конечно, только эта функция не рабочая, volatile нельзя пропускать:[/uquote]Согласен, просто IAR такие вещи "прощает" и при компиляции им эта функция рабочая. А так да, volatile, конечно же.

Re: Мелкие вопросы по МК и ПЛИС.

Добавлено: Сб сен 07, 2019 11:21:10
Chettuser
[uquote="VladislavS",url="/forum/viewtopic.php?p=3696100#p3696100"]а мы пользуемся и не подозреваем.[/uquote]
Я переправил 0b100000000 на 0x100 и заработало, ЧЯДНТ?

(В двоичном виде удобнее менять регистры дисплея, чем писать простыни для изменения пары бит, как это любят делать программеры)

Re: Мелкие вопросы по МК и ПЛИС.

Добавлено: Сб сен 07, 2019 11:26:41
VladislavS
Вот кусок из рабочего проекта

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

enum class STM32F1_PinMode : uint32_t
{
  NotDefined = 0x12345678,
  // ODR[4] : CNF[3:2] : MODE[1:0]
  Floating                    = 0b0'01'00, // 0x04
  PullUp                      = 0b1'10'00, // 0x18
  PullDown                    = 0b0'10'00, // 0x08
  // Analog mode
  Analog                      = 0b0'00'00, // 0x00
  // Output Open Drain modes
  OpenDrain_LowSpeed          = 0b0'01'10, // 0x06
  OpenDrain_MediumSpeed       = 0b0'01'01, // 0x05
  OpenDrain_HighSpeed         = 0b0'01'11, // 0x07
  // Output Push-Pull modes
  PushPull_LowSpeed           = 0b0'00'10, // 0x02
  PushPull_MediumSpeed        = 0b0'00'01, // 0x01
  PushPull_HighSpeed          = 0b0'00'11, // 0x03
  // Alternate Function Open Drain modes
  AF_OpenDrain_LowSpeed       = 0b0'11'10, // 0x0E
  AF_OpenDrain_MediumSpeed    = 0b0'11'01, // 0x0D
  AF_OpenDrain_HighSpeed      = 0b0'11'11, // 0x0F
  // Alternate Function Push-Pull modes
  AF_PushPull_LowSpeed        = 0b0'10'10, // 0x0A
  AF_PushPull_MediumSpeed     = 0b0'10'01, // 0x09
  AF_PushPull_HighSpeed       = 0b0'10'11  // 0x0B
};
ЧМДНТ?

Попробуй вот это скомпилировать

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

int main()
{
  [](){[](){[](){[](){[](){}();}();}();}();}();
  for(;;);
}

Re: Мелкие вопросы по МК и ПЛИС.

Добавлено: Сб сен 07, 2019 11:33:21
Reflector
[uquote="Chettuser",url="/forum/viewtopic.php?p=3696000#p3696000"]Всё оказалось просто - в IAR нет поддержки записи двоичных чисел. GCC судя по всему поддерживает.[/uquote]
Не gcc, а С++14.

Re: Мелкие вопросы по МК и ПЛИС.

Добавлено: Сб сен 07, 2019 12:00:51
VladislavS
Тссс, я плавно подвожу либо к включению С++ режима компилятора, либо обновлению последнего. Но я уже даже забыл когда он С++14 не поддерживал и где такую древнюю версию можно откопать.

Re: Мелкие вопросы по МК и ПЛИС.

Добавлено: Сб сен 07, 2019 12:40:10
Chettuser
[uquote="VladislavS",url="/forum/viewtopic.php?p=3696152#p3696152"]и где такую древнюю версию можно откопать.[/uquote]
С официального сайта с ограничением )

Re: Мелкие вопросы по МК и ПЛИС.

Добавлено: Сб сен 07, 2019 12:45:05
VladislavS
Ну версию то хоть озвучь, что-ли...

Re: Мелкие вопросы по МК и ПЛИС.

Добавлено: Сб сен 07, 2019 13:18:49
Chettuser
IAR Embedded Workbench for ARM 8.40.1.21539 - свежак ) Ещё мухи не снош..сь!

Re: Мелкие вопросы по МК и ПЛИС.

Добавлено: Сб сен 07, 2019 13:26:13
VladislavS
Тогда поставь галку С++ в настройках проекта раз и навсегда и не пудри нам мозги.

Re: Мелкие вопросы по МК и ПЛИС.

Добавлено: Сб сен 07, 2019 14:21:48
Chettuser
Ок, не буду )

Re: Мелкие вопросы по МК и ПЛИС.

Добавлено: Пн сен 09, 2019 05:21:30
smalcom
*(T*)&SPI1->DR = data;
Потенциальный источник ошибок. Лучше правую часть приводить к левой:
"*(volatile uint16_t*)&SPI1->DR = cd;" => "SPI1->DR = (decltype(SPI1->DR))cd;" или просто "SPI1->DR = (uint16_t)cd;"; эстеты могут использовать static_cast.

Re: Мелкие вопросы по МК и ПЛИС.

Добавлено: Пн сен 09, 2019 13:38:07
VladislavS
Нет, так не прокатит. Регистр SPI_DR чувствителен к разрядности команды записи в него. Правая часть автоматом из uint32_t во время записи командой STRH или STRB обрежется до необходимых 16 и 8 бит.

Насчёт volatile при записи по указателю надо бы стандарт почитать на досуге. Iar, например, "понимает", что если я пишу по указателю, то это не просто так.

Добавлено after 7 hours 2 minutes 45 seconds:
Проделел эксперимент.

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

  *(uint8_t *)&SPI1->DR = 0xA0;
  *(uint8_t *)&SPI1->DR = 0xA1;
  *(uint8_t *)&SPI1->DR = 0xA2;
  *const_cast<uint8_t *>((uint8_t *)&SPI1->DR) = 0xA3;
  *const_cast<uint8_t *>((uint8_t *)&SPI1->DR) = 0xA4;
  *const_cast<uint8_t *>((uint8_t *)&SPI1->DR) = 0xA5;
  *(volatile uint8_t *)&SPI1->DR = 0xA6;
  *(volatile uint8_t *)&SPI1->DR = 0xA7;
  *(volatile uint8_t *)&SPI1->DR = 0xA8;
IAR делает 9 операций записи, GCC три. Комментарии излишни.

Re: Мелкие вопросы по МК и ПЛИС.

Добавлено: Пн сен 09, 2019 14:11:10
Reflector
[uquote="VladislavS",url="/forum/viewtopic.php?p=3697189#p3697189"]IAR делает 9 операций записи, GCC три. Комментарии излишни.[/uquote]
Кстати, volatile не работает в constexpr контексте, потому из языка его выпиливают, в С++20 большинство volatile уже deprecated, вместо него предлагают использовать функции volatile_load/store(), как в Rust.

Re: Мелкие вопросы по МК и ПЛИС.

Добавлено: Пн сен 09, 2019 14:20:25
VladislavS
Ну чтож, будем загонять регистры в классы и продолжать пользоваться присваиваниями :)