Страница 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)
а код такой:
ошибка такая:
Error[Pe018]: expected a ")" D:\My designs\PJT\IAR\Nokia_1616.c 101
А такой код:
его устраивает.
Как переписать дефайн, чтобы заработало?
Макрофункцией? Тоже не работает (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
Ну чтож, будем загонять регистры в классы и продолжать пользоваться присваиваниями
