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

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Открыл глаза
Аватара пользователя
Сообщения: 56
Зарегистрирован: Вт дек 29, 2015 11:33:49

Сообщение pavell »

Подскажите еще один момент с DMA - > UART.
Первый канал DMA пишет данные из периферии в память по 16 бит, с этим проблем нет, а вот дальше возникает нюанс. Указываю второму каналу, что разрядность и памяти, и периферии 8 бит, но при отправке каждый второй байт теряется.
Т.е. имеем в памяти допустим:

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

0xAA 0xBB 0xCC 0xDD 
а UART дает на выходе:

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

0xAA 0xCC 
По какой причине это происходит?

Надо было сразу напомнить, код в спойлере
Последний раз редактировалось pavell Ср фев 27, 2019 12:34:10, всего редактировалось 1 раз.
Реклама
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

[uquote="WiseLord",url="/forum/viewtopic.php?p=3578774#p3578774"]Какими бы шаблонами или хитрыми макросами ни пользоваться, одновременно в разные порты не записать в принципе. Потому что существует такого машинного кода, в который это должно было бы развернуться.[/uquote]Я с периферией STM32 ещё плохо знаком, по этому и спросил, на всякий случай. Вдруг там есть какие хитрости...
pavell писал(а):По какой причине это происходит?
На мой взгляд, только по одной единственной. Ширина данных в источнике указана в 2 раза больше чем в приёмнике.
Реклама
Открыл глаза
Аватара пользователя
Сообщения: 56
Зарегистрирован: Вт дек 29, 2015 11:33:49

Сообщение pavell »

[uquote="Аlex",url="/forum/viewtopic.php?p=3578911#p3578911"]На мой взгляд, только по одной единственной. Ширина данных в источнике в 2 раза больше чем в приёмнике.[/uquote]
А разве есть разница какая ширина данных в источнике?
В регистре DMA->MSIZE мы задаем значение которое является инкриментом указателя. И указав 8 бит я ожидаю, что указатель и будет увеличиваться на 8 бит. При этом, что и как я укладывал в память на первом этапе никакой роли играть не должно.
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Размер пересылаемых данных указывается как в источнике, так и в приёмнике. Именно по этим значениям DMA знает на сколько байт делать инкременты.
Реклама
Эиком - электронные компоненты и радиодетали
Открыл глаза
Аватара пользователя
Сообщения: 56
Зарегистрирован: Вт дек 29, 2015 11:33:49

Сообщение pavell »

Все это так, но.
По логике вещей раз мы не инкриминируем приемник, то по сути нам не важно какую ширину данных мы ему указываем. Если вернуться к моему случаю, то размерность источника и получателя одинакова и равна 8 бит
Реклама
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

pavell писал(а):мы не инкриминируем приемник
Приёмник - нет, а источник - да. И если он будет = 16 бит, то как раз и получится как в Вашем случае.
В общем, чудес не бывает. Явно что-то с размерами не то.
Реклама
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Сообщение СКАЗОЧНИК »

А мой вопрос остался без ответов... :(
Станислав
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

СКАЗОЧНИК, Создайте функцию, принимающую значение. В ней побитно читайте это значение и дёргайте портами.
На чистом Си больше никак.
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Сообщение СКАЗОЧНИК »

Я пошел путем дефайнов. Обозначаю каждому пину свое имя и состояние, а ему уже соотношу обращение к пинам порта. Однако, как было выложено здесь же, получается обработка такая выльется в хренову тучу ассемблерных конструкций, ибо все пины по отдельности ставятся и снимаются...
Типа такого:

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

# define _1_Stroka_ON  GPIOA->BSRR |= (GPIO_BSRR_BS11);
# define _1_Stroka_OFF GPIOA->BSRR |= (GPIO_BSRR_BR11);
И все в таком же духе. Будет работать или нет, не знаю еще. :)))

И не знаю как сам порт теперь обозвать, точнее, что ему присвоить.

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

# define _KeyPORT_Stroki ?????
# define _KeyPORT_Stolbi ?????
Добавлено after 6 minutes 24 seconds:
А вообще, зачем их называть, если я уже и так все сделал?! Чет не догоняю, чего сам напихал.

Добавлено after 2 minutes 10 seconds:
Все. Догнал. Надо не так, а вот так примерно:

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

# define _1_Stroka_ON  GPIO_BSRR_BS11;
# define _1_Stroka_OFF GPIO_BSRR_BR11;
# define _2_Stroka_ON  GPIO_BSRR_BS10;
# define _2_Stroka_OFF GPIO_BSRR_BR10; 

# define _KeyPORT_Stroki GPIOA->BSRR;
# define _KeyPORT_Stolbi GPIOD->BSRR;
Добавлено after 8 minutes 39 seconds:
И, по моему, первый вариант лучше, т.к. он действительно позволяет назначать любые пины любых портов, а второй способ все же собирает в пару портов эти пины...

Добавлено after 37 minutes 7 seconds:
Почему я эту конструкцию не могу сразу затащить как условие в if?

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

# define _1_Stolb_Read	(GPIOB->IDR & GPIO_IDR_IDR15);

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

if (_1_Stolb_Read)
{
}
Не работает. Но зато могу это присвоить переменной...
Станислав
Друг Кота
Аватара пользователя
Сообщения: 4906
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Имхо, не очень красивые макросы. Легко ошибку сделать при их описании и пользоваться неудобно.

Я предпочитаю такой вариант, когда использование выглядит следующим образом:

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

SET(MUTE); // пин MUTE выставляем в 1
CLR(STBY); // пин STBY выставляем в 0

READ(RC); // читаем пин RC
и т.п.

Подсмотреть принцип объявления пинов в этом случае можно у меня здесь.

Правда, я эти макросы с использованием LL библиотеки делал, но и на чистом CMSIS никакой сложности их объявить нет.

P.S. За эти "stroka" и "stolbets" и прочее подобное хочется сильно бить по голове учебником английского. Почему не "line" или "row"?
Контактная информация:
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Сообщение СКАЗОЧНИК »

А вот здесь типа цикл сделали, чтобы просто объединить группу действий?

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

#define OUT_INIT(p, t, s)   \
    do {                    \
        OUT(p);             \
        SPEED(p, s);        \
        OTYPE(p, t);        \
    } while (0);
И, вроде все понятно, но это не понятно... :oops:

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

#define OUT(p)                  (LL_GPIO_SetPinMode(CONCAT(p, _Port), CONCAT(p, _Pin), LL_GPIO_MODE_OUTPUT))
Можно словами эту строку описать. Зачем столько скобок? И почему OUT с таким "параметром" (р)?

Добавлено after 2 minutes 46 seconds:
И сверху обозначены прототипы функций?
Станислав
Друг Кота
Аватара пользователя
Сообщения: 4906
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Там нету цикла (while (0)). Просто несколько операций группируются в одну.

Попробую объяснить.

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

#define CONCAT(x,y)             x ## y
Здесь всё достаточно понятно. Обычная конкатенация. Любой макрос вида
CONCAT(test, pin) развернётся в строчку testpin.
Объявляю пин MUTE:

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

#define MUTE_Port               GPIOA
#define MUTE_Pin                LL_GPIO_PIN_13
Инициализирую его с помощью макроса

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

#define OUT(p)                  (LL_GPIO_SetPinMode(CONCAT(p, _Port), CONCAT(p, _Pin), LL_GPIO_MODE_OUTPUT))
В C-коде инициализация будет следующая:

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

{
  ...
  OUT(MUTE); // Переводим пин в режим выхода
 ..
}
Как это работает (стадии препроцессора, в качестве параметра p макроса идёт MUTE):

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

1: OUT(MUTE);
2: (LL_GPIO_SetPinMode(CONCAT(MUTE, _Port), CONCAT(MUTE, _Pin), LL_GPIO_MODE_OUTPUT));
3: (LL_GPIO_SetPinMode(MUTE_Port, MUTE_Pin, LL_GPIO_MODE_OUTPUT));
4: (LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_13, LL_GPIO_MODE_OUTPUT));
Аналогично и все прочие макросы (SET, CLR и т.д).

Единственное, всё это у меня разворачивается до функций библиотеки LL. Но по тому же принципу и "чистый" CMSIS можно вызывать.
Последний раз редактировалось WiseLord Ср фев 27, 2019 16:55:42, всего редактировалось 1 раз.
Контактная информация:
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Сообщение СКАЗОЧНИК »

[uquote="WiseLord",url="/forum/viewtopic.php?p=3579081#p3579081"]P.S. За эти "stroka" и "stolbets" и прочее подобное хочется сильно бить по голове учебником английского. Почему не "line" или "row"?[/uquote]

Точно! А я думал, как в транслите написать букву Ц! :)))
А серьезнее, то так мне было проще, типа я художник, я так вижу. Изначально хотел написать ROW COLUMN, но я в них постоянно путаюсь, кто из них строка, а кто столбец, еще с Ехеля начиная. Ну, не англичанин я... :dont_know:

Добавлено after 3 minutes 25 seconds:

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

#define CONCAT(x,y)             x ## y
Я вообще думал, что это строка к С++ относится... Ни разу с такой не встречался. Пойду почитаю за конкатенацию.
А вот именно все скобки у макроса и не понятны все равно. :( Вот эти:

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

#define OUT(p)                  (LL_GPIO_SetPinMode(CONCAT(p, _Port), CONCAT(p, _Pin), LL_GPIO_MODE_OUTPUT))
А про НЕцикл я понял. Просто мне стало интересно, неужели в группу никаким другим образом несколько действий нельзя объединить больше? :idea:

Добавлено after 6 minutes 25 seconds:
О! Начинает доходить. ))) Начал внимательно смотреть в скобки!

Благодарю.

Добавлено after 10 minutes 13 seconds:
Блин... что за оператор такой ##?
Станислав
Друг Кота
Аватара пользователя
Сообщения: 4906
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Прочитайте по макросы в C. ## соединяет две текстовые лексемы.
Контактная информация:
afz
Опытный кот
Аватара пользователя
Сообщения: 744
Зарегистрирован: Сб дек 22, 2012 08:17:42
Откуда: Караганда, Казахстан

Сообщение afz »

[uquote="СКАЗОЧНИК",url="/forum/viewtopic.php?p=3579028#p3579028"]Почему я эту конструкцию не могу сразу затащить как условие в if?

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

# define _1_Stolb_Read	(GPIOB->IDR & GPIO_IDR_IDR15);

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

if (_1_Stolb_Read)
{
}
Не работает. Но зато могу это присвоить переменной...[/uquote] Вероятно потому, что в дефайне стоит точка с запятой после выражения. Что нарушает синтаксис if'а.
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Сообщение СКАЗОЧНИК »

Ну ооочень сложные макросы у меня тогда получаются. Я разобрался в Ваших уже, наверное, основательно. С LL это много проще, похоже, чем на CMSYS.
:facepalm:

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

#define CONCAT(x,y)        x ## y

#define STROKA_1_PORT		GPIOA
#define STROKA_1_PIN    11

OUT_OD (p)    /
if (CONCAT(p,_PIN) > 7)    /
   { CONCAT(CONCAT(p,_PORT),->CRH) |= (CONCAT(CONCAT(GPIO_CRH_CNF,CONCAT(p,_PIN)),_0) }    /
else    /
    { CONCAT(CONCAT(p,_PORT),->CRL) |= (CONCAT(CONCAT(GPIO_CRL_CNF,CONCAT(p,_PIN)),_0) }    /
И дальше в том же духе... настройки частоты, входов, начального состояния выходов...

Собраться верхняя штуковина должна примерно в такой вид:

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

GPIOA->CRH |= (GPIO_CRH_CNF11_0) 
Ну и вызов да, простой:

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

OUT_OD(STROKA_1); // 1-я строка настроена на выход с открытым стоком.
Станислав
Собутыльник Кота
Аватара пользователя
Сообщения: 2723
Зарегистрирован: Пт сен 07, 2018 20:20:02
Откуда: деревня в Тульской губернии

Сообщение ПростоНуб »

[uquote="СКАЗОЧНИК",url="/forum/viewtopic.php?p=3583398#p3583398"]Ну ооочень сложные макросы у меня тогда получаются.[/uquote]
Пусть меня забросают шапками, но я именно по этой причине CONCAT() не пользуюсь.
Просто в makefile проезжаюсь по исходникам дубовым perl скриптом:

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

#!bin\perl
open INFILE, $ARGV[0];
if ( $#ARGV>0  ) {
  open OUTFILE, '>', $ARGV[1];
}
LINE:
    while (<INFILE>) {
      s/(`\|)|(`\[)|(`\])|(`\{)|(`\})|(`;)|(`:)|(`!)/
        if (length($2)>0 | length($3)>0) {chr(0x22)} 
        elsif (length($4)>0 | length($5)>0) {chr(0x27)}
        elsif (length($6)>0) {chr(0x2F)}
        elsif (length($7)>0) {chr(0x5C)}
        elsif (length($8)>0) {chr(0x0A)}
        else {''}/eg;
    } continue {
      if ( $#ARGV>0  ) {
        print OUTFILE;
      } else {
        print;
      }
    }
То бишь, для конкатенации пишу `| что удобней и быстрее.

P.S. Остальные замены нужны, преимущественно, для использования макросов внутри одинарных или двойных кавычек.
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Вт июн 04, 2013 20:25:13

Сообщение Satarych »

А есть ли тут гуру ассемблера? Должны быть))

В частности интересует во что компилируются инкремент/декремент обычных переменных и указателей.
Насколько я помню, в AVR'ках инкремент/декремент обычной переменной подразумевал:
1. Загрузку значения из оперативки в регистр
2. Инкремент значения в регистре одной командой
3. Выгрузку значения обратно в оперативку
Тобишь процесс не атомарен. А как это устроено в ARM'ках? Тут тоже инкремент/декремент осуществляется через регистры или как?
И что насчёт адресной арифметики? Есть какие то специальные инкременты на степени двойки? Или это реализуется уже обычными арифметическими командами?

И ещё вопрос. Насколько эффективно компиляторы реализует остаток от деления? Со степенями двойки всё должно быть просто, а с произвольными числами неизвестными на этапе компиляции? Условно, что эффективнее?

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

a += b;
if (a >= maxValue)    a -= maxValue;

// или обойтись без if'а и просто взять остаток от деления?
a += b;
a %= maxValue;
PS если где-то это уже разжёвано, буду благодарен за ссылочку.
Друг Кота
Аватара пользователя
Сообщения: 4906
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Эмм.. вообще-то 2-я и последняя строки в приведенном коде считают совершенно разные вещи.
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Satarych, вместо кучи дурацких вопросов написал бы интересующий тебя код и посмотрел во что он компилируется. Лучше один раз увидеть, чем сто раз услышать.
Ответить

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