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

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="Lum1noFor",url="/forum/viewtopic.php?p=4236774#p4236774"]нужно выполнить сначала чтение из USART1->DR, а затем чтение из USART1->SR.[/uquote]Даташиты то когда будем читать?
Изображение
SR дополнительно читать не надо, так как вы делает это при проверке статуса (правильная последовательность чтения - сначала SR, затем DR). А в вашем случае даже затрудняюсь посчитать сколько раз SR прочитан. Я приводил вот в этом сообщении скелет прерывания. Больше там ничего не нужно.

[uquote="Lum1noFor",url="/forum/viewtopic.php?p=4236833#p4236833"]

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

if ((((USART1->SR & USART_SR_RXNE) >> USART_SR_RXNE_Pos) == 1) & (((USART1->SR & USART_SR_ORE) >> USART_SR_ORE_Pos) != 1) & (((USART1->SR & USART_SR_IDLE) >> USART_SR_IDLE_Pos) != 1))
[/uquote]Код получился %цензор%. Ну что это? Что ещё за "&"?

Уберите всё. Сделайте приём с минимальным количеством кода без таймаутов. После этого добавьте обнуление и запуск таймера при приёме каждого байта. В прерывании от таймера реакция на таймаут. Это всё.

ore.png
(27.04 КБ) 989 скачиваний
Добавлено after 1 minute 59 seconds:
[uquote="ARV",url="/forum/viewtopic.php?p=4236795#p4236795"]как я понял, истинная причина проблемы в отсутствии считывания регистра принятых данных[/uquote]Нет, в непрочтении документации и переусложнении алгоритма.
Последний раз редактировалось VladislavS Чт май 26, 2022 13:37:05, всего редактировалось 2 раза.
Реклама
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

Код получился %цензор%. Ну что это? Что ещё ща "&"?
Но, как ни странно, работать будет. Потому что остальные условия тоже по-дурацки написаны и выставляют только младший бит.
Это не отменяет, разумеется, того, что переписать по-человечески надо.
Lum1noFor, проверка отдельного бита делается так:

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

(USART1->SR & USART_SR_RXNE)
И все - никаких сдвигов не нужно.
Даташиты то когда будем читать?
Где ж вы раньше были? Сейчас-то, когда ТС сам нашел упоминание этого бита (который он вообще не трогал!), легко тыкать в документацию.
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="Lum1noFor",url="/forum/viewtopic.php?p=4236833#p4236833"]

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

if (((USART1->SR & USART_SR_ORE) >> USART_SR_ORE_Pos) == 1)
[/uquote]Прекратите писать лишние буквы. Это пишеся просто вот так

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

if (USART1->SR & USART_SR_ORE)
Работает так же, писать менешь - быстрее и меньше ошибок. А результат ещё и быстрее может оказаться.
СпойлерСравниваем

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

void foo1()
{
  if (((USART1->ISR & USART_ISR_ORE) >> USART_ISR_ORE_Pos) == 1) 
    __NOP();
}

void foo2()
{
  if (USART1->ISR & USART_ISR_ORE) 
    __NOP();
}


_Z4foo1v:
        LDR.N    R0,??DataTable2_2
        LDR      R1,[R0, #+0]   
        UBFX     R0,R1,#+3,#+1  
        CBZ.N    R0,??foo1_0    
        Nop                     
??foo1_0:
        BX       LR             

_Z4foo2v:
        LDR.N    R0,??DataTable2_2
        LDR      R1,[R0, #+0]   
        LSLS     R2,R1,#+28     
        IT       MI                
        NopMI                   
        BX       LR
Добавлено after 4 minutes 5 seconds:
[uquote="COKPOWEHEU",url="/forum/viewtopic.php?p=4236933#p4236933"]
Даташиты то когда будем читать?
Где ж вы раньше были? Сейчас-то, когда ТС сам нашел упоминание этого бита (который он вообще не трогал!), легко тыкать в документацию.[/uquote]Я где раньше был? Я уже давно скелет прерывания показал. В нём ORE автоматом скидывается. Да и откуда ему возникнуть, если прерывание короткое как полёт пули. Разве что приоритет задушить и сидеть в каком-нибудь другом прерывании. Ну так это ССЗБ.
Открыл глаза
Сообщения: 65
Зарегистрирован: Ср сен 24, 2014 12:30:09

Сообщение Lum1noFor »

Ну уж извините, туповат я, я и не спорю. Не в том я уже возрасте, чтобы все сходу понимать. Был бы крутым программистом - не обращался бы в тему для новичков. Спасибо Вам за критику и помощь. Учту все. Но, согласитесь, если просто взять чужое решение, ничего в голове не останется. Надо вникать, почему именно так. Что я и пытаюсь сделать.

Добавлено after 5 minutes 50 seconds:
[uquote="VladislavS",url="/forum/viewtopic.php?p=4236938#p4236938"][uquote="Lum1noFor",url="/forum/viewtopic.php?p=4236833#p4236833"]

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

if (((USART1->SR & USART_SR_ORE) >> USART_SR_ORE_Pos) == 1)
[/uquote]Прекратите писать лишние буквы. Это пишеся просто вот так

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

if (USART1->SR & USART_SR_ORE)
Работает так же, писать менешь - быстрее и меньше ошибок. А результат ещё и быстрее может оказаться.
СпойлерСравниваем

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

void foo1()
{
  if (((USART1->ISR & USART_ISR_ORE) >> USART_ISR_ORE_Pos) == 1) 
    __NOP();
}

void foo2()
{
  if (USART1->ISR & USART_ISR_ORE) 
    __NOP();
}


_Z4foo1v:
        LDR.N    R0,??DataTable2_2
        LDR      R1,[R0, #+0]   
        UBFX     R0,R1,#+3,#+1  
        CBZ.N    R0,??foo1_0    
        Nop                     
??foo1_0:
        BX       LR             

_Z4foo2v:
        LDR.N    R0,??DataTable2_2
        LDR      R1,[R0, #+0]   
        LSLS     R2,R1,#+28     
        IT       MI                
        NopMI                   
        BX       LR
Добавлено after 4 minutes 5 seconds:
[uquote="COKPOWEHEU",url="/forum/viewtopic.php?p=4236933#p4236933"]
Даташиты то когда будем читать?
Где ж вы раньше были? Сейчас-то, когда ТС сам нашел упоминание этого бита (который он вообще не трогал!), легко тыкать в документацию.[/uquote]Я где раньше был? Я уже давно скелет прерывания показал. В нём ORE автоматом скидывается. Да и откуда ему возникнуть, если прерывание короткое как полёт пули. Разве что приоритет задушить и сидеть в каком-нибудь другом прерывании. Ну так это ССЗБ.[/uquote]


А раз уж Вы решили сразу код мне привести готовый, можно Вас попросить написать все это вместе с таймером таймаута? Тогда уж буду анализировать все вместе и думать, почему так и где я был не прав. Сегодня 6 часов просидел уже - все равно не работает нормально.
Реклама
Эиком - электронные компоненты и радиодетали
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 362
Зарегистрирован: Вс апр 03, 2022 07:01:29

Сообщение НовыйДень »

Быть может, стоило бы прочесть Reference Manual, раздел USART? Потому что там очень доходчиво, даже с диаграммами, расписано всё. Можете через гугл-переводчик, если проблемы с английским
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01

Сообщение Eddy_Em »

[uquote="tonyk",url="/forum/viewtopic.php?p=4236792#p4236792"]Мне страшно представить, когда ты начнёшь осваивать UART+DMA... А ведь там без IDLE или RTO никак...[/uquote]
У меня UART работает через DMA: где-то только передача, где-то - и передача, и прием. И я ни разу в жизни ни IDLE, ни RTO не использовал. ЧЯДНТ?
Ну и код приема в прерывании с контролем таймаутов я уже приводил, если кому интересно. Прием через DMA с таймаутами тоже несложно реализуется: достаточно в поллинге время проверять.
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Контактная информация:
Реклама
Открыл глаза
Сообщения: 65
Зарегистрирован: Ср сен 24, 2014 12:30:09

Сообщение Lum1noFor »

[uquote="НовыйДень",url="/forum/viewtopic.php?p=4237052#p4237052"]Быть может, стоило бы прочесть Reference Manual, раздел USART? Потому что там очень доходчиво, даже с диаграммами, расписано всё. Можете через гугл-переводчик, если проблемы с английским[/uquote]

Читал, но я много чего там не понимаю. Не в смысле языка, а а смысле работы всего этого хозяйства. Например, мне не понятно, выставляется ли бит RXNE при срабатывании прерывания по Idle. Со временем, думаю, пойму.
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 362
Зарегистрирован: Вс апр 03, 2022 07:01:29

Сообщение НовыйДень »

Но ведь это несложно и проверить на деле.
Нет, не выставляется, ведь ничего не было принято, поскольку старт-бит и стоп-бит не были обнаружены, и запуска сдвигового регистра приема не было.
Во время приема флаг RXNE выставляется в конце приема байта, а флаг IDLE будет выставлен после того, как линия RX будет оставаться свободной в течение времени, равного длительности кадра (обычно 10 бит).
Флаг ORE (overrun) будет выставляться тогда, когда был принят новый байт, а предыдущий не был прочитан.

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

oid USART2_IRQHandler(void)
{
	/* Линия свободна (idle frame) */
	if((USART2->ISR & USART_ISR_IDLE)&&(USART2->CR1 & USART_CR1_IDLEIE))
	{
		Start_RTOTimer();
		USART2->ICR = USART_ICR_IDLECF;
	}

	/* Предыдущий принятый символ не был прочитан */
	if(USART2->ISR & USART_ISR_ORE)
	{
		ToRXBuff(USART2->RDR);
		USART2->ICR = USART_ICR_ORECF;
	}

	/* Символ был принят */
	if((USART2->ISR & USART_ISR_RXNE)&&(USART2->CR1 & USART_CR1_RXNEIE))
	{
		Stop_RTOTimer();
		ToRXBuff(USART2->RDR);
	}

	/* Готов к передаче символа */
	if((USART2->ISR & USART_ISR_TXE)&&(USART2->CR1 & USART_CR1_TXEIE))
	{
		uint8_t ch;
		if(FromTXBuff(&ch))
			USART2->TDR = ch;
		else
			USART2->CR1 &= ~USART_CR1_TXEIE;
	}

	/* Передача символа была завершена и передающий буфер пуст */
	if((USART2->ISR & USART_ISR_TC)&&(USART2->CR1 & USART_CR1_TCIE))
	{

	}

	/* Ошибка кадра в приемнике */
	if(USART2->ISR & USART_ISR_FE)
	{
		USART2->ICR = USART_ICR_FECF;
	}
}
причем, запуск RTO-таймера можно делать или в IDLE, или в RXNE. В последнем случае таймер не останавливается, а перезапускается с начала.
Так же, я настоятельно рекомендую использовать проверку не только флага источника прерывания, но и бита разрешения этого источника. Особенно это необходимо при передаче по TXE-флагу. Этот флаг устанавливается независимо от того, включен передатчик (TE) или выключен. И попадая в прерывание по другому источнику, будет лишняя загрузка передающего регистра. Именно с помощью запрета прерывания TXEIE прекращается передача (в варианте передачи по прерываниям).
Флаг TC устанавливается по завершению передачи символа, если в передающем буфере нет загруженных байтов (TXE = 1).

Ну и не надо писать if((USART1->SR & USART_SR_RXNE) >> USART_SR_RXNE_Pos) == 1), поскольку это излишние действия. Нужно отталкиваться от того, что по правилам языка Си, выражение в if() будет истинно при любом ненулевом значении. А запись USART1->SR & USART_SR_RXNE представляет собой логическую побитовую операцию AND с содержимым регистра и значением битовой маски. То есть, например 0110 AND 0100 = 0100, это есть ненулевое значение и условие if будет истинно и выполнится. Если же 0010 AND 0100 = 0000, то условие if будет ложно и не выполнится.

& - означает побитовую операцию AND двух чисел.
&& - означает логическое AND выражений: "если (ВЫРАЖЕНИЕ_1 = истина) И (ВЫРАЖЕНИЕ_2 = истина)"
Открыл глаза
Сообщения: 65
Зарегистрирован: Ср сен 24, 2014 12:30:09

Сообщение Lum1noFor »

НовыйДень писал(а):Но ведь это несложно и проверить на деле.
Нет, не выставляется, ведь ничего не было принято, поскольку старт-бит и стоп-бит не были обнаружены, и запуска сдвигового регистра приема не было.
Во время приема флаг RXNE выставляется в конце приема байта, а флаг IDLE будет выставлен после того, как линия RX будет оставаться свободной в течение времени, равного длительности кадра (обычно 10 бит).
Флаг ORE (overrun) будет выставляться тогда, когда был принят новый байт, а предыдущий не был прочитан.


"
Спасибо, ну прямо очень подробно! Сохранил себе в текстовый документ. Попробую!
Последний раз редактировалось Lum1noFor Пт май 27, 2022 09:20:08, всего редактировалось 2 раза.
Это не хвост, это антенна
Сообщения: 1379
Зарегистрирован: Вт ноя 19, 2019 06:10:18

Сообщение tonyk »

Eddy_Em писал(а):У меня UART работает через DMA: где-то только передача, где-то - и передача, и прием. И я ни разу в жизни ни IDLE, ни RTO не использовал. ЧЯДНТ?
Расскажи, как ты определяешь конец сообщения, при приёме с использованием DMA?
Возможны всего два варианта: по паузе между байтами или по коду символа.
Друг Кота
Аватара пользователя
Сообщения: 25996
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

[uquote="tonyk",url="/forum/viewtopic.php?p=4237344#p4237344"]Возможны всего два варианта: по паузе между байтами или по коду символа.[/uquote]
Не только.
Есть еще весьма широко распространенный вариант с ФИКСИРОВАННОЙ ДЛИНОЙ пакета.
Скажем, лично я использую во всех своих проектах именно такой вариант. Он происходит из простого факта применения в коммуникациях проекта, в том числе, кастомного HID USB с пакетом в 64 байта. Вот эти пакеты у меня везде и гуляют через DMA<->RS485/RS422.
Собутыльник Кота
Аватара пользователя
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01

Сообщение Eddy_Em »

[uquote="tonyk",url="/forum/viewtopic.php?p=4237344#p4237344"]Расскажи, как ты определяешь конец сообщения, при приёме с использованием DMA?[/uquote]
Элементарно: в STM32F0x2 есть прерывание по символу. Вот я по '\n' и вызываю прерывание, выключаю в нем DMA, меняю местами буферы и выставляю флаг готовности принятой строки. А DMA тем временем во второй буфер поступающие данные копит.
Там, где нет такого прерывания, я обычно прием без DMA делаю. Потому как пользователь не обязан отправлять блоки строго по одной строке: может и несколько строк отправить, а у меня логическая единица - одна строчка. Вот, чтобы не париться с промежуточным буфером, который будет на токены принятое разделять, я и заканчиваю прием строго на '\n', меняю буферы и выставляю флаг готовности.
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Контактная информация:
Это не хвост, это антенна
Сообщения: 1379
Зарегистрирован: Вт ноя 19, 2019 06:10:18

Сообщение tonyk »

[uquote="КРАМ",url="/forum/viewtopic.php?p=4237370#p4237370"][uquote="tonyk",url="/forum/viewtopic.php?p=4237344#p4237344"]Возможны всего два варианта: по паузе между байтами или по коду символа.[/uquote]
Не только.
Есть еще весьма широко распространенный вариант с ФИКСИРОВАННОЙ ДЛИНОЙ пакета.
Скажем, лично я использую во всех своих проектах именно такой вариант. Он происходит из простого факта применения в коммуникациях проекта, в том числе, кастомного HID USB с пакетом в 64 байта. Вот эти пакеты у меня везде и гуляют через DMA<->RS485/RS422.[/uquote]
Ага, а если последний байт пакета не потеряется, например, с передатчика сняли питание? Тогда как? Опять звать на помощь таймер для измерения длительности паузы при приёме? Или тупо ждать следующего пакета, чтоб не заводить таймер? В итоге всё равно не получается третий вариант, однако.

Добавлено after 2 minutes 23 seconds:
[uquote="Eddy_Em",url="/forum/viewtopic.php?p=4237376#p4237376"][uquote="tonyk",url="/forum/viewtopic.php?p=4237344#p4237344"]Расскажи, как ты определяешь конец сообщения, при приёме с использованием DMA?[/uquote]
Элементарно: в STM32F0x2 есть прерывание по символу. Вот я по '\n' и вызываю прерывание, выключаю в нем DMA, меняю местами буферы и выставляю флаг готовности принятой строки. А DMA тем временем во второй буфер поступающие данные копит.
Там, где нет такого прерывания, я обычно прием без DMA делаю. Потому как пользователь не обязан отправлять блоки строго по одной строке: может и несколько строк отправить, а у меня логическая единица - одна строчка. Вот, чтобы не париться с промежуточным буфером, который будет на токены принятое разделять, я и заканчиваю прием строго на '\n', меняю буферы и выставляю флаг готовности.[/uquote]
Так ведь я тебя и спрашивал, по паузе или коду символа? То есть по коду символа, как и ожидалось. Ибо по-другому никак.
Друг Кота
Аватара пользователя
Сообщения: 25996
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

[uquote="tonyk",url="/forum/viewtopic.php?p=4237377#p4237377"]а если последний байт пакета не потеряется, например, с передатчика сняли питание? Тогда как?[/uquote]
Ну сняли и сняли. Пропадет последний незавершенный и первый пакет после включения. Первый после включения завершит сессию DMA и перезапустит ожидание адресного байта.
Это не хвост, это антенна
Сообщения: 1379
Зарегистрирован: Вт ноя 19, 2019 06:10:18

Сообщение tonyk »

[uquote="КРАМ",url="/forum/viewtopic.php?p=4237380#p4237380"][uquote="tonyk",url="/forum/viewtopic.php?p=4237377#p4237377"]а если последний байт пакета не потеряется, например, с передатчика сняли питание? Тогда как?[/uquote]
Ну сняли и сняли. Пропадет последний незавершенный и первый пакет после включения. Первый после включения завершит сессию DMA и перезапустит ожидание адресного байта.[/uquote]
Хм, то есть факт потери связи зафиксирован не будет.
Собутыльник Кота
Аватара пользователя
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01

Сообщение Eddy_Em »

tonyk, почему же по-другому - никак? Можно и по таймауту. Только придется городить промежуточную буферизацию (кольцевой буфер) с построчной выдачей.
Я вот баловался с передачей по USB, используя кольцевой буфер — чтобы максимально увеличить скорость выдачи данных и избавиться от блокирующих операций.
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 25996
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

[uquote="tonyk",url="/forum/viewtopic.php?p=4237381#p4237381"]Хм, то есть факт потери связи зафиксирован не будет.[/uquote]
Почему не будет? Будет. Это делает хост (сиречь программа в винде). А девайсу болт положить на связь. Его функционирование никак с наличием обмена не связано. Через обмен идет управление и мониторинг. Все это не обязательно.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18795
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Eddy_Em писал(а):Элементарно: в STM32F0x2 есть прерывание по символу. Вот я по '\n' и вызываю прерывание, выключаю в нем DMA, меняю местами буферы и выставляю флаг готовности принятой строки.
а контроль переполнения буфера как реализован? а то ведь это классическая дыра...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 25996
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

[uquote="ARV",url="/forum/viewtopic.php?p=4237401#p4237401"]контроль переполнения буфера как реализован?[/uquote]
Очевидно, что по прерыванию от ДМА. Только не переполнение, а заполненный буфер.
Это не хвост, это антенна
Сообщения: 1379
Зарегистрирован: Вт ноя 19, 2019 06:10:18

Сообщение tonyk »

Eddy_Em писал(а):Можно и по таймауту. Только придется городить промежуточную буферизацию (кольцевой буфер) с построчной выдачей.
А можно ничего не городить, а использовать уже имеющийся во всех STM32 IDLE или, что лучше, RTO. :)))
Ответить

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